Skip to content
| Marketplace
Sign in
Visual Studio Code>Programming Languages>ESDMNew to Visual Studio Code? Get it now.
ESDM

ESDM

the native web GmbH

|
2 installs
| (0) | Free
Visualize and edit ESDM (Event Sourcing Domain Modeling) workspaces directly in VS Code.
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

ESDM Viewer — VS Code Extension

Visualize and edit ESDM (Event Sourcing Domain Modeling) workspaces directly in VS Code. The extension renders an interactive Mermaid diagram of all bounded contexts, aggregates, commands, events, policies, read models, queries and external systems in your workspace, integrates the esdm CLI as live VS Code diagnostics, and adds language intelligence for *.esdm.yaml — completion, cross-file navigation, hover, CodeLens, quick fixes and reference validation.


Table of contents

  1. Features
  2. Quick start (development)
  3. Repository layout
  4. Detailed setup
  5. Running the extension on a separate ESDM workspace
  6. Available commands
  7. Settings
  8. Architecture
  9. Common development tasks
  10. Tests
  11. Troubleshooting
  12. Packaging & publishing
  13. License

Features

  • Interactive diagram in a side-panel webview (Mermaid + d3-zoom).
  • Live reload — changes to any *.esdm.yaml re-render the diagram automatically.
  • Diagnostics — esdm lint output appears as VS Code error/warning squiggles, both on save and live while typing (debounced).
  • Details panel next to the diagram — shows the selected element with its metadata (subdomain assignment, actors, per-context statistics). Resizable by dragging its left edge and collapsible; the chosen width and the collapsed state survive a reload.
  • Outline tree in the Explorer sidebar, grouped by element kind (bounded contexts, aggregates, read models, queries, policies, external systems).
  • Find element quick-pick (Cmd/Ctrl+Shift+E) jumps to any BC, aggregate, command, event, policy, read model, query or external system.
  • Go to Definition — double-click a node in the diagram (or right-click → Go to Definition) opens the corresponding YAML at the right line.
  • In-diagram search (Cmd/Ctrl+F) with highlight + step-through navigation.
  • SVG export — save or copy to clipboard (Figma-friendly).
  • Sub-diagram export — export just one bounded context, one aggregate (or DCB) or all external systems as SVG.
  • Theme-aware diagram — colours follow the active VS Code theme and recolour when you switch.
  • Language intelligence for *.esdm.yaml, backed by a position-aware index and working across files:
    • Autocompletion of kind: values and of references (scope.aggregate, publishes, handles.event, emits.command, …) from the elements defined in the workspace.
    • Go to Definition and Find All References on any reference or definition.
    • Rename (F2) — renames the definition and every reference that resolves to it, across all files. Descriptions, comments and same-named elements of another kind stay untouched.
    • Symbols — breadcrumbs, the built-in Outline, "Go to Symbol in Editor" (Cmd/Ctrl+Shift+O) and "Go to Symbol in Workspace" (Cmd/Ctrl+T).
    • Reference warnings — a name that resolves to no defined element is underlined instantly, without running the CLI (toggle with esdm.validateReferences).
    • Duplicate warnings — an element defined twice under one name is flagged at every definition, each pointing at the others (same toggle).
    • Hover shows an element's kind, name and description.
    • "N references" CodeLens above every definition; click it for the reference peek.
    • Quick fixes — version actions on an unknown apiVersion, and "Create <kind> …" to scaffold a missing referenced element into a new file.
    • Snippets (esdm-aggregate, esdm-command, esdm-event, esdm-policy, esdm-read-model, esdm-query, esdm-bounded-context) and the "ESDM: New Domain" command to scaffold a starter model.

Quick start (development)

Five minutes from zero to a running development instance.

# 1. Clone (or open in VS Code)
cd ~/Dev/esdm-vscode-plugin

# 2. Install dependencies (only needed once)
npm install

# 3. Compile TypeScript once
npm run compile

# 4. Open this project in VS Code
code .

# 5. Hit F5 in VS Code → an "Extension Development Host" window opens.

The launch configuration "Run Extension (with sample workspace)" automatically opens ~/Dev/esdm-test as the workspace inside the development host — handy if you keep a model of your own there. If not, use "Run Extension (no folder)" and open any folder containing *.esdm.yaml from inside the dev host; examples/library in this repository works as one.


Repository layout

esdm-vscode-plugin/
├── package.json              VS Code manifest, scripts, settings, commands
├── tsconfig.json             strict mode + noUnusedLocals
├── tsconfig.test.json        build config for the node:test unit tests
├── language-configuration.json
├── .editorconfig
├── .vscodeignore             what stays out of the .vsix
├── LICENSE                   MIT
├── CHANGELOG.md
├── .vscode/
│   ├── launch.json           F5-debug profiles
│   └── tasks.json
├── docs/
│   ├── status-quo.md         what the extension can do today (German)
│   ├── veroeffentlichung.md  release path and version strategy (German)
│   ├── manual-test-checklist.md                    binary/version handling
│   └── manual-test-checklist-language-features.md  language features
├── examples/
│   ├── library/              small sample workspace
│   └── unknown-api-version/  fixture for the apiVersion quick fixes
├── src/
│   ├── extension.ts          activate() — commands, watchers, lifecycle
│   ├── constants.ts          IDs, globs, magic strings (single source of truth)
│   ├── logger.ts             OutputChannel logger with configurable level
│   ├── parser.ts             YAML → Workspace for the diagram (uses js-yaml)
│   ├── mermaid.ts            Workspace → Mermaid string + metadata
│   ├── subdiagram.ts         Filter Workspace for sub-diagram exports
│   ├── linter.ts             spawn esdm lint, parse JSON → Diagnostics
│   ├── diagram-panel.ts      WebviewPanel host + typed message protocol
│   ├── outline-provider.ts   TreeDataProvider for the Explorer sidebar
│   ├── find-element.ts       QuickPick "Find element…"
│   ├── esdm-release.ts       pinned version, asset names, release URLs
│   ├── esdm-download.ts      download + sha256-verify the managed binary
│   ├── esdm-download-ports.ts  Node side effects (HTTP, fs) behind an interface
│   ├── esdm-version.ts       parse/compare/resolve esdm versions
│   ├── esdm-runner.ts        build + run the esdm lint child process
│   ├── esdm-index.ts         *.esdm.yaml → position-aware symbol/reference index (uses yaml)
│   ├── index-manager.ts      live index from open buffers + files (vscode glue)
│   ├── completion-context.ts which field a caret completes (pure)
│   ├── completion.ts         CompletionItemProvider
│   ├── navigation.ts         Definition + Reference providers
│   ├── hover.ts              HoverProvider
│   ├── codelens.ts           "N references" CodeLensProvider
│   ├── code-actions.ts       quick fixes (version actions, create element)
│   ├── rename-edits.ts       which occurrences a rename rewrites (pure)
│   ├── rename.ts             RenameProvider (F2)
│   ├── symbols.ts            Document + Workspace symbol providers
│   ├── element-skeleton.ts   minimal document skeleton (pure)
│   ├── reference-diagnostics.ts  unresolved-reference warnings (pure)
│   ├── duplicate-diagnostics.ts  duplicate-definition warnings (pure)
│   ├── starter-model.ts      "New Domain" starter slice (pure)
│   └── types/
│       ├── model.ts          domain model (Workspace, Aggregate, …)
│       └── webview-messages.ts  typed messages host↔webview
├── snippets/
│   └── esdm.code-snippets    document scaffolds (esdm-aggregate, …)
├── media/
│   ├── icon.png              Marketplace icon
│   ├── webview.css           themed via VS Code colour tokens
│   ├── webview.js            renders the diagram; recolours on theme change
│   ├── mermaid.min.js         Mermaid UMD build, shipped for offline use
│   └── d3.min.js              d3 UMD build, shipped for offline use
├── out/                      compiled extension JS (generated)
└── out-test/                 compiled unit tests (generated)

Modules with (pure) above do not import vscode; they hold the logic and are unit-tested with node:test. The providers/managers are thin adapters over them. Their tests live next to them as src/<module>.test.ts.


Detailed setup

Prerequisites

  • Node.js ≥ 18 (TypeScript compiler + the js-yaml and yaml runtime dependencies)
  • VS Code ≥ 1.85 (Extension Host API used here)
  • esdm CLI — only required for the lint integration; the language features (completion, navigation, reference warnings, …) work without it. The CLI lives separately in the esdm repo. By default the extension downloads the pinned version on demand into its global storage, so no manual install is needed. How it is located is controlled by esdm.binarySource:
    • auto (default): esdm.binaryPath if set → the managed download → $PATH / the workspace root or its parent.
    • managed: always the downloaded copy.
    • path: only esdm.binaryPath or $PATH, never download.

Installing dependencies

npm install

This installs js-yaml and yaml (runtime) and typescript, @types/node, @types/vscode, @types/js-yaml, rimraf (dev only). mermaid and d3 are dev dependencies as well: they are the source of the UMD builds vendored into media/, not runtime imports of the extension host.

Compiling

npm run compile   # one-shot tsc build
npm run watch     # rebuild on every source change
npm run lint:ts   # type-check only, no output
npm test          # compile and run the node:test unit tests
npm run clean     # rm -rf out/ out-test/

The compiled output lives in out/. package.json points VS Code to out/extension.js via the main field. The unit tests compile separately into out-test/, see Tests.


Running the extension on a separate ESDM workspace

This is the central development workflow: you edit the extension in one VS Code window, F5 starts a second VS Code window with your real ESDM data loaded.

Option A — F5 with the sample workspace from the launch profile

The shipped .vscode/launch.json has a profile "Run Extension (with sample workspace)" that uses ${env:HOME}/Dev/esdm-test as the sample folder. If you keep a model in that path, just press F5 and pick that profile.

Option B — F5 with no folder, then open one manually

Use the "Run Extension (no folder)" launch profile. The development host opens empty; inside that window:

  1. File → Open Folder…
  2. Pick any directory that contains *.esdm.yaml files — examples/library from this repository will do
  3. The extension auto-activates (it listens on workspaceContains:**/*.esdm.yaml)

Option C — Run via CLI without an outer VS Code instance

If you don't want to keep the extension source open in a window, you can launch VS Code directly with the extension loaded and an arbitrary folder mounted:

code --extensionDevelopmentPath=/Users/you/Dev/esdm-vscode-plugin \
     /path/to/your/esdm-domain

This is identical to what F5 does under the hood. Useful for screenshots, demos and CI smoke tests.

What you should see

After activation:

  • The Explorer sidebar shows an "ESDM Outline" section with grouped BCs, aggregates, read models, queries, policies, external systems.
  • Running "ESDM: Open Diagram" (Cmd/Ctrl+Shift+P → start typing) opens the Mermaid diagram in a side panel.
  • Opening any *.esdm.yaml file works normally with VS Code's YAML highlighter. Type a typo into a field name → after ~400 ms a red squiggle appears (assuming esdm is available).
  • Editing a *.esdm.yaml file offers completion for references, F12 / Shift+F12 navigation, hover, the reference CodeLens, and a warning on any name that resolves to no defined element.
  • A full walkthrough of the language features for a manual test run is in docs/manual-test-checklist-language-features.md.

Iteration workflow

┌──────────────────────┐         F5 / reload         ┌──────────────────────────┐
│  Extension source    │  ───────────────────────►   │  Extension Dev Host      │
│  (one VS Code win)   │                             │  (second VS Code win)    │
│                      │  ◄───────────────────────   │   ESDM workspace open    │
│  edit, save,         │       Cmd+R reloads         │   diagram, outline,      │
│  npm run watch       │       the dev host          │   diagnostics            │
└──────────────────────┘                             └──────────────────────────┘
  • Save TypeScript → npm run watch rebuilds out/.
  • Inside the dev host: Cmd+R (Window: Reload Window) picks up the new build.
  • For pure HTML/CSS/JS changes in media/ it is often enough to close the diagram tab and open it again (ESDM: Open Diagram).

Available commands

Open the Command Palette with Cmd/Ctrl+Shift+P and type "ESDM" to filter.

Command ID Default shortcut
ESDM: Open Diagram esdm.openDiagram —
ESDM: Find Element… esdm.findElement Cmd/Ctrl+Shift+E
ESDM: New Domain esdm.newDomain —
ESDM: Reload Workspace esdm.reload —
ESDM: Lint Workspace esdm.lintNow —
ESDM: Export Diagram as SVG esdm.exportSvg —
ESDM: Show Output Channel esdm.showOutput —
ESDM: Select esdm Version esdm.selectVersion —
ESDM: Update esdm Binary esdm.updateBinary —

Two notes on the table:

  • "ESDM: Export Diagram as SVG" only points you to the export menu inside the diagram: the rendered SVG lives in the webview, which owns the whole export flow.
  • Cmd/Ctrl+Shift+E is bound while an editor has focus or a .yaml file is selected, so it shadows VS Code's "focus Explorer" default in exactly those situations.

Inside the diagram tab:

  • Click node/cluster → details panel updates
  • Double-click → opens the YAML at the definition
  • Right-click → context menu (Export sub-diagram + Go to Definition + Copy SVG)
  • Export button (bottom) → menu with the full diagram and every available sub-diagram, each as "save to file" or "copy to clipboard"
  • Cmd/Ctrl+F → in-diagram search
  • Mouse wheel / drag → zoom / pan
  • Drag the details panel's left edge → resize it; the toggle collapses and restores it

In any *.esdm.yaml file: completion, Go to Definition (F12), Find All References (Shift+F12), Rename (F2), Go to Symbol (Cmd/Ctrl+Shift+O in the file, Cmd/Ctrl+T workspace-wide), hover, the reference CodeLens, and quick fixes (the lightbulb) are all available.


Settings

All under the esdm.* namespace (Settings UI → search "ESDM"):

Key Default Description
esdm.binaryPath "" Absolute path to an esdm CLI. Takes precedence over the managed download and $PATH.
esdm.binarySource auto How esdm is located: auto, managed (always the download) or path (never download).
esdm.version "" Managed-binary version. Empty → the version shipped with the extension; or a pin like 0.14.0, or latest.
esdm.checkForUpdates true Periodically check for a newer esdm and notify (never upgrades automatically).
esdm.validateReferences true Warn in the editor about references to elements that are not defined in the workspace.
esdm.lintOnSave true Run lint on save of an *.esdm.yaml.
esdm.lintOnChange true Run lint while typing (debounced).
esdm.lintDebounceMs 400 Debounce delay (100–5000).
esdm.logLevel info error, warn, info or debug. Output goes to the ESDM channel.

Architecture

┌────────────────────────────────────────────────────────────────────┐
│ Extension host (Node.js context inside VS Code)                    │
│                                                                    │
│  ┌──────────┐   loadWorkspace()   ┌──────────────┐                 │
│  │ extension│ ──────────────────► │ parser.ts    │ ──► Workspace   │
│  │ .ts      │                     └──────────────┘                 │
│  │ (activate│                                                      │
│  │  + cmds) │   buildDiagram(ws)  ┌──────────────┐                 │
│  │          │ ──────────────────► │ mermaid.ts   │ ──► Diagram     │
│  │          │                     └──────────────┘                 │
│  │          │                                                      │
│  │          │ ──► OutlineProvider (Explorer TreeView)              │
│  │          │ ──► DiagnosticCollection (esdm lint)                 │
│  │          │ ──► DiagramPanel (Webview)                           │
│  │          │ ──► EsdmIndexManager ──► esdm-index.ts               │
│  │          │            │            (symbols + positions)        │
│  │          │            └──► completion, definition, references,  │
│  │          │                 hover, CodeLens, code actions,       │
│  │          │                 reference diagnostics (esdm-refs)    │
│  └──────────┘                                                      │
│                    ▲   postMessage (typed FromWebview/ToWebview)   │
│                    │                                               │
│  ┌──────────────────────────────────────────────────────────────┐  │
│  │ Webview process (Chromium)                                   │  │
│  │   media/webview.js                                           │  │
│  │     · loads mermaid + d3 from the media folder (offline)     │  │
│  │     · renders SVG, handles zoom/pan/search/menus             │  │
│  │     · talks back via vscode.postMessage(...)                 │  │
│  └──────────────────────────────────────────────────────────────┘  │
└────────────────────────────────────────────────────────────────────┘

Key design choices:

  • No bundler for the extension host — VS Code loads out/extension.js directly, Node-style. Keeps the build trivial; if startup time ever matters, esbuild can be bolted on later.
  • Mermaid/d3 shipped locally in media/ (UMD builds), loaded by the webview via asWebviewUri. The diagram works fully offline and the webview CSP allows no external origin. The trade-off is .vsix size (Mermaid alone is ≈ 3.5 MB).
  • Single message protocol in src/types/webview-messages.ts. Both ends of the webview boundary type-check against it.
  • Buffer-aware lint — lintWithBuffer writes the in-editor buffer to a temp copy of the file, runs esdm lint, then restores. Serialised through a mutex so concurrent edits never corrupt the backup.
  • Position-aware index behind the language features — esdm-index.ts parses the workspace (with the yaml package) into a symbol/reference graph with exact source ranges. Every language provider (completion, definition, references, hover, CodeLens, quick fixes, reference warnings) is a thin adapter over this one index, kept live from the open buffers by index-manager.ts. The index and the per-feature logic import no vscode, so they are unit-tested with node:test.
  • Providers by pattern, not language id — the language providers register on the glob **/*.esdm.{yaml,yml}, so they apply whether VS Code resolves the file as esdm-yaml or as plain yaml. Only the snippets are bound to the esdm-yaml language id.
  • Two separate diagnostic sources — the client-side reference warnings use their own DiagnosticCollection (esdm-refs), independent of the esdm lint diagnostics, so the two never clear each other.
  • Theme-coupled diagram — the webview re-initializes Mermaid and re-renders when VS Code switches theme, preserving the zoom viewport.

Common development tasks

Add a new command

  1. Add ID to src/constants.ts → commands.
  2. Add to package.json → contributes.commands.
  3. Register handler in registerCommands() inside src/extension.ts.

Add a new setting

  1. Declare in package.json → contributes.configuration.properties.
  2. Read in code with vscode.workspace.getConfiguration(configSection).get(...).

Tail the extension's logs

Cmd/Ctrl+Shift+P → "ESDM: Show Output Channel" (or View → Output → ESDM). Set esdm.logLevel = "debug" for verbose tracing.

Change diagram colours / styling

The Mermaid classDef definitions live in src/mermaid.ts (around the lines.push(...) section). Diagram CSS is in media/webview.css. Themed via VS Code colour CSS variables — automatic light/dark adaption.

Upgrade mermaid or d3

The webview loads the UMD builds from media/, not from node_modules — those copies are what actually ships. Upgrading the package alone therefore has no effect; copy the build over as well:

npm install --save-dev mermaid@<version> d3@<version>
cp node_modules/mermaid/dist/mermaid.min.js media/mermaid.min.js
cp node_modules/d3/dist/d3.min.js media/d3.min.js

Note that npm audit only ever sees node_modules, so it cannot tell you whether the shipped copies are current. Verify the version inside the copy itself:

grep -o 'version:"11\.[0-9.]*"' media/mermaid.min.js | head -1

Mermaid bundles its own DOMPurify, which an npm audit fix on the top-level dompurify does not reach — another reason the check above is on the file, not on the tree.


Tests

npm test          # compiles with tsconfig.test.json into out-test/, then runs node --test

The unit tests use node:test and cover the vscode-free modules: the binary and version tooling (esdm-download, esdm-release, esdm-runner, esdm-version) and the language feature logic (esdm-index, completion-context, reference-diagnostics, element-skeleton, starter-model).

Everything that needs the extension host — the providers, diagnostics, theme coupling, the managed download and the binary resolver chain — as well as parser, mermaid, subdiagram, outline-provider and find-element is not covered automatically yet. Two manual checklists cover that layer for a release:

  • docs/manual-test-checklist.md — binary and version handling
  • docs/manual-test-checklist-language-features.md — the language features, run via F5

examples/library is a small workspace to run these checklists against; examples/unknown-api-version triggers the apiVersion quick fixes.


Troubleshooting

Symptom Likely cause / fix
"No ESDM workspace found" No *.esdm.yaml in the opened folder. Open a different folder.
"Invalid workspace: no kind: domain found." Workspace has no kind: domain. Add one or check parse errors in ESDM output.
"esdm binary not found" The managed download failed (check network/proxy in the ESDM output) or esdm.binarySource is path. Install the esdm CLI on $PATH or set esdm.binaryPath absolute.
Diagram blank / spinner forever Open dev tools in the webview (Help → Toggle Developer Tools) and check the console; the Mermaid text may have a syntax error, or the local media/mermaid.min.js / media/d3.min.js failed to load.
Live-lint flashes on/off rapidly Raise esdm.lintDebounceMs to 800–1000.
Compile fails after pulling npm run clean && npm install && npm run compile.

Packaging & publishing

npm install -g @vscode/vsce      # one-off
npm run package                  # produces esdm-viewer-<version>.vsix

# Local install for testing:
code --install-extension esdm-viewer-0.1.0.vsix

.vscodeignore keeps src/, out-test/, docs/, examples/ and the tooling files out of the .vsix; of node_modules, only js-yaml and yaml are shipped.

Publishing runs through npm run publish:vscode (Marketplace, via vsce) and npm run publish:openvsx (Open VSX, via ovsx, also installed globally). Note that publisher and repository.url in package.json are still placeholders — nothing is published under them yet. The release path, the remaining prerequisites and the version strategy are described in docs/veroeffentlichung.md.


License

MIT — see the LICENSE file for details.

  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
© 2026 Microsoft