synergycodes/ng-diagram/ng-diagram-middleware
Claude Code and agent skill by synergycodes/ng-diagram
- community
- ext:[{"type":"config","description":"Configuration overrides"}]
Checking that the SKILL.md file is still in the repository.
Use when blocking, validating or changing ng-diagram updates with a middleware (createMiddlewares, registerMiddleware), a read-only or viewer mode, locked nodes, limits, or updates that hang, "already registered", "executed next() multiple times".
Install
npx vskill@latest install synergycodes/ng-diagram/ng-diagram-middlewareSemi-extensibleMentions customization, but needs skill-specific knowledge. Read the extensible skills standard
SKILL.md
Custom middlewares
A middleware sees every change before it reaches the model and can let it pass, change it, or cancel it. This skill covers when to write one, registration and order, the rules that keep the update pipeline alive, and recipes. Reacting to finished user actions is in ng-diagram-events; batching is in ng-diagram-transactions.
Middleware, event or service call?
| You want to | Use | |
|---|---|---|
| Block or validate a change before it is applied | a middleware that calls cancel() | |
| Adjust a change, or add derived changes to the same update | a middleware that calls next(update) | |
| React after a change was applied (save, refresh a panel, analytics) | diagram events (ng-diagram-events) or the model signals | |
| Make a change from UI code | a service call (ng-diagram-state-updates) |
A middleware runs for every update: initialization, each drag step, every measurement update. Keep that in mind for cost and for what you block.
Rules
- Call `next()` exactly once, or `cancel()` once, on every code path. If neither is called, the update never finishes and every later update waits behind it: nodes and edges stop changing and awaited service calls never resolve. A second
next()call does not run the chain again; it logs the console errorMiddleware <name> executed next() multiple times. - Never `await` a mutating call inside a middleware: service methods,
transaction(),invalidateMeasurements(). The pipeline is locked while your middleware runs, and those promises resolve only after the current update finishes, so theawaitdeadlocks. Change the current update withnext(update)instead. A call withoutawait(void modelService.updateNode(...)) is safe: it runs as a separate update afterwards, and it passes through your middleware again, so guard against loops. - Keep it fast and pass through early. While a middleware runs or waits, no other update can start (drags, measurements, other calls). Test cheap conditions first:
if (!context.helpers.anyNodesAdded()) { next(); return; }. - Do not mutate objects from `context`. Send changes as patches:
next({ nodesToUpdate: [{ id, ... }] }). - Block only the action types you mean. Never cancel
init, port or label measurement (...PortsBulk,...EdgeLabelsBulk),templateVisibilityChangeorupdateViewportSize(the diagram element changed size). Node sizes measured after initialization arrive asupdateNodes, andng-diagram-base-edgewrites itsrouting/pointsinputs asupdateEdge. - Use unique names. Registering a name that is already in the chain throws
Middleware <name> already registered. - Throwing rejects, cancelling resolves. An error thrown in
execute(or a rejected asyncexecute) discards the update and rejects the promise of the call that started it (since 1.3.0; before, it froze the diagram).cancel()discards the update, the caller's promise resolves normally, and no diagram events fire. For expected failures, cancel and report through your own channel (a signal, a toast). An error thrown after yournext()call, once the rest of the chain has finished, is only logged as[ngDiagram] <error>and the update is applied: validate before you callnext().
Shape, registration and order
A middleware is { name, execute(context, next, cancel) }; execute may be async. Register it through the [middlewares] input with createMiddlewares, which hands you the built-in defaults to arrange:
- The array you bind replaces the built-ins. Always build it with
createMiddlewares((defaults) => [...yours, ...defaults]); a plain[middlewares]="[mine]"drops edge routing, z-index and internal ids. - The
[middlewares]input is read only when a model is initialized; a new array has no effect until the next model. To switch behavior at runtime, read a flag inside the middleware (see read-only mode), or add and remove it withregisterMiddleware/unregisterMiddleware. NgDiagramService.registerMiddleware(m)returns an unregister function;unregisterMiddleware(name)removes by name. It needs the engine (call it after(diagramInit)or whenisInitialized()is true), appends after your[middlewares]list, and is lost when a new model is loaded: register again after the next(diagramInit).- The defaults are
internal-id-assignment(internal ids that let an element deleted and re-added with the same id render fresh),z-index(layering,computedZIndex) andedges-routing(edge points). Removing one removes that behavior. Theloggeris not in the defaults; it always runs near the end and prints only withdebugMode. Do not importloggerMiddleware: the typings declare it, but the package does not export it (a build error orundefinedin your chain, depending on the bundler).
Order of one update:
hidden-computation(computescomputedHidden)- your
[middlewares]list, in your order - middlewares added with
registerMiddleware, in registration order - built-in finishing steps: visibility re-check, measured bounds, logger, measurement tracking, diagram events
Put validators that cancel first. Put transformers that add, move or resize elements or change zOrder/groupId before the defaults; after them, edge routing and layering of the same update miss your changes. Put observers last.
Read-only mode
The docs "Custom Middleware" example stores the switch in custom config keys; a signal keeps it typed:
editFlags hides the resize and rotate handles in read-only mode, except on nodes with their own resizable/rotatable (the middleware still blocks those changes). A press on a port still starts a draw, which the middleware cancels. To hide the ports, use the port [hidden] input as in the ng-diagram-ports recipe "Ports visible only in edit mode": a port hidden from its first render is never measured and its edges are not drawn, so when the diagram can start in read-only mode, keep the ports shown until (diagramInit) and hide them after it. Never bind a plain [hidden]="readOnly()" from the start.
Selection stays allowed; add 'changeSelection' to the set to block it. Pointer panning does not run middlewares: turn it off with the viewportPanningEnabled config if needed (ng-diagram-config). Your own code can still change the diagram with updateNode/updateNodeData/updateNodes/updateEdge(s), grouping and attachEdge/detachEdge, because they share action types with measurement and template syncs: disable your own editing UI in read-only mode. Undo/redo shortcuts call the model adapter directly and are not stopped by middlewares.
Validation: limits and protected nodes
Change the update in flight
Register it before the defaults so edges added together with the nodes are routed to the snapped positions. For an audit log (observer) and for validation that waits for your server, read references/recipes.md.
Edge cases
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 90 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingskills/ng-diagram-middleware/SKILL.md
Popularity
- Repository stars
- 583
- Repository forks
- 41
- 7-day trend score
- 0
Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.
Extension points
configConfiguration overrides
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/synergycodes/ng-diagram/ng-diagram-middleware)