EvoX Genesis
EvoX Genesis turns a high-level software objective into a persistent recursive software world: finite-lived agents recursively develop software, while only accepted consequences persist across develop
Map a NestJS app's modules, providers and injections straight from its TypeScript source, then explore the map in your browser.
Developer toolsTypeScript · CSSGitHub @DoIttikornOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
demonstrators nest project
Translation pending
Taken from the repository README
Loading the full README.
Read the full README ↗Map a NestJS app — modules, providers, controllers and who injects what — straight from its TypeScript source, then explore the map in your browser.
npx nest-cartograph
Nothing in your app runs: no database, no environment variables, no build. The analyzer reads the code with the TypeScript compiler API, the same way your editor does.
Two steps, like go test -coverprofile followed by go tool cover -html:
| Step | Command | Output |
|---|---|---|
| 1. Analyze | npx nest-cartograph analyze | cartograph.json |
| 2. View | npx nest-cartograph view cartograph.json | an interactive map at http://localhost:4300 |
npx nest-cartograph with no command does both, without writing the JSON.
cartograph.json is deterministic — no timestamps, everything sorted — so you can commit it and review how the architecture changed in a pull request.
npx nest-cartograph analyze # writes ./cartograph.json
npx nest-cartograph analyze -p apps/api/tsconfig.json -o docs/cartograph.json
npx nest-cartograph analyze -o - | jq '.cycles' # JSON to stdout
npx nest-cartograph analyze --fail-on-cycles # exit code 2 on circular imports without forwardRef()
npx nest-cartograph view # serves ./cartograph.json and opens the browser
npx nest-cartograph view docs/cartograph.json --port 5055 --no-open
npx nest-cartograph view -o cartograph.html # one self-contained HTML file, no server needed
Summaries, warnings and cycles go to stderr. Run npx nest-cartograph --help for everything.
On a big app the Providers view is too dense to read. Type a name in the search box and press Enter to see only the flow around the matches, laid out left to right from controllers to repositories and Kafka producers. The panel on the left filters it:
Controller → IFooService → FooService reads Controller → FooService.ReportModule when searching employee,
with a checkbox to drop it.Esc closes the panels, then leaves the flow view. Show flow in a node's details does the same for that node.
When the map is served by nest-cartograph view (or plain npx nest-cartograph), a node's details
have Open in VS Code and Open in Zed links that jump to the class's line, through the editors'
vscode:// and zed:// links. A file written with -o leaves them out: it is meant to be shared, so
it carries no paths from your machine.
| In your code | On the map |
|---|---|
@Module({ imports, providers, controllers, exports }) | modules, what they own, what they export |
ConfigModule.forRoot(...), TypeOrmModule.forFeature(...) | an import labelled with the method |
static forRoot() { return { module: ThisModule, providers, exports, global } } | the returned module's providers and exports |
@Global() | global modules |
forwardRef(() => X) in imports and @Inject() | dashed edges and cycle detection |
[...SHARED_PROVIDERS], providers: ORDERS_PROVIDERS, .concat() | arrays held in constants, across files |
useClass, useValue, useFactory + inject, useExisting | custom providers |
constructor parameters, @Inject(TOKEN), @Optional(), @Inject() properties | injection edges |
string tokens, Symbol('x'), constants holding either | one node per token, shared by provider and consumer |
@InjectRepository(User), @InjectModel(Cat.name), ... | a token named after the decorator call |
It also warns about decorated classes that no module registers, injections without a token, and anything it could not resolve.
Limits. Static analysis does not run code: modules picked at runtime (both sides of cond ? A : B are shown), providers built in loops, and providers created inside third-party dynamic modules are not visible.
{
"schemaVersion": 1,
"project": { "root": ".", "tsconfig": "tsconfig.json" },
"nodes": [
{ "id": "src/users/users.module.ts#UsersModule", "kind": "module", "name": "UsersModule", "file": "src/users/users.module.ts", "line": 6 },
{ "id": "src/users/users.service.ts#UsersService", "kind": "provider", "providerType": "class", "name": "UsersService", "file": "src/users/users.service.ts", "line": 8 }
],
"edges": [
{ "from": "src/app.module.ts#AppModule", "to": "src/users/users.module.ts#UsersModule", "kind": "imports" },
{ "from": "src/users/users.module.ts#UsersModule", "to": "src/users/users.service.ts#UsersService", "kind": "provides" }
],
"cycles": [{ "ids": ["..."], "names": ["UsersModule", "OrdersModule"], "guarded": true }],
"warnings": []
}
Edge kinds: imports, provides, controls, exports, injects, aliases. The full types are in src/schema.ts, and also exported:
import { analyze, type Cartograph } from 'nest-cartograph';
const map: Cartograph = analyze({ project: 'tsconfig.json' });
Node.js 22 or later. The analyzer brings its own TypeScript 6, so it works whatever TypeScript your project uses — including TypeScript 7, which has no compiler API yet.
npm install
npm test # analyzer golden test + UI logic tests (vitest)
npm run test:update # rewrite test/testdata/app.golden.json after an intended change
npm run lint # oxlint
npm run typecheck # src + test, and ui/
npm run build # tsc → dist/, then vite → dist/ui/index.html
npm run dev:ui # UI with hot reload, on the fixture app's map
npm run build:website # website/ → website/dist, with the fixture app's map as the live demo
node dist/cli/index.js -p test/fixtures/tsconfig.json # try the built CLI
src/
cli/ index.ts (commands) · analyze.ts (step 1) · view.ts (step 2: server, browser) · html.ts (embed JSON in the UI)
analyzer/ index.ts (the passes) · program.ts (tsconfig → ts.Program) · resolve.ts (names → classes, tokens, arrays)
modules.ts (@Module, forRoot) · providers.ts (custom providers) · injection.ts (constructors, @Inject)
context.ts (shared state) · ast.ts (syntax helpers)
graph/ builder.ts (dedupe, placeholders, stable order) · cycles.ts (Tarjan)
schema.ts the cartograph.json contract, shared with the UI
ui/ React + React Flow (@xyflow/react) + elkjs, built by Vite into ONE html file
src/ App.tsx · load.ts · toFlow.ts (JSON → nodes/edges) · layout.ts (ELK positions + edge routes)
measure.ts (text widths) · nodes/ · edges/RoutedEdge.tsx · panels/
test/
fixtures/app a NestJS app exercising every case above
testdata/ golden output
Releases: bump version in package.json, commit, then git tag v0.1.0 && git push --tags. The release workflow publishes with npm Trusted Publishing. The very first version has to be published by hand (npm publish), because the Trusted Publisher setting lives on the package's page on npmjs.com.
MIT. The bundled UI includes elkjs (EPL-2.0) and React Flow (MIT).