@kajitiluna/erd-cli 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +240 -0
- package/erd-cli.cjs +290 -0
- package/package.json +37 -0
package/README.md
ADDED
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
# @kajitiluna/erd-cli
|
|
2
|
+
|
|
3
|
+
Schema verification for [ERD Designer](https://github.com/kajitiluna/erd-designer)
|
|
4
|
+
`.erd` files — compare a design against a live database or another revision, from the
|
|
5
|
+
command line or CI.
|
|
6
|
+
|
|
7
|
+
## What is ERD Designer?
|
|
8
|
+
|
|
9
|
+
**ERD Designer** is a free, open-source tool for visually designing database schemas.
|
|
10
|
+
You lay out tables and relationships on a canvas and generate DDL for PostgreSQL, MySQL,
|
|
11
|
+
MariaDB, MS SQL Server, SQLite, BigQuery, and Snowflake. It runs in three places, all
|
|
12
|
+
reading and writing the same file format:
|
|
13
|
+
|
|
14
|
+
- **Browser** — [kajitiluna.github.io/erd-designer](https://kajitiluna.github.io/erd-designer)
|
|
15
|
+
(no installation, no account)
|
|
16
|
+
- **VSCode extension** — [VS Code Marketplace](https://marketplace.visualstudio.com/items?itemName=kajitiluna.erd-designer)
|
|
17
|
+
- **Google Drive app** — [Google Workspace Marketplace](https://workspace.google.com/marketplace/app/erd_designer/952307856491)
|
|
18
|
+
|
|
19
|
+
The design is saved as a `.erd` file — plain JSON, so it lives in Git alongside the code
|
|
20
|
+
it describes and shows up as a readable diff in a pull request.
|
|
21
|
+
|
|
22
|
+
## Why this CLI?
|
|
23
|
+
|
|
24
|
+
A diagram checked into Git is only useful while it still describes reality. Two things
|
|
25
|
+
break that, and neither is visible from inside the editor:
|
|
26
|
+
|
|
27
|
+
- **The design drifts from production.** A manual `ALTER`, or a migration tool running its
|
|
28
|
+
own scripts, changes the database without touching the `.erd` file.
|
|
29
|
+
- **A schema change lands unreviewed.** `.erd` is JSON, so a pull request diff shows moved
|
|
30
|
+
coordinates and internal ids next to the one column that actually matters.
|
|
31
|
+
|
|
32
|
+
This package closes both gaps by making the comparison mechanical, so it can run in CI:
|
|
33
|
+
`erd-diff` turns a `.erd` revision diff into a schema-level summary a reviewer can read;
|
|
34
|
+
`db-diff` connects to a live database and reports where it has drifted from the design,
|
|
35
|
+
with exit codes a CI job can act on; `migrate-ddl` drafts the `ALTER` statements that
|
|
36
|
+
close the gap. None of the three ever writes to a database — `db-diff` issues `SELECT`
|
|
37
|
+
only, and `migrate-ddl` prints SQL for you to review before you run it.
|
|
38
|
+
|
|
39
|
+
This package ships the schema-verification commands only (`erd-diff`, `db-diff`,
|
|
40
|
+
`migrate-ddl`). To edit `.erd` files or drive them through an AI agent, use the
|
|
41
|
+
[`erd-designer` agent plugin](https://github.com/kajitiluna/erd-designer#ai-agent-integration-agent-plugin)
|
|
42
|
+
instead.
|
|
43
|
+
|
|
44
|
+
## Installation
|
|
45
|
+
|
|
46
|
+
| Distribution | Command | Notes |
|
|
47
|
+
|---|---|---|
|
|
48
|
+
| npm (recommended for CI) | `npx @kajitiluna/erd-cli erd-diff --file docs/schema.erd --from /tmp/base.erd` | `pg` / `mysql2` install automatically as needed for `db-diff` |
|
|
49
|
+
| GitHub Release | `curl -sSL -o erd-cli.cjs https://github.com/kajitiluna/erd-designer/releases/latest/download/erd-cli.cjs && node erd-cli.cjs erd-diff ...` | Single file, no `npm install` |
|
|
50
|
+
| Agent plugin | `node <SKILL.md dir>/scripts/erd-agent.cjs erd-diff ...` | Same commands, bundled alongside the [agent plugin](https://github.com/kajitiluna/erd-designer#ai-agent-integration-agent-plugin) |
|
|
51
|
+
|
|
52
|
+
`db-diff` needs a database driver that isn't bundled. This npm package declares `pg` and `mysql2`
|
|
53
|
+
as optional dependencies and installs them automatically; the other two distributions require
|
|
54
|
+
installing the driver yourself in the working directory (`npm install pg` or `npm install mysql2`).
|
|
55
|
+
|
|
56
|
+
To pin the version rather than resolving it on every `npx` run:
|
|
57
|
+
|
|
58
|
+
```sh
|
|
59
|
+
npm install --save-dev @kajitiluna/erd-cli
|
|
60
|
+
npx erd-cli erd-diff --file docs/schema.erd --from /tmp/base.erd
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Commands
|
|
64
|
+
|
|
65
|
+
### `erd-diff`
|
|
66
|
+
|
|
67
|
+
Compares two `.erd` revisions and reports the schema-level differences (added/removed tables and
|
|
68
|
+
columns, type changes, index and foreign-key changes, and more) in a form a reviewer can read
|
|
69
|
+
without diffing the raw JSON. No database connection is required, and it works with every database
|
|
70
|
+
dialect ERD Designer supports.
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
erd-cli erd-diff --file <path.erd> --from <path.erd> [options]
|
|
74
|
+
|
|
75
|
+
--ignore-table <regex> Exclude tables by name pattern. Repeatable.
|
|
76
|
+
--no-index Skip index comparison.
|
|
77
|
+
--no-foreign-key Skip foreign key comparison.
|
|
78
|
+
--no-comment Skip table/column comment comparison.
|
|
79
|
+
--no-schema Compare by table name only, ignoring schema qualification.
|
|
80
|
+
--format text|json|markdown Output format. Defaults to text.
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
```sh
|
|
84
|
+
git show origin/main:docs/schema.erd > /tmp/base.erd
|
|
85
|
+
npx @kajitiluna/erd-cli erd-diff --file docs/schema.erd --from /tmp/base.erd --format markdown
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Exit code is always `0`, whether or not differences were found (differences are meant to be
|
|
89
|
+
reviewed, not to fail a build). A read failure (missing file, invalid `.erd`) exits `2`.
|
|
90
|
+
|
|
91
|
+
### `db-diff`
|
|
92
|
+
|
|
93
|
+
Compares the `.erd` design against a live database and reports where they've drifted apart. Only
|
|
94
|
+
`SELECT` statements are issued; nothing is written to the database.
|
|
95
|
+
|
|
96
|
+
```
|
|
97
|
+
erd-cli db-diff --file <path.erd> [options]
|
|
98
|
+
|
|
99
|
+
--dsn <url> Connection string. ERD_DB_URL takes precedence.
|
|
100
|
+
--schema <name> Target schema (PostgreSQL). Defaults to the schemas the .erd design uses.
|
|
101
|
+
--ignore-table <regex> Exclude tables by name pattern. Repeatable. Matches either the bare
|
|
102
|
+
table name or the schema-qualified `schema.table` form.
|
|
103
|
+
--no-index Skip index comparison.
|
|
104
|
+
--no-foreign-key Skip foreign key comparison.
|
|
105
|
+
--no-comment Skip table/column comment comparison.
|
|
106
|
+
--no-schema Compare by table name only, ignoring schema qualification.
|
|
107
|
+
--format text|json|markdown Output format. Defaults to text.
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
```sh
|
|
111
|
+
export ERD_DB_URL='postgres://readonly@db.internal:5432/shop'
|
|
112
|
+
npx @kajitiluna/erd-cli db-diff --file docs/schema.erd
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Pass the connection string via `ERD_DB_URL` rather than `--dsn` where possible — command-line
|
|
116
|
+
arguments can end up in shell history, `ps` output, and CI logs. A read-only database user is
|
|
117
|
+
recommended. `pg` and `mysql2` are declared as `optionalDependencies` and are installed
|
|
118
|
+
automatically by `npm install` / `npx`.
|
|
119
|
+
|
|
120
|
+
On PostgreSQL, without `--schema`, only the schemas the `.erd` design actually uses are scanned —
|
|
121
|
+
system namespaces (`pg_*`, `information_schema`) are never included unless you name one explicitly
|
|
122
|
+
with `--schema`. Tables created by migration tools (Flyway, Liquibase, etc.) are not excluded by
|
|
123
|
+
default; add them with `--ignore-table`:
|
|
124
|
+
|
|
125
|
+
```sh
|
|
126
|
+
npx @kajitiluna/erd-cli db-diff --file docs/schema.erd \
|
|
127
|
+
--ignore-table '^flyway_schema_history$' --ignore-table '^databasechangelog'
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Supported dialects for this command: PostgreSQL, MySQL, MariaDB. `erd-diff` above supports every
|
|
131
|
+
dialect ERD Designer supports, since it never connects to a database.
|
|
132
|
+
|
|
133
|
+
| Exit code | Meaning |
|
|
134
|
+
|---|---|
|
|
135
|
+
| `0` | No differences found |
|
|
136
|
+
| `1` | Differences found |
|
|
137
|
+
| `2` | Execution error (connection failure, missing driver, invalid `.erd`, unsupported dialect) |
|
|
138
|
+
|
|
139
|
+
If a table has never had its comment set, `--no-comment` avoids a wall of noise on the first run.
|
|
140
|
+
|
|
141
|
+
### `migrate-ddl`
|
|
142
|
+
|
|
143
|
+
Generates `ALTER` statements that bring a database — or another `.erd` revision — in line with the
|
|
144
|
+
design. Nothing is applied automatically; the output is a draft to review before running it.
|
|
145
|
+
|
|
146
|
+
```
|
|
147
|
+
erd-cli migrate-ddl --file <path.erd> [options]
|
|
148
|
+
|
|
149
|
+
--dsn <url> Target database. ERD_DB_URL takes precedence. Mutually exclusive with --from.
|
|
150
|
+
--from <path.erd> Compare against another .erd revision instead of a live database.
|
|
151
|
+
--schema <name> Target schema (database connections only).
|
|
152
|
+
--out <path.sql> Write output to a file. Defaults to stdout.
|
|
153
|
+
--allow-destructive Emit destructive operations (DROP ...) without commenting them out.
|
|
154
|
+
--ignore-table <regex> Exclude tables by name pattern. Repeatable.
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
```sh
|
|
158
|
+
# From a live database
|
|
159
|
+
ERD_DB_URL='postgres://readonly@db.internal:5432/shop' \
|
|
160
|
+
npx @kajitiluna/erd-cli migrate-ddl --file docs/schema.erd --out /tmp/migrate.sql
|
|
161
|
+
|
|
162
|
+
# From another .erd revision (no database connection needed)
|
|
163
|
+
git show origin/main:docs/schema.erd > /tmp/base.erd
|
|
164
|
+
npx @kajitiluna/erd-cli migrate-ddl --file docs/schema.erd --from /tmp/base.erd
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Destructive operations (`DROP COLUMN` / `DROP TABLE` / `DROP INDEX` / dropping a constraint) are
|
|
168
|
+
commented out by default; pass `--allow-destructive` to emit them as executable SQL. Differences
|
|
169
|
+
that cannot be safely turned into SQL (e.g. adding a `NOT NULL` column with no `DEFAULT`, since
|
|
170
|
+
existing rows' values are unknown) are marked `-- unsupported:` rather than silently dropped.
|
|
171
|
+
Whole missing tables are reported the same way — run `export-ddl` to generate their `CREATE TABLE`.
|
|
172
|
+
|
|
173
|
+
## CI integration
|
|
174
|
+
|
|
175
|
+
```yaml
|
|
176
|
+
name: ERD schema check
|
|
177
|
+
|
|
178
|
+
on:
|
|
179
|
+
pull_request:
|
|
180
|
+
paths:
|
|
181
|
+
- 'docs/schema.erd'
|
|
182
|
+
schedule:
|
|
183
|
+
# Drift from production happens independently of PRs, so also run on a schedule.
|
|
184
|
+
- cron: '0 0 * * *'
|
|
185
|
+
|
|
186
|
+
permissions:
|
|
187
|
+
contents: read
|
|
188
|
+
|
|
189
|
+
jobs:
|
|
190
|
+
erd-diff:
|
|
191
|
+
if: github.event_name == 'pull_request'
|
|
192
|
+
runs-on: ubuntu-latest
|
|
193
|
+
permissions:
|
|
194
|
+
contents: read
|
|
195
|
+
pull-requests: write
|
|
196
|
+
steps:
|
|
197
|
+
- uses: actions/checkout@v6
|
|
198
|
+
with:
|
|
199
|
+
fetch-depth: 0
|
|
200
|
+
- uses: actions/setup-node@v6
|
|
201
|
+
with:
|
|
202
|
+
node-version: 22
|
|
203
|
+
- name: Diff against base branch
|
|
204
|
+
run: |
|
|
205
|
+
git show origin/${{ github.base_ref }}:docs/schema.erd > /tmp/base.erd
|
|
206
|
+
npx @kajitiluna/erd-cli erd-diff \
|
|
207
|
+
--file docs/schema.erd --from /tmp/base.erd --format markdown > /tmp/erd-diff.md
|
|
208
|
+
- name: Comment on PR
|
|
209
|
+
uses: actions/github-script@v8
|
|
210
|
+
with:
|
|
211
|
+
script: |
|
|
212
|
+
const fs = require('node:fs');
|
|
213
|
+
const body = fs.readFileSync('/tmp/erd-diff.md', 'utf-8');
|
|
214
|
+
await github.rest.issues.createComment({
|
|
215
|
+
owner: context.repo.owner, repo: context.repo.repo,
|
|
216
|
+
issue_number: context.issue.number, body: body
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
db-diff:
|
|
220
|
+
runs-on: ubuntu-latest
|
|
221
|
+
environment: staging
|
|
222
|
+
steps:
|
|
223
|
+
- uses: actions/checkout@v6
|
|
224
|
+
- uses: actions/setup-node@v6
|
|
225
|
+
with:
|
|
226
|
+
node-version: 22
|
|
227
|
+
- name: Check schema drift
|
|
228
|
+
env:
|
|
229
|
+
ERD_DB_URL: ${{ secrets.ERD_DB_URL }}
|
|
230
|
+
run: |
|
|
231
|
+
npx @kajitiluna/erd-cli db-diff \
|
|
232
|
+
--file docs/schema.erd --ignore-table '^flyway_schema_history$'
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
The `db-diff` job is scheduled independently of PRs because drift from a manual `ALTER` has nothing
|
|
236
|
+
to do with pull requests — only a recurring check catches it.
|
|
237
|
+
|
|
238
|
+
## License
|
|
239
|
+
|
|
240
|
+
Apache-2.0
|