Skip to content

Commit 8f1943a

Browse files
akoclaude
andcommitted
docs: add BSON tooling guide for contributors
Explains which BSON tool to use when: bson dump, bson compare, bson discover, TUI, Python scripts, and mx check. Covers both adding new document types and debugging serialization issues. Updates implement-mdl-feature.md to use `mxcli bson dump` instead of the outdated `go run ./cmd/debug/main.go`, and adds cross-references from both skill files to the new guide. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent edb8672 commit 8f1943a

3 files changed

Lines changed: 261 additions & 4 deletions

File tree

.claude/skills/debug-bson.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@ for t, props in crash_props.items():
230230

231231
## Related Documentation
232232

233+
- [BSON Tooling Guide](../../docs/03-development/BSON_TOOLING_GUIDE.md) — Which BSON tool to use when (dump, compare, discover, TUI, Python)
233234
- [PAGE_BSON_SERIALIZATION.md](../../docs/03-development/PAGE_BSON_SERIALIZATION.md) — Full BSON format reference and CE0463 analysis
234235
- [sdk/widgets/templates/README.md](../../sdk/widgets/templates/README.md) — Template extraction requirements
235236
- [implement-mdl-feature.md](./implement-mdl-feature.md) — Full feature implementation workflow

.claude/skills/implement-mdl-feature.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,10 @@ First, create or find an example of the feature in Mendix Studio Pro:
8686

8787
### Step 3: Dump Raw BSON
8888

89-
Use the debug tool to dump the raw BSON structure:
89+
Use `mxcli bson dump` to inspect the raw BSON structure (see [BSON Tooling Guide](../../docs/03-development/BSON_TOOLING_GUIDE.md) for the full tool reference):
9090

9191
```bash
92-
go run ./cmd/debug/main.go mx-test-projects/test2-go-app/test2-go.mpr <document-id>
92+
mxcli bson dump -p mx-test-projects/test2-go-app/test2-go.mpr --type microflow --object "RestTemplate.GetWebpage"
9393
```
9494

9595
Example output (abbreviated):
@@ -573,7 +573,8 @@ Before considering the implementation complete:
573573
| Debug | `cmd/debug/main.go` | Raw BSON dump tool |
574574
| Examples | `mdl-examples/doctype-tests/` | MDL examples |
575575

576-
## Related Skills
576+
## Related Documentation
577577

578-
- [BSON Serialization Debugging](./debug-bson.md) - Fixing BSON serialization issues
578+
- [BSON Tooling Guide](../../docs/03-development/BSON_TOOLING_GUIDE.md) - Which BSON tool to use when (dump, compare, discover, TUI, Python)
579+
- [Debug BSON](./debug-bson.md) - Fixing BSON serialization issues (CE errors, widget templates)
579580
- [Write Microflows](./write-microflows.md) - MDL microflow syntax reference
Lines changed: 255 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,255 @@
1+
# BSON Tooling Guide
2+
3+
How to use mxcli's BSON tools when adding support for a new Mendix document type or debugging serialization issues. This guide covers which tool to use at each stage.
4+
5+
## Tool inventory
6+
7+
| Tool | Command | Best for |
8+
|------|---------|----------|
9+
| **bson dump** | `mxcli bson dump` | Seeing raw BSON structure of any document |
10+
| **bson compare** | `mxcli bson compare` | Diffing two documents (same or cross-project) |
11+
| **bson discover** | `mxcli bson discover` | Finding which BSON fields your MDL covers |
12+
| **TUI** | `mxcli tui -p app.mpr` | Interactive browsing and side-by-side comparison |
13+
| **Python bson diff** | See debug-bson.md | Finding crash-causing extra fields across all documents |
14+
| **mx check** | `mx check app.mpr` | Validating BSON output against Mendix runtime |
15+
16+
## Part 1: Adding a new document type
17+
18+
### Stage 1 -- Understand the BSON structure
19+
20+
You need a reference project that has the document type created in Studio Pro.
21+
22+
**List all instances of a type:**
23+
24+
```bash
25+
mxcli bson dump -p app.mpr --type workflow --list
26+
```
27+
28+
Output: names of all workflows in the project. Supported types: `page`, `microflow`, `nanoflow`, `enumeration`, `snippet`, `layout`, `constant`, `workflow`, `imagecollection`, `javaaction`, `javascriptaction`, `entity`, `association`.
29+
30+
**Dump a single document as JSON:**
31+
32+
```bash
33+
mxcli bson dump -p app.mpr --type workflow --object "Module.MyWorkflow"
34+
```
35+
36+
This shows the complete BSON tree with `$Type`, `$ID`, nested objects, and arrays. Use this output to understand which fields exist and how they're structured.
37+
38+
**Dump as NDSL (normalized DSL) for a cleaner view:**
39+
40+
```bash
41+
mxcli bson dump -p app.mpr --type workflow --object "Module.MyWorkflow" --format ndsl
42+
```
43+
44+
NDSL renders the BSON as a structured text format that's easier to scan: type headers, alphabetized fields, array markers. Useful for sharing with others or feeding to an LLM.
45+
46+
**When to use Python instead:** Only if you need to scan across ALL documents in a project (e.g., collecting every `$Type` and its fields) or if the type isn't supported by `bson dump`. See the Python script in `.claude/skills/debug-bson.md`.
47+
48+
### Stage 2 -- Compare against a known-good baseline
49+
50+
After you've written parser/writer code and created a document via MDL, compare your output against a Studio Pro-created reference.
51+
52+
**Same project, two different documents:**
53+
54+
```bash
55+
mxcli bson compare -p app.mpr --type workflow StudioProWorkflow MdlWorkflow
56+
```
57+
58+
**Cross-project comparison (reference vs your output):**
59+
60+
```bash
61+
mxcli bson compare -p reference.mpr -p2 test.mpr --type workflow MyWorkflow
62+
```
63+
64+
The diff output shows:
65+
- **OnlyInLeft**: fields present in the reference but missing from your output (you need to add these)
66+
- **OnlyInRight**: fields you're writing that shouldn't be there (remove these)
67+
- **ValueMismatch**: fields with different values (check defaults)
68+
69+
By default, structural fields (`$ID`, `PersistentId`, `RelativeMiddlePoint`, `Size`) are skipped. Use `--all` to include them.
70+
71+
**NDSL diff format:**
72+
73+
```bash
74+
mxcli bson compare -p reference.mpr -p2 test.mpr --type workflow MyWorkflow --format ndsl
75+
```
76+
77+
Shows the two documents side by side in NDSL format instead of a structured diff.
78+
79+
### Stage 3 -- Check field coverage
80+
81+
After implementing DESCRIBE for a type, check how many BSON fields your MDL output covers:
82+
83+
```bash
84+
mxcli bson discover -p app.mpr --type workflow
85+
mxcli bson discover -p app.mpr --type workflow --object "Module.MyWorkflow"
86+
```
87+
88+
Output shows per-`$Type` coverage:
89+
- How many instances exist
90+
- Each field's status: covered (appears in MDL output), uncovered, or default value
91+
- Sample values for uncovered fields
92+
- Fields categorized as semantic, structural, or layout
93+
94+
Use this to find fields you forgot to handle in your DESCRIBE implementation, or to prioritize which fields to support next.
95+
96+
### Stage 4 -- Interactive exploration with the TUI
97+
98+
For browsing and comparing documents interactively:
99+
100+
```bash
101+
mxcli tui -p app.mpr
102+
```
103+
104+
- Navigate the project tree to find your document
105+
- Press **`b`** to view raw BSON in NDSL format
106+
- Press **`c`** to enter compare mode, then:
107+
- **`1`** for NDSL vs NDSL (raw BSON side by side)
108+
- **`2`** for NDSL vs MDL (BSON vs your DESCRIBE output)
109+
- **`3`** for MDL vs MDL
110+
- Press **`s`** to toggle synchronized scrolling
111+
- Press **`D`** for a diff view
112+
113+
The TUI is best for exploratory work -- when you're browsing multiple documents to understand patterns, or visually comparing your MDL output against the raw BSON to spot gaps.
114+
115+
### Stage 5 -- Validate with mx check
116+
117+
After writing BSON, always validate:
118+
119+
```bash
120+
# If mx is cached from setup
121+
~/.mxcli/mxbuild/*/modeler/mx check app.mpr
122+
123+
# Or via mxcli
124+
mxcli docker check -p app.mpr
125+
```
126+
127+
`mx check` is the definitive validator. If it passes, Studio Pro will accept the document. If it fails, note the error code -- common ones are documented in `.claude/skills/debug-bson.md`.
128+
129+
## Part 2: Debugging BSON issues
130+
131+
### Symptom: Studio Pro crashes on open
132+
133+
**Error:** `System.InvalidOperationException: Sequence contains no matching element` at `MprProperty..ctor`
134+
135+
**Cause:** Your BSON contains a field that doesn't exist on the `$Type`. Studio Pro's type cache crashes on unrecognized fields.
136+
137+
**Diagnosis with Python** (best tool for this case -- you need to diff ALL fields across all types):
138+
139+
```python
140+
import bson, os
141+
from collections import defaultdict
142+
143+
type_props = defaultdict(set)
144+
145+
def walk_bson(obj, tp):
146+
if isinstance(obj, dict):
147+
t = obj.get("$Type", "")
148+
if t:
149+
for k in obj.keys():
150+
if k not in ("$Type", "$ID"):
151+
tp[t].add(k)
152+
for v in obj.values():
153+
walk_bson(v, tp)
154+
elif isinstance(obj, list):
155+
for item in obj:
156+
walk_bson(item, tp)
157+
158+
# Collect from your broken project
159+
for root, dirs, files in os.walk("broken-project/mprcontents"):
160+
for f in files:
161+
if f.endswith(".mxunit"):
162+
with open(os.path.join(root, f), "rb") as fh:
163+
walk_bson(bson.decode(fh.read()), type_props)
164+
165+
# Collect from a known-good project the same way (baseline_props)
166+
# Then compare:
167+
for t, props in type_props.items():
168+
if t in baseline_props:
169+
extra = props - baseline_props[t]
170+
if extra:
171+
print(f"{t}: EXTRA props = {sorted(extra)}")
172+
```
173+
174+
**Fix:** Remove the extra fields from your writer function.
175+
176+
**Why Python and not `bson compare`?** Because the crash could be caused by ANY document in the project, not a specific one you know about. The Python script scans everything.
177+
178+
### Symptom: mx check reports CE errors
179+
180+
**Use `bson compare` to find the difference:**
181+
182+
```bash
183+
# Create the same element in Studio Pro, then compare
184+
mxcli bson compare -p studio-pro.mpr -p2 mdl-generated.mpr --type page MyPage
185+
```
186+
187+
The diff shows exactly which fields differ. Common causes:
188+
189+
| Error | Typical cause | Fix |
190+
|-------|--------------|-----|
191+
| CE0463 | Widget property values inconsistent with mode rules | Check editorConfig.js visibility rules |
192+
| CE0642 | Required property missing | Add the missing field with its default value |
193+
| CE1613 | Association stored as attribute (or vice versa) | Check resolveMemberChange logic |
194+
| CE0066 | Access rule on wrong entity | Check ParentPointer/ChildPointer semantics |
195+
196+
### Symptom: DESCRIBE output doesn't roundtrip
197+
198+
Your DESCRIBE output should be re-parseable by `mxcli check` and produce the same document when executed.
199+
200+
**Use the TUI to compare NDSL vs MDL:**
201+
202+
```bash
203+
mxcli tui -p app.mpr
204+
# Navigate to the document, press c, then 2 for NDSL | MDL view
205+
```
206+
207+
This shows the raw BSON on the left and your MDL output on the right. Scan for BSON fields that don't appear in the MDL -- those are gaps in your DESCRIBE implementation.
208+
209+
**Or use `bson discover` for a quantitative check:**
210+
211+
```bash
212+
mxcli bson discover -p app.mpr --type workflow --object "Module.MyWorkflow"
213+
```
214+
215+
## Decision tree: which tool to use
216+
217+
```
218+
What are you trying to do?
219+
|
220+
|-- "See the BSON structure of a document"
221+
| --> mxcli bson dump --format json (or ndsl)
222+
|
223+
|-- "Compare my output against Studio Pro's"
224+
| --> mxcli bson compare -p2 reference.mpr
225+
|
226+
|-- "Find which BSON fields my DESCRIBE misses"
227+
| --> mxcli bson discover
228+
|
229+
|-- "Browse and explore interactively"
230+
| --> mxcli tui (press b for BSON, c for compare)
231+
|
232+
|-- "Find crash-causing fields across ALL documents"
233+
| --> Python bson diff script (walk all .mxunit files)
234+
|
235+
|-- "Validate that my BSON output is correct"
236+
| --> mx check app.mpr
237+
```
238+
239+
## Reflection data reference
240+
241+
The Mendix type definitions live in `reference/mendixmodellib/reflection-data/`. Each JSON file defines one metamodel domain with:
242+
- Type names and their storage names (`$Type` values)
243+
- Properties with types, defaults, and whether they're required
244+
- Inheritance hierarchy
245+
246+
Check these when you're unsure whether a field belongs on a type. For example, `DomainModels.json` shows that `ParentConnection` exists on `DomainModels$Association` but not on `DomainModels$CrossAssociation`.
247+
248+
The generated Go metamodel in `generated/metamodel/types.go` mirrors these definitions and is used by `bson discover` for field coverage analysis.
249+
250+
## Related documentation
251+
252+
- [Implement MDL Feature](../../.claude/skills/implement-mdl-feature.md) -- full pipeline from investigation to testing
253+
- [Debug BSON](../../.claude/skills/debug-bson.md) -- widget-specific debugging (CE0463, templates, mpk inspection)
254+
- [PAGE_BSON_SERIALIZATION.md](PAGE_BSON_SERIALIZATION.md) -- page/widget BSON format reference
255+
- [MDL_PARSER_ARCHITECTURE.md](MDL_PARSER_ARCHITECTURE.md) -- ANTLR parser pipeline

0 commit comments

Comments
 (0)