{"id":50330291,"url":"https://github.com/rexebin/event-storming-plugin","last_synced_at":"2026-05-29T09:02:33.076Z","repository":{"id":359135235,"uuid":"1244663065","full_name":"rexebin/event-storming-plugin","owner":"rexebin","description":null,"archived":false,"fork":false,"pushed_at":"2026-05-20T19:00:16.000Z","size":89,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-20T19:10:48.163Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rexebin.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-20T13:29:28.000Z","updated_at":"2026-05-20T19:00:29.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/rexebin/event-storming-plugin","commit_stats":null,"previous_names":["rexebin/event-storming-plugin"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/rexebin/event-storming-plugin","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rexebin%2Fevent-storming-plugin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rexebin%2Fevent-storming-plugin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rexebin%2Fevent-storming-plugin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rexebin%2Fevent-storming-plugin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rexebin","download_url":"https://codeload.github.com/rexebin/event-storming-plugin/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rexebin%2Fevent-storming-plugin/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33644313,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-29T02:00:06.066Z","response_time":107,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-05-29T09:02:27.843Z","updated_at":"2026-05-29T09:02:33.060Z","avatar_url":"https://github.com/rexebin.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Event Storming Diagram Renderer for GitHub and VS Code\n\nA **browser extension** (Manifest V3) and **VS Code Markdown preview extension** that render **event storming** diagrams from fenced code blocks.\n\n## Features\n\n- 🎨 Full event storming visual language: events, commands, queries, aggregates, actors, policies, views, read models, external systems, errors, and note nodes\n- 📦 Container-based layout: JSON DSL containers render as visual boxes for aggregates, external systems, read models, and process containers\n- 🗂️ Nested process groups: each child group renders inside a dashed sub-container with the group name in the top-left corner\n- ⬅️→ Left-to-right process flows: actor → command/query/policy → event inside containers, with policy failure branches rendered below\n- ↘️ Directional arrows with shared-target fan-in layouts for commands and views\n- 🔍 Interactive zoom \u0026 pan\n- 💡 Notes-only tooltips: tooltips appear only for containers, groups, or nodes that have notes\n- 📝 Note badges on containers, groups, and nodes that have notes\n- 🎯 Collapsible diagrams with toggle button\n- 🌈 Color-coded rectangles (black border) per event storming standard:\n  - **Orange** (`#FFA500`) → Domain Events\n  - **Light Green** (`#91D49C`) → Commands\n  - **Dark Green** (`#5BAA62`) → Queries / Read Models\n  - **Yellow** (`#FEE254`) → Aggregates\n  - **Yellow** (`#FEE254`) → Views\n  - **Gray** (`#D4D3D3`) → Actors\n  - **Blue** (`#859EBF`) → Policies\n  - **Pink** (`#FB8597`) → External Systems\n  - **Cyan** (`#8DCFF9`) → Errors\n  - **Light Yellow** (`#FFF1AA`) → Temp Objects / Notes\n\n## Getting Started\n\n### 1. Install Dependencies\n\n```bash\nnpm install\n```\n\n### 2. Build\n\n```bash\nnpm run build\n```\n\nThis bundles TypeScript (via esbuild IIFE) and copies assets into `dist/`.\n\n### 3. Run Tests\n\n```bash\nnpm test\n```\n\n### 4. Load in Edge (or Chrome)\n\n1. Open `edge://extensions/` (or `chrome://extensions/`)\n2. Enable **Developer mode** (toggle in top-right)\n3. Click **Load unpacked**\n4. Select the `dist/` folder\n\n### 5. Package for VS Code\n\n```bash\nnpm run package:vscode\n```\n\nThis creates a `.vsix` file that can be shared or installed using **Extensions: Install from VSIX...**\n\n## Usage on GitHub\n\nIn any Markdown file (README, issue, PR comment, wiki), you can use:\n\n- `eventstorming` for the text DSL\n- `json` for the JSON DSL, which gives editors JSON syntax help\n\n```json\n[\n  {\n    \"type\": \"Aggregate\",\n    \"name\": \"User\",\n    \"notes\": [\"This aggregate represents a user in the system, including their registration and profile management processes.\"],\n    \"children\": [\n      {\n        \"name\": \"User Registration\",\n        \"nodes\": [\n          { \"type\": \"Actor\", \"name\": \"Customer1\", \"next\": \"Register\" },\n          { \"type\": \"Command\", \"name\": \"Register\", \"next\": \"Is Email Valid?\" },\n          { \"type\": \"Policy\", \"name\": \"Is Email Valid?\", \"next\": \"UserRegistered\", \"negativeNext\": \"Invalid Email\" },\n          { \"type\": \"Error\", \"name\": \"Invalid Email\", \"notes\": [\"The email address provided is not valid. Please enter a valid email address and try again.\"] },\n          { \"type\": \"Event\", \"name\": \"UserRegistered\", \"next\":\"Some Note\" },\n          { \"type\": \"Note\", \"name\": \"Some Note\", \"notes\": [\"This is a note attached to the UserRegistered event.\"] }\n        ],\n        \"notes\": [\"This process handles user registration, including validating the email address and creating a new user account if the email is valid.\"]\n      }\n    ]\n  },\n  {\n    \"type\": \"Aggregate\",\n    \"name\": \"Morning Routine\",\n    \"children\": [\n      {\n        \"name\": \"Wake Up\",\n        \"nodes\": [\n          { \"type\": \"Actor\", \"name\": \"Me\", \"next\": \"Wake Up\" },\n          { \"type\": \"Command\", \"name\": \"Wake Up\", \"next\": \"Is Alarm Ringing?\" },\n          { \"type\": \"Policy\", \"name\": \"Is Alarm Ringing?\", \"next\": \"Got Out of Bed\", \"negativeNext\": \"Sleep In\" },\n          { \"type\": \"Error\", \"name\": \"Sleep In\" },\n          { \"type\": \"Event\", \"name\": \"Got Out of Bed\" }\n        ]\n      },\n      {\n        \"name\": \"Shower\",\n        \"nodes\": [\n          { \"type\": \"Command\", \"name\": \"Have Shower\", \"next\": \"Is the shower running?\" },\n          { \"type\": \"Policy\", \"name\": \"Is the shower running?\", \"next\": \"Have shower gel?\", \"negativeNext\": \"Switch on shower\" },\n          { \"type\": \"ExternalSystem\", \"name\": \"Switch on shower\", \"next\": \"Have shower gel?\" },\n          { \"type\": \"Policy\", \"name\": \"Have shower gel?\", \"next\": \"Had Shower\", \"negativeNext\": \"Go Buy Shower Gel\" },\n          { \"type\": \"Error\", \"name\": \"Go Buy Shower Gel\" },\n          { \"type\": \"Event\", \"name\": \"Had Shower\" }\n        ]\n      }\n    ]\n  },\n  {\n    \"type\": \"Aggregate\",\n    \"name\": \"User Profile\",\n    \"children\": [\n      {\n        \"name\": \"Update Profile\",\n        \"nodes\": [\n          { \"type\": \"Actor\", \"name\": \"Customer\", \"next\": \"UpdateProfile\" },\n          { \"type\": \"Command\", \"name\": \"UpdateProfile\", \"next\": \"Is User Authenticated?\" },\n          { \"type\": \"Policy\", \"name\": \"Is User Authenticated?\", \"next\": \"ProfileUpdated\", \"negativeNext\": \"Authentication Required\" },\n          { \"type\": \"Error\", \"name\": \"Authentication Required\", \"notes\": [\"You must be logged in to update your profile. Please log in and try again.\"] },\n          { \"type\": \"Event\", \"name\": \"ProfileUpdated\" }\n        ],\n        \"notes\": [\"This process allows users to update their profile information, but only if they are authenticated. If the user is not authenticated, an error is returned.\"]\n      }\n    ]\n  },\n  {\n    \"type\": \"Aggregate\",\n    \"name\": \"Order\",\n    \"children\": [    \n      {\n        \"name\": \"Place Order\",\n        \"nodes\": [\n          { \"type\": \"Command\", \"name\": \"PlaceOrder\", \"next\": \"InventoryService\" },\n          { \"type\": \"ExternalSystem\", \"name\": \"InventoryService\", \"next\": \"Do We Have Stock?\" },\n          { \"type\": \"Policy\", \"name\": \"Do We Have Stock?\", \"next\": \"Is Order Detail Valid?\", \"negativeNext\": \"Out Of Stock\" },\n          { \"type\": \"Policy\", \"name\": \"Is Order Detail Valid?\", \"next\": \"PaymentGateway\", \"negativeNext\": \"Invalid Order Detail\" },\n          { \"type\": \"Error\", \"name\": \"Invalid Order Detail\", \"notes\": [\"Order details are invalid, please review your order and try again.\"] },\n          { \"type\": \"ExternalSystem\", \"name\": \"PaymentGateway\", \"next\": \"Is Payment Successful?\" },\n          { \"type\": \"Policy\", \"name\": \"Is Payment Successful?\", \"next\": \"OrderPlaced\", \"negativeNext\": \"PaymentFailed\" },\n          { \"type\": \"Error\", \"name\": \"PaymentFailed\", \"notes\": [\"Payment failed, please try again or use a different payment method.\", \"Client should handle this error.\"] },\n          { \"type\": \"Event\", \"name\": \"OrderPlaced\" }       \n        ]\n      },      \n      {\n        \"name\": \"Cancel Order\",\n        \"nodes\": [\n          { \"type\": \"Actor\", \"name\": \"Customer\", \"next\": \"CancelOrder\" },\n          { \"type\": \"Actor\", \"name\": \"Staff\", \"next\": \"CancelOrder\" },\n          { \"type\": \"Event\", \"name\": \"PaymentFailed\", \"next\": \"CancelOrder\" },\n          { \"type\": \"Command\", \"name\": \"CancelOrder\", \"next\": \"Is Cancellation Allowed?\" },\n          { \"type\": \"Policy\", \"name\": \"Is Cancellation Allowed?\", \"next\": \"OrderCancelled\", \"negativeNext\": \"CancellationDenied\" },\n          { \"type\": \"Event\", \"name\": \"OrderCancelled\", \"notes\": [\"Order has been cancelled successfully.\", \"another note\"] }         \n        ]\n      }\n    ]\n  },\n  {\n    \"type\": \"ExternalSystem\",\n    \"name\": \"Inventory Service\",\n    \"children\": [\n      { \"name\": \"Inventory Check\", \"nodes\": [\n        {\"type\": \"Command\", \"name\": \"Check Inventory\", \"next\": \"Get Inventory\"},\n        {\"type\": \"Query\", \"name\": \"Get Inventory\", \"next\": \"Has Stock?\"},\n        {\"type\": \"Policy\", \"name\": \"Has Stock?\", \"next\": \"InventoryCheckPassed\", \"negativeNext\": \"Out of Stock\"},\n        {\"type\": \"Event\", \"name\": \"Inventory Check Passed\"}\n      ]}\n    ]\n  },\n  {\n    \"type\": \"ReadModel\",\n    \"name\": \"OrderDetail\",\n    \"children\": [\n      {\n        \"name\": \"Order Detail Projection\",\n        \"nodes\": [\n          { \"type\": \"Event\", \"name\": \"OrderPlaced\", \"next\": \"Order Detail View\" },\n          { \"type\": \"Event\", \"name\": \"OrderCancelled\", \"next\": \"Order Detail View\" },\n          { \"type\": \"Event\", \"name\": \"OrderUpdated\", \"next\": \"Order Detail View\" },\n          { \"type\": \"Event\", \"name\": \"OrderShipped\", \"next\": \"Order Detail View\" },\n          { \"type\": \"View\", \"name\": \"Order Detail View\", \"notes\": [\"This view is used to display the details of an order, including its status, items, and other relevant information.\"] }\n        ]\n      }\n    ]\n  },\n  {\n    \"type\": \"Process\",\n    \"name\": \"Customer Order View\",\n    \"children\": [\n      {\n        \"name\": \"View Order Details\",\n        \"nodes\": [\n          { \"type\": \"Actor\", \"name\": \"Customer\", \"next\": \"GetOrderDetails\" },\n          { \"type\": \"Query\", \"name\": \"GetOrderDetails\", \"next\": \"Order Detail Projection\" },\n          { \"type\": \"View\", \"name\": \"Order Detail Projection\" }\n        ]\n      }\n    ]\n  }\n]\n```\n\nThe diagram will render inline, replacing the code block automatically.\n\nFor the JSON DSL shown above, supported container types are `Aggregate`, `ExternalSystem`, `ReadModel`, and `Process`.\n\n## Usage in VS Code\n\nOpen a Markdown file containing an `eventstorming` fenced block or a matching `json` fenced block, then run **Markdown: Open Preview to the Side**.\n\nThe built-in Markdown preview keeps normal Markdown rendering and replaces matching blocks with the diagram UI.\n\n\u003e **Note:** The current VS Code integration targets the desktop Markdown preview.\n\n## DSL Reference\n\nThe current DSL is JSON. Its shape matches the implementation in `src/dsl-type.ts`:\n\n```ts\ntype ContainerType = \"Aggregate\" | \"ExternalSystem\" | \"ReadModel\" | \"Process\";\n\ntype NodeType =\n  | \"Aggregate\"\n  | \"Actor\"\n  | \"Command\"\n  | \"Event\"\n  | \"Query\"\n  | \"Policy\"\n  | \"Error\"\n  | \"ExternalSystem\"\n  | \"Note\"\n  | \"View\";\n\ninterface Container {\n  type: ContainerType;\n  name: string;\n  notes?: string[];\n  children: Group[];\n}\n\ninterface Group {\n  name: string;\n  nodes: Node[];\n  notes?: string[];\n}\n\ninterface Node {\n  type: NodeType;\n  name: string;\n  next?: string;\n  negativeNext?: string;\n  notes?: string[];\n}\n```\n\n### Schema Notes\n\n- `children` defines independent process groups inside a container.\n- `next` links to another node in the same group and renders to the **right**.\n- `negativeNext` is used for policy failure paths and renders **below** the policy.\n- If a policy omits a matching negative-path node, the renderer creates a default error node.\n- `notes` can be added to containers, groups, or nodes. Elements with notes show a small `i` badge, and hovering them shows a notes-only tooltip.\n- `Note` is a supported JSON node type and renders as a light-yellow note node rather than a command.\n\n## Project Structure\n\n```\n├── src/                  # TypeScript source\n│   ├── content.ts          # GitHub content script\n│   ├── dsl.ts              # DSL parser + types\n│   ├── dsl-type.ts          # Container/Process type definitions\n│   ├── dsl.test.ts          # DSL parser tests\n│   ├── renderer.ts          # D3.js diagram renderer\n│   ├── renderer.test.ts     # Renderer tests\n│   └── types.d.ts          # D3 type declarations\n├── dist/                   # Built output (load this as extension)\n│   ├── manifest.json\n│   ├── content.js          # Single bundled file (IIFE)\n│   └── style.css\n├── package.json\n├── tsconfig.json\n├── build.mjs               # esbuild bundler\n└── vitest.config.ts        # Test configuration\n```\n\n### Testing\n\n73 tests (51 DSL + 22 renderer) using Vitest with jsdom:\n\n```bash\nnpm test              # Run once\nnpm run test:watch    # Watch mode\n```\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frexebin%2Fevent-storming-plugin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frexebin%2Fevent-storming-plugin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frexebin%2Fevent-storming-plugin/lists"}