Skip to content

feat: leverage structures.json as single source of truth for metamodel-driven development #142

@engalar

Description

@engalar

Problem

{version}-structures.json (from mendixmodellib) contains the complete Mendix metamodel schema: type names, storage names, properties, defaults, inheritance, array markers, required fields. This is the single source of truth for how BSON should be structured.

Currently, this information is manually duplicated across dozens of files:

Information In structures.json Manually maintained in code
Type names ($Type) qualifiedName + storageName ~200 raw string literals in parser/writer
Property field names properties[].storageName Fallback chains like []string{"sortItemList", "NewSortings", "Sortings"}
Required fields properties[].required Hardcoded in writer functions
Array markers properties[].storageListType Hardcoded int32(2) vs int32(3)
Default values defaultSettings Hardcoded, often copied from Studio Pro
Type hierarchy allCompatibleTypes Manual switch/case coverage
Widget type info Type + property definitions 3 separate maps in theme_reader.go (100+ entries)

This causes real bugs: wrong $Type strings → TypeCacheUnknownTypeException (MPR unreadable in Studio Pro), wrong array markers → silent data corruption, incomplete parser coverage → lost data on roundtrip.

Proposal: Data-Driven Metamodel

Treat structures.json as a runtime data source, not just a codegen input. The existing cmd/codegen infrastructure already parses this format — extend it to unlock multiple layers of value.

Layer 1: Compile-Time Safety (constants)

Generate sdk/mpr/bsontype/ package with:

  • $Type constants organized by namespace — typos become compiler errors
  • StorageName ↔ QualifiedName bidirectional map — eliminates manual mapping (e.g., CreateObjectActionCreateChangeAction)
  • Property storage name lookup — eliminates fallback chains

Layer 2: Automated Validation (find bugs without running)

  • Parser coverage checker — compare allCompatibleTypes against parser switch cases, report unhandled types
  • Writer required-field checker — verify all required: true properties are emitted
  • Array marker validatorstorageListType tells us the correct marker value, compare against hardcoded values in writer code

Layer 3: Code Generation (reduce hand-written code)

  • Default value templates — generate writer defaults from defaultSettings, no need to extract from Studio Pro
  • Widget type registry — generate unified registry replacing the 3 separate maps in theme_reader.go
  • DESCRIBE output scaffolding — generate property listing from type definitions

Layer 4: Multi-Version Runtime (version-aware operations)

Embed multiple versions via go:embed, load at runtime based on MPR's Mendix version:

  • Version diff — compare two structures.json versions, output: added types, removed properties, changed defaults
  • Compatibility checking — MDL script references a type that doesn't exist in the project's Mendix version → actionable error before writing BSON
  • Migration guidance — "upgrading from 10.0 to 11.0, these types/properties changed"

Version matching strategy: highest embedded version ≤ project version (conservative — never introduces types the project version doesn't support).

Implementation Path

  1. Extend cmd/codegen to generate constants package + registry loader (requires structures.json access)
  2. Embed 3-4 version snapshots (9.24, 10.0, 10.21, 11.6) for runtime multi-version support
  3. Incrementally migrate parser/writer to use constants (one domain per PR, no logic changes)
  4. Add validation commands: mxcli check --metamodel to surface coverage gaps

Why This Needs Core Developer Access

The structures.json files are in libs/mendixmodellib/reflection-data/ (internal npm package, gitignored). The codegen infrastructure already consumes them — this proposal extends their use from "generate Go structs" to "drive the entire type system."

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions