@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.
Files changed (3) hide show
  1. package/README.md +240 -0
  2. package/erd-cli.cjs +290 -0
  3. 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