@codemarc/blt 1.10.1 → 1.10.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 +94 -6
- package/dist/blt +2 -0
- package/dist/blt.d.ts.map +1 -1
- package/dist/blt.js.map +1 -1
- package/dist/commands/db/diff-endpoint.d.ts +16 -0
- package/dist/commands/db/diff-endpoint.d.ts.map +1 -0
- package/dist/commands/db/diff-endpoint.js +39 -0
- package/dist/commands/db/diff-endpoint.js.map +1 -0
- package/dist/commands/db/dump.d.ts +23 -0
- package/dist/commands/db/dump.d.ts.map +1 -0
- package/dist/commands/db/dump.js +49 -0
- package/dist/commands/db/dump.js.map +1 -0
- package/dist/commands/db/env-url.d.ts +4 -0
- package/dist/commands/db/env-url.d.ts.map +1 -0
- package/dist/commands/db/env-url.js +34 -0
- package/dist/commands/db/env-url.js.map +1 -0
- package/dist/commands/db/patch.d.ts +14 -0
- package/dist/commands/db/patch.d.ts.map +1 -0
- package/dist/commands/db/patch.js +58 -0
- package/dist/commands/db/patch.js.map +1 -0
- package/dist/commands/db/run.d.ts +4 -0
- package/dist/commands/db/run.d.ts.map +1 -0
- package/dist/commands/db/run.js +19 -0
- package/dist/commands/db/run.js.map +1 -0
- package/dist/commands/db/schema-loader.d.ts +28 -0
- package/dist/commands/db/schema-loader.d.ts.map +1 -0
- package/dist/commands/db/schema-loader.js +121 -0
- package/dist/commands/db/schema-loader.js.map +1 -0
- package/dist/commands/db/sql.d.ts +10 -0
- package/dist/commands/db/sql.d.ts.map +1 -0
- package/dist/commands/db/sql.js +152 -0
- package/dist/commands/db/sql.js.map +1 -0
- package/dist/commands/db/supabase-schema.d.ts +38 -0
- package/dist/commands/db/supabase-schema.d.ts.map +1 -0
- package/dist/commands/db/supabase-schema.js +132 -0
- package/dist/commands/db/supabase-schema.js.map +1 -0
- package/dist/commands/db.d.ts +3 -0
- package/dist/commands/db.d.ts.map +1 -0
- package/dist/commands/db.js +116 -0
- package/dist/commands/db.js.map +1 -0
- package/dist/commands/init/script.d.ts +37 -1
- package/dist/commands/init/script.d.ts.map +1 -1
- package/dist/commands/init/script.js +142 -78
- package/dist/commands/init/script.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +13 -8
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/show/repo.js +3 -3
- package/dist/commands/show/repo.js.map +1 -1
- package/dist/lib/repositories.d.ts +21 -5
- package/dist/lib/repositories.d.ts.map +1 -1
- package/dist/lib/repositories.js +98 -80
- package/dist/lib/repositories.js.map +1 -1
- package/dist/lib/repositories.manifest.json +54 -0
- package/package.json +12 -7
- package/repositories.json.example +14 -0
package/README.md
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
- **Bucket**: Supabase storage — list buckets, list/upload/download files, get URLs
|
|
12
12
|
- **Cleanup**: Remove generated SQL/instance files, clean infrequently used YAML tags
|
|
13
13
|
- **Data**: Read-only pull of live menu graph into versioned snapshots; apply to a dev database
|
|
14
|
+
- **Db**: Run ad-hoc SQL strings or `.sql` files; compare schemas between trailz envs
|
|
14
15
|
- **Deploy**: Deploy schema/data from SQL files, run a single SQL file
|
|
15
16
|
- **Env**: Decrypt trailz `.trailz/env/env.<name>.bin` to `.env` via smash (`blt env get`; expands `$VAR` by default; requires `SMASH_KEY`)
|
|
16
17
|
- **Image**: WebP conversion, sharpening, color manipulation, and enhancement
|
|
@@ -74,6 +75,7 @@ blt deploy schema
|
|
|
74
75
|
| `blt bucket` | names, list, upload, download, url, clear |
|
|
75
76
|
| `blt cleanup` | generated, tags |
|
|
76
77
|
| `blt data` | Pull / apply instance data snapshots |
|
|
78
|
+
| `blt db` | sql, run, dump, patch (schema tools) |
|
|
77
79
|
| `blt deploy` | Schema, data, sql file |
|
|
78
80
|
| `blt env` | get (decrypt trailz env to `.env`) |
|
|
79
81
|
| `blt image` | Convert, sharpen, enhance, recolor |
|
|
@@ -394,6 +396,87 @@ blt build data my_instance
|
|
|
394
396
|
|
|
395
397
|
---
|
|
396
398
|
|
|
399
|
+
## Db Commands
|
|
400
|
+
|
|
401
|
+
Ad-hoc SQL against the load database (`BLT_DATA_LOAD_URL` or `SUPABASE_CONNECTION_STRING`).
|
|
402
|
+
|
|
403
|
+
### `blt db sql <query>`
|
|
404
|
+
|
|
405
|
+
Execute a SQL string.
|
|
406
|
+
|
|
407
|
+
```bash
|
|
408
|
+
blt db sql "SELECT count(*) FROM settings"
|
|
409
|
+
blt db sql "SELECT * FROM settings LIMIT 5" --format json
|
|
410
|
+
blt db sql "SELECT * FROM settings LIMIT 5" --format jsonl
|
|
411
|
+
blt db sql "SELECT name,role FROM profiles LIMIT 5" --format jsonl | jq -c 'select(.role == "manager")'
|
|
412
|
+
blt db sql "SELECT * FROM settings LIMIT 5" --format toon
|
|
413
|
+
blt db sql "SELECT * FROM settings LIMIT 5" --format csv > settings.csv
|
|
414
|
+
blt db sql "UPDATE settings SET props = props WHERE false" --verbose
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
**Options:**
|
|
418
|
+
|
|
419
|
+
- `-f, --format <format>` — Result format for SELECT queries: `table` (default), `json`, `jsonl`, `toon`, or `csv`
|
|
420
|
+
- `--verbose` — Execute each statement separately with progress labels
|
|
421
|
+
|
|
422
|
+
### `blt db run <file>`
|
|
423
|
+
|
|
424
|
+
Execute a `.sql` file.
|
|
425
|
+
|
|
426
|
+
```bash
|
|
427
|
+
blt db run ./scripts/my-migration.sql
|
|
428
|
+
blt db run ./dist/bltcore-v1.0.0.sql --verbose
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
**Options:**
|
|
432
|
+
|
|
433
|
+
- `--verbose` — Log each SQL statement as it runs
|
|
434
|
+
|
|
435
|
+
### `blt db dump <env>`
|
|
436
|
+
|
|
437
|
+
Dump the schema from a single trailz environment (name from `blt env list`).
|
|
438
|
+
|
|
439
|
+
```bash
|
|
440
|
+
cd data
|
|
441
|
+
blt db dump laf
|
|
442
|
+
blt db dump laf --schema public --dir ./diff
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
Writes `<env>.sql` (e.g. `laf.sql`) and `manifest.json` under `--dir` (default `diff`).
|
|
446
|
+
|
|
447
|
+
**Options:**
|
|
448
|
+
|
|
449
|
+
- `-s, --schema <name>` — Postgres schema to dump (default: `public`)
|
|
450
|
+
- `--dir <path>` — Output directory (default: `diff`)
|
|
451
|
+
|
|
452
|
+
### `blt db patch <source-env> <target-env>`
|
|
453
|
+
|
|
454
|
+
Generate a single roll-forward patch SQL file from **source** (desired schema) to **target** (database to update). Does **not** apply the patch — review the file, then run it with `blt db run`.
|
|
455
|
+
|
|
456
|
+
Names come from `blt env list`; paths ending in `.sql` reuse an existing dump.
|
|
457
|
+
|
|
458
|
+
```bash
|
|
459
|
+
cd data
|
|
460
|
+
blt db patch laf test1
|
|
461
|
+
blt db patch diff/laf.sql test1
|
|
462
|
+
blt db patch laf test1 --schema public,auth --name p1.sql --dir ./diff
|
|
463
|
+
blt db run ./diff/p1.sql
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
**`.sql` endpoints:** when either side is a file, Docker loads the dump(s) into temporary Postgres so `supabase db diff` can run.
|
|
467
|
+
|
|
468
|
+
**Options:**
|
|
469
|
+
|
|
470
|
+
- `-s, --schema <schemas>` — Comma-separated Postgres schemas (default: `public`)
|
|
471
|
+
- `-n, --name <file>` — Patch SQL filename (default: `patch.sql`)
|
|
472
|
+
- `--dir <path>` — Output directory (default: `diff`)
|
|
473
|
+
|
|
474
|
+
**Prerequisites:** `SMASH_KEY` (for env endpoints), trailz env bundles at `.trailz/env/env.<name>.bin`, [Supabase CLI](https://supabase.com/docs/guides/cli) on `PATH`, and **Docker** when either side is a `.sql` file path.
|
|
475
|
+
|
|
476
|
+
Generated SQL is evidence for review — not auto-approved production SQL. Prefer direct Postgres URLs (port 5432) in env bundles when pooler URLs cause patch timeouts.
|
|
477
|
+
|
|
478
|
+
---
|
|
479
|
+
|
|
397
480
|
## Deploy Commands
|
|
398
481
|
|
|
399
482
|
### `blt deploy schema [name]`
|
|
@@ -534,20 +617,25 @@ Snapshots default under `data-snapshots/` from the **current working directory**
|
|
|
534
617
|
|
|
535
618
|
### `blt init [options]`
|
|
536
619
|
|
|
537
|
-
Create a shell script to
|
|
620
|
+
Create a shell script to fast-forward sync sibling BLT repositories. Run the generated script from the **umbrella repo root** (`bltcore-com/blt`), not from a parent directory.
|
|
538
621
|
|
|
539
622
|
```bash
|
|
540
|
-
blt
|
|
541
|
-
blt init -w -
|
|
623
|
+
git clone git@github.com:bltcore-com/blt.git && cd blt
|
|
624
|
+
blt init -w -s
|
|
625
|
+
blt init -b -s # bundle: single-root workspace
|
|
542
626
|
./getblt.sh
|
|
543
627
|
```
|
|
544
628
|
|
|
545
629
|
**Options:**
|
|
546
630
|
|
|
547
|
-
- `-o, --output <path>` — Output path for the script (default:
|
|
631
|
+
- `-o, --output <path>` — Output path for the script (default: `./getblt.sh`)
|
|
548
632
|
- `-s, --ssh` — Use SSH URLs instead of HTTPS
|
|
549
|
-
- `-
|
|
550
|
-
- `-
|
|
633
|
+
- `-g, --gh` — Use GitHub CLI (`gh repo clone`) instead of `git clone`
|
|
634
|
+
- `-w, --workspace` — Generate `blt.code-workspace` (umbrella at `.` plus one folder per sibling repo)
|
|
635
|
+
- `-b, --bundle` — Sync umbrella into `.` when needed; single-root workspace (`blt` → `.`)
|
|
636
|
+
- `-c, --connections` — Add `sqltools.connections` from `.env` (requires `-w` or `-b`)
|
|
637
|
+
|
|
638
|
+
**Repository list:** `repositories.json` in the umbrella repo root (or `BLT_REPOSITORIES_PATH`). Re-run `blt init` after editing it to refresh `getblt.sh`.
|
|
551
639
|
|
|
552
640
|
---
|
|
553
641
|
|
package/dist/blt
CHANGED
|
@@ -5,6 +5,7 @@ import bucketCommand from "./commands/bucket";
|
|
|
5
5
|
import buildCommand from "./commands/build";
|
|
6
6
|
import cleanupCommand from "./commands/cleanup";
|
|
7
7
|
// import dataCommand from "./commands/data";
|
|
8
|
+
import dbCommand from "./commands/db";
|
|
8
9
|
import deployCommand from "./commands/deploy";
|
|
9
10
|
import envCommand from "./commands/env";
|
|
10
11
|
import imageCommand from "./commands/image";
|
|
@@ -35,6 +36,7 @@ bucketCommand(program);
|
|
|
35
36
|
buildCommand(program);
|
|
36
37
|
cleanupCommand(program);
|
|
37
38
|
// dataCommand(program);
|
|
39
|
+
dbCommand(program);
|
|
38
40
|
deployCommand(program);
|
|
39
41
|
envCommand(program);
|
|
40
42
|
imageCommand(program);
|
package/dist/blt.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blt.d.ts","sourceRoot":"","sources":["../src/blt.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"blt.d.ts","sourceRoot":"","sources":["../src/blt.ts"],"names":[],"mappings":";AA6BA,wBAAgB,iBAAiB,IAAI,MAAM,CAG1C"}
|
package/dist/blt.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blt.js","sourceRoot":"","sources":["../src/blt.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,UAAU,MAAM,gBAAgB,CAAC;AACxC,OAAO,aAAa,MAAM,mBAAmB,CAAC;AAC9C,OAAO,YAAY,MAAM,kBAAkB,CAAC;AAC5C,OAAO,cAAc,MAAM,oBAAoB,CAAC;AAChD,6CAA6C;AAC7C,OAAO,aAAa,MAAM,mBAAmB,CAAC;AAC9C,OAAO,UAAU,MAAM,gBAAgB,CAAC;AACxC,OAAO,YAAY,MAAM,kBAAkB,CAAC;AAC5C,OAAO,WAAW,MAAM,iBAAiB,CAAC;AAC1C,OAAO,aAAa,MAAM,mBAAmB,CAAC;AAC9C,OAAO,UAAU,MAAM,gBAAgB,CAAC;AACxC,OAAO,WAAW,MAAM,iBAAiB,CAAC;AAC1C,OAAO,WAAW,MAAM,iBAAiB,CAAC;AAC1C,OAAO,eAAe,MAAM,qBAAqB,CAAC;AAClD,OAAO,cAAc,MAAM,oBAAoB,CAAC;AAChD,OAAO,UAAU,MAAM,gBAAgB,CAAC;AACxC,OAAO,eAAe,MAAM,qBAAqB,CAAC;AAElD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AACtC,MAAM,eAAe,GAAG,IAAI,CAAC,SAAS,EAAG,IAAI,EAAE,cAAc,CAAC,CAAC;AAE/D,MAAM,UAAU,iBAAiB;IAC/B,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC,CAAC;IACtE,OAAO,WAAW,CAAC,OAAO,CAAC;AAC7B,CAAC;AAED,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC;KACjB,OAAO,CAAC,iBAAiB,EAAE,CAAC;KAC5B,WAAW,CAAC,cAAc,CAAC,CAAC;AAE5B,UAAU,CAAC,OAAO,CAAC,CAAC;AACpB,aAAa,CAAC,OAAO,CAAC,CAAC;AACvB,YAAY,CAAC,OAAO,CAAC,CAAC;AACtB,cAAc,CAAC,OAAO,CAAC,CAAC;AACxB,wBAAwB;AACxB,aAAa,CAAC,OAAO,CAAC,CAAC;AACvB,UAAU,CAAC,OAAO,CAAC,CAAC;AACpB,YAAY,CAAC,OAAO,CAAC,CAAC;AACtB,WAAW,CAAC,OAAO,CAAC,CAAC;AACrB,aAAa,CAAC,OAAO,CAAC,CAAC;AACvB,UAAU,CAAC,OAAO,CAAC,CAAC;AACpB,WAAW,CAAC,OAAO,CAAC,CAAC;AACrB,WAAW,CAAC,OAAO,CAAC,CAAC;AACrB,eAAe,CAAC,OAAO,CAAC,CAAC;AACzB,cAAc,CAAC,OAAO,CAAC,CAAC;AACxB,UAAU,CAAC,OAAO,CAAC,CAAC;AACpB,eAAe,CAAC,OAAO,CAAC,CAAC;AAE3B,uCAAuC;AACvC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACnC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;IACtB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AAC9B,CAAC;AACD,OAAO,CAAC,GAAG,EAAE,CAAC"}
|
|
1
|
+
{"version":3,"file":"blt.js","sourceRoot":"","sources":["../src/blt.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,UAAU,MAAM,gBAAgB,CAAC;AACxC,OAAO,aAAa,MAAM,mBAAmB,CAAC;AAC9C,OAAO,YAAY,MAAM,kBAAkB,CAAC;AAC5C,OAAO,cAAc,MAAM,oBAAoB,CAAC;AAChD,6CAA6C;AAC7C,OAAO,SAAS,MAAM,eAAe,CAAC;AACtC,OAAO,aAAa,MAAM,mBAAmB,CAAC;AAC9C,OAAO,UAAU,MAAM,gBAAgB,CAAC;AACxC,OAAO,YAAY,MAAM,kBAAkB,CAAC;AAC5C,OAAO,WAAW,MAAM,iBAAiB,CAAC;AAC1C,OAAO,aAAa,MAAM,mBAAmB,CAAC;AAC9C,OAAO,UAAU,MAAM,gBAAgB,CAAC;AACxC,OAAO,WAAW,MAAM,iBAAiB,CAAC;AAC1C,OAAO,WAAW,MAAM,iBAAiB,CAAC;AAC1C,OAAO,eAAe,MAAM,qBAAqB,CAAC;AAClD,OAAO,cAAc,MAAM,oBAAoB,CAAC;AAChD,OAAO,UAAU,MAAM,gBAAgB,CAAC;AACxC,OAAO,eAAe,MAAM,qBAAqB,CAAC;AAElD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AACtC,MAAM,eAAe,GAAG,IAAI,CAAC,SAAS,EAAG,IAAI,EAAE,cAAc,CAAC,CAAC;AAE/D,MAAM,UAAU,iBAAiB;IAC/B,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC,CAAC;IACtE,OAAO,WAAW,CAAC,OAAO,CAAC;AAC7B,CAAC;AAED,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC;KACjB,OAAO,CAAC,iBAAiB,EAAE,CAAC;KAC5B,WAAW,CAAC,cAAc,CAAC,CAAC;AAE5B,UAAU,CAAC,OAAO,CAAC,CAAC;AACpB,aAAa,CAAC,OAAO,CAAC,CAAC;AACvB,YAAY,CAAC,OAAO,CAAC,CAAC;AACtB,cAAc,CAAC,OAAO,CAAC,CAAC;AACxB,wBAAwB;AACxB,SAAS,CAAC,OAAO,CAAC,CAAC;AACnB,aAAa,CAAC,OAAO,CAAC,CAAC;AACvB,UAAU,CAAC,OAAO,CAAC,CAAC;AACpB,YAAY,CAAC,OAAO,CAAC,CAAC;AACtB,WAAW,CAAC,OAAO,CAAC,CAAC;AACrB,aAAa,CAAC,OAAO,CAAC,CAAC;AACvB,UAAU,CAAC,OAAO,CAAC,CAAC;AACpB,WAAW,CAAC,OAAO,CAAC,CAAC;AACrB,WAAW,CAAC,OAAO,CAAC,CAAC;AACrB,eAAe,CAAC,OAAO,CAAC,CAAC;AACzB,cAAc,CAAC,OAAO,CAAC,CAAC;AACxB,UAAU,CAAC,OAAO,CAAC,CAAC;AACpB,eAAe,CAAC,OAAO,CAAC,CAAC;AAE3B,uCAAuC;AACvC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACnC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;IACtB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AAC9B,CAAC;AACD,OAAO,CAAC,GAAG,EAAE,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Logger } from "@caporal/core";
|
|
2
|
+
export type DiffEndpoint = {
|
|
3
|
+
kind: "env";
|
|
4
|
+
spec: string;
|
|
5
|
+
dbUrl: string;
|
|
6
|
+
} | {
|
|
7
|
+
kind: "file";
|
|
8
|
+
spec: string;
|
|
9
|
+
path: string;
|
|
10
|
+
};
|
|
11
|
+
export declare function isSqlFileSpec(spec: string): boolean;
|
|
12
|
+
export declare function resolveSqlFilePath(spec: string, cwd: string, logger: Logger): string;
|
|
13
|
+
export declare function resolveDiffEndpoint(spec: string, logger: Logger, cwd: string): DiffEndpoint;
|
|
14
|
+
/** Copy an existing dump into the diff output dir when it is not already there. */
|
|
15
|
+
export declare function materializeDumpArtifact(sourcePath: string, artifactPath: string, logger: Logger): string;
|
|
16
|
+
//# sourceMappingURL=diff-endpoint.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff-endpoint.d.ts","sourceRoot":"","sources":["../../../src/commands/db/diff-endpoint.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAG5C,MAAM,MAAM,YAAY,GACrB;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC5C;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEnD;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAOpF;AAED,wBAAgB,mBAAmB,CAClC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,GACT,YAAY,CAcd;AAED,mFAAmF;AACnF,wBAAgB,uBAAuB,CACtC,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,GACZ,MAAM,CAQR"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { copyFileSync, existsSync } from "node:fs";
|
|
2
|
+
import { isAbsolute, resolve } from "node:path";
|
|
3
|
+
import { resolveTrailzConnectionString } from "./env-url";
|
|
4
|
+
export function isSqlFileSpec(spec) {
|
|
5
|
+
return /\.sql$/i.test(spec.trim());
|
|
6
|
+
}
|
|
7
|
+
export function resolveSqlFilePath(spec, cwd, logger) {
|
|
8
|
+
const path = isAbsolute(spec) ? spec : resolve(cwd, spec);
|
|
9
|
+
if (!existsSync(path)) {
|
|
10
|
+
logger.error(`SQL file not found: ${path}`);
|
|
11
|
+
process.exit(1);
|
|
12
|
+
}
|
|
13
|
+
return path;
|
|
14
|
+
}
|
|
15
|
+
export function resolveDiffEndpoint(spec, logger, cwd) {
|
|
16
|
+
if (isSqlFileSpec(spec)) {
|
|
17
|
+
return {
|
|
18
|
+
kind: "file",
|
|
19
|
+
spec,
|
|
20
|
+
path: resolveSqlFilePath(spec, cwd, logger),
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
return {
|
|
24
|
+
kind: "env",
|
|
25
|
+
spec,
|
|
26
|
+
dbUrl: resolveTrailzConnectionString(spec, logger, cwd),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/** Copy an existing dump into the diff output dir when it is not already there. */
|
|
30
|
+
export function materializeDumpArtifact(sourcePath, artifactPath, logger) {
|
|
31
|
+
if (resolve(sourcePath) === resolve(artifactPath)) {
|
|
32
|
+
logger.info(`Using existing dump: ${sourcePath}`);
|
|
33
|
+
return sourcePath;
|
|
34
|
+
}
|
|
35
|
+
copyFileSync(sourcePath, artifactPath);
|
|
36
|
+
logger.info(`Copied ${sourcePath} → ${artifactPath}`);
|
|
37
|
+
return artifactPath;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=diff-endpoint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff-endpoint.js","sourceRoot":"","sources":["../../../src/commands/db/diff-endpoint.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEhD,OAAO,EAAE,6BAA6B,EAAE,MAAM,WAAW,CAAC;AAM1D,MAAM,UAAU,aAAa,CAAC,IAAY;IACzC,OAAO,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,IAAY,EAAE,GAAW,EAAE,MAAc;IAC3E,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAC1D,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACvB,MAAM,CAAC,KAAK,CAAC,uBAAuB,IAAI,EAAE,CAAC,CAAC;QAC5C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACjB,CAAC;IACD,OAAO,IAAI,CAAC;AACb,CAAC;AAED,MAAM,UAAU,mBAAmB,CAClC,IAAY,EACZ,MAAc,EACd,GAAW;IAEX,IAAI,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC;QACzB,OAAO;YACN,IAAI,EAAE,MAAM;YACZ,IAAI;YACJ,IAAI,EAAE,kBAAkB,CAAC,IAAI,EAAE,GAAG,EAAE,MAAM,CAAC;SAC3C,CAAC;IACH,CAAC;IAED,OAAO;QACN,IAAI,EAAE,KAAK;QACX,IAAI;QACJ,KAAK,EAAE,6BAA6B,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC;KACvD,CAAC;AACH,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,uBAAuB,CACtC,UAAkB,EAClB,YAAoB,EACpB,MAAc;IAEd,IAAI,OAAO,CAAC,UAAU,CAAC,KAAK,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;QACnD,MAAM,CAAC,IAAI,CAAC,wBAAwB,UAAU,EAAE,CAAC,CAAC;QAClD,OAAO,UAAU,CAAC;IACnB,CAAC;IACD,YAAY,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;IACvC,MAAM,CAAC,IAAI,CAAC,UAAU,UAAU,MAAM,YAAY,EAAE,CAAC,CAAC;IACtD,OAAO,YAAY,CAAC;AACrB,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Logger } from "@caporal/core";
|
|
2
|
+
export type DbDumpOptions = {
|
|
3
|
+
env: string;
|
|
4
|
+
schema: string;
|
|
5
|
+
dir: string;
|
|
6
|
+
cwd?: string;
|
|
7
|
+
};
|
|
8
|
+
export type DumpManifest = {
|
|
9
|
+
generatedAt: string;
|
|
10
|
+
env: string;
|
|
11
|
+
schema: string;
|
|
12
|
+
dir: string;
|
|
13
|
+
connection: string;
|
|
14
|
+
artifacts: {
|
|
15
|
+
[fileName: string]: {
|
|
16
|
+
path: string;
|
|
17
|
+
bytes: number;
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
export declare function dumpFileName(envName: string): string;
|
|
22
|
+
export declare function dbDump(opts: DbDumpOptions, logger: Logger): Promise<void>;
|
|
23
|
+
//# sourceMappingURL=dump.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dump.d.ts","sourceRoot":"","sources":["../../../src/commands/db/dump.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAY5C,MAAM,MAAM,aAAa,GAAG;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE;QACV,CAAC,QAAQ,EAAE,MAAM,GAAG;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC;KACpD,CAAC;CACF,CAAC;AAEF,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED,wBAAsB,MAAM,CAAC,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA4C/E"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { writeFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { redactedDbUrl } from "../data/helpers";
|
|
4
|
+
import { resolveTrailzConnectionString } from "./env-url";
|
|
5
|
+
import { ensureOutDir, fileBytes, requireSupabaseCli, resolveOutDir, runSchemaDump, sqlFileHeader, } from "./supabase-schema";
|
|
6
|
+
export function dumpFileName(envName) {
|
|
7
|
+
return `${envName}.sql`;
|
|
8
|
+
}
|
|
9
|
+
export async function dbDump(opts, logger) {
|
|
10
|
+
const cwd = opts.cwd ?? process.cwd();
|
|
11
|
+
const outDir = resolveOutDir(opts.dir, cwd);
|
|
12
|
+
const generatedAt = new Date().toISOString();
|
|
13
|
+
const fileName = dumpFileName(opts.env);
|
|
14
|
+
const outputFile = join(outDir, fileName);
|
|
15
|
+
requireSupabaseCli(logger);
|
|
16
|
+
ensureOutDir(outDir, logger);
|
|
17
|
+
logger.info(`Schema: ${opts.schema}`);
|
|
18
|
+
const dbUrl = resolveTrailzConnectionString(opts.env, logger, cwd);
|
|
19
|
+
runSchemaDump({
|
|
20
|
+
dbUrl,
|
|
21
|
+
schema: opts.schema,
|
|
22
|
+
outputFile,
|
|
23
|
+
header: sqlFileHeader({
|
|
24
|
+
command: "dump",
|
|
25
|
+
kind: "dump",
|
|
26
|
+
env: opts.env,
|
|
27
|
+
schema: opts.schema,
|
|
28
|
+
generatedAt,
|
|
29
|
+
}),
|
|
30
|
+
logger,
|
|
31
|
+
cwd,
|
|
32
|
+
label: `Dumping ${opts.env} schema…`,
|
|
33
|
+
});
|
|
34
|
+
const manifest = {
|
|
35
|
+
generatedAt,
|
|
36
|
+
env: opts.env,
|
|
37
|
+
schema: opts.schema,
|
|
38
|
+
dir: outDir,
|
|
39
|
+
connection: redactedDbUrl(dbUrl),
|
|
40
|
+
artifacts: {
|
|
41
|
+
[fileName]: { path: outputFile, bytes: fileBytes(outputFile) },
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
const manifestPath = join(outDir, "manifest.json");
|
|
45
|
+
writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`, "utf8");
|
|
46
|
+
logger.info(`Wrote ${outputFile}`);
|
|
47
|
+
logger.info(`Wrote ${manifestPath}`);
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=dump.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dump.js","sourceRoot":"","sources":["../../../src/commands/db/dump.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,6BAA6B,EAAE,MAAM,WAAW,CAAC;AAC1D,OAAO,EACN,YAAY,EACZ,SAAS,EACT,kBAAkB,EAClB,aAAa,EACb,aAAa,EACb,aAAa,GACb,MAAM,mBAAmB,CAAC;AAoB3B,MAAM,UAAU,YAAY,CAAC,OAAe;IAC3C,OAAO,GAAG,OAAO,MAAM,CAAC;AACzB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,IAAmB,EAAE,MAAc;IAC/D,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IACtC,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAC5C,MAAM,WAAW,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC7C,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACxC,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAE1C,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAC3B,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,MAAM,CAAC,IAAI,CAAC,WAAW,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IAEtC,MAAM,KAAK,GAAG,6BAA6B,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC;IAEnE,aAAa,CAAC;QACb,KAAK;QACL,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,UAAU;QACV,MAAM,EAAE,aAAa,CAAC;YACrB,OAAO,EAAE,MAAM;YACf,IAAI,EAAE,MAAM;YACZ,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,WAAW;SACX,CAAC;QACF,MAAM;QACN,GAAG;QACH,KAAK,EAAE,WAAW,IAAI,CAAC,GAAG,UAAU;KACpC,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAiB;QAC9B,WAAW;QACX,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,GAAG,EAAE,MAAM;QACX,UAAU,EAAE,aAAa,CAAC,KAAK,CAAC;QAChC,SAAS,EAAE;YACV,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,CAAC,UAAU,CAAC,EAAE;SAC9D;KACD,CAAC;IAEF,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACnD,aAAa,CAAC,YAAY,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAC9E,MAAM,CAAC,IAAI,CAAC,SAAS,UAAU,EAAE,CAAC,CAAC;IACnC,MAAM,CAAC,IAAI,CAAC,SAAS,YAAY,EAAE,CAAC,CAAC;AACtC,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Logger } from "@caporal/core";
|
|
2
|
+
/** Decrypt a trailz env bundle and return `SUPABASE_CONNECTION_STRING`. */
|
|
3
|
+
export declare function resolveTrailzConnectionString(envName: string, logger: Logger, cwd?: string): string;
|
|
4
|
+
//# sourceMappingURL=env-url.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env-url.d.ts","sourceRoot":"","sources":["../../../src/commands/db/env-url.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAY5C,2EAA2E;AAC3E,wBAAgB,6BAA6B,CAC5C,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,GAAG,GAAE,MAAsB,GACzB,MAAM,CAiCR"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { ensureAppEnv, parseDotEnvAssignments, resolveTrailzEnvPaths, } from "../app/env-check";
|
|
2
|
+
import { decryptTrailzEnvBase } from "../app/env-decrypt";
|
|
3
|
+
import { redactedDbUrl } from "../data/helpers";
|
|
4
|
+
import { readTrailzKeysExpansionContext } from "../notify/keys";
|
|
5
|
+
const NAME_RE = /^[a-zA-Z0-9][a-zA-Z0-9._-]*$/;
|
|
6
|
+
/** Decrypt a trailz env bundle and return `SUPABASE_CONNECTION_STRING`. */
|
|
7
|
+
export function resolveTrailzConnectionString(envName, logger, cwd = process.cwd()) {
|
|
8
|
+
if (!NAME_RE.test(envName)) {
|
|
9
|
+
logger.error(`Invalid environment name "${envName}": use one segment (letters, numbers, . _ -).`);
|
|
10
|
+
process.exit(1);
|
|
11
|
+
}
|
|
12
|
+
ensureAppEnv({ envName, cwd, logger, trailzOnly: true });
|
|
13
|
+
const resolved = resolveTrailzEnvPaths(cwd, envName);
|
|
14
|
+
if (!resolved) {
|
|
15
|
+
logger.error(`Trailz env bundle not found for "${envName}"`);
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
const keysContext = readTrailzKeysExpansionContext({ cwd });
|
|
19
|
+
const body = decryptTrailzEnvBase(resolved.basePath, {
|
|
20
|
+
cwd,
|
|
21
|
+
expand: true,
|
|
22
|
+
expansionContext: keysContext,
|
|
23
|
+
});
|
|
24
|
+
const parsed = parseDotEnvAssignments(body);
|
|
25
|
+
const url = parsed.SUPABASE_CONNECTION_STRING;
|
|
26
|
+
if (!url) {
|
|
27
|
+
logger.error(`SUPABASE_CONNECTION_STRING not found in trailz env "${envName}".\n` +
|
|
28
|
+
` Run: blt env get ${envName} and verify the bundle contents.`);
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
logger.info(`Resolved ${envName} → ${redactedDbUrl(url)}`);
|
|
32
|
+
return url;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=env-url.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env-url.js","sourceRoot":"","sources":["../../../src/commands/db/env-url.ts"],"names":[],"mappings":"AACA,OAAO,EACN,YAAY,EACZ,sBAAsB,EACtB,qBAAqB,GACrB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,8BAA8B,EAAE,MAAM,gBAAgB,CAAC;AAEhE,MAAM,OAAO,GAAG,8BAA8B,CAAC;AAE/C,2EAA2E;AAC3E,MAAM,UAAU,6BAA6B,CAC5C,OAAe,EACf,MAAc,EACd,MAAc,OAAO,CAAC,GAAG,EAAE;IAE3B,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5B,MAAM,CAAC,KAAK,CACX,6BAA6B,OAAO,+CAA+C,CACnF,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACjB,CAAC;IAED,YAAY,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC;IACzD,MAAM,QAAQ,GAAG,qBAAqB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IACrD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,oCAAoC,OAAO,GAAG,CAAC,CAAC;QAC7D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACjB,CAAC;IAED,MAAM,WAAW,GAAG,8BAA8B,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;IAC5D,MAAM,IAAI,GAAG,oBAAoB,CAAC,QAAQ,CAAC,QAAQ,EAAE;QACpD,GAAG;QACH,MAAM,EAAE,IAAI;QACZ,gBAAgB,EAAE,WAAW;KAC7B,CAAC,CAAC;IACH,MAAM,MAAM,GAAG,sBAAsB,CAAC,IAAI,CAAC,CAAC;IAC5C,MAAM,GAAG,GAAG,MAAM,CAAC,0BAA0B,CAAC;IAC9C,IAAI,CAAC,GAAG,EAAE,CAAC;QACV,MAAM,CAAC,KAAK,CACX,uDAAuD,OAAO,MAAM;YACnE,sBAAsB,OAAO,kCAAkC,CAChE,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACjB,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,YAAY,OAAO,MAAM,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC3D,OAAO,GAAG,CAAC;AACZ,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Logger } from "@caporal/core";
|
|
2
|
+
export type DbPatchOptions = {
|
|
3
|
+
sourceEnv: string;
|
|
4
|
+
targetEnv: string;
|
|
5
|
+
schema: string;
|
|
6
|
+
name: string;
|
|
7
|
+
dir: string;
|
|
8
|
+
cwd?: string;
|
|
9
|
+
};
|
|
10
|
+
export declare const DEFAULT_PATCH_NAME = "patch.sql";
|
|
11
|
+
/** Roll-forward diff args: apply to target so it matches source. */
|
|
12
|
+
export declare function buildPatchArgs(sourceUrl: string, targetUrl: string, schema: string, outputFile: string): string[];
|
|
13
|
+
export declare function dbPatch(opts: DbPatchOptions, logger: Logger): Promise<void>;
|
|
14
|
+
//# sourceMappingURL=patch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"patch.d.ts","sourceRoot":"","sources":["../../../src/commands/db/patch.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAe5C,MAAM,MAAM,cAAc,GAAG;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,eAAO,MAAM,kBAAkB,cAAc,CAAC;AAE9C,oEAAoE;AACpE,wBAAgB,cAAc,CAC7B,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,GAChB,MAAM,EAAE,CAEV;AAED,wBAAsB,OAAO,CAAC,IAAI,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA8DjF"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { runCommand } from "../app/shell";
|
|
3
|
+
import { resolveDiffEndpoint } from "./diff-endpoint";
|
|
4
|
+
import { resolveSchemaUrlsForDiff } from "./schema-loader";
|
|
5
|
+
import { buildSupabaseDiffArgs, ensureOutDir, fileBytes, normalizeSchemaOption, prependHeader, requireSupabaseCli, resolveOutDir, sqlFileHeader, } from "./supabase-schema";
|
|
6
|
+
export const DEFAULT_PATCH_NAME = "patch.sql";
|
|
7
|
+
/** Roll-forward diff args: apply to target so it matches source. */
|
|
8
|
+
export function buildPatchArgs(sourceUrl, targetUrl, schema, outputFile) {
|
|
9
|
+
return buildSupabaseDiffArgs(targetUrl, sourceUrl, schema, outputFile);
|
|
10
|
+
}
|
|
11
|
+
export async function dbPatch(opts, logger) {
|
|
12
|
+
const cwd = opts.cwd ?? process.cwd();
|
|
13
|
+
const outDir = resolveOutDir(opts.dir, cwd);
|
|
14
|
+
const schema = normalizeSchemaOption(opts.schema);
|
|
15
|
+
const generatedAt = new Date().toISOString();
|
|
16
|
+
const outputFile = join(outDir, opts.name);
|
|
17
|
+
if (!schema) {
|
|
18
|
+
logger.error("At least one schema is required (e.g. --schema public or public,auth).");
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
if (opts.sourceEnv === opts.targetEnv) {
|
|
22
|
+
logger.error("Source and target must differ.");
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
requireSupabaseCli(logger);
|
|
26
|
+
ensureOutDir(outDir, logger);
|
|
27
|
+
logger.info(`Schema: ${schema}`);
|
|
28
|
+
const source = resolveDiffEndpoint(opts.sourceEnv, logger, cwd);
|
|
29
|
+
const target = resolveDiffEndpoint(opts.targetEnv, logger, cwd);
|
|
30
|
+
const { sourceUrl, targetUrl, cleanup } = resolveSchemaUrlsForDiff({
|
|
31
|
+
source: source.kind === "env"
|
|
32
|
+
? { kind: "env", dbUrl: source.dbUrl }
|
|
33
|
+
: { kind: "file", path: source.path },
|
|
34
|
+
target: target.kind === "env"
|
|
35
|
+
? { kind: "env", dbUrl: target.dbUrl }
|
|
36
|
+
: { kind: "file", path: target.path },
|
|
37
|
+
logger,
|
|
38
|
+
});
|
|
39
|
+
try {
|
|
40
|
+
logger.info("Generating patch SQL (target → source)…");
|
|
41
|
+
runCommand("supabase", buildPatchArgs(sourceUrl, targetUrl, schema, outputFile), logger, { cwd });
|
|
42
|
+
prependHeader(outputFile, sqlFileHeader({
|
|
43
|
+
command: "patch",
|
|
44
|
+
kind: "patch",
|
|
45
|
+
env: opts.sourceEnv,
|
|
46
|
+
otherEnv: opts.targetEnv,
|
|
47
|
+
schema,
|
|
48
|
+
generatedAt,
|
|
49
|
+
}));
|
|
50
|
+
}
|
|
51
|
+
finally {
|
|
52
|
+
cleanup();
|
|
53
|
+
}
|
|
54
|
+
const bytes = fileBytes(outputFile);
|
|
55
|
+
logger.info(`Wrote ${outputFile} (${bytes} bytes)`);
|
|
56
|
+
logger.info(`Apply when ready: blt db run ${outputFile}`);
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=patch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"patch.js","sourceRoot":"","sources":["../../../src/commands/db/patch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../../src/commands/db/run.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAG5C,OAAO,EAAc,KAAK,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE3E,wBAAsB,KAAK,CAC1B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,aAAa,EACtB,MAAM,EAAE,MAAM,GACZ,OAAO,CAAC,IAAI,CAAC,CAcf"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
import { runSqlFile } from "../../lib/database-runner";
|
|
4
|
+
export async function dbRun(filePath, options, logger) {
|
|
5
|
+
const resolved = resolve(filePath);
|
|
6
|
+
if (!existsSync(resolved)) {
|
|
7
|
+
logger.error(`SQL file not found: ${resolved}`);
|
|
8
|
+
process.exit(1);
|
|
9
|
+
}
|
|
10
|
+
try {
|
|
11
|
+
await runSqlFile(resolved, undefined, options);
|
|
12
|
+
}
|
|
13
|
+
catch (error) {
|
|
14
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
15
|
+
logger.error(`Failed to run SQL file: ${message}`);
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=run.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../../src/commands/db/run.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAsB,MAAM,2BAA2B,CAAC;AAE3E,MAAM,CAAC,KAAK,UAAU,KAAK,CAC1B,QAAgB,EAChB,OAAsB,EACtB,MAAc;IAEd,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IACnC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC3B,MAAM,CAAC,KAAK,CAAC,uBAAuB,QAAQ,EAAE,CAAC,CAAC;QAChD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACjB,CAAC;IAED,IAAI,CAAC;QACJ,MAAM,UAAU,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;IAChD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,MAAM,CAAC,KAAK,CAAC,2BAA2B,OAAO,EAAE,CAAC,CAAC;QACnD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACjB,CAAC;AACF,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Logger } from "@caporal/core";
|
|
2
|
+
export type SchemaUrlPair = {
|
|
3
|
+
sourceUrl: string;
|
|
4
|
+
targetUrl: string;
|
|
5
|
+
cleanup: () => void;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Load one or two schema dump files into a temporary Postgres (Docker) so
|
|
9
|
+
* `supabase db diff` can compare them via connection URLs.
|
|
10
|
+
*/
|
|
11
|
+
export declare function resolveSchemaUrlsForDiff(opts: {
|
|
12
|
+
source: {
|
|
13
|
+
kind: "env";
|
|
14
|
+
dbUrl: string;
|
|
15
|
+
} | {
|
|
16
|
+
kind: "file";
|
|
17
|
+
path: string;
|
|
18
|
+
};
|
|
19
|
+
target: {
|
|
20
|
+
kind: "env";
|
|
21
|
+
dbUrl: string;
|
|
22
|
+
} | {
|
|
23
|
+
kind: "file";
|
|
24
|
+
path: string;
|
|
25
|
+
};
|
|
26
|
+
logger: Logger;
|
|
27
|
+
}): SchemaUrlPair;
|
|
28
|
+
//# sourceMappingURL=schema-loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-loader.d.ts","sourceRoot":"","sources":["../../../src/commands/db/schema-loader.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAK5C,MAAM,MAAM,aAAa,GAAG;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,IAAI,CAAC;CACpB,CAAC;AAgEF;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE;IAC9C,MAAM,EAAE;QAAE,IAAI,EAAE,KAAK,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACxE,MAAM,EAAE;QAAE,IAAI,EAAE,KAAK,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACxE,MAAM,EAAE,MAAM,CAAC;CACf,GAAG,aAAa,CAkFhB"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { spawnSync } from "node:child_process";
|
|
3
|
+
const PG_IMAGE = "postgres:16";
|
|
4
|
+
const PG_PASSWORD = "blt_diff_temp";
|
|
5
|
+
function dockerAvailable() {
|
|
6
|
+
const result = spawnSync("docker", ["version"], { encoding: "utf8" });
|
|
7
|
+
return !result.error && (result.status ?? 1) === 0;
|
|
8
|
+
}
|
|
9
|
+
function requireDocker(logger) {
|
|
10
|
+
if (!dockerAvailable()) {
|
|
11
|
+
logger.error("Docker is required when diffing from .sql file paths.\n" +
|
|
12
|
+
" Install Docker or pass trailz env names instead of .sql files.");
|
|
13
|
+
process.exit(1);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function runDocker(args, logger, opts = {}) {
|
|
17
|
+
const result = spawnSync("docker", args, {
|
|
18
|
+
encoding: "utf8",
|
|
19
|
+
input: opts.input,
|
|
20
|
+
maxBuffer: 64 * 1024 * 1024,
|
|
21
|
+
});
|
|
22
|
+
if (result.error) {
|
|
23
|
+
throw result.error;
|
|
24
|
+
}
|
|
25
|
+
if ((result.status ?? 1) !== 0) {
|
|
26
|
+
const detail = [result.stderr, result.stdout].filter(Boolean).join("\n").trim();
|
|
27
|
+
throw new Error(`docker ${args.join(" ")} failed${detail ? `: ${detail}` : ""}`);
|
|
28
|
+
}
|
|
29
|
+
return result.stdout ?? "";
|
|
30
|
+
}
|
|
31
|
+
function waitForPostgres(containerName, logger) {
|
|
32
|
+
for (let attempt = 0; attempt < 30; attempt++) {
|
|
33
|
+
const result = spawnSync("docker", ["exec", containerName, "pg_isready", "-U", "postgres"], { encoding: "utf8" });
|
|
34
|
+
if ((result.status ?? 1) === 0) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
spawnSync("sleep", ["1"]);
|
|
38
|
+
}
|
|
39
|
+
logger.error("Timed out waiting for temporary Postgres container.");
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
function parsePublishedPort(dockerPortOutput) {
|
|
43
|
+
const match = dockerPortOutput.trim().match(/:(\d+)$/);
|
|
44
|
+
if (!match) {
|
|
45
|
+
throw new Error(`Could not parse docker port mapping: ${dockerPortOutput}`);
|
|
46
|
+
}
|
|
47
|
+
return Number(match[1]);
|
|
48
|
+
}
|
|
49
|
+
function dbUrl(hostPort, database) {
|
|
50
|
+
return `postgresql://postgres:${PG_PASSWORD}@127.0.0.1:${hostPort}/${database}`;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Load one or two schema dump files into a temporary Postgres (Docker) so
|
|
54
|
+
* `supabase db diff` can compare them via connection URLs.
|
|
55
|
+
*/
|
|
56
|
+
export function resolveSchemaUrlsForDiff(opts) {
|
|
57
|
+
if (opts.source.kind === "env" && opts.target.kind === "env") {
|
|
58
|
+
return {
|
|
59
|
+
sourceUrl: opts.source.dbUrl,
|
|
60
|
+
targetUrl: opts.target.dbUrl,
|
|
61
|
+
cleanup: () => { },
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
requireDocker(opts.logger);
|
|
65
|
+
const containerName = `blt-db-diff-${process.pid}`;
|
|
66
|
+
let stopped = false;
|
|
67
|
+
const cleanup = () => {
|
|
68
|
+
if (stopped)
|
|
69
|
+
return;
|
|
70
|
+
stopped = true;
|
|
71
|
+
spawnSync("docker", ["rm", "-f", containerName], { encoding: "utf8" });
|
|
72
|
+
};
|
|
73
|
+
try {
|
|
74
|
+
opts.logger.info("Starting temporary Postgres container for .sql schema diff…");
|
|
75
|
+
runDocker([
|
|
76
|
+
"run",
|
|
77
|
+
"-d",
|
|
78
|
+
"--rm",
|
|
79
|
+
"--name",
|
|
80
|
+
containerName,
|
|
81
|
+
"-e",
|
|
82
|
+
`POSTGRES_PASSWORD=${PG_PASSWORD}`,
|
|
83
|
+
"-p",
|
|
84
|
+
"127.0.0.1::5432",
|
|
85
|
+
PG_IMAGE,
|
|
86
|
+
], opts.logger);
|
|
87
|
+
const portOutput = runDocker(["port", containerName, "5432"], opts.logger);
|
|
88
|
+
const hostPort = parsePublishedPort(portOutput);
|
|
89
|
+
waitForPostgres(containerName, opts.logger);
|
|
90
|
+
const ensureLoaded = (database, sqlPath, label) => {
|
|
91
|
+
opts.logger.info(`Loading ${label} schema from ${sqlPath}…`);
|
|
92
|
+
runDocker(["exec", containerName, "createdb", "-U", "postgres", database], opts.logger);
|
|
93
|
+
const sql = readFileSync(sqlPath, "utf8");
|
|
94
|
+
runDocker([
|
|
95
|
+
"exec",
|
|
96
|
+
"-i",
|
|
97
|
+
containerName,
|
|
98
|
+
"psql",
|
|
99
|
+
"-U",
|
|
100
|
+
"postgres",
|
|
101
|
+
"-d",
|
|
102
|
+
database,
|
|
103
|
+
"-v",
|
|
104
|
+
"ON_ERROR_STOP=1",
|
|
105
|
+
], opts.logger, { input: sql });
|
|
106
|
+
return dbUrl(hostPort, database);
|
|
107
|
+
};
|
|
108
|
+
const sourceUrl = opts.source.kind === "env"
|
|
109
|
+
? opts.source.dbUrl
|
|
110
|
+
: ensureLoaded("blt_source", opts.source.path, "source");
|
|
111
|
+
const targetUrl = opts.target.kind === "env"
|
|
112
|
+
? opts.target.dbUrl
|
|
113
|
+
: ensureLoaded("blt_target", opts.target.path, "target");
|
|
114
|
+
return { sourceUrl, targetUrl, cleanup };
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
cleanup();
|
|
118
|
+
throw error;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=schema-loader.js.map
|