usm/structurizr-bridge [built]
Structurizr bridge — import a Structurizr workspace JSON into .usm system and service specs via usm import, and export a Structurizr DSL workspace from .usm via a new generate target (usm generate --only structurizr). USM as the hub: one model, many notations.
Status: built
Usage
# Import a Structurizr workspace into .usm specs
usm import workspace.json
# List planned writes without writing
usm import workspace.json --dry-run
# Set id prefix and domain, overwrite existing
usm import workspace.json --id acme --domain acme.com --forceWhy this exists
Teams already modelling in diagram-as-code (Structurizr/C4) face manual re-entry to adopt USM, and USM users embedded in those shops need round-trip coexistence. Import gives a one-command migration path in; export lets USM become the hub with Structurizr as one more projection alongside Mermaid, OpenAPI, ArchiMate and TOGAF. Both treat .usm as canonical — adapters are bridges, never the store.
Design decisions
json-import-first
Decision: Import the Structurizr workspace JSON format, not the DSL grammar
Rationale: Structurizr serialises workspaces to JSON; parsing that is tractable, while the DSL grammar would need a real parser — deferred until demand is demonstrated (Fowler threshold).
features-as-components
Decision: Export features as components inside their service container
Rationale: Preserves the C4 hierarchy (system, container, component) and gives Structurizr users feature-level detail.
How it works
Import a Structurizr workspace JSON (import-workspace)
- Read — workspace JSON model.softwareSystems
- Map — first softwareSystem becomes .usm/system.usm with identity.name and summary
- Map — containers become .usm/services/<slug>.usm with inferred type and runtime
- Guard — refuse to overwrite existing files unless --force; --dry-run lists planned writes
Export Structurizr DSL as a generate target (export-target)
- Parse — system.usm plus services and features
- Generate — softwareSystem with a container per service and a component per feature
- Write — .usm-workspace/structurizr/workspace.dsl with landscape and container views
Import then export stays coherent (roundtrip)
- Import — a workspace JSON
- Export — the structurizr target from the imported specs
- Verify — names and container set survive the round trip
Guarantees
import-never-destroys
Import guards existing work
Acceptance criteria:
- [ ] Existing system.usm or service files are never overwritten without --force
- [ ] --dry-run lists planned writes without writing
- [ ] Invalid or non-workspace JSON fails with a clear message
export-valid-dsl
Exported workspace.dsl is well-formed Structurizr DSL
Acceptance criteria:
- [ ] workspace, model and views structure with balanced braces
- [ ] Quotes in names and descriptions escaped
- [ ] System name from identity.name, containers from services, components from features with $service set
target-registered
Export participates in the standard generate target system
Acceptance criteria:
- [ ] structurizr accepted by --only
- [ ] Output written under .usm-workspace/structurizr/
conservative-mapping
Mapping choices are documented and reversible
Acceptance criteria:
- [ ] Container becomes service with type api by default, or database, cache, queue when technology suggests it
- [ ] Unmappable detail preserved in summary text, never dropped silently
Test specifications
import-maps-workspace
Given:
- fixture: "one softwareSystem with two containers"
Then:
- assertion: system.usm written with identity.name from softwareSystem name
- assertion: two service files written with $system set
- assertion: validate passes on all written files
import-guards
Given:
- existing: "system.usm already present"
Then:
- assertion: import refuses without --force and prints which files block
- assertion: --dry-run writes nothing
export-well-formed
Given:
- fixture: "system with services and features"
Then:
- assertion: workspace.dsl contains softwareSystem, one container per service, components for features
- assertion: braces balanced and quoted names escaped
target-wired
Given:
- run: "usm generate --only structurizr"
Then:
- assertion: target accepted and file written under .usm-workspace/structurizr/
Implementation
- Primary: src/generators/structurizr.ts
- Test code: tests/structurizr.test.ts
- Test code status: manual
See Also
- usm/gen-markdown
- usm/cli-generate
- usm/scan-codebase