eventmodeler 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/client-config.js +10 -0
- package/dist/api/generated/client/client.gen.js +235 -0
- package/dist/api/generated/client/index.js +6 -0
- package/dist/api/generated/client/types.gen.js +2 -0
- package/dist/api/generated/client/utils.gen.js +228 -0
- package/dist/api/generated/client.gen.js +4 -0
- package/dist/api/generated/core/auth.gen.js +14 -0
- package/dist/api/generated/core/bodySerializer.gen.js +57 -0
- package/dist/api/generated/core/params.gen.js +100 -0
- package/dist/api/generated/core/pathSerializer.gen.js +106 -0
- package/dist/api/generated/core/queryKeySerializer.gen.js +92 -0
- package/dist/api/generated/core/serverSentEvents.gen.js +133 -0
- package/dist/api/generated/core/types.gen.js +2 -0
- package/dist/api/generated/core/utils.gen.js +87 -0
- package/dist/api/generated/index.js +2 -0
- package/dist/api/generated/sdk.gen.js +4222 -0
- package/dist/api/generated/types.gen.js +2 -0
- package/dist/api/generated/zod.gen.js +7217 -0
- package/dist/commands/add.js +315 -0
- package/dist/commands/auth.js +14 -0
- package/dist/commands/create.js +192 -0
- package/dist/commands/design.js +108 -0
- package/dist/commands/guide.js +15 -0
- package/dist/commands/init.js +21 -0
- package/dist/commands/list-schemas.js +177 -0
- package/dist/commands/list.js +39 -0
- package/dist/commands/loop.js +101 -0
- package/dist/commands/map.js +40 -0
- package/dist/commands/mark.js +27 -0
- package/dist/commands/move.js +35 -0
- package/dist/commands/remove.js +170 -0
- package/dist/commands/rename.js +53 -0
- package/dist/commands/resize.js +30 -0
- package/dist/commands/search.js +14 -0
- package/dist/commands/set.js +199 -0
- package/dist/commands/show-schemas.js +259 -0
- package/dist/commands/show.js +56 -0
- package/dist/commands/summary.js +13 -0
- package/dist/commands/update.js +240 -0
- package/dist/index.js +46 -2379
- package/dist/lib/auth.js +1 -1
- package/dist/lib/config.js +0 -15
- package/dist/lib/excalidraw-schema.js +66 -0
- package/dist/lib/globals.js +8 -0
- package/dist/lib/model.js +11 -0
- package/dist/lib/project-config.js +20 -0
- package/dist/lib/resolve.js +59 -0
- package/dist/lib/scenario.js +15 -0
- package/dist/slices/add-scenario/index.js +2 -206
- package/dist/slices/guide/guides/codegen.js +1 -1
- package/dist/slices/guide/guides/connect-slices.js +38 -38
- package/dist/slices/guide/guides/create-slices.js +110 -140
- package/dist/slices/guide/guides/explore.js +37 -50
- package/dist/slices/guide/guides/information-flow.js +70 -84
- package/dist/slices/guide/guides/scenarios.js +82 -137
- package/dist/slices/guide/index.js +6 -6
- package/dist/slices/help/index.js +96 -0
- package/dist/slices/help/topics/build-codegen.js +109 -0
- package/dist/slices/help/topics/build-slice.js +147 -0
- package/dist/slices/help/topics/check-completeness.js +57 -0
- package/dist/slices/help/topics/connect-slices.js +99 -0
- package/dist/slices/help/topics/explore-model.js +112 -0
- package/dist/slices/help/topics/json-reference.js +188 -0
- package/dist/slices/help/topics/linked-copies.js +89 -0
- package/dist/slices/help/topics/manipulate-canvas.js +150 -0
- package/dist/slices/help/topics/write-scenarios.js +162 -0
- package/dist/slices/init/index.js +10 -4
- package/dist/slices/init/loop.js +60 -0
- package/dist/slices/login/index.js +2 -2
- package/dist/slices/logout/index.js +2 -2
- package/dist/slices/whoami/index.js +11 -36
- package/package.json +8 -3
- package/dist/api/index.d.ts +0 -285
- package/dist/api/index.js +0 -323
- package/dist/cloud/slices/index.d.ts +0 -276
- package/dist/cloud/slices/index.js +0 -406
- package/dist/eventmodeler.js +0 -5646
- package/dist/formatters.d.ts +0 -17
- package/dist/formatters.js +0 -482
- package/dist/index.d.ts +0 -2
- package/dist/lib/auth.d.ts +0 -24
- package/dist/lib/backend.d.ts +0 -43
- package/dist/lib/backend.js +0 -73
- package/dist/lib/chapter-utils.d.ts +0 -13
- package/dist/lib/chapter-utils.js +0 -71
- package/dist/lib/cloud-client.d.ts +0 -69
- package/dist/lib/cloud-client.js +0 -364
- package/dist/lib/config.d.ts +0 -30
- package/dist/lib/diff/merge-rules.d.ts +0 -45
- package/dist/lib/diff/merge-rules.js +0 -210
- package/dist/lib/diff/model-differ.d.ts +0 -8
- package/dist/lib/diff/model-differ.js +0 -568
- package/dist/lib/diff/three-way-merge.d.ts +0 -7
- package/dist/lib/diff/three-way-merge.js +0 -390
- package/dist/lib/diff/types.d.ts +0 -75
- package/dist/lib/diff/types.js +0 -1
- package/dist/lib/element-lookup.d.ts +0 -58
- package/dist/lib/element-lookup.js +0 -126
- package/dist/lib/file-loader.d.ts +0 -8
- package/dist/lib/file-loader.js +0 -108
- package/dist/lib/flow-utils.d.ts +0 -53
- package/dist/lib/flow-utils.js +0 -348
- package/dist/lib/format.d.ts +0 -10
- package/dist/lib/format.js +0 -23
- package/dist/lib/project-config.d.ts +0 -27
- package/dist/lib/slice-utils.d.ts +0 -59
- package/dist/lib/slice-utils.js +0 -140
- package/dist/local/slices/index.d.ts +0 -11
- package/dist/local/slices/index.js +0 -13
- package/dist/projection.d.ts +0 -3
- package/dist/projection.js +0 -828
- package/dist/slices/add-field/index.d.ts +0 -8
- package/dist/slices/add-field/index.js +0 -211
- package/dist/slices/add-scenario/index.d.ts +0 -27
- package/dist/slices/codegen-chapter-events/index.d.ts +0 -2
- package/dist/slices/codegen-chapter-events/index.js +0 -145
- package/dist/slices/codegen-slice/index.d.ts +0 -2
- package/dist/slices/codegen-slice/index.js +0 -448
- package/dist/slices/create-automation-slice/index.d.ts +0 -2
- package/dist/slices/create-automation-slice/index.js +0 -304
- package/dist/slices/create-flow/index.d.ts +0 -2
- package/dist/slices/create-flow/index.js +0 -183
- package/dist/slices/create-state-change-slice/index.d.ts +0 -2
- package/dist/slices/create-state-change-slice/index.js +0 -263
- package/dist/slices/create-state-view-slice/index.d.ts +0 -2
- package/dist/slices/create-state-view-slice/index.js +0 -128
- package/dist/slices/diff/index.d.ts +0 -11
- package/dist/slices/diff/index.js +0 -293
- package/dist/slices/export-eventmodel-to-json/index.d.ts +0 -2
- package/dist/slices/export-eventmodel-to-json/index.js +0 -355
- package/dist/slices/git/index.d.ts +0 -2
- package/dist/slices/git/index.js +0 -125
- package/dist/slices/guide/guides/codegen.d.ts +0 -5
- package/dist/slices/guide/guides/connect-slices.d.ts +0 -5
- package/dist/slices/guide/guides/create-slices.d.ts +0 -5
- package/dist/slices/guide/guides/explore.d.ts +0 -5
- package/dist/slices/guide/guides/information-flow.d.ts +0 -5
- package/dist/slices/guide/guides/scenarios.d.ts +0 -5
- package/dist/slices/guide/index.d.ts +0 -1
- package/dist/slices/import/index.d.ts +0 -8
- package/dist/slices/import/index.js +0 -63
- package/dist/slices/init/index.d.ts +0 -5
- package/dist/slices/list-chapters/index.d.ts +0 -3
- package/dist/slices/list-chapters/index.js +0 -21
- package/dist/slices/list-commands/index.d.ts +0 -3
- package/dist/slices/list-commands/index.js +0 -20
- package/dist/slices/list-events/index.d.ts +0 -3
- package/dist/slices/list-events/index.js +0 -98
- package/dist/slices/list-processors/index.d.ts +0 -3
- package/dist/slices/list-processors/index.js +0 -20
- package/dist/slices/list-readmodels/index.d.ts +0 -3
- package/dist/slices/list-readmodels/index.js +0 -21
- package/dist/slices/list-scenarios/index.d.ts +0 -3
- package/dist/slices/list-scenarios/index.js +0 -35
- package/dist/slices/list-screens/index.d.ts +0 -3
- package/dist/slices/list-screens/index.js +0 -47
- package/dist/slices/list-slices/index.d.ts +0 -3
- package/dist/slices/list-slices/index.js +0 -35
- package/dist/slices/login/index.d.ts +0 -1
- package/dist/slices/logout/index.d.ts +0 -1
- package/dist/slices/map-fields/index.d.ts +0 -2
- package/dist/slices/map-fields/index.js +0 -269
- package/dist/slices/mark-slice-status/index.d.ts +0 -2
- package/dist/slices/mark-slice-status/index.js +0 -31
- package/dist/slices/merge/index.d.ts +0 -19
- package/dist/slices/merge/index.js +0 -147
- package/dist/slices/open-app/index.d.ts +0 -1
- package/dist/slices/remove-field/index.d.ts +0 -8
- package/dist/slices/remove-field/index.js +0 -167
- package/dist/slices/remove-scenario/index.d.ts +0 -2
- package/dist/slices/remove-scenario/index.js +0 -77
- package/dist/slices/search/index.d.ts +0 -3
- package/dist/slices/search/index.js +0 -302
- package/dist/slices/show-actor/index.d.ts +0 -4
- package/dist/slices/show-actor/index.js +0 -115
- package/dist/slices/show-aggregate/index.d.ts +0 -3
- package/dist/slices/show-aggregate/index.js +0 -108
- package/dist/slices/show-aggregate-completeness/index.d.ts +0 -4
- package/dist/slices/show-aggregate-completeness/index.js +0 -181
- package/dist/slices/show-chapter/index.d.ts +0 -3
- package/dist/slices/show-chapter/index.js +0 -195
- package/dist/slices/show-command/index.d.ts +0 -3
- package/dist/slices/show-command/index.js +0 -133
- package/dist/slices/show-completeness/index.d.ts +0 -4
- package/dist/slices/show-completeness/index.js +0 -731
- package/dist/slices/show-event/index.d.ts +0 -3
- package/dist/slices/show-event/index.js +0 -118
- package/dist/slices/show-model-summary/index.d.ts +0 -3
- package/dist/slices/show-model-summary/index.js +0 -31
- package/dist/slices/show-processor/index.d.ts +0 -3
- package/dist/slices/show-processor/index.js +0 -111
- package/dist/slices/show-readmodel/index.d.ts +0 -3
- package/dist/slices/show-readmodel/index.js +0 -158
- package/dist/slices/show-scenario/index.d.ts +0 -3
- package/dist/slices/show-scenario/index.js +0 -196
- package/dist/slices/show-screen/index.d.ts +0 -3
- package/dist/slices/show-screen/index.js +0 -139
- package/dist/slices/show-slice/index.d.ts +0 -3
- package/dist/slices/show-slice/index.js +0 -696
- package/dist/slices/update-field/index.d.ts +0 -15
- package/dist/slices/update-field/index.js +0 -208
- package/dist/slices/whoami/index.d.ts +0 -2
- package/dist/types.d.ts +0 -195
- package/dist/types.js +0 -1
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { meta as exploreModelMeta, content as exploreModelContent } from './topics/explore-model';
|
|
2
|
+
import { meta as buildSliceMeta, content as buildSliceContent } from './topics/build-slice';
|
|
3
|
+
import { meta as connectSlicesMeta, content as connectSlicesContent } from './topics/connect-slices';
|
|
4
|
+
import { meta as writeScenariosMeta, content as writeScenariosContent } from './topics/write-scenarios';
|
|
5
|
+
import { meta as manipulateCanvasMeta, content as manipulateCanvasContent } from './topics/manipulate-canvas';
|
|
6
|
+
import { meta as linkedCopiesMeta, content as linkedCopiesContent } from './topics/linked-copies';
|
|
7
|
+
import { meta as checkCompletenessMeta, content as checkCompletenessContent } from './topics/check-completeness';
|
|
8
|
+
import { meta as jsonReferenceMeta, content as jsonReferenceContent } from './topics/json-reference';
|
|
9
|
+
import { meta as buildCodegenMeta, content as buildCodegenContent } from './topics/build-codegen';
|
|
10
|
+
const TOPICS = [
|
|
11
|
+
{ meta: exploreModelMeta, content: exploreModelContent },
|
|
12
|
+
{ meta: buildSliceMeta, content: buildSliceContent },
|
|
13
|
+
{ meta: connectSlicesMeta, content: connectSlicesContent },
|
|
14
|
+
{ meta: writeScenariosMeta, content: writeScenariosContent },
|
|
15
|
+
{ meta: manipulateCanvasMeta, content: manipulateCanvasContent },
|
|
16
|
+
{ meta: linkedCopiesMeta, content: linkedCopiesContent },
|
|
17
|
+
{ meta: checkCompletenessMeta, content: checkCompletenessContent },
|
|
18
|
+
{ meta: jsonReferenceMeta, content: jsonReferenceContent },
|
|
19
|
+
{ meta: buildCodegenMeta, content: buildCodegenContent },
|
|
20
|
+
];
|
|
21
|
+
export function runHelp(query) {
|
|
22
|
+
if (!query) {
|
|
23
|
+
printTopicIndex();
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
// Exact name match
|
|
27
|
+
const exact = TOPICS.find(t => t.meta.name === query);
|
|
28
|
+
if (exact) {
|
|
29
|
+
console.log(exact.content);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
// Fuzzy keyword match
|
|
33
|
+
const matches = fuzzyMatch(query);
|
|
34
|
+
if (matches.length === 0) {
|
|
35
|
+
console.error(`No help topics matched: "${query}"`);
|
|
36
|
+
console.error(`Run "eventmodeler help" to see all topics.`);
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
if (matches.length === 1) {
|
|
40
|
+
console.log(matches[0].topic.content);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
console.log(`\nMultiple topics matched "${query}":\n`);
|
|
44
|
+
for (const m of matches) {
|
|
45
|
+
console.log(` ${m.topic.meta.name.padEnd(24)} ${m.topic.meta.description} (${m.score} keyword hits)`);
|
|
46
|
+
}
|
|
47
|
+
console.log(`\nRun "eventmodeler help <topic-name>" to read one.\n`);
|
|
48
|
+
}
|
|
49
|
+
function fuzzyMatch(query) {
|
|
50
|
+
const words = query.toLowerCase().split(/\s+/).filter(w => w.length > 0);
|
|
51
|
+
if (words.length === 0)
|
|
52
|
+
return [];
|
|
53
|
+
const scored = [];
|
|
54
|
+
for (const topic of TOPICS) {
|
|
55
|
+
let score = 0;
|
|
56
|
+
const allKeywords = topic.meta.keywords.map(k => k.toLowerCase());
|
|
57
|
+
const nameWords = topic.meta.name.toLowerCase().split('-');
|
|
58
|
+
const descWords = topic.meta.description.toLowerCase().split(/\s+/);
|
|
59
|
+
const searchable = [...allKeywords, ...nameWords, ...descWords];
|
|
60
|
+
for (const word of words) {
|
|
61
|
+
for (const kw of searchable) {
|
|
62
|
+
if (kw === word) {
|
|
63
|
+
score += 2;
|
|
64
|
+
break;
|
|
65
|
+
}
|
|
66
|
+
else if (kw.startsWith(word) || word.startsWith(kw)) {
|
|
67
|
+
score += 1;
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
if (score > 0) {
|
|
73
|
+
scored.push({ topic, score });
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
scored.sort((a, b) => b.score - a.score);
|
|
77
|
+
return scored.slice(0, 5);
|
|
78
|
+
}
|
|
79
|
+
function printTopicIndex() {
|
|
80
|
+
console.log(`
|
|
81
|
+
eventmodeler help - Task-oriented help for the Event Modeler CLI
|
|
82
|
+
|
|
83
|
+
USAGE:
|
|
84
|
+
eventmodeler help <topic> Show a specific topic
|
|
85
|
+
eventmodeler help <search words> Search topics by keyword
|
|
86
|
+
|
|
87
|
+
TOPICS:
|
|
88
|
+
${TOPICS.map(t => ` ${t.meta.name.padEnd(24)} ${t.meta.description}`).join('\n')}
|
|
89
|
+
|
|
90
|
+
EXAMPLES:
|
|
91
|
+
eventmodeler help build-slice
|
|
92
|
+
eventmodeler help json
|
|
93
|
+
eventmodeler help place move canvas
|
|
94
|
+
eventmodeler help scenario given when then
|
|
95
|
+
`);
|
|
96
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
export const meta = {
|
|
2
|
+
name: 'build-codegen',
|
|
3
|
+
keywords: ['codegen', 'generator', 'generate', 'code', 'export', 'template', 'scaffold', 'boilerplate', 'loop', 'ralph', 'ai', 'agent', 'automation', 'pipeline', 'show', 'model', 'slice', 'chapter', 'context', 'schema', 'shape', 'response'],
|
|
4
|
+
description: 'Build a code generator that consumes show-* outputs to scaffold a slice',
|
|
5
|
+
};
|
|
6
|
+
export const content = `
|
|
7
|
+
# Building a Code Generator
|
|
8
|
+
|
|
9
|
+
WHEN TO USE: You want to turn an event model into code — REST endpoints,
|
|
10
|
+
handlers, projections, tests, whatever your stack uses. The CLI gives you
|
|
11
|
+
JSON; you own the template.
|
|
12
|
+
|
|
13
|
+
## The input surface
|
|
14
|
+
|
|
15
|
+
The CLI is the export layer. These four commands emit JSON that a code
|
|
16
|
+
generator can consume:
|
|
17
|
+
|
|
18
|
+
eventmodeler show model # whole model, all elements
|
|
19
|
+
eventmodeler show context <name> # one bounded context + its chapters + slices
|
|
20
|
+
eventmodeler show chapter <name> # one chapter + its slices
|
|
21
|
+
eventmodeler show slice <name> # one slice: elements, fields, flows, scenarios
|
|
22
|
+
|
|
23
|
+
Pick the grain that fits what you generate. Most generators work at the
|
|
24
|
+
slice level — one slice maps to one vertical feature's worth of code.
|
|
25
|
+
|
|
26
|
+
## Response shapes
|
|
27
|
+
|
|
28
|
+
Every show-* command documents its exact response schema in its own --help:
|
|
29
|
+
|
|
30
|
+
eventmodeler show model --help
|
|
31
|
+
eventmodeler show context --help
|
|
32
|
+
eventmodeler show chapter --help
|
|
33
|
+
eventmodeler show slice --help
|
|
34
|
+
eventmodeler show event --help # same shape for command/readmodel/screen/processor/external-event
|
|
35
|
+
eventmodeler show completeness --help
|
|
36
|
+
|
|
37
|
+
The schemas include every field, all enum values, and the nested types
|
|
38
|
+
(ElementView, FieldView, FlowView, ScenarioView, etc.). Read them before
|
|
39
|
+
writing templates — don't guess.
|
|
40
|
+
|
|
41
|
+
## Minimum viable pipeline
|
|
42
|
+
|
|
43
|
+
# 1. Fetch one slice as JSON
|
|
44
|
+
eventmodeler show slice "Place Order" > slice.json
|
|
45
|
+
|
|
46
|
+
# 2. Read it in any language — it's just JSON matching the shapes above
|
|
47
|
+
# 3. Render your templates (one per elementType is a common split)
|
|
48
|
+
# 4. Write files into your target project
|
|
49
|
+
|
|
50
|
+
A good generator is idempotent: running it twice produces the same output.
|
|
51
|
+
Use the slice name or ID as the stable key.
|
|
52
|
+
|
|
53
|
+
## Ralph loop — driving generation from the model
|
|
54
|
+
|
|
55
|
+
The "loop" command polls for slices marked "planned" and runs your script
|
|
56
|
+
against each one. Combined with your codegen, you get a closed loop: mark
|
|
57
|
+
a slice "planned" in the UI, and the generator picks it up.
|
|
58
|
+
|
|
59
|
+
Config (.eventmodeler.json):
|
|
60
|
+
|
|
61
|
+
{
|
|
62
|
+
"loop": {
|
|
63
|
+
"command": "./generate.sh",
|
|
64
|
+
"interval": 30
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
Run:
|
|
69
|
+
|
|
70
|
+
eventmodeler loop
|
|
71
|
+
|
|
72
|
+
The loop doesn't touch slice status — your script does. A typical
|
|
73
|
+
generate.sh:
|
|
74
|
+
|
|
75
|
+
#!/usr/bin/env bash
|
|
76
|
+
set -e
|
|
77
|
+
SLICE="$1"
|
|
78
|
+
|
|
79
|
+
eventmodeler mark "$SLICE" in-progress
|
|
80
|
+
|
|
81
|
+
eventmodeler show slice "$SLICE" > /tmp/slice.json
|
|
82
|
+
./render-templates.sh /tmp/slice.json || {
|
|
83
|
+
eventmodeler mark "$SLICE" blocked
|
|
84
|
+
exit 1
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
eventmodeler mark "$SLICE" done
|
|
88
|
+
|
|
89
|
+
If the script crashes before marking anything, the slice stays "planned"
|
|
90
|
+
and the next poll retries it.
|
|
91
|
+
|
|
92
|
+
## Good generator patterns
|
|
93
|
+
|
|
94
|
+
- One template per elementType (screen, command, event, readmodel, processor).
|
|
95
|
+
- Use the slice's flows to decide wiring — flows tell you which handler
|
|
96
|
+
emits which event and which projection reads which event.
|
|
97
|
+
- Scenarios map naturally to test cases: Given = fixture, When = command
|
|
98
|
+
invocation, Then = assertion.
|
|
99
|
+
- Treat the model as the source of truth. Don't hand-edit generated files
|
|
100
|
+
— regenerate.
|
|
101
|
+
- Skip elements with "linkedCopy": true during codegen — they're visual
|
|
102
|
+
proxies and the real element lives in another slice.
|
|
103
|
+
|
|
104
|
+
## Related
|
|
105
|
+
|
|
106
|
+
eventmodeler help explore-model # how to navigate a model
|
|
107
|
+
eventmodeler help json-reference # write-command input shapes
|
|
108
|
+
eventmodeler loop --help # loop flags and script contract
|
|
109
|
+
`;
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
export const meta = {
|
|
2
|
+
name: 'build-slice',
|
|
3
|
+
keywords: ['build', 'create', 'slice', 'new', 'add', 'field', 'subfield', 'element', 'command', 'event', 'readmodel', 'screen', 'processor', 'type', 'custom', 'UUID', 'String', 'Int', 'Boolean', 'state-change', 'automation', 'state-view'],
|
|
4
|
+
description: 'Build a complete slice from scratch with elements, fields, and flows',
|
|
5
|
+
};
|
|
6
|
+
export const content = `
|
|
7
|
+
# Building a Slice from Scratch
|
|
8
|
+
|
|
9
|
+
WHEN TO USE: You need to create a new vertical feature slice with its elements, fields, and flows.
|
|
10
|
+
|
|
11
|
+
## Slice Types
|
|
12
|
+
|
|
13
|
+
STATE-CHANGE: Screen -> Command -> Event (user action)
|
|
14
|
+
AUTOMATION: ReadModel -> Processor -> Command -> Event (system reaction)
|
|
15
|
+
STATE-VIEW: ReadModel (fed by events from other slices) (query/projection)
|
|
16
|
+
|
|
17
|
+
## Task: Create a slice with elements and flows in one command
|
|
18
|
+
|
|
19
|
+
COMMAND:
|
|
20
|
+
eventmodeler create slice '<json>'
|
|
21
|
+
|
|
22
|
+
EXAMPLE:
|
|
23
|
+
eventmodeler create slice '{
|
|
24
|
+
"sliceName": "Place Order",
|
|
25
|
+
"elements": [
|
|
26
|
+
{"id": "a1b2c3d4-0001-0000-0000-000000000001", "type": "screen", "name": "OrderForm", "fields": [
|
|
27
|
+
{"name": "customerId", "type": "UUID"},
|
|
28
|
+
{"name": "items", "type": "Custom", "isList": true, "subfields": [
|
|
29
|
+
{"name": "productId", "type": "UUID"},
|
|
30
|
+
{"name": "quantity", "type": "Int"}
|
|
31
|
+
]}
|
|
32
|
+
]},
|
|
33
|
+
{"id": "a1b2c3d4-0001-0000-0000-000000000002", "type": "command", "name": "PlaceOrder", "fields": [
|
|
34
|
+
{"name": "orderId", "type": "UUID", "isGenerated": true},
|
|
35
|
+
{"name": "customerId", "type": "UUID"},
|
|
36
|
+
{"name": "items", "type": "Custom", "isList": true, "subfields": [
|
|
37
|
+
{"name": "productId", "type": "UUID"},
|
|
38
|
+
{"name": "quantity", "type": "Int"}
|
|
39
|
+
]}
|
|
40
|
+
]},
|
|
41
|
+
{"id": "a1b2c3d4-0001-0000-0000-000000000003", "type": "event", "name": "OrderPlaced", "fields": [
|
|
42
|
+
{"name": "orderId", "type": "UUID"},
|
|
43
|
+
{"name": "customerId", "type": "UUID"},
|
|
44
|
+
{"name": "placedAt", "type": "DateTime", "isGenerated": true}
|
|
45
|
+
]}
|
|
46
|
+
],
|
|
47
|
+
"flows": [
|
|
48
|
+
{"id": "f1000000-0000-0000-0000-000000000001", "from": "OrderForm", "to": "PlaceOrder"},
|
|
49
|
+
{"id": "f1000000-0000-0000-0000-000000000002", "from": "PlaceOrder", "to": "OrderPlaced"}
|
|
50
|
+
]
|
|
51
|
+
}'
|
|
52
|
+
|
|
53
|
+
NOTES:
|
|
54
|
+
- The JSON is a positional argument (not a --json flag)
|
|
55
|
+
- Every element and flow needs a unique UUID
|
|
56
|
+
- Valid flow pairs: screen->command, command->event, command->external-event,
|
|
57
|
+
event->readmodel, readmodel->screen, readmodel->processor, processor->command,
|
|
58
|
+
external-event->processor
|
|
59
|
+
- "from" and "to" reference element names within the slice
|
|
60
|
+
- Layout is auto-calculated from Y bands and X spacing
|
|
61
|
+
|
|
62
|
+
## Task: Place individual elements (alternative to create slice)
|
|
63
|
+
|
|
64
|
+
COMMAND:
|
|
65
|
+
eventmodeler create place <type> <name> --x <n> --y <n>
|
|
66
|
+
|
|
67
|
+
EXAMPLES:
|
|
68
|
+
eventmodeler create place screen "OrderForm" --x 2040 --y 120
|
|
69
|
+
eventmodeler create place command "PlaceOrder" --x 2040 --y 460
|
|
70
|
+
eventmodeler create place event "OrderPlaced" --x 2040 --y 860
|
|
71
|
+
|
|
72
|
+
NOTES:
|
|
73
|
+
- See "help manipulate-canvas" for Y band positions and spacing rules
|
|
74
|
+
- Use this when adding elements to an existing slice or building incrementally
|
|
75
|
+
|
|
76
|
+
## Task: Add a field to an existing element
|
|
77
|
+
|
|
78
|
+
COMMAND:
|
|
79
|
+
eventmodeler add field [elementName] '<json>'
|
|
80
|
+
eventmodeler --id <uuid> add field '<json>'
|
|
81
|
+
|
|
82
|
+
EXAMPLES:
|
|
83
|
+
eventmodeler add field "PlaceOrder" '{"name": "email", "type": "String"}'
|
|
84
|
+
eventmodeler add field "OrderPlaced" '{"name": "orderId", "type": "UUID", "isGenerated": true}'
|
|
85
|
+
eventmodeler add field "PlaceOrder" '{"name": "address", "type": "Custom", "subfields": [
|
|
86
|
+
{"name": "street", "type": "String"},
|
|
87
|
+
{"name": "city", "type": "String"},
|
|
88
|
+
{"name": "zip", "type": "String"}
|
|
89
|
+
]}'
|
|
90
|
+
|
|
91
|
+
FIELD TYPES:
|
|
92
|
+
UUID, String, Int, Long, Double, Decimal, Boolean, Date, DateTime, Custom
|
|
93
|
+
|
|
94
|
+
FIELD ATTRIBUTES (add to the JSON, all optional):
|
|
95
|
+
"isOptional": true — field may be absent
|
|
96
|
+
"isGenerated": true — system-generated (IDs, timestamps)
|
|
97
|
+
"isList": true — array of this type
|
|
98
|
+
"isUserInput": true — provided by user (screens only)
|
|
99
|
+
|
|
100
|
+
CUSTOM TYPE RULES:
|
|
101
|
+
- Custom fields MUST have "subfields" array — empty Custom is invalid
|
|
102
|
+
- Subfields can themselves be Custom (arbitrary nesting)
|
|
103
|
+
- Combine with "isList": true for arrays of objects
|
|
104
|
+
|
|
105
|
+
## Task: Add a subfield to an existing Custom field
|
|
106
|
+
|
|
107
|
+
COMMAND:
|
|
108
|
+
eventmodeler add subfield [elementName] '{"name": "country", "type": "String"}' --field "address"
|
|
109
|
+
|
|
110
|
+
NOTES:
|
|
111
|
+
- --field identifies the parent field by name
|
|
112
|
+
- Parent field must be type "Custom"
|
|
113
|
+
|
|
114
|
+
## Task: Remove a field
|
|
115
|
+
|
|
116
|
+
COMMAND:
|
|
117
|
+
eventmodeler remove field [elementName] --field <fieldName>
|
|
118
|
+
|
|
119
|
+
EXAMPLE:
|
|
120
|
+
eventmodeler remove field "OrderPlaced" --field "legacyId"
|
|
121
|
+
|
|
122
|
+
## Task: Update a field (rename, change type, mark flags)
|
|
123
|
+
|
|
124
|
+
COMMAND:
|
|
125
|
+
eventmodeler update field [elementName] --field <name> [--name <new>] [--type <new>] [--optional true|false] [--generated true|false] [--list true|false] [--user-input true|false]
|
|
126
|
+
|
|
127
|
+
EXAMPLES:
|
|
128
|
+
eventmodeler update field "OrderPlaced" --field "total" --type Decimal
|
|
129
|
+
eventmodeler update field "OrderPlaced" --field "promoCode" --optional true
|
|
130
|
+
eventmodeler update field "Checkout" --field "email" --user-input true
|
|
131
|
+
|
|
132
|
+
## Task: Update a subfield (rename, change type)
|
|
133
|
+
|
|
134
|
+
COMMAND:
|
|
135
|
+
eventmodeler update subfield [elementName] --subfield <subfieldId> [--name <new>] [--type <new>]
|
|
136
|
+
|
|
137
|
+
NOTES:
|
|
138
|
+
- Subfield ID comes from show output (not the field name)
|
|
139
|
+
|
|
140
|
+
## Task: Reorder a field
|
|
141
|
+
|
|
142
|
+
COMMAND:
|
|
143
|
+
eventmodeler update reorder [elementName] --field <name> --position <n>
|
|
144
|
+
|
|
145
|
+
EXAMPLE:
|
|
146
|
+
eventmodeler update reorder "OrderPlaced" --field "orderId" --position 0
|
|
147
|
+
`;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
export const meta = {
|
|
2
|
+
name: 'check-completeness',
|
|
3
|
+
keywords: ['completeness', 'missing', 'unsatisfied', 'incomplete', 'mapping', 'field', 'flow', 'aggregate', 'model', 'health', 'check', 'validate'],
|
|
4
|
+
description: 'Find and fix missing field mappings and incomplete flows',
|
|
5
|
+
};
|
|
6
|
+
export const content = `
|
|
7
|
+
# Checking Completeness
|
|
8
|
+
|
|
9
|
+
WHEN TO USE: You need to verify that all fields are properly mapped across flows.
|
|
10
|
+
|
|
11
|
+
## Task: Check completeness of a specific element
|
|
12
|
+
|
|
13
|
+
COMMANDS:
|
|
14
|
+
eventmodeler show completeness "<name>"
|
|
15
|
+
eventmodeler show completeness --id "<uuid>"
|
|
16
|
+
|
|
17
|
+
EXAMPLE:
|
|
18
|
+
eventmodeler show completeness "OrderSummary"
|
|
19
|
+
|
|
20
|
+
NOTES:
|
|
21
|
+
- Auto-detects element type (command, event, readmodel, screen, processor)
|
|
22
|
+
- Shows: incoming flows, satisfied fields, unsatisfied fields
|
|
23
|
+
- An unsatisfied field has no source mapping from any incoming flow
|
|
24
|
+
|
|
25
|
+
## Task: Check completeness of the entire model
|
|
26
|
+
|
|
27
|
+
COMMANDS:
|
|
28
|
+
eventmodeler show model-completeness
|
|
29
|
+
|
|
30
|
+
NOTES:
|
|
31
|
+
- Returns: complete count, incomplete count, total
|
|
32
|
+
- Lists all incomplete flows with their unsatisfied fields
|
|
33
|
+
- Use this as a health check after making changes
|
|
34
|
+
|
|
35
|
+
## Task: Check aggregate ID field consistency
|
|
36
|
+
|
|
37
|
+
COMMANDS:
|
|
38
|
+
eventmodeler show aggregate-completeness "<aggregateName>"
|
|
39
|
+
|
|
40
|
+
EXAMPLE:
|
|
41
|
+
eventmodeler show aggregate-completeness "Order"
|
|
42
|
+
|
|
43
|
+
NOTES:
|
|
44
|
+
- Checks if all events in the aggregate have the aggregate's ID field
|
|
45
|
+
- Events missing the aggregate ID field are flagged
|
|
46
|
+
|
|
47
|
+
## Fixing Incomplete Flows
|
|
48
|
+
|
|
49
|
+
STRATEGY:
|
|
50
|
+
1. Run: eventmodeler show model-completeness
|
|
51
|
+
2. For each incomplete flow, check what fields are missing
|
|
52
|
+
3. Either:
|
|
53
|
+
a. Add the missing field to the source element:
|
|
54
|
+
eventmodeler add field "SourceElement" '{"name": "missingField", "type": "String"}'
|
|
55
|
+
b. Map an existing source field to the target field:
|
|
56
|
+
eventmodeler map fields '[{"source": "existingField", "target": "missingField"}]' --from "Source" --to "Target"
|
|
57
|
+
`;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
export const meta = {
|
|
2
|
+
name: 'connect-slices',
|
|
3
|
+
keywords: ['connect', 'flow', 'wire', 'link', 'map', 'mapping', 'field', 'between', 'cross-slice', 'inbound', 'outbound', 'from', 'to', 'remove', 'mapping'],
|
|
4
|
+
description: 'Wire slices together with flows and field mappings',
|
|
5
|
+
};
|
|
6
|
+
export const content = `
|
|
7
|
+
# Connecting Slices with Flows and Field Mappings
|
|
8
|
+
|
|
9
|
+
WHEN TO USE: You need to wire elements together within or across slices.
|
|
10
|
+
|
|
11
|
+
## Task: Create a flow between two elements
|
|
12
|
+
|
|
13
|
+
COMMAND:
|
|
14
|
+
eventmodeler create flow --from <sourceName> --to <targetName>
|
|
15
|
+
|
|
16
|
+
EXAMPLES:
|
|
17
|
+
eventmodeler create flow --from "OrderPlaced" --to "OrderSummary"
|
|
18
|
+
eventmodeler create flow --from "OrderForm" --to "PlaceOrder"
|
|
19
|
+
eventmodeler create flow --from "OrderSummary" --to "Order Details Screen"
|
|
20
|
+
|
|
21
|
+
VALID FLOW PAIRS:
|
|
22
|
+
screen -> command
|
|
23
|
+
command -> event
|
|
24
|
+
command -> external-event
|
|
25
|
+
event -> readmodel
|
|
26
|
+
readmodel -> screen
|
|
27
|
+
readmodel -> processor
|
|
28
|
+
processor -> command
|
|
29
|
+
external-event -> processor
|
|
30
|
+
|
|
31
|
+
NOTES:
|
|
32
|
+
- Flows can connect elements within the same slice or across slices
|
|
33
|
+
- The CLI auto-detects the flow type from the source/target element types
|
|
34
|
+
- Use --id for source/target when elements share names (linked copies)
|
|
35
|
+
|
|
36
|
+
## Task: Map fields on a flow
|
|
37
|
+
|
|
38
|
+
COMMAND:
|
|
39
|
+
eventmodeler map fields '<json>' --from <sourceName> --to <targetName>
|
|
40
|
+
|
|
41
|
+
EXAMPLE:
|
|
42
|
+
eventmodeler map fields '[
|
|
43
|
+
{"source": "orderId", "target": "orderId"},
|
|
44
|
+
{"source": "customerId", "target": "customerId"},
|
|
45
|
+
{"source": "totalAmount", "target": "total"}
|
|
46
|
+
]' --from "OrderPlaced" --to "OrderSummary"
|
|
47
|
+
|
|
48
|
+
MAPPINGS JSON:
|
|
49
|
+
[ { "source": "sourceFieldName", "target": "targetFieldName" } ]
|
|
50
|
+
|
|
51
|
+
NOTES:
|
|
52
|
+
- Source and target are field names on the respective elements
|
|
53
|
+
- You can map fields with different names (e.g., source "userId" -> target "customerId")
|
|
54
|
+
- Unmapped fields show up as incomplete in completeness checks
|
|
55
|
+
- Run multiple map commands to add mappings incrementally
|
|
56
|
+
|
|
57
|
+
## Task: Remove a specific field mapping
|
|
58
|
+
|
|
59
|
+
COMMAND:
|
|
60
|
+
eventmodeler remove mapping --from <sourceName> --to <targetName> --mapping <mappingId>
|
|
61
|
+
|
|
62
|
+
NOTES:
|
|
63
|
+
- Mapping IDs are visible in show slice output (flow mappings section)
|
|
64
|
+
|
|
65
|
+
## Task: Remove a flow entirely
|
|
66
|
+
|
|
67
|
+
COMMAND:
|
|
68
|
+
eventmodeler remove flow --from <sourceName> --to <targetName>
|
|
69
|
+
|
|
70
|
+
## Task: View existing flows
|
|
71
|
+
|
|
72
|
+
COMMANDS:
|
|
73
|
+
eventmodeler show slice "Place Order" (shows all flows + field mappings)
|
|
74
|
+
eventmodeler show event "OrderPlaced" (shows cross-cutting flow connections)
|
|
75
|
+
eventmodeler show completeness (shows which fields are unmapped)
|
|
76
|
+
|
|
77
|
+
## Typical Workflow: Connect Slice A's event to Slice B's readmodel
|
|
78
|
+
|
|
79
|
+
1. Check what events Slice A produces:
|
|
80
|
+
eventmodeler show slice "Place Order"
|
|
81
|
+
|
|
82
|
+
2. Check what readmodel Slice B has:
|
|
83
|
+
eventmodeler show slice "View Order"
|
|
84
|
+
|
|
85
|
+
3. If the event needs to appear in Slice B, create a linked copy:
|
|
86
|
+
eventmodeler create place-copy event "OrderPlaced" --x 3000 --y 860
|
|
87
|
+
|
|
88
|
+
4. Create the flow:
|
|
89
|
+
eventmodeler create flow --from "OrderPlaced" --to "OrderHistory"
|
|
90
|
+
|
|
91
|
+
5. Map the fields:
|
|
92
|
+
eventmodeler map fields '[
|
|
93
|
+
{"source": "orderId", "target": "orderId"},
|
|
94
|
+
{"source": "customerId", "target": "customerId"}
|
|
95
|
+
]' --from "OrderPlaced" --to "OrderHistory"
|
|
96
|
+
|
|
97
|
+
6. Verify completeness:
|
|
98
|
+
eventmodeler show completeness
|
|
99
|
+
`;
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
export const meta = {
|
|
2
|
+
name: 'explore-model',
|
|
3
|
+
keywords: ['explore', 'list', 'show', 'search', 'summary', 'navigate', 'query', 'overview', 'inspect', 'detail', 'slice', 'chapter', 'event', 'command', 'readmodel', 'screen', 'processor', 'aggregate', 'actor', 'scenario', 'status', 'mark'],
|
|
4
|
+
description: 'Navigate, query, and understand an existing event model',
|
|
5
|
+
};
|
|
6
|
+
export const content = `
|
|
7
|
+
# Exploring an Event Model
|
|
8
|
+
|
|
9
|
+
WHEN TO USE: You have an existing model and need to understand what's in it.
|
|
10
|
+
|
|
11
|
+
## Task: Get a high-level overview
|
|
12
|
+
|
|
13
|
+
COMMANDS:
|
|
14
|
+
eventmodeler summary
|
|
15
|
+
|
|
16
|
+
NOTES:
|
|
17
|
+
- Returns counts of all element types (slices, events, commands, etc.)
|
|
18
|
+
|
|
19
|
+
## Task: List all slices
|
|
20
|
+
|
|
21
|
+
COMMANDS:
|
|
22
|
+
eventmodeler list slices
|
|
23
|
+
eventmodeler list slices --chapter "User Onboarding"
|
|
24
|
+
|
|
25
|
+
NOTES:
|
|
26
|
+
- Each slice is a vertical feature with status: created, in-progress, blocked, done
|
|
27
|
+
- --chapter filters to slices within that chapter
|
|
28
|
+
|
|
29
|
+
## Task: List elements by type
|
|
30
|
+
|
|
31
|
+
COMMANDS:
|
|
32
|
+
eventmodeler list events
|
|
33
|
+
eventmodeler list commands
|
|
34
|
+
eventmodeler list readmodels
|
|
35
|
+
eventmodeler list screens
|
|
36
|
+
eventmodeler list processors
|
|
37
|
+
eventmodeler list scenarios
|
|
38
|
+
eventmodeler list aggregates
|
|
39
|
+
eventmodeler list actors
|
|
40
|
+
eventmodeler list chapters
|
|
41
|
+
|
|
42
|
+
NOTES:
|
|
43
|
+
- All list commands output JSON
|
|
44
|
+
|
|
45
|
+
## Task: Search for something by name
|
|
46
|
+
|
|
47
|
+
COMMANDS:
|
|
48
|
+
eventmodeler search "order"
|
|
49
|
+
|
|
50
|
+
NOTES:
|
|
51
|
+
- Searches across all entity names: slices, events, commands, read models, aggregates, actors
|
|
52
|
+
|
|
53
|
+
## Task: Inspect a specific slice
|
|
54
|
+
|
|
55
|
+
COMMANDS:
|
|
56
|
+
eventmodeler show slice "Place Order"
|
|
57
|
+
|
|
58
|
+
NOTES:
|
|
59
|
+
- Returns: components (screens, commands, events, readmodels, processors), flows, fields, scenarios
|
|
60
|
+
- Shows inbound flows (external elements flowing INTO this slice) and outbound flows (flowing OUT)
|
|
61
|
+
- Scenarios define the slice's behavior as Given-When-Then test cases
|
|
62
|
+
|
|
63
|
+
## Task: Inspect a specific element
|
|
64
|
+
|
|
65
|
+
COMMANDS:
|
|
66
|
+
eventmodeler show event "OrderPlaced"
|
|
67
|
+
eventmodeler show command "PlaceOrder"
|
|
68
|
+
eventmodeler show readmodel "OrderSummary"
|
|
69
|
+
eventmodeler show screen "OrderForm"
|
|
70
|
+
eventmodeler show processor "NotifyCustomer"
|
|
71
|
+
eventmodeler show aggregate "Order"
|
|
72
|
+
eventmodeler show scenario "Successfully place order"
|
|
73
|
+
eventmodeler show chapter "Order Management"
|
|
74
|
+
eventmodeler show actor "Customer"
|
|
75
|
+
|
|
76
|
+
NOTES:
|
|
77
|
+
- show event/command: fields, connections, containing slice
|
|
78
|
+
- show readmodel: fields, source events, consumers
|
|
79
|
+
- show screen: fields, source readmodels, triggered commands
|
|
80
|
+
- show processor: fields, source readmodels, triggered commands
|
|
81
|
+
- show aggregate: ID field, contained events
|
|
82
|
+
- show scenario: full Given-When-Then with field values
|
|
83
|
+
- show chapter: contained slices, inter-slice flow graph, external dependencies
|
|
84
|
+
- show actor: associated screens
|
|
85
|
+
|
|
86
|
+
## Task: Use --id to target a specific element by UUID
|
|
87
|
+
|
|
88
|
+
COMMANDS:
|
|
89
|
+
eventmodeler show event --id "550e8400-e29b-41d4-a716-446655440000"
|
|
90
|
+
|
|
91
|
+
NOTES:
|
|
92
|
+
- Skips name resolution, targets element by UUID directly
|
|
93
|
+
- Essential when multiple elements share the same name (linked copies)
|
|
94
|
+
- Works on all name-based commands
|
|
95
|
+
|
|
96
|
+
## Task: Mark a slice's status
|
|
97
|
+
|
|
98
|
+
COMMANDS:
|
|
99
|
+
eventmodeler mark "Place Order" in-progress
|
|
100
|
+
eventmodeler mark "Place Order" done
|
|
101
|
+
eventmodeler mark "Place Order" blocked
|
|
102
|
+
eventmodeler mark "Place Order" created
|
|
103
|
+
|
|
104
|
+
## Exploration strategy
|
|
105
|
+
|
|
106
|
+
1. eventmodeler summary -> understand scale
|
|
107
|
+
2. eventmodeler list slices -> what features exist?
|
|
108
|
+
3. eventmodeler list chapters -> how are features organized?
|
|
109
|
+
4. eventmodeler show slice "<name>" -> how does one feature work?
|
|
110
|
+
5. Read the scenarios -> what does it actually do?
|
|
111
|
+
6. eventmodeler search "<term>" -> find related elements
|
|
112
|
+
`;
|