supabee 0.3.2 → 0.3.4

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 CHANGED
@@ -1,413 +1,505 @@
1
- # Supabee
2
-
3
- [![CI](https://github.com/kaihochak/supabee/actions/workflows/ci.yml/badge.svg)](https://github.com/kaihochak/supabee/actions/workflows/ci.yml)
4
- [![npm version](https://img.shields.io/npm/v/supabee)](https://www.npmjs.com/package/supabee)
5
- [![license](https://img.shields.io/npm/l/supabee)](./LICENSE)
6
-
7
- Orchestrate local Supabase schema/data workflows: split giant SQL dumps into organized files, and apply post-seed migrations in a production-like order.
8
-
9
- ## Why?
10
-
11
- Supabase workflows often end up with two pain points:
12
-
13
- 1. **One huge dump file** (`supabase db dump` / `--data-only`) that's painful to review, edit, or selectively seed from.
14
- 2. **Local reset/start ordering** (migrations → seeds) that can diverge from production deploys (new migrations applied onto an already-populated database).
15
-
16
- `supabee` addresses both:
17
-
18
- - **Split + validate dumps:** split schema and data dumps into focused files (by category / by table), then reconstruct and validate round-trip (PR-friendly diffs, easier navigation, and smaller merge conflicts).
19
- - **Defer post-seed migrations:** temporarily move newer migrations out of the way for `supabase db reset` / `supabase start`, then restore + reapply them after seeds load.
20
-
21
- ### Use cases
22
-
23
- - **Seed data you can control:** keep per-table seed files and point `[db.seed].sql_paths` at only the ones you want.
24
- - **Schema as docs / source of truth:** keep schema readable in-repo (tables, functions, RLS, permissions, etc.).
25
- - **Mimic production locally:** catch “works on reset” vs “works on deploy” issues by applying post-seed migrations after data exists.
26
- - **One-liners with validation:** `sync schema` / `sync data` run dump → split → reconstruct → validate.
27
-
28
- ### Repo hygiene (recommended)
29
-
30
- Commit split outputs (for example `supabase/schemas/split/**` and `supabase/seeds/split/**`), and ignore large generated artifacts in your repo:
31
-
32
- ```gitignore
33
- # raw dumps (generated from prod; optional to keep locally)
34
- supabase/schemas/prod-schemas.sql
35
- supabase/seeds/prod-data.sql
36
-
37
- # reconstructed outputs (validation artifacts)
38
- supabase/schemas/reconstructed-schemas.sql
39
- supabase/seeds/reconstructed-data.sql
40
- ```
41
-
42
- ## Prerequisites
43
-
44
- - [Node.js](https://nodejs.org/) >= 18
45
- - [Supabase CLI](https://supabase.com/docs/guides/cli/getting-started) installed and authenticated
46
-
47
- ## Install
48
-
49
- Global install (recommended):
50
-
51
- ```bash
52
- npm i -g supabee
53
- pnpm add -g supabee
54
- bun add -g supabee
55
- ```
56
-
57
- One-off run without global install:
58
-
59
- ```bash
60
- npx supabee --help
61
- pnpm dlx supabee --help
62
- bunx supabee --help
63
- ```
64
-
65
- Project-local install (optional):
66
-
67
- ```bash
68
- npm install --save-dev supabee
69
- ```
70
-
71
- ## Setup
72
-
73
- ### 1. Initialize config
74
-
75
- Run `init` to generate `supabee.config.json` (if it doesn't exist) and update `supabase/config.toml` seed paths:
76
-
77
- ```bash
78
- supabee init
79
- ```
80
-
81
- Review the generated `supabee.config.json` and adjust paths/limits for your project.
82
-
83
- ### 2. Link your Supabase project
84
-
85
- If you haven't already, link your local repo to your Supabase project. This is required before you can dump schema or data:
86
-
87
- ```bash
88
- supabase link
89
- ```
90
-
91
- You'll be prompted for your project ref and database password. See the [Supabase CLI docs](https://supabase.com/docs/reference/cli/supabase-link) for details.
92
-
93
- ### 3. Run the primary workflows
94
-
95
- ```bash
96
- supabee sync schema
97
- supabee sync data
98
- supabee db reset [cutoff_timestamp]
99
- supabee start [cutoff_timestamp]
100
- ```
101
-
102
- `sync` commands run end-to-end:
103
-
104
- - schema: `supabase db dump` -> split -> reconstruct -> validate
105
- - data: `supabase db dump --data-only` -> split -> reconstruct -> validate
106
-
107
- ### Selective seeding example (optional)
108
-
109
- By default, `supabee init` configures `supabase/config.toml` to load all split seed files (for example `./seeds/split/*.sql`).
110
- To seed only a subset, replace `[db.seed].sql_paths` with an explicit ordered list (keep `001_setup.sql` and `999_cleanup.sql`; add the generated `*_sequences.sql` file if you need sequence values):
111
-
112
- ```toml
113
- [db.seed]
114
- sql_paths = [
115
- "./seeds/split/001_setup.sql",
116
- "./seeds/split/002_public_users.sql",
117
- "./seeds/split/003_public_projects.sql",
118
- "./seeds/split/999_cleanup.sql",
119
- ]
120
- ```
121
-
122
- ## Commands
123
-
124
- ### `init`
125
-
126
- Creates `supabee.config.json` if missing, then updates `supabase/config.toml` `[db.seed].sql_paths` so Supabase knows where to find your split seed files.
127
-
128
- ```bash
129
- supabee init
130
- ```
131
-
132
- ### `schema`
133
-
134
- Processes an existing schema dump into categorized folders:
135
-
136
- ```
137
- supabase/schemas/split/
138
- ├── 00_extensions/
139
- ├── 01_setup/
140
- ├── 02_types/
141
- ├── 03_functions/
142
- ├── 04_tables/
143
- ├── 05_views/
144
- ├── 06_constraints/
145
- ├── 07_indexes/
146
- ├── 08_foreign_keys/
147
- ├── 09_rls/
148
- ├── 10_permissions/
149
- ├── 11_ownership/
150
- └── 12_others/
151
- ```
152
-
153
- ```bash
154
- # Full chain (split → reconstruct → validate)
155
- supabee schema
156
-
157
- # Individual steps
158
- supabee schema split
159
- supabee schema reconstruct
160
- supabee schema validate
161
- ```
162
-
163
- ### `data`
164
-
165
- Processes an existing data dump into per-table files with configurable row/statement limits:
166
-
167
- ```bash
168
- # Full chain (split → reconstruct → validate)
169
- supabee data
170
-
171
- # Individual steps
172
- supabee data split
173
- supabee data reconstruct
174
- supabee data validate
175
- ```
176
-
177
- ### `sync schema`
178
-
179
- Dumps schema from the linked Supabase project, then runs full schema processing:
180
-
1
+ # Supabee
2
+
3
+ [![CI](https://github.com/kaihochak/supabee/actions/workflows/ci.yml/badge.svg)](https://github.com/kaihochak/supabee/actions/workflows/ci.yml)
4
+ [![npm version](https://img.shields.io/npm/v/supabee)](https://www.npmjs.com/package/supabee)
5
+ [![license](https://img.shields.io/npm/l/supabee)](./LICENSE)
6
+
7
+ Orchestrate local Supabase schema/data workflows: split giant SQL dumps into organized files, and apply post-seed migrations in a production-like order.
8
+
9
+ ## Why?
10
+
11
+ Supabase workflows often end up with two pain points:
12
+
13
+ 1. **One huge dump file** (`supabase db dump` / `--data-only`) that's painful to review, edit, or selectively seed from.
14
+ 2. **Local reset/start ordering** (migrations → seeds) that can diverge from production deploys (new migrations applied onto an already-populated database).
15
+
16
+ `supabee` addresses both:
17
+
18
+ - **Split + validate dumps:** split schema and data dumps into focused files (by category / by table), then reconstruct and validate round-trip (PR-friendly diffs, easier navigation, and smaller merge conflicts).
19
+ - **Defer post-seed migrations:** temporarily move newer migrations out of the way for `supabase db reset` / `supabase start`, then restore + reapply them after seeds load.
20
+
21
+ ### Use cases
22
+
23
+ - **Seed data you can control:** keep per-table seed files and point `[db.seed].sql_paths` at only the ones you want.
24
+ - **Schema as docs / source of truth:** keep schema readable in-repo (tables, functions, RLS, permissions, etc.).
25
+ - **Mimic production locally:** catch “works on reset” vs “works on deploy” issues by applying post-seed migrations after data exists.
26
+ - **One-liners with validation:** `sync schema` / `sync data` run dump → split → reconstruct → validate.
27
+
28
+ ### Repo hygiene (recommended)
29
+
30
+ Commit split outputs (for example `supabase/schemas/split/**` and `supabase/seeds/split/**`), and ignore large generated artifacts in your repo:
31
+
32
+ ```gitignore
33
+ # raw dumps (generated from prod; optional to keep locally)
34
+ supabase/schemas/prod-schemas.sql
35
+ supabase/seeds/prod-data.sql
36
+
37
+ # reconstructed outputs (validation artifacts)
38
+ supabase/schemas/reconstructed-schemas.sql
39
+ supabase/seeds/reconstructed-data.sql
40
+ ```
41
+
42
+ ## Prerequisites
43
+
44
+ - [Node.js](https://nodejs.org/) >= 18
45
+ - [Supabase CLI](https://supabase.com/docs/guides/cli/getting-started) installed and authenticated
46
+
47
+ ## Install
48
+
49
+ Global install (recommended):
50
+
51
+ ```bash
52
+ npm i -g supabee
53
+ pnpm add -g supabee
54
+ bun add -g supabee
55
+ ```
56
+
57
+ One-off run without global install:
58
+
59
+ ```bash
60
+ npx supabee --help
61
+ pnpm dlx supabee --help
62
+ bunx supabee --help
63
+ ```
64
+
65
+ Project-local install (optional):
66
+
67
+ ```bash
68
+ npm install --save-dev supabee
69
+ ```
70
+
71
+ ## Setup
72
+
73
+ ### 1. Initialize config
74
+
75
+ Run `init` to generate `supabee.config.json` (if it doesn't exist) and update `supabase/config.toml` seed paths:
76
+
77
+ ```bash
78
+ supabee init
79
+ ```
80
+
81
+ Review the generated `supabee.config.json` and adjust paths/limits for your project.
82
+
83
+ ### 2. Link your Supabase project
84
+
85
+ If you haven't already, link your local repo to your Supabase project. This is required before you can dump schema or data:
86
+
87
+ ```bash
88
+ supabase link
89
+ ```
90
+
91
+ You'll be prompted for your project ref and database password. See the [Supabase CLI docs](https://supabase.com/docs/reference/cli/supabase-link) for details.
92
+
93
+ ### 3. Run the primary workflows
94
+
95
+ ```bash
96
+ supabee sync schema
97
+ supabee sync data
98
+ supabee db reset [cutoff_timestamp]
99
+ supabee start [cutoff_timestamp]
100
+ ```
101
+
102
+ `sync` commands run end-to-end:
103
+
104
+ - schema: `supabase db dump` -> split -> reconstruct -> validate
105
+ - data: `supabase db dump --data-only` -> split -> reconstruct -> validate
106
+
107
+ ### Selective seeding example (optional)
108
+
109
+ By default, `supabee init` configures `supabase/config.toml` to load all split seed files (for example `./seeds/split/*.sql`).
110
+ To seed only a subset, replace `[db.seed].sql_paths` with an explicit ordered list (keep `001_setup.sql` and `999_cleanup.sql`; add the generated `*_sequences.sql` file if you need sequence values):
111
+
112
+ ```toml
113
+ [db.seed]
114
+ sql_paths = [
115
+ "./seeds/split/001_setup.sql",
116
+ "./seeds/split/002_public_users.sql",
117
+ "./seeds/split/003_public_projects.sql",
118
+ "./seeds/split/999_cleanup.sql",
119
+ ]
120
+ ```
121
+
122
+ ## Commands
123
+
124
+ ### `init`
125
+
126
+ Creates `supabee.config.json` if missing, then updates `supabase/config.toml` `[db.seed].sql_paths` so Supabase knows where to find your split seed files.
127
+
128
+ ```bash
129
+ supabee init
130
+ ```
131
+
132
+ ### `schema`
133
+
134
+ Processes an existing schema dump into categorized folders:
135
+
136
+ ```
137
+ supabase/schemas/split/
138
+ ├── 00_extensions/
139
+ ├── 01_setup/
140
+ ├── 02_types/
141
+ ├── 03_functions/
142
+ ├── 04_tables/
143
+ ├── 05_views/
144
+ ├── 06_constraints/
145
+ ├── 07_indexes/
146
+ ├── 08_foreign_keys/
147
+ ├── 09_rls/
148
+ ├── 10_permissions/
149
+ ├── 11_ownership/
150
+ └── 12_others/
151
+ ```
152
+
153
+ ```bash
154
+ # Full chain (split → reconstruct → validate)
155
+ supabee schema
156
+
157
+ # Individual steps
158
+ supabee schema split
159
+ supabee schema reconstruct
160
+ supabee schema validate
161
+ ```
162
+
163
+ ### `data`
164
+
165
+ Processes an existing data dump into per-table files with configurable row/statement limits:
166
+
167
+ ```bash
168
+ # Full chain (split → reconstruct → validate)
169
+ supabee data
170
+
171
+ # Individual steps
172
+ supabee data split
173
+ supabee data reconstruct
174
+ supabee data validate
175
+ ```
176
+
177
+ ### `sync schema`
178
+
179
+ Dumps schema from the linked Supabase project, then runs full schema processing:
180
+
181
181
  ```bash
182
182
  supabee sync schema
183
183
  supabee sync schema --input supabase/schemas/prod-schemas.sql --output supabase/schemas/split
184
184
  supabee sync schema --backup
185
+ supabee sync schema --force
185
186
  ```
186
-
187
- ### `sync data`
188
-
189
- Dumps data (`--data-only`) from the linked Supabase project, then runs full data processing:
190
-
187
+
188
+ ### `sync data`
189
+
190
+ Dumps data (`--data-only`) from the linked Supabase project, then runs full data processing:
191
+
191
192
  ```bash
192
193
  supabee sync data
193
194
  supabee sync data --input supabase/seeds/prod-data.sql --output supabase/seeds/split
194
195
  supabee sync data --backup
195
196
  supabee sync data --no-backup
197
+ supabee sync data --force
196
198
  ```
197
-
199
+
198
200
  ### `db reset`
199
201
 
200
202
  Defers post-seed migrations newer than the cutoff timestamp, runs `supabase db reset`, restores deferred migrations, then reapplies them.
201
-
202
- If `[cutoff_timestamp]` is omitted, `supabee` auto-detects it from `supabase migration list --linked` by taking the latest migration version that exists in both local and remote (works even when remote has gaps).
203
- When linked lookup succeeds, `supabee` stores the value in `supabee.config.json` as `postSeedCutoff`.
204
- If linked lookup fails (for example in CI), it falls back to `postSeedCutoff` from config.
203
+ For historical data migrations at or before cutoff, `supabee` executes a temporary no-op stub during reset, then restores original SQL.
204
+ Classification is automatic by SQL patterns (`INSERT/UPDATE/DELETE/...` vs `CREATE/ALTER/DROP ...`), and optional markers can override classification.
205
+ Mixed schema+DML migrations are blocked when they are after cutoff and must be split.
206
+ Mixed migrations at/before cutoff run in compatibility mode by default (warning only). Use `--strict-mixed` to fail on any mixed migration.
207
+
208
+ If `[cutoff_timestamp]` is omitted, `supabee` auto-detects it from `supabase migration list --linked` by taking the latest migration version that exists in both local and remote (works even when remote has gaps).
209
+ When linked lookup succeeds, `supabee` stores the value in `supabee.config.json` as `postSeedCutoff` (or `postSeedCutoffByEnv.<env>` when `--env` is set).
210
+ If linked lookup fails (for example in CI), it falls back to `postSeedCutoffByEnv.<env>` when `--env` is set, otherwise `postSeedCutoff`.
205
211
  If not linked, `supabee` runs `supabase link` and retries once.
206
-
207
- ```bash
212
+
213
+ ```bash
208
214
  # default re-apply mode: supabase migration up
209
215
  supabee db reset 20260309180959
210
216
  supabee db reset
217
+ supabee db reset --env staging
211
218
 
212
219
  # optional re-apply mode: psql
213
220
  supabee db reset 20260309180959 --psql
214
- ```
215
221
 
222
+ # strict mixed policy
223
+ supabee db reset --strict-mixed
224
+ ```
225
+
216
226
  ### `start`
217
227
 
218
228
  Defers post-seed migrations newer than the cutoff timestamp, runs `supabase start`, restores deferred migrations, then reapplies them.
219
-
220
- If `[cutoff_timestamp]` is omitted, `supabee` auto-detects it from `supabase migration list --linked` the same way as `db reset`.
221
-
222
- ```bash
223
- # explicit cutoff
224
- supabee start 20260309180959
225
-
229
+ For historical data-migration files, `supabee` temporarily swaps the file body to a no-op during the run, then restores the original SQL file content.
230
+
231
+ If `[cutoff_timestamp]` is omitted, `supabee` auto-detects it from `supabase migration list --linked` the same way as `db reset`.
232
+
233
+ ```bash
234
+ # explicit cutoff
235
+ supabee start 20260309180959
236
+
226
237
  # auto cutoff from linked migration alignment
227
238
  supabee start
228
239
 
229
240
  # optional re-apply mode: psql
230
241
  supabee start --psql
242
+ supabee start --env production
243
+
244
+ # strict mixed policy
245
+ supabee start --strict-mixed
231
246
  ```
232
247
 
233
- ### Supabase passthrough
248
+ ### `cutoff detect`
234
249
 
235
- Unknown commands are forwarded to Supabase CLI:
250
+ Resolves cutoff from argument, linked migration alignment, or config fallback.
236
251
 
237
252
  ```bash
238
- supabee migration up # forwards to: supabase migration up
239
- supabee db dump # forwards to: supabase db dump
253
+ supabee cutoff detect
254
+ supabee cutoff detect --env staging
255
+ supabee cutoff detect 20260309180959 --json
240
256
  ```
241
257
 
242
- ### Overriding paths
258
+ ### `migration audit`
243
259
 
244
- `schema`, `data`, and `sync` commands accept `--input` and `--output` flags:
260
+ Classifies migration files as `data`, `schema`, `mixed`, or `unknown`, and shows recommended marker actions.
245
261
 
246
262
  ```bash
247
- supabee schema split --input path/to/schema.sql --output path/to/split
248
- supabee schema split --input path/to/schema.sql --output path/to/split --backup
249
- supabee data split --input path/to/data.sql --output path/to/split
250
- supabee data split --input path/to/data.sql --output path/to/split --no-backup
263
+ supabee migration audit
264
+ supabee migration audit --migrations-dir supabase/migrations
265
+ supabee migration audit --verbose
266
+ supabee migration audit --json
267
+ supabee migration audit --json --verbose
251
268
  ```
252
269
 
253
- By default, split operations replace existing output in-place (while preserving configured `keepFiles`) without creating a backup folder.
254
- Use `--backup` to keep a timestamped backup before replacement.
270
+ ### `migration mark`
271
+
272
+ Adds suggested marker comments by default with interactive confirmation prompts.
273
+
274
+ ```bash
275
+ # default: interactive apply
276
+ supabee migration mark
277
+
278
+ # preview only (no writes)
279
+ supabee migration mark --dry-run
255
280
 
256
- ## Configuration
281
+ # non-interactive apply (CI/scripts)
282
+ supabee migration mark --yes
283
+ ```
257
284
 
258
- `supabee` reads `supabee.config.json` from your project root.
285
+ ### `migration unmark`
259
286
 
260
- **Precedence:** CLI flags > config file > built-in defaults.
287
+ Removes marker comments with the same interaction model as `mark`.
261
288
 
262
- If the config file is missing, built-in defaults are used. Run `supabee init` to generate one.
289
+ ```bash
290
+ # default: interactive remove
291
+ supabee migration unmark
263
292
 
264
- Legacy support: `supabase-splitter.config.json` is still recognized, but `supabee.config.json` is preferred.
293
+ # preview only (no writes)
294
+ supabee migration unmark --dry-run
265
295
 
266
- ### Full config reference
296
+ # non-interactive remove
297
+ supabee migration unmark --yes
298
+ ```
267
299
 
300
+ ### Supabase passthrough
301
+
302
+ Unknown commands are forwarded to Supabase CLI:
303
+
304
+ ```bash
305
+ supabee migration up # forwards to: supabase migration up
306
+ supabee db dump # forwards to: supabase db dump
307
+ ```
308
+
309
+ ### Overriding paths
310
+
311
+ `schema`, `data`, and `sync` commands accept `--input` and `--output` flags:
312
+
313
+ ```bash
314
+ supabee schema split --input path/to/schema.sql --output path/to/split
315
+ supabee schema split --input path/to/schema.sql --output path/to/split --backup
316
+ supabee data split --input path/to/data.sql --output path/to/split
317
+ supabee data split --input path/to/data.sql --output path/to/split --no-backup
318
+ ```
319
+
320
+ By default, split operations replace existing output in-place (while preserving configured `keepFiles`) without creating a backup folder.
321
+ Use `--backup` to keep a timestamped backup before replacement.
322
+
323
+ ## Configuration
324
+
325
+ `supabee` reads `supabee.config.json` from your project root.
326
+
327
+ **Precedence:** CLI flags > config file > built-in defaults.
328
+
329
+ If the config file is missing, built-in defaults are used. Run `supabee init` to generate one.
330
+
331
+ Legacy support: `supabase-splitter.config.json` is still recognized, but `supabee.config.json` is preferred.
332
+
333
+ ### Full config reference
334
+
268
335
  ```json
269
336
  {
270
337
  "postSeedCutoff": "",
271
- "schema": {
272
- "input": "supabase/schemas/prod-schemas.sql",
273
- "output": "supabase/schemas/split",
274
- "reconstructed": "supabase/schemas/reconstructed-schemas.sql",
275
- "backup": false,
276
- "keepFiles": []
338
+ "postSeedCutoffByEnv": {
339
+ "staging": "",
340
+ "production": ""
277
341
  },
278
- "data": {
279
- "input": "supabase/seeds/prod-data.sql",
280
- "output": "supabase/seeds/split",
281
- "reconstructed": "supabase/seeds/reconstructed-data.sql",
282
- "backup": false,
283
- "maxLinesPerFile": 2000,
284
- "maxStatementsPerFile": 20,
285
- "maxRowsPerInsert": 200,
286
- "tableRules": {},
287
- "keepFiles": [],
288
- "ignoreInReconstruct": []
289
- },
290
- "init": {
291
- "seedSqlPaths": ["./seeds/split/*.sql"]
292
- }
293
- }
294
- ```
295
-
296
- | Key | Description |
297
- |-----|-------------|
298
- | `schema.input` | Path to your schema dump file |
299
- | `schema.output` | Directory for split schema files |
300
- | `schema.reconstructed` | Path for the reconstructed schema (used in validation) |
301
- | `schema.backup` | Whether split should create backup folder before replacing output (default: `false`) |
302
- | `schema.keepFiles` | Files in the split dir to preserve across re-splits |
303
- | `data.input` | Path to your data dump file |
304
- | `data.output` | Directory for split data files |
305
- | `data.reconstructed` | Path for the reconstructed data (used in validation) |
306
- | `data.backup` | Whether split should create backup folder before replacing output (default: `false`) |
307
- | `data.maxLinesPerFile` | Max lines per split file (default: 2000) |
308
- | `data.maxStatementsPerFile` | Max INSERT statements per file (default: 20) |
309
- | `data.maxRowsPerInsert` | Max rows per INSERT statement (default: 200) |
310
- | `data.tableRules` | Per-table overrides (see below) |
342
+ "dataMigrationMarker": "supabee:data-migration",
343
+ "schemaMigrationMarker": "supabee:schema-migration",
344
+ "schema": {
345
+ "input": "supabase/schemas/prod-schemas.sql",
346
+ "output": "supabase/schemas/split",
347
+ "reconstructed": "supabase/schemas/reconstructed-schemas.sql",
348
+ "backup": false,
349
+ "keepFiles": []
350
+ },
351
+ "data": {
352
+ "input": "supabase/seeds/prod-data.sql",
353
+ "output": "supabase/seeds/split",
354
+ "reconstructed": "supabase/seeds/reconstructed-data.sql",
355
+ "backup": false,
356
+ "maxLinesPerFile": 2000,
357
+ "maxStatementsPerFile": 20,
358
+ "maxRowsPerInsert": 200,
359
+ "tableRules": {},
360
+ "keepFiles": [],
361
+ "ignoreInReconstruct": []
362
+ },
363
+ "init": {
364
+ "seedSqlPaths": ["./seeds/split/*.sql"]
365
+ }
366
+ }
367
+ ```
368
+
369
+ | Key | Description |
370
+ |-----|-------------|
371
+ | `schema.input` | Path to your schema dump file |
372
+ | `schema.output` | Directory for split schema files |
373
+ | `schema.reconstructed` | Path for the reconstructed schema (used in validation) |
374
+ | `schema.backup` | Whether split should create backup folder before replacing output (default: `false`) |
375
+ | `schema.keepFiles` | Files in the split dir to preserve across re-splits |
376
+ | `data.input` | Path to your data dump file |
377
+ | `data.output` | Directory for split data files |
378
+ | `data.reconstructed` | Path for the reconstructed data (used in validation) |
379
+ | `data.backup` | Whether split should create backup folder before replacing output (default: `false`) |
380
+ | `data.maxLinesPerFile` | Max lines per split file (default: 2000) |
381
+ | `data.maxStatementsPerFile` | Max INSERT statements per file (default: 20) |
382
+ | `data.maxRowsPerInsert` | Max rows per INSERT statement (default: 200) |
383
+ | `data.tableRules` | Per-table overrides (see below) |
311
384
  | `data.keepFiles` | Files in the split dir to preserve across re-splits |
312
385
  | `data.ignoreInReconstruct` | Files to skip during reconstruction |
313
386
  | `init.seedSqlPaths` | Paths written to `supabase/config.toml` `[db.seed].sql_paths` |
314
387
  | `postSeedCutoff` | Fallback cutoff timestamp used by `db reset`/`start` when linked lookup is unavailable (for example in CI) |
315
-
316
- ### Table-specific rules
317
-
318
- Override limits or skip specific tables:
319
-
320
- ```json
321
- {
322
- "data": {
323
- "tableRules": {
324
- "public.cities": {
325
- "maxLinesPerFile": 800,
326
- "maxStatementsPerFile": 8,
327
- "maxRowsPerInsert": 80
328
- },
329
- "public.audit_logs": {
330
- "skip": true
331
- }
332
- }
333
- }
334
- }
335
- ```
336
-
337
- ## Flags
338
-
388
+ | `postSeedCutoffByEnv` | Optional per-environment fallback cutoff map (for example `staging`, `production`) |
389
+ | `dataMigrationMarker` | Optional override marker for data migrations (default: `supabee:data-migration`) |
390
+ | `schemaMigrationMarker` | Optional override marker for schema migrations (default: `supabee:schema-migration`) |
391
+
392
+ ### Table-specific rules
393
+
394
+ Override limits or skip specific tables:
395
+
396
+ ```json
397
+ {
398
+ "data": {
399
+ "tableRules": {
400
+ "public.cities": {
401
+ "maxLinesPerFile": 800,
402
+ "maxStatementsPerFile": 8,
403
+ "maxRowsPerInsert": 80
404
+ },
405
+ "public.audit_logs": {
406
+ "skip": true
407
+ }
408
+ }
409
+ }
410
+ }
411
+ ```
412
+
413
+ ## Flags
414
+
339
415
  `schema`, `data`, `sync schema`, and `sync data` support:
340
416
 
341
417
  - `--input`: source SQL file
342
418
  - `--output`: output path (split dir for `split`, reconstructed file for `reconstruct`/`validate`)
343
419
  - `--backup`: create backup of dirty split directory before running split
344
420
  - `--no-backup`: disable backup of dirty split directory before running split
421
+ - `--force` (sync commands only): skip linked migration alignment preflight
345
422
 
346
423
  For `validate`, you can pass reconstructed path either as `--output <path>` or as the second positional argument.
347
-
424
+
348
425
  `db reset` supports:
349
426
 
350
427
  - `--psql`: apply deferred migrations via `psql` instead of `supabase migration up`
428
+ - `--strict-mixed`: fail when any mixed schema+DML migration is detected (default behavior only fails when mixed migrations are after cutoff)
351
429
  - `--migrations-dir <path>`: override migrations directory (default `supabase/migrations`)
352
430
  - `--temp-dir <path>`: override temporary defer directory (default `supabase/.tmp-migrations`)
431
+ - `--env <name>`: use `postSeedCutoffByEnv.<name>` as fallback cutoff source
353
432
 
354
433
  `start` supports:
355
434
 
356
435
  - `--psql`: apply deferred migrations via `psql` instead of `supabase migration up`
436
+ - `--strict-mixed`: fail when any mixed schema+DML migration is detected (default behavior only fails when mixed migrations are after cutoff)
357
437
  - `--migrations-dir <path>`: override migrations directory (default `supabase/migrations`)
358
438
  - `--temp-dir <path>`: override temporary defer directory (default `supabase/.tmp-migrations`)
359
-
360
- ## Deep dive: why `supabee db reset` and `supabee start`
361
-
362
- The short version is in the **Why?** section above. These commands matter most when local replay order diverges from how production data actually evolved:
363
-
364
- 1. Seed files may be shaped for pre-migration schema.
365
- 2. Some migrations intentionally mutate/seed production data for traceability (for example RBAC rows).
366
- 3. Local `migrations -> seed` replay can fail even when production worked on already-populated data.
367
-
368
- By deferring post-seed migrations and applying them after seed load, `supabee` better matches this production-style path.
369
-
370
- ## Migration + Seed Duplication Caveat
371
-
372
- If the same logical data mutation exists in both migration SQL and seed files, local replay can become order-dependent and brittle.
373
-
374
- Typical symptoms:
375
- - enum/value already exists errors,
376
- - duplicate key or constraint violations,
377
- - reset/start-only failures that don’t appear on incremental production deploys.
378
-
439
+ - `--env <name>`: use `postSeedCutoffByEnv.<name>` as fallback cutoff source
440
+
441
+ `cutoff detect` supports:
442
+
443
+ - `--env <name>`: include environment fallback lookup
444
+ - `--json`: print machine-readable output
445
+
446
+ ## Deep dive: why `supabee db reset` and `supabee start`
447
+
448
+ The short version is in the **Why?** section above. These commands matter most when local replay order diverges from how production data actually evolved:
449
+
450
+ 1. Seed files may be shaped for pre-migration schema.
451
+ 2. Some migrations intentionally mutate/seed production data for traceability (for example RBAC rows).
452
+ 3. Local `migrations -> seed` replay can fail even when production worked on already-populated data.
453
+
454
+ By deferring post-seed migrations and applying them after seed load, `supabee` better matches this production-style path.
455
+
456
+ ## Migration + Seed Duplication Caveat
457
+
458
+ If the same logical data mutation exists in both migration SQL and seed files, local replay can become order-dependent and brittle.
459
+
460
+ Typical symptoms:
461
+ - enum/value already exists errors,
462
+ - duplicate key or constraint violations,
463
+ - reset/start-only failures that don’t appear on incremental production deploys.
464
+
379
465
  Recommended approach:
380
466
 
381
467
  1. Keep schema structure changes in migrations.
382
468
  2. Keep baseline/reference seed rows in seed files.
383
- 3. Make migration-time data mutations idempotent (`IF NOT EXISTS`, `ON CONFLICT DO NOTHING`, guarded updates).
384
- 4. Avoid duplicating the exact same inserts/enum mutations in both seeds and migrations unless both paths are explicitly idempotent.
385
-
386
- ## Help
387
-
388
- ```bash
389
- supabee --help
390
- supabee init --help
391
- supabee sync --help
392
- supabee sync schema --help
393
- supabee sync data --help
394
- supabee schema --help
469
+ 3. Put data mutations in dedicated migration files; `supabee` auto-detects these by SQL patterns.
470
+ 4. Use `supabee migration audit` to review classification and `supabee migration mark` if you want explicit marker comments in files.
471
+ 5. Keep data migrations free of schema DDL (`CREATE`/`ALTER`/`DROP ...`); mixed files are blocked and must be split.
472
+ 6. Make migration-time data mutations idempotent (`IF NOT EXISTS`, `ON CONFLICT DO NOTHING`, guarded updates).
473
+
474
+ ## Help
475
+
476
+ ```bash
477
+ supabee --help
478
+ supabee init --help
479
+ supabee sync --help
480
+ supabee sync schema --help
481
+ supabee sync data --help
482
+ supabee schema --help
395
483
  supabee data --help
396
484
  supabee start --help
397
485
  supabee db --help
398
486
  supabee db reset --help
487
+ supabee cutoff detect --help
488
+ supabee migration audit --help
489
+ supabee migration mark --help
490
+ supabee migration unmark --help
399
491
  ```
400
-
401
- Legacy CLI alias is still available: `supabase-splitter --help`.
402
-
403
- ## Development
404
-
405
- ```bash
406
- npm install
407
- npm run typecheck
408
- npm run build
409
- npm run test
410
- npm run pack:check
411
- ```
412
-
413
- RC gate checklist: `docs/rc-checklist.md`
492
+
493
+ Legacy CLI alias is still available: `supabase-splitter --help`.
494
+
495
+ ## Development
496
+
497
+ ```bash
498
+ npm install
499
+ npm run typecheck
500
+ npm run build
501
+ npm run test
502
+ npm run pack:check
503
+ ```
504
+
505
+ RC gate checklist: `docs/rc-checklist.md`