@tie-di/devtools
v0.1.1
Published
Terminal UI for inspecting a tie-di container: dependency graph, live construction and release, scope tree.
Maintainers
Readme
@tie-di/devtools
A terminal UI and CLI for inspecting a @tie-di/core container: the dependency graph, what has
been constructed, which scopes are open, and what gets released.
No runtime dependencies beyond @tie-di/core. Requires Node 20 or newer, and Node 22.18 or newer to point
the CLI at a .ts file directly.
npm add -D @tie-di/devtoolsPrinting a graph
tie-di graph loads a module and prints it as Mermaid, which GitHub and most markdown viewers render
inline:
tie-di graph src/wiring.ts # Mermaid
tie-di graph src/wiring.ts --lr # left to right
tie-di graph src/wiring.ts --legend # with a key
tie-di graph src/wiring.ts --dot # GraphvizNothing is constructed — the graph comes from the module. Verification runs as it does in build(), so an
invalid module is reported here too.
Shapes carry lifetime and arrows carry the kind of dependency:
graph TD
n0["Config"]
n1["Db ⏏"]
n2(["Session"])
n3{{"Conn ⏏"}}
n1 --> n0
n2 --> n1
n2 == lease ==> n3Rectangle is a singleton, stadium a scoped service, hexagon a transient, parallelogram a multi-token. ⏏
marks a service with a teardown. A dotted arrow is lazy or optional, a thick one a lease.
The file should export its module as default, AppModule, or module.
Exploring a graph
tie-di show opens the same graph in a terminal UI, which is more use than a diagram once a graph has more
than a dozen services:
tie-di show src/wiring.ts tie-di app.ts 10 services · 9 live · 3 scopes · 1 failed
────────────────────────────────────────────────────────────────────────────────────────────
● scp Api │ SCOPES
● scp ├─ UserRepo │ #0 Config, Logger, Db, Cache, Mailer
● sgl │ ├─ Db ⏏ │ #1 Session, UserRepo, Api
● sgl │ │ ├─ Config │ #2 Session
● sgl │ │ └─ Logger │
● sgl │ │ └─ Config ↩ │ Api · scoped · factory · 5 deps · built 1, live 1
● scp │ ├─ Session │ EVENTS
○ trn │ └─ Conn ⏏ (lease) │ + Session scope 1
● sgl ├─ Mailer │ + UserRepo scope 1
sgl └─ Plugins [] │ − Conn
────────────────────────────────────────────────────────────────────────────────────────────
↑↓ move ←→ fold tab pane / filter p pause c clear q quit │ sgl scp trn · ⏏ releasableA dependency graph is not a tree, so a service depended on by several others appears more than once. The
first occurrence is expanded and the rest are marked ↩ rather than duplicating the subtree.
| | |
| --- | --- |
| ↑ ↓ or k j | Move |
| ← → | Fold and unfold, space toggles |
| g G | First and last |
| tab | Switch between the tree and the event log |
| / | Filter by name. Matches keep their ancestors, so a result stays in context |
| p | Pause the event stream |
| c | Clear the log |
| q | Quit |
Below 64 columns the event log is dropped and the tree takes the whole width.
Following a running application
tie-di watch listens for an application to connect, so a server can be watched while it handles requests —
scopes opening and closing, what each one built, and whether anything is still held afterwards.
In the application, swap build for devtools:
import { devtools } from '@tie-di/devtools';
import { AppModule } from './wiring.js';
export const app = devtools(AppModule);Then, in another terminal:
tie-di watchEither can start first. devtools() connects over a unix socket, defaulting to $TIE_DI_DEVTOOLS and then
a path in the temp directory; --socket overrides it on the CLI, and the socket option in the
application.
When nothing is listening, devtools() discards everything and behaves exactly like build. It never
throws, never blocks, and never holds the process open. Pass { enabled: false } to switch it off outright.
It is still a development tool. It streams every construction and resolution over a socket, which is not something to leave switched on in production.
Programmatic use
The pieces the CLI is built from are available if you would rather render something else:
import { graphOf, toMermaid, toDot, inspect } from '@tie-di/core/inspect';graphOf gives you plain data — nodes with lifetimes, provider kinds, and dependencies tagged
direct/lazy/optional/lease — and inspect gives you the event stream. Both are documented in
@tie-di/core.
License
MIT
