@xubylele/schema-forge 1.1.1 → 1.4.0

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 +136 -21
  2. package/dist/cli.js +1717 -148
  3. package/package.json +4 -2
package/README.md CHANGED
@@ -8,7 +8,9 @@ A modern CLI tool for database schema management with a clean DSL and automatic
8
8
  - **Migration Generation** - Automatically generate SQL migrations from schema changes
9
9
  - **State Tracking** - Built-in state management to track your schema evolution
10
10
  - **Type Safety** - Validates your schema before generating SQL
11
+ - **Default Change Detection** - Detects added/removed/modified column defaults and generates ALTER COLUMN SET/DROP DEFAULT
11
12
  - **Postgres/Supabase** - Currently supports PostgreSQL and Supabase
13
+ - **Constraint Diffing** - Detects UNIQUE and PRIMARY KEY changes with deterministic constraint names
12
14
 
13
15
  ## Installation
14
16
 
@@ -78,15 +80,15 @@ Edit `schemaforge/schema.sf`:
78
80
 
79
81
  table users {
80
82
  id uuid pk
81
- email varchar unique
82
- name text
83
+ email varchar unique not null
84
+ name text not null
83
85
  created_at timestamptz default now()
84
86
  }
85
87
 
86
88
  table posts {
87
89
  id uuid pk
88
- user_id uuid fk users.id
89
- title varchar
90
+ user_id uuid fk users.id not null
91
+ title varchar not null
90
92
  content text
91
93
  published boolean default false
92
94
  created_at timestamptz default now()
@@ -108,8 +110,8 @@ Edit `schemaforge/schema.sf` to add a new column:
108
110
  ```sql
109
111
  table users {
110
112
  id uuid pk
111
- email varchar unique
112
- name text
113
+ email varchar unique not null
114
+ name text not null
113
115
  avatar_url text # New column!
114
116
  created_at timestamptz default now()
115
117
  }
@@ -131,6 +133,25 @@ schema-forge diff
131
133
 
132
134
  If your schema matches the state file, you'll see "No changes detected". If there are changes, it will display the SQL that would be generated.
133
135
 
136
+ ### Default value changes
137
+
138
+ Schema Forge also tracks default changes on existing columns when diffing `schema.sf` against `state.json`.
139
+
140
+ Supported migration output:
141
+
142
+ ```sql
143
+ ALTER TABLE <table_name> ALTER COLUMN <column_name> SET DEFAULT <expr>;
144
+ ALTER TABLE <table_name> ALTER COLUMN <column_name> DROP DEFAULT;
145
+ ```
146
+
147
+ Examples:
148
+
149
+ - Add default: `created_at timestamptz` -> `created_at timestamptz default now()`
150
+ - Remove default: `created_at timestamptz default now()` -> `created_at timestamptz`
151
+ - Modify default: `default now()` -> `default timezone('utc', now())`
152
+
153
+ For common function-style defaults, comparisons are normalized to avoid obvious false positives (for example `NOW()` and `now()`).
154
+
134
155
  ## Commands
135
156
 
136
157
  ### `schema-forge init`
@@ -167,6 +188,99 @@ schema-forge diff
167
188
 
168
189
  Shows what SQL would be generated if you ran `generate`. Useful for previewing changes.
169
190
 
191
+ ### `schema-forge import`
192
+
193
+ Reconstruct `schemaforge/schema.sf` from existing PostgreSQL/Supabase SQL migrations.
194
+
195
+ ```bash
196
+ schema-forge import <path-to-sql-file-or-migrations-dir>
197
+ ```
198
+
199
+ **Options:**
200
+
201
+ - `--out <path>` - Optional output schema file path (default: `schemaforge/schema.sf`)
202
+
203
+ Behavior:
204
+
205
+ - Parses supported DDL statements in order from a file or from sorted migration filenames in a directory
206
+ - Ignores unsupported SQL safely and prints warnings
207
+ - Writes a normalized SchemaForge DSL schema file
208
+
209
+ ### `schema-forge validate`
210
+
211
+ Detect destructive or risky schema changes before generating/applying migrations.
212
+
213
+ ```bash
214
+ schema-forge validate
215
+ ```
216
+
217
+ Validation checks include:
218
+
219
+ - Dropped tables (`DROP_TABLE`, error)
220
+ - Dropped columns (`DROP_COLUMN`, error)
221
+ - Column type changes (`ALTER_COLUMN_TYPE`, warning/error based on compatibility heuristics)
222
+ - Nullable to NOT NULL changes (`SET_NOT_NULL`, warning)
223
+
224
+ Use JSON mode for CI and automation:
225
+
226
+ ```bash
227
+ schema-forge validate --json
228
+ ```
229
+
230
+ Exit codes:
231
+
232
+ - `1` when one or more `error` findings are detected
233
+ - `0` when no `error` findings are detected (warnings alone do not fail)
234
+
235
+ ## Constraint Change Detection
236
+
237
+ SchemaForge detects and generates migrations for:
238
+
239
+ - Column-level `unique` added/removed
240
+ - Table primary key added/removed/changed (single-column PK)
241
+
242
+ ### Deterministic Constraint Names
243
+
244
+ To keep migrations stable and safe to drop later, generated constraint names are deterministic:
245
+
246
+ - Primary key: `pk_<table>` (example: `pk_users`)
247
+ - Unique (column): `uq_<table>_<column>` (example: `uq_users_email`)
248
+
249
+ Identifiers are normalized to lowercase, non-alphanumeric characters are replaced with `_`, and repeated `_` are collapsed.
250
+
251
+ ### Generated SQL Examples
252
+
253
+ Add unique:
254
+
255
+ ```sql
256
+ ALTER TABLE users ADD CONSTRAINT uq_users_email UNIQUE (email);
257
+ ```
258
+
259
+ Remove unique:
260
+
261
+ ```sql
262
+ ALTER TABLE users DROP CONSTRAINT IF EXISTS uq_users_email;
263
+ ALTER TABLE users DROP CONSTRAINT IF EXISTS users_email_key;
264
+ ```
265
+
266
+ Change primary key column (`id` -> `user_id`):
267
+
268
+ ```sql
269
+ ALTER TABLE users DROP CONSTRAINT IF EXISTS pk_users;
270
+ ALTER TABLE users DROP CONSTRAINT IF EXISTS users_pkey;
271
+
272
+ ALTER TABLE users ADD CONSTRAINT pk_users PRIMARY KEY (user_id);
273
+ ```
274
+
275
+ When dropping constraints, SchemaForge attempts deterministic names first, then PostgreSQL legacy defaults (`<table>_pkey`, `<table>_<column>_key`) for compatibility.
276
+
277
+ Also includes nullability migrations when `not null` is added or removed:
278
+
279
+ ```sql
280
+ ALTER TABLE users ALTER COLUMN email SET NOT NULL;
281
+ ALTER TABLE users ALTER COLUMN email DROP NOT NULL;
282
+ ```
283
+
170
284
  ## Schema DSL Format
171
285
 
172
286
  Schemas are defined using the `.sf` format with a clean, readable syntax.
@@ -195,7 +309,8 @@ table table_name {
195
309
 
196
310
  - `pk` - Primary key
197
311
  - `unique` - Unique constraint
198
- - `nullable` - Allow NULL values (columns are NOT NULL by default)
312
+ - `not null` - Disallow NULL values
313
+ - `nullable` - Allow NULL values (default when `not null` is not provided)
199
314
  - `default <value>` - Default value (e.g., `default now()`, `default false`, `default 0`)
200
315
  - `fk <table>.<column>` - Foreign key reference (e.g., `fk users.id`)
201
316
 
@@ -206,8 +321,8 @@ table table_name {
206
321
  ```sql
207
322
  table users {
208
323
  id uuid pk
209
- email varchar unique
210
- name text
324
+ email varchar unique not null
325
+ name text not null
211
326
  created_at timestamptz default now()
212
327
  }
213
328
  ```
@@ -217,20 +332,20 @@ table users {
217
332
  ```sql
218
333
  table posts {
219
334
  id uuid pk
220
- author_id uuid fk users.id
221
- title varchar
335
+ author_id uuid fk users.id not null
336
+ title varchar not null
222
337
  content text
223
338
  published boolean default false
224
339
  created_at timestamptz default now()
225
340
  }
226
341
  ```
227
342
 
228
- #### Table with nullable columns
343
+ #### Table with mixed nullability
229
344
 
230
345
  ```sql
231
346
  table profiles {
232
347
  id uuid pk
233
- user_id uuid fk users.id
348
+ user_id uuid fk users.id not null
234
349
  bio text nullable
235
350
  avatar_url text nullable
236
351
  website varchar nullable
@@ -242,14 +357,14 @@ table profiles {
242
357
 
243
358
  ```bash
244
359
  your-project/
245
- ├── schemaforge/
246
- ├── schema.sf # Your schema definition (edit this!)
247
- ├── config.json # Project configuration
248
- └── state.json # State tracking (auto-generated)
249
- └── supabase/
250
- └── migrations/ # Generated SQL migrations
251
- ├── 20240101120000-initial.sql
252
- └── 20240101120100-add-user-avatar.sql
360
+ +-- schemaforge/
361
+ | +-- schema.sf # Your schema definition (edit this!)
362
+ | +-- config.json # Project configuration
363
+ | \-- state.json # State tracking (auto-generated)
364
+ \-- supabase/
365
+ \-- migrations/ # Generated SQL migrations
366
+ +-- 20240101120000-initial.sql
367
+ \-- 20240101120100-add-user-avatar.sql
253
368
  ```
254
369
 
255
370
  ## Configuration