@castachick/erd
v0.2.1
Published
Decompose PostgreSQL schemas into readable Mermaid ER diagrams
Maintainers
Readme
@castachick/erd
English | 日本語
A CLI that reads a live PostgreSQL schema and splits related tables into readable Mermaid ER diagrams, with SVG previews. It works independently of ORMs and migration files and never reads table rows.
Preview
An example with seven fictional store tables: customers, orders, order items, payments, products, categories, and inventory. These SVGs are generated by the same API used by the CLI.
Overview
The overview shows every selected table and foreign key without columns.
Detail diagram
Related tables are grouped around a hub. A neighboring table from another group appears as context, so relationships remain visible across groups.
Browse all diagrams and Mermaid sources · Example generator
To regenerate the example from the repository checkout, run npm ci and npm run docs:example. No database is needed; Chrome is required as described below. The example uses maxTables: 4, maxContextTables: 1, and columns: 'all'. When changing documentation or examples, update both language versions together.
Installation
Requires Node.js 20 or later.
npm install -g @castachick/erd
export DATABASE_URL='postgresql://user:password@localhost:5432/app'
erd --schema public --max-tables 15 --out ./docs/erdFor a project-local development dependency, use npm install -D @castachick/erd and run npx erd. For a one-off run, use npx --package @castachick/erd erd --schema public.
SVG generation uses Chrome managed by Puppeteer. It is normally downloaded during npm installation, increasing the download size. If the download was skipped, install the matching browser:
npx --package [email protected] puppeteer browsers install chromeTo use an existing Chrome installation, set PUPPETEER_EXECUTABLE_PATH to its executable. Linux also requires Chrome's shared libraries. SVG rendering runs locally; database schemas are never sent to an external rendering service.
Developing from source
npm ci
npm run build
export DATABASE_URL='postgresql://user:password@localhost:5432/app'
node dist/cli.js --schema public --max-tables 15 --out ./docs/erdDuring development, you can also run npm run dev -- --schema public --out ./docs/erd. Installing the package globally makes the erd command available:
npm install -g .
erd --schema public --schema auth --out ./docs/erdOptions
| Option | Default | Description |
| --- | --- | --- |
| --database-url <url> | DATABASE_URL | Connection URL; an explicit value takes precedence |
| --schema <schema> | public | Schema to include; repeatable |
| --out <directory> | ./erd | Output directory |
| --max-tables <number> | 15 | Maximum primary tables per diagram; at least 1 |
| --context-depth <number> | 1 | Include neighboring tables; 0 or 1 |
| --max-context-tables <number> | 5 | Maximum additional context tables; at least 0 |
| --columns <all\|keys\|none> | keys | All columns, PK/FK/UNIQUE columns, or no columns |
| --cardinality <inferred\|simple> | inferred | Infer from constraints, or show 0..N at both ends |
| --include-table <glob> | All | Match a table name or schema.table; repeatable |
| --exclude-table <glob> | None | Exclude matching tables; repeatable; overrides include |
| --help | | Show usage |
erd --schema public --exclude-table '__drizzle_*' --columns keys --out ./docs/erdQuote globs to prevent shell expansion. System schemas are excluded. Application tables are never implicitly excluded, so explicitly filter out migration tracking tables if needed.
Output
docs/erd/
├── index.md
├── overview.mmd
├── overview.svg
├── 02-orders.mmd
├── 02-orders.svg
├── 01-products.mmd
├── 01-products.svg
└── graph.jsonDiagram names depend on the selected schema and grouping. index.md embeds the overview and detail SVGs, lists hubs, primary and context tables, and warnings, and links to standalone SVGs and Mermaid sources. Every .mmd has a matching .svg. Mermaid sources can also be opened in a Mermaid-compatible viewer. The overview shows all selected tables and foreign keys without columns; detail diagrams label hubs and context tables. graph.json preserves original types, column order, composite PK/UNIQUE/FK constraints, referential actions, and communities (table groups).
With the same database state, options, dependency versions, and Chrome/font environment, output is deterministic and contains no timestamps. SVG dimensions and layout can vary by OS or fonts. If SVG rendering fails, the command exits with an error without writing a new index. Generated files with matching names are overwritten. Old diagrams and user files are not deleted; after changing grouping options, use index.md as the current list of diagrams.
Grouping and relationship interpretation
- Analysis uses a simple undirected graph with a weight of 1 per FK constraint. Multiple FKs between a table pair add weight; a composite FK counts as one.
- Louvain runs in a fixed order, and oversized communities are split again. If splitting fails, a greedy fallback adds strongly connected neighbors in sequence.
- Every table belongs to exactly one primary group. Hubs are selected by internal neighbor count, total neighbor count, then table ID.
- Context tables are selected by FK count to the primary group, direct connection to the hub, total neighbor count, then ID. Relationships between context tables and two-hop relationships are omitted.
max-tableslimits primary tables only. The total limit per diagram ismax-tables + max-context-tables.- Tables with no connections to other selected tables are collected into an isolated group. Self-referencing FKs do not contribute to analysis weights but remain in diagrams and JSON.
- FKs to excluded tables or schemas remain in JSON but are omitted from diagrams with a warning. Add required schemas with
--schema.
The parent end is 1 when all FK columns are NOT NULL, otherwise 0..1. The child end is 0..1 if the FK column set contains every column of a PK or UNIQUE constraint, otherwise 0..N. A relationship is solid when all FK columns belong to the child's PK, otherwise dashed.
Mermaid's UK marker also appears on members of composite UNIQUE constraints, with a comment identifying their membership. It does not mean that each column is individually unique; see JSON for the original constraints. Names and types containing special characters are normalized for Mermaid, while labels, column comments, and JSON preserve original names.
Supported relations are ordinary and partitioned tables, including child partitions. Views, materialized views, foreign tables, standalone unique indexes that are not UNIQUE constraints, FK MATCH FULL semantics, and application-level relationships are not inferred. The simple mode shows 0..N at both ends and is only a structural overview. Identifiers containing dots or other special characters use SQL-style quoting in JSON table IDs to avoid collisions.
Safety and errors
Metadata is read in a REPEATABLE READ READ ONLY transaction, with a 10-second connection timeout and a 30-second SQL timeout. The connection user needs permission to inspect metadata in the selected schemas. Credentials and connection URLs are excluded from generated files and logs, and raw database-driver errors are not displayed.
Connection failures, nonexistent schemas, empty selections, output failures, and invalid options exit with code 1. Omitted external FKs, isolated tables, and fallback grouping produce warnings.
Validation
npm run check
npm test
npm run buildThe regular test suite covers graph invariants, determinism, composite constraints, cardinality, CLI argument validation and credential redaction, syntax validation with the real Mermaid parser, Chrome SVG rendering, deterministic SVGs, matching Mermaid/SVG files, and image references in the index. Chrome is required for regular tests too.
PostgreSQL integration tests require a dedicated test database and are skipped when none is configured. They create temporary schemas in that database and remove them afterward. Tested with PostgreSQL 16.
TEST_DATABASE_URL='postgresql://localhost/erd_test' npm run test:integrationIntegration tests cover composite FK ordering, duplicate constraint names, multiple schemas, types and nullability, partitions, CLI output and repeatability, and failure cases.
Architecture
src/postgres handles SQL and connections; src/schema-graph defines and filters the intermediate model; src/analysis groups tables; and src/render produces Mermaid, JSON, and the index. generate() is a synchronous, browser-free API that returns Mermaid, JSON, and a link-based index. await generateWithSvg() also returns SVGs and an index with embedded images. run() and the CLI handle everything from database introspection to writing all output files, including SVGs.
The design reference is the handoff document (Japanese). Relationship notation follows the official Mermaid syntax; Louvain settings follow the Graphology documentation and the installed package's declarations and implementation.
Publishing to npm (maintainers)
The package name is @castachick/erd. publishConfig selects the official npm registry and public access.
After merging, run the following on the latest main branch:
npm ci
npm run test:package
npm publish --dry-run
# Review the package contents and version before publishing.
npm publishtest:package creates a tarball, installs it with production dependencies in a temporary directory, and verifies the CLI, ESM API, and SVG generation. Temporary files are removed afterward. During npm publish, prepublishOnly runs type checking and tests, and prepack rebuilds dist. The package includes dist, both READMEs, generated example output, LICENSE, and package.json; development sources and tests are excluded.
To also run database integration tests, set TEST_DATABASE_URL to a dedicated database. They are skipped otherwise. A dry run does not guarantee successful publishing or two-factor authentication. Follow npm's authentication instructions when prompted.
For each release, update to an unpublished version; an existing version cannot be republished. After publishing, verify with npm view @castachick/erd version and npx --package @castachick/erd erd --help.
License
Licensed under the MIT License.
