@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.
Files changed (56) hide show
  1. package/README.md +94 -6
  2. package/dist/blt +2 -0
  3. package/dist/blt.d.ts.map +1 -1
  4. package/dist/blt.js.map +1 -1
  5. package/dist/commands/db/diff-endpoint.d.ts +16 -0
  6. package/dist/commands/db/diff-endpoint.d.ts.map +1 -0
  7. package/dist/commands/db/diff-endpoint.js +39 -0
  8. package/dist/commands/db/diff-endpoint.js.map +1 -0
  9. package/dist/commands/db/dump.d.ts +23 -0
  10. package/dist/commands/db/dump.d.ts.map +1 -0
  11. package/dist/commands/db/dump.js +49 -0
  12. package/dist/commands/db/dump.js.map +1 -0
  13. package/dist/commands/db/env-url.d.ts +4 -0
  14. package/dist/commands/db/env-url.d.ts.map +1 -0
  15. package/dist/commands/db/env-url.js +34 -0
  16. package/dist/commands/db/env-url.js.map +1 -0
  17. package/dist/commands/db/patch.d.ts +14 -0
  18. package/dist/commands/db/patch.d.ts.map +1 -0
  19. package/dist/commands/db/patch.js +58 -0
  20. package/dist/commands/db/patch.js.map +1 -0
  21. package/dist/commands/db/run.d.ts +4 -0
  22. package/dist/commands/db/run.d.ts.map +1 -0
  23. package/dist/commands/db/run.js +19 -0
  24. package/dist/commands/db/run.js.map +1 -0
  25. package/dist/commands/db/schema-loader.d.ts +28 -0
  26. package/dist/commands/db/schema-loader.d.ts.map +1 -0
  27. package/dist/commands/db/schema-loader.js +121 -0
  28. package/dist/commands/db/schema-loader.js.map +1 -0
  29. package/dist/commands/db/sql.d.ts +10 -0
  30. package/dist/commands/db/sql.d.ts.map +1 -0
  31. package/dist/commands/db/sql.js +152 -0
  32. package/dist/commands/db/sql.js.map +1 -0
  33. package/dist/commands/db/supabase-schema.d.ts +38 -0
  34. package/dist/commands/db/supabase-schema.d.ts.map +1 -0
  35. package/dist/commands/db/supabase-schema.js +132 -0
  36. package/dist/commands/db/supabase-schema.js.map +1 -0
  37. package/dist/commands/db.d.ts +3 -0
  38. package/dist/commands/db.d.ts.map +1 -0
  39. package/dist/commands/db.js +116 -0
  40. package/dist/commands/db.js.map +1 -0
  41. package/dist/commands/init/script.d.ts +37 -1
  42. package/dist/commands/init/script.d.ts.map +1 -1
  43. package/dist/commands/init/script.js +142 -78
  44. package/dist/commands/init/script.js.map +1 -1
  45. package/dist/commands/init.d.ts.map +1 -1
  46. package/dist/commands/init.js +13 -8
  47. package/dist/commands/init.js.map +1 -1
  48. package/dist/commands/show/repo.js +3 -3
  49. package/dist/commands/show/repo.js.map +1 -1
  50. package/dist/lib/repositories.d.ts +21 -5
  51. package/dist/lib/repositories.d.ts.map +1 -1
  52. package/dist/lib/repositories.js +98 -80
  53. package/dist/lib/repositories.js.map +1 -1
  54. package/dist/lib/repositories.manifest.json +54 -0
  55. package/package.json +12 -7
  56. 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 clone or pull all BLT repositories.
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 init
541
- blt init -w -c
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: ./getblt.sh)
631
+ - `-o, --output <path>` — Output path for the script (default: `./getblt.sh`)
548
632
  - `-s, --ssh` — Use SSH URLs instead of HTTPS
549
- - `-w, --workspace` — Also generate blt.code-workspace with folder entries
550
- - `-c, --connections` — Add sqltools.connections from .env (requires -w)
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":";AA4BA,wBAAgB,iBAAiB,IAAI,MAAM,CAG1C"}
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,4 @@
1
+ import type { Logger } from "@caporal/core";
2
+ import { type RunSqlOptions } from "../../lib/database-runner";
3
+ export declare function dbRun(filePath: string, options: RunSqlOptions, logger: Logger): Promise<void>;
4
+ //# sourceMappingURL=run.d.ts.map
@@ -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