@codemarc/blt 1.6.5 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/README.md +192 -0
  2. package/dist/blt +4 -0
  3. package/dist/blt.d.ts.map +1 -1
  4. package/dist/blt.js.map +1 -1
  5. package/dist/commands/data/apply.d.ts +6 -0
  6. package/dist/commands/data/apply.d.ts.map +1 -0
  7. package/dist/commands/data/apply.js +363 -0
  8. package/dist/commands/data/apply.js.map +1 -0
  9. package/dist/commands/data/helpers.d.ts +15 -0
  10. package/dist/commands/data/helpers.d.ts.map +1 -0
  11. package/dist/commands/data/helpers.js +53 -0
  12. package/dist/commands/data/helpers.js.map +1 -0
  13. package/dist/commands/data/pull.d.ts +11 -0
  14. package/dist/commands/data/pull.d.ts.map +1 -0
  15. package/dist/commands/data/pull.js +101 -0
  16. package/dist/commands/data/pull.js.map +1 -0
  17. package/dist/commands/data/remove.d.ts +7 -0
  18. package/dist/commands/data/remove.d.ts.map +1 -0
  19. package/dist/commands/data/remove.js +29 -0
  20. package/dist/commands/data/remove.js.map +1 -0
  21. package/dist/commands/data.d.ts +3 -0
  22. package/dist/commands/data.d.ts.map +1 -0
  23. package/dist/commands/data.js +115 -0
  24. package/dist/commands/data.js.map +1 -0
  25. package/dist/commands/spin/dns.d.ts +7 -0
  26. package/dist/commands/spin/dns.d.ts.map +1 -0
  27. package/dist/commands/spin/dns.js +42 -0
  28. package/dist/commands/spin/dns.js.map +1 -0
  29. package/dist/commands/spin/down.d.ts +3 -0
  30. package/dist/commands/spin/down.d.ts.map +1 -0
  31. package/dist/commands/spin/down.js +17 -0
  32. package/dist/commands/spin/down.js.map +1 -0
  33. package/dist/commands/spin/helpers.d.ts +7 -0
  34. package/dist/commands/spin/helpers.d.ts.map +1 -0
  35. package/dist/commands/spin/helpers.js +38 -0
  36. package/dist/commands/spin/helpers.js.map +1 -0
  37. package/dist/commands/spin/list.d.ts +3 -0
  38. package/dist/commands/spin/list.d.ts.map +1 -0
  39. package/dist/commands/spin/list.js +20 -0
  40. package/dist/commands/spin/list.js.map +1 -0
  41. package/dist/commands/spin/setup.d.ts +3 -0
  42. package/dist/commands/spin/setup.d.ts.map +1 -0
  43. package/dist/commands/spin/setup.js +32 -0
  44. package/dist/commands/spin/setup.js.map +1 -0
  45. package/dist/commands/spin/ssh.d.ts +3 -0
  46. package/dist/commands/spin/ssh.d.ts.map +1 -0
  47. package/dist/commands/spin/ssh.js +14 -0
  48. package/dist/commands/spin/ssh.js.map +1 -0
  49. package/dist/commands/spin/status.d.ts +3 -0
  50. package/dist/commands/spin/status.d.ts.map +1 -0
  51. package/dist/commands/spin/status.js +21 -0
  52. package/dist/commands/spin/status.js.map +1 -0
  53. package/dist/commands/spin/up.d.ts +11 -0
  54. package/dist/commands/spin/up.d.ts.map +1 -0
  55. package/dist/commands/spin/up.js +34 -0
  56. package/dist/commands/spin/up.js.map +1 -0
  57. package/dist/commands/spin.d.ts +3 -0
  58. package/dist/commands/spin.d.ts.map +1 -0
  59. package/dist/commands/spin.js +166 -0
  60. package/dist/commands/spin.js.map +1 -0
  61. package/dist/lib/data-pull-extra-tables.d.ts +26 -0
  62. package/dist/lib/data-pull-extra-tables.d.ts.map +1 -0
  63. package/dist/lib/data-pull-extra-tables.js +212 -0
  64. package/dist/lib/data-pull-extra-tables.js.map +1 -0
  65. package/dist/lib/data-pull-manifest.d.ts +97 -0
  66. package/dist/lib/data-pull-manifest.d.ts.map +1 -0
  67. package/dist/lib/data-pull-manifest.js +603 -0
  68. package/dist/lib/data-pull-manifest.js.map +1 -0
  69. package/dist/lib/database-runner.d.ts +28 -2
  70. package/dist/lib/database-runner.d.ts.map +1 -1
  71. package/dist/lib/database-runner.js +112 -49
  72. package/dist/lib/database-runner.js.map +1 -1
  73. package/dist/lib/digitalocean.d.ts +60 -0
  74. package/dist/lib/digitalocean.d.ts.map +1 -0
  75. package/dist/lib/digitalocean.js +108 -0
  76. package/dist/lib/digitalocean.js.map +1 -0
  77. package/dist/lib/yaml-converter.d.ts +25 -1
  78. package/dist/lib/yaml-converter.d.ts.map +1 -1
  79. package/dist/lib/yaml-converter.js +98 -15
  80. package/dist/lib/yaml-converter.js.map +1 -1
  81. package/package.json +2 -1
package/README.md CHANGED
@@ -13,11 +13,13 @@
13
13
  - **Init**: Clone repo script for BLT repositories
14
14
  - **WAI**: AI config templates (Claude + Codex: AGENTS.md, skills, rules, commands, settings, MCP, PLAN, IMPLEMENT) — bltwai.com
15
15
  - **Build**: Build schema from DDL files, build data from instance directory
16
+ - **Data**: Read-only pull of live menu graph into versioned snapshots; apply to a dev database
16
17
  - **Deploy**: Deploy schema/data from SQL files, run a single SQL file
17
18
  - **Bucket**: Supabase storage — list buckets, list/upload/download files, get URLs
18
19
  - **Workflow**: List, show, delete, reload, and deploy GitHub Actions workflows (requires `gh`)
19
20
  - **Show**: Schema info, row counts, env vars, DB version, repo list
20
21
  - **Env**: Decrypt trailz `.trailz/env/.env.<name>.bin` to `.env` via smash (`blt env get`; requires `SMASH_KEY`)
22
+ - **Spin**: Manage DigitalOcean droplets and DNS for BLT test environments
21
23
  - **Cleanup**: Remove generated SQL/instance files, clean infrequently used YAML tags
22
24
 
23
25
  ## Installation
@@ -50,6 +52,9 @@ blt template render legal/nda/mutual --data ./doc/nda/mutual-nda-blt-otter.yaml
50
52
  # Update version.json in current directory
51
53
  blt version update
52
54
 
55
+ # List DigitalOcean droplets
56
+ blt spin list
57
+
53
58
  # List Supabase storage buckets
54
59
  blt bucket names
55
60
 
@@ -71,10 +76,12 @@ blt deploy schema
71
76
  | `blt init` | Clone script for BLT repos |
72
77
  | `blt wai` | Claude Code config (claude, agents, skills, rules, commands, settings, mcp) |
73
78
  | `blt build` | Schema (DDL), data (instance) |
79
+ | `blt data` | Pull / apply instance data snapshots |
74
80
  | `blt deploy` | Schema, data, sql file |
75
81
  | `blt workflow`| list, show, delete, reload, deploy |
76
82
  | `blt bucket` | names, list, upload, download, url, clear |
77
83
  | `blt show` | schema, counts, env, db, repo |
84
+ | `blt spin` | up, down, list, status, ssh, dns, setup |
78
85
  | `blt env` | get (decrypt trailz env to `.env`) |
79
86
  | `blt cleanup` | generated, tags |
80
87
 
@@ -416,6 +423,76 @@ blt deploy sql ./migrations/001_init.sql
416
423
 
417
424
  ---
418
425
 
426
+ ## Data snapshots (`blt data`)
427
+
428
+ Export **instance-shaped** rows from Postgres into portable **JSON**, **YAML**, or **TOON** ([Token-Oriented Object Notation](https://toonformat.dev)) payloads that mirror `data/schema/instances/<instance>/yaml/`: `table:` / `procedure:` / `function:` targets plus `{ row }[]`. TOON yields smaller prompts for LLM workflows; `blt data apply` accepts `.toon` snapshots the same as JSON/YAML.
429
+
430
+ **Curated pulled assets:** `role_props`, `modules`, `settings` (one file per `kind`, e.g. `10-020-settings-02-location`), `payment_providers` (`10-020-settings-04-payment-providers`), `nodes`, `create_user` + `add_profile_role_by_email` (optional via flags), `insert_tax`, menu graph — `insert_menu`, `insert_category`, **`public.items`** as **table-mode** rows split into `10-121-items-menu` + `10-125-items-NN-<tag>` (stable `id` values for FKs such as `order_items`), and `insert_modifier_group` split into `10-135-groups-NN-<tag>`. Older snapshots may still contain a legacy `insert_item` function asset instead of `public.items`.
431
+
432
+ **Extra `public.*` tables (default):** By default, pull also discovers other `public` base tables not covered above and writes one asset per table (stems like `10-900-public-<table>`). Use **`--skip-extra-tables`** to pull only the curated manifest.
433
+
434
+ Use snapshots to seed a disposable dev DB from production-shaped data **without writes on pull**.
435
+
436
+ ### Environment variables
437
+
438
+ | Variable | Purpose |
439
+ |----------|---------|
440
+ | `BLT_DATA_PULL_URL` | **Recommended.** Read URL for `blt data pull`. Use a replica or READ ONLY role. |
441
+ | `BLT_DATA_LOAD_URL` | Optional dev target for `blt data apply`. Falls back to `SUPABASE_CONNECTION_STRING`. |
442
+
443
+ If `BLT_DATA_PULL_URL` is unset, pull falls back to `SUPABASE_CONNECTION_STRING` (still runs inside `BEGIN READ ONLY`).
444
+
445
+ **Never** aim `blt data apply` at production. Apply first runs **`TRUNCATE … RESTART IDENTITY CASCADE`** only for **snapshot targets present in that manifest** that replace whole tables: function-mode replay targets (`insert_menu` → `menus`, `insert_category` → `categories`, `insert_modifier_group` → `groups`, `insert_tax` → `taxes`) and **table-mode `public.items`** when included. That clears dependent rows (e.g. `order_items` referencing `items`). Other table/procedure assets (`settings`, `nodes`, `payment_providers`, extra `public.*` dumps, etc.) are applied with **`INSERT` … `ON CONFLICT`**, `CALL`, or `SELECT` function calls — they are **not** covered by that truncate block unless their target is in the truncate set above.
446
+
447
+ ### Pull / apply / remove flags and caveats
448
+
449
+ | Flag | Purpose |
450
+ |------|---------|
451
+ | `--skip-users` | Omit `10-070-users` and `10-071-profile-roles-extra`. Use when pulling from prod to avoid staff PII in files. |
452
+ | `--include-secrets` | Include `api_key`, `secret_key_encrypted`, `webhook_secret_encrypted` on `payment_providers` (default: secrets nulled). |
453
+ | `--skip-extra-tables` | Only pull the curated manifest; omit discovered extra `public.*` base tables. |
454
+
455
+ - **`create_user` / PINs:** Pulled rows set `p_pin: null`; PINs are not recoverable from `auth.users`. To restore deterministic dev PINs after apply, re-run `blt build data <instance>` against the same DB from canonical instance YAML, or edit snapshot rows.
456
+ - **`payment_providers`:** If the table is missing (older schema), pull writes an empty asset file.
457
+ - **Item / group file names:** Splits follow content rules (`props.category` vs first `props.tags[]`), not byte-identical parity with hand-authored multi-file YAML (e.g. pizza menu + toppings in one file).
458
+ - **`blt data remove`:** Deletes **`data-snapshots/<instance>/`** (all stamped runs) under the snapshot base. Use `-o, --out <dir>` to match your pull base (default `data-snapshots`). `--dry-run` prints the path that would be removed.
459
+
460
+ ### Commands
461
+
462
+ ```bash
463
+ # Pull (read-only) — writes ./data-snapshots/<instance>/<utc-stamp>/manifest.json + per-asset files
464
+ export BLT_DATA_PULL_URL="postgresql://readonly:...@...:5432/postgres"
465
+ cd /path/to/blt-core-data
466
+ blt data pull laf --format yaml
467
+ blt data pull laf --format toon
468
+ # Prod-safe: omit users / profile_roles junction
469
+ blt data pull prod --skip-users
470
+ # Curated manifest only (no extra public.* dumps)
471
+ blt data pull laf --skip-extra-tables
472
+
473
+ # Replay onto dev (truncates menu-graph targets from manifest, then UPSERT / CALL / SELECT — dev only)
474
+ export BLT_DATA_LOAD_URL="postgresql://...@localhost:5432/postgres"
475
+ blt data apply ./data-snapshots/laf/2026-05-12T12-30-45Z
476
+
477
+ # Inspect generated SQL without executing
478
+ blt data apply ./data-snapshots/laf/2026-05-12T12-30-45Z --dry-run
479
+
480
+ # Remove every stamped snapshot under ./data-snapshots/<instance>/
481
+ blt data remove laf
482
+ blt data remove laf --dry-run
483
+ ```
484
+
485
+ Snapshots default under `data-snapshots/` from the **current working directory**. The **`data`** git repo ignores `data-snapshots/` so accidental commits of customer data are avoided.
486
+
487
+ ### Workflow vs `blt build data`
488
+
489
+ | Path | Direction |
490
+ |------|-----------|
491
+ | `blt build data` + deploy | Git instance YAML → `dist/data.sql` → DB |
492
+ | `blt data pull` → `blt data apply` | Live DB rows → snapshot files → DB (dev replay) |
493
+
494
+ ---
495
+
419
496
  ## Init Commands
420
497
 
421
498
  ### `blt init [options]`
@@ -735,6 +812,121 @@ blt show repo --ssh
735
812
 
736
813
  ---
737
814
 
815
+ ## Spin Commands (DigitalOcean)
816
+
817
+ Manage DigitalOcean droplets and DNS records for BLT test environments. Uses the `blt spin` namespace.
818
+
819
+ **Authentication:** The token is resolved in this order:
820
+
821
+ 1. `DIGITALOCEAN_ACCESS_TOKEN` environment variable
822
+ 2. `DIGITALOCEAN_TOKEN` environment variable
823
+ 3. doctl config file (written by `doctl auth init`)
824
+
825
+ If you've already run `doctl auth init`, no extra env var setup is needed.
826
+
827
+ ### `blt spin up`
828
+
829
+ Create a new droplet. Waits for the droplet to become active and reports its IP.
830
+
831
+ ```bash
832
+ blt spin up --name test-laf --ssh-keys 12345678
833
+ blt spin up --name test-laf --size s-1vcpu-1gb --region nyc3 --image ubuntu-24-04-x64 --tag blt
834
+ ```
835
+
836
+ **Options:**
837
+
838
+ - `--name <name>` — Droplet name (required)
839
+ - `--size <size>` — Droplet size slug (default: `s-1vcpu-512mb-10gb`)
840
+ - `--region <region>` — Region slug (default: `nyc3`)
841
+ - `--image <image>` — OS image slug (default: `ubuntu-24-04-x64`)
842
+ - `--ssh-keys <keys>` — Comma-separated SSH key IDs or fingerprints
843
+ - `--tag <tag>` — Tag for the droplet (default: `blt`)
844
+
845
+ ### `blt spin down <name>`
846
+
847
+ Destroy a droplet. Prompts for confirmation unless `--force` is passed.
848
+
849
+ ```bash
850
+ blt spin down test-laf
851
+ blt spin down test-laf --force
852
+ ```
853
+
854
+ **Options:**
855
+
856
+ - `--force` — Skip confirmation prompt
857
+
858
+ ### `blt spin list`
859
+
860
+ List droplets filtered by tag.
861
+
862
+ ```bash
863
+ blt spin list
864
+ blt spin list --tag staging
865
+ ```
866
+
867
+ **Options:**
868
+
869
+ - `--tag <tag>` — Filter by tag (default: `blt`)
870
+
871
+ ### `blt spin status <name>`
872
+
873
+ Show detailed information about a droplet.
874
+
875
+ ```bash
876
+ blt spin status test-laf
877
+ blt spin status 12345678
878
+ ```
879
+
880
+ ### `blt spin ssh <name>`
881
+
882
+ SSH into a droplet. Resolves the droplet's public IP and opens an interactive SSH session.
883
+
884
+ ```bash
885
+ blt spin ssh test-laf
886
+ blt spin ssh test-laf --user root
887
+ ```
888
+
889
+ **Options:**
890
+
891
+ - `--user <user>` — SSH user (default: `blt`)
892
+
893
+ ### `blt spin dns <action>`
894
+
895
+ Manage DNS records for a domain.
896
+
897
+ ```bash
898
+ # Create an A record
899
+ blt spin dns create --domain bltcore.com --name test-laf --ip 1.2.3.4
900
+
901
+ # List all DNS records
902
+ blt spin dns list --domain bltcore.com
903
+
904
+ # Delete a record by ID
905
+ blt spin dns delete --domain bltcore.com --record-id 12345678
906
+ ```
907
+
908
+ **Options:**
909
+
910
+ - `--domain <domain>` — Domain name (default: `bltcore.com`)
911
+ - `--name <name>` — Record name / subdomain (for create)
912
+ - `--ip <ip>` — IP address for A record (for create)
913
+ - `--record-id <id>` — Record ID (for delete)
914
+
915
+ ### `blt spin setup <name>`
916
+
917
+ Bootstrap a fresh droplet by uploading and running `deploy/scripts/bootstrap-droplet.sh`. If the script doesn't exist, prints what would run.
918
+
919
+ ```bash
920
+ blt spin setup test-laf
921
+ blt spin setup test-laf --user root
922
+ ```
923
+
924
+ **Options:**
925
+
926
+ - `--user <user>` — SSH user for bootstrap (default: `root`)
927
+
928
+ ---
929
+
738
930
  ## Env Commands
739
931
 
740
932
  ### `blt env get <name>`
package/dist/blt CHANGED
@@ -13,6 +13,8 @@ import workflowCommand from "./commands/workflow";
13
13
  import waiCommand from "./commands/wai";
14
14
  import templateCommand from "./commands/template";
15
15
  import envCommand from "./commands/env";
16
+ import dataCommand from "./commands/data";
17
+ import spinCommand from "./commands/spin";
16
18
  import { join, dirname } from "node:path";
17
19
  import { readFileSync } from "node:fs";
18
20
  import { fileURLToPath } from "node:url";
@@ -39,6 +41,8 @@ workflowCommand(program);
39
41
  waiCommand(program);
40
42
  templateCommand(program);
41
43
  envCommand(program);
44
+ dataCommand(program);
45
+ spinCommand(program);
42
46
  // If no command is provided, show help
43
47
  const args = process.argv.slice(2);
44
48
  if (args.length === 0) {
package/dist/blt.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"blt.d.ts","sourceRoot":"","sources":["../src/blt.ts"],"names":[],"mappings":";AAwBA,wBAAgB,iBAAiB,IAAI,MAAM,CAG1C"}
1
+ {"version":3,"file":"blt.d.ts","sourceRoot":"","sources":["../src/blt.ts"],"names":[],"mappings":";AA0BA,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,aAAa,MAAM,mBAAmB,CAAC;AAC9C,OAAO,YAAY,MAAM,kBAAkB,CAAC;AAC5C,OAAO,aAAa,MAAM,mBAAmB,CAAC;AAC9C,OAAO,YAAY,MAAM,kBAAkB,CAAC;AAC5C,OAAO,WAAW,MAAM,iBAAiB,CAAC;AAC1C,OAAO,UAAU,MAAM,gBAAgB,CAAC;AACxC,OAAO,cAAc,MAAM,oBAAoB,CAAC;AAChD,OAAO,WAAW,MAAM,iBAAiB,CAAC;AAC1C,OAAO,cAAc,MAAM,oBAAoB,CAAC;AAChD,OAAO,eAAe,MAAM,qBAAqB,CAAC;AAClD,OAAO,UAAU,MAAM,gBAAgB,CAAC;AACxC,OAAO,eAAe,MAAM,qBAAqB,CAAC;AAClD,OAAO,UAAU,MAAM,gBAAgB,CAAC;AAExC,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,YAAY,CAAC,OAAO,CAAC,CAAC;AACtB,WAAW,CAAC,OAAO,CAAC,CAAC;AACrB,UAAU,CAAC,OAAO,CAAC,CAAC;AACpB,cAAc,CAAC,OAAO,CAAC,CAAC;AACxB,YAAY,CAAC,OAAO,CAAC,CAAC;AACtB,aAAa,CAAC,OAAO,CAAC,CAAC;AACvB,aAAa,CAAC,OAAO,CAAC,CAAC;AACvB,WAAW,CAAC,OAAO,CAAC,CAAC;AACrB,cAAc,CAAC,OAAO,CAAC,CAAC;AACxB,eAAe,CAAC,OAAO,CAAC,CAAC;AACzB,UAAU,CAAC,OAAO,CAAC,CAAC;AACpB,eAAe,CAAC,OAAO,CAAC,CAAC;AACzB,UAAU,CAAC,OAAO,CAAC,CAAC;AAEtB,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,aAAa,MAAM,mBAAmB,CAAC;AAC9C,OAAO,YAAY,MAAM,kBAAkB,CAAC;AAC5C,OAAO,aAAa,MAAM,mBAAmB,CAAC;AAC9C,OAAO,YAAY,MAAM,kBAAkB,CAAC;AAC5C,OAAO,WAAW,MAAM,iBAAiB,CAAC;AAC1C,OAAO,UAAU,MAAM,gBAAgB,CAAC;AACxC,OAAO,cAAc,MAAM,oBAAoB,CAAC;AAChD,OAAO,WAAW,MAAM,iBAAiB,CAAC;AAC1C,OAAO,cAAc,MAAM,oBAAoB,CAAC;AAChD,OAAO,eAAe,MAAM,qBAAqB,CAAC;AAClD,OAAO,UAAU,MAAM,gBAAgB,CAAC;AACxC,OAAO,eAAe,MAAM,qBAAqB,CAAC;AAClD,OAAO,UAAU,MAAM,gBAAgB,CAAC;AACxC,OAAO,WAAW,MAAM,iBAAiB,CAAC;AAC1C,OAAO,WAAW,MAAM,iBAAiB,CAAC;AAE1C,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,YAAY,CAAC,OAAO,CAAC,CAAC;AACtB,WAAW,CAAC,OAAO,CAAC,CAAC;AACrB,UAAU,CAAC,OAAO,CAAC,CAAC;AACpB,cAAc,CAAC,OAAO,CAAC,CAAC;AACxB,YAAY,CAAC,OAAO,CAAC,CAAC;AACtB,aAAa,CAAC,OAAO,CAAC,CAAC;AACvB,aAAa,CAAC,OAAO,CAAC,CAAC;AACvB,WAAW,CAAC,OAAO,CAAC,CAAC;AACrB,cAAc,CAAC,OAAO,CAAC,CAAC;AACxB,eAAe,CAAC,OAAO,CAAC,CAAC;AACzB,UAAU,CAAC,OAAO,CAAC,CAAC;AACpB,eAAe,CAAC,OAAO,CAAC,CAAC;AACzB,UAAU,CAAC,OAAO,CAAC,CAAC;AACpB,WAAW,CAAC,OAAO,CAAC,CAAC;AACrB,WAAW,CAAC,OAAO,CAAC,CAAC;AAEvB,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,6 @@
1
+ import type { Logger } from "@caporal/core";
2
+ export type DataApplyOpts = {
3
+ dryRun: boolean;
4
+ };
5
+ export declare function dataApply(snapshotDir: string, opts: DataApplyOpts, logger: Logger): Promise<void>;
6
+ //# sourceMappingURL=apply.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apply.d.ts","sourceRoot":"","sources":["../../../src/commands/data/apply.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAc5C,MAAM,MAAM,aAAa,GAAG;IAC3B,MAAM,EAAE,OAAO,CAAC;CAChB,CAAC;AAoNF,wBAAsB,SAAS,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA2NvG"}
@@ -0,0 +1,363 @@
1
+ import { readFileSync, existsSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import yaml from "js-yaml";
4
+ import { decode } from "@toon-format/toon";
5
+ import pg from "pg";
6
+ import { fetchPublicTableColumnUdts, fetchPublicTableGeneratedStoredColumnNames, fetchPublicTableIdentityAlwaysColumns } from "../../lib/data-pull-extra-tables";
7
+ import { getLoadConnectionString, runSqlContent } from "../../lib/database-runner";
8
+ import { jsonToSql, processEnvVars } from "../../lib/yaml-converter";
9
+ import { getApplyTruncateSqlForManifest, sortManifestAssetsForApply, } from "../../lib/data-pull-manifest";
10
+ function readPayload(path, logger) {
11
+ const raw = readFileSync(path, "utf8");
12
+ if (path.endsWith(".toon")) {
13
+ try {
14
+ return decode(raw);
15
+ }
16
+ catch (e) {
17
+ const msg = e instanceof Error ? e.message : String(e);
18
+ logger.error(`Failed to parse TOON: ${path} — ${msg}`);
19
+ process.exit(1);
20
+ }
21
+ }
22
+ if (path.endsWith(".yaml") || path.endsWith(".yml")) {
23
+ try {
24
+ return yaml.load(raw);
25
+ }
26
+ catch (e) {
27
+ const msg = e instanceof Error ? e.message : String(e);
28
+ logger.error(`Failed to parse YAML: ${path} — ${msg}`);
29
+ process.exit(1);
30
+ }
31
+ }
32
+ try {
33
+ return JSON.parse(raw);
34
+ }
35
+ catch (e) {
36
+ const msg = e instanceof Error ? e.message : String(e);
37
+ logger.error(`Failed to parse JSON: ${path} — ${msg}`);
38
+ process.exit(1);
39
+ }
40
+ }
41
+ function prepareRows(rows) {
42
+ return rows.map((r) => ({
43
+ row: processEnvVars(r.row),
44
+ }));
45
+ }
46
+ function resolveSqlType(payload, asset) {
47
+ return payload.sqlType ?? asset.sqlType ?? "function";
48
+ }
49
+ /** Curated assets use bare names; extra-table dumps use `public.table`. */
50
+ function publicTableFromSnapshotTarget(target) {
51
+ if (!target.startsWith("public."))
52
+ return undefined;
53
+ const rest = target.slice("public.".length);
54
+ return rest.length > 0 ? rest : undefined;
55
+ }
56
+ /** Map snapshot auth.users id → email from create_user asset (for settings FK repair). */
57
+ function loadCreateUserAuthIdToEmail(snapshotDir, manifest, logger) {
58
+ const m = new Map();
59
+ const asset = manifest.assets.find((a) => a.function === "create_user");
60
+ if (!asset)
61
+ return m;
62
+ const payload = readPayload(join(snapshotDir, asset.file), logger);
63
+ for (const pr of payload.rows || []) {
64
+ const row = processEnvVars((pr.row ?? {}));
65
+ const email = row.p_email;
66
+ const aid = row.p_authid;
67
+ if (typeof email === "string" && typeof aid === "string" && aid.length > 0) {
68
+ m.set(aid, email);
69
+ }
70
+ }
71
+ return m;
72
+ }
73
+ /**
74
+ * When target DB already had auth.users for an email, create_user reuses that row's id while
75
+ * settings rows still carry source UUIDs — replace with a subselect by email so FK holds.
76
+ */
77
+ function rewriteSettingsAuthidForApply(rows, authidToEmail) {
78
+ if (authidToEmail.size === 0)
79
+ return rows;
80
+ return rows.map(({ row }) => {
81
+ const authid = row.authid;
82
+ if (typeof authid !== "string")
83
+ return { row };
84
+ const email = authidToEmail.get(authid);
85
+ if (!email)
86
+ return { row };
87
+ return {
88
+ row: {
89
+ ...row,
90
+ authid: { __blt_auth_users_id_by_email: email },
91
+ },
92
+ };
93
+ });
94
+ }
95
+ /**
96
+ * `audit.changed_by` FK targets `users` (typically `auth.users` ids). Same cross-env issue as
97
+ * `settings.authid`: emit `(SELECT id FROM auth.users WHERE email = …)` when the snapshot has a
98
+ * matching `create_user` row; otherwise NULL so apply does not reference missing users.
99
+ */
100
+ function rewriteAuditChangedByForApply(rows, authidToEmail) {
101
+ return rows.map(({ row }) => {
102
+ const changedBy = row.changed_by;
103
+ if (changedBy === null || changedBy === undefined)
104
+ return { row };
105
+ if (typeof changedBy !== "string")
106
+ return { row };
107
+ const email = authidToEmail.get(changedBy);
108
+ if (email) {
109
+ return {
110
+ row: {
111
+ ...row,
112
+ changed_by: { __blt_auth_users_id_by_email: email },
113
+ },
114
+ };
115
+ }
116
+ return { row: { ...row, changed_by: null } };
117
+ });
118
+ }
119
+ /**
120
+ * `pins.authid` FK to `users` (same ids as `auth.users`). Remap like `audit.changed_by`: subselect
121
+ * by email when we have a `create_user` row; otherwise NULL so apply does not reference missing users.
122
+ */
123
+ function rewritePinsAuthidForApply(rows, authidToEmail) {
124
+ return rows.map(({ row }) => {
125
+ const authid = row.authid;
126
+ if (authid === null || authid === undefined)
127
+ return { row };
128
+ if (typeof authid !== "string")
129
+ return { row };
130
+ const email = authidToEmail.get(authid);
131
+ if (email) {
132
+ return {
133
+ row: {
134
+ ...row,
135
+ authid: { __blt_auth_users_id_by_email: email },
136
+ },
137
+ };
138
+ }
139
+ return { row: { ...row, authid: null } };
140
+ });
141
+ }
142
+ /** True when the nodes snapshot carries source UUIDs (required for `devices.node_id` FK). */
143
+ function checkNodesSnapshotHasStableIds(snapshotDir, manifest, logger) {
144
+ const asset = manifest.assets.find((a) => a.function === "nodes");
145
+ if (!asset)
146
+ return false;
147
+ const filePath = join(snapshotDir, asset.file);
148
+ if (!existsSync(filePath))
149
+ return false;
150
+ const payload = readPayload(filePath, logger);
151
+ const first = payload.rows?.[0]?.row;
152
+ const id = first?.id;
153
+ return typeof id === "string" && id.length > 0;
154
+ }
155
+ /** Legacy pulls omitted `nodes.id`, so target inserts get new UUIDs while `devices` still hold source ids. */
156
+ function nullDevicesNodeIdWhenNodesLackIds(rows) {
157
+ return rows.map(({ row }) => {
158
+ if (!Object.prototype.hasOwnProperty.call(row, "node_id"))
159
+ return { row };
160
+ return { row: { ...row, node_id: null } };
161
+ });
162
+ }
163
+ /** Snapshot row set includes any column that is GENERATED ALWAYS AS IDENTITY on the target. */
164
+ function preparedTouchesIdentityAlwaysColumns(prepared, identityAlways) {
165
+ if (identityAlways.length === 0)
166
+ return false;
167
+ const idSet = new Set(identityAlways);
168
+ for (const pr of prepared) {
169
+ for (const k of Object.keys(pr.row)) {
170
+ if (idSet.has(k))
171
+ return true;
172
+ }
173
+ }
174
+ return false;
175
+ }
176
+ /** Remove stored-generated columns from rows — Postgres rejects explicit values for them on INSERT/UPSERT. */
177
+ function stripGeneratedStoredColumnsFromPrepared(prepared, generatedCols) {
178
+ if (generatedCols.length === 0)
179
+ return prepared;
180
+ const drop = new Set(generatedCols);
181
+ return prepared.map(({ row }) => {
182
+ const next = { ...row };
183
+ for (const c of drop)
184
+ delete next[c];
185
+ return { row: next };
186
+ });
187
+ }
188
+ export async function dataApply(snapshotDir, opts, logger) {
189
+ const mf = join(snapshotDir, "manifest.json");
190
+ if (!existsSync(mf)) {
191
+ logger.error(`manifest.json not found under: ${snapshotDir}`);
192
+ process.exit(1);
193
+ }
194
+ let manifest;
195
+ try {
196
+ manifest = JSON.parse(readFileSync(mf, "utf8"));
197
+ }
198
+ catch (e) {
199
+ logger.error(`Invalid manifest.json: ${e instanceof Error ? e.message : String(e)}`);
200
+ process.exit(1);
201
+ }
202
+ const sqlParts = [
203
+ `-- BLT snapshot apply — instance ${manifest.instance} pulled ${manifest.pulledAt}`,
204
+ `SET search_path = public, auth, extensions;`,
205
+ ``,
206
+ ];
207
+ const orderedAssets = sortManifestAssetsForApply(manifest.assets);
208
+ const authidToEmail = loadCreateUserAuthIdToEmail(snapshotDir, manifest, logger);
209
+ const nodesSnapshotHasStableIds = checkNodesSnapshotHasStableIds(snapshotDir, manifest, logger);
210
+ if (!nodesSnapshotHasStableIds &&
211
+ orderedAssets.some((a) => a.function === "public.devices")) {
212
+ logger.warn("Snapshot `nodes` has no `id` column (legacy pull). Clearing `public.devices.node_id` for apply; re-pull with current CLI to keep device→node links.");
213
+ }
214
+ const truncateSql = getApplyTruncateSqlForManifest(orderedAssets);
215
+ if (truncateSql)
216
+ sqlParts.push(truncateSql);
217
+ const url = opts.dryRun ? "" : getLoadConnectionString();
218
+ let metaClient = null;
219
+ const udtCache = new Map();
220
+ const identityAlwaysCache = new Map();
221
+ const generatedStoredCache = new Map();
222
+ if (!opts.dryRun) {
223
+ metaClient = new pg.Client({ connectionString: url });
224
+ await metaClient.connect();
225
+ }
226
+ try {
227
+ for (const asset of orderedAssets) {
228
+ const filePath = join(snapshotDir, asset.file);
229
+ if (!existsSync(filePath)) {
230
+ logger.error(`Missing asset file referenced in manifest: ${filePath}`);
231
+ process.exit(1);
232
+ }
233
+ const payload = readPayload(filePath, logger);
234
+ if (payload.function !== asset.function) {
235
+ logger.error(`Target mismatch for ${asset.id}: manifest=${asset.function} file=${payload.function}`);
236
+ process.exit(1);
237
+ }
238
+ let prepared = prepareRows(payload.rows || []);
239
+ if (asset.function === "settings" && authidToEmail.size > 0) {
240
+ prepared = rewriteSettingsAuthidForApply(prepared, authidToEmail);
241
+ }
242
+ if (asset.function === "public.audit") {
243
+ prepared = rewriteAuditChangedByForApply(prepared, authidToEmail);
244
+ }
245
+ if (asset.function === "public.pins") {
246
+ prepared = rewritePinsAuthidForApply(prepared, authidToEmail);
247
+ }
248
+ if (asset.function === "public.devices" && !nodesSnapshotHasStableIds) {
249
+ prepared = nullDevicesNodeIdWhenNodesLackIds(prepared);
250
+ }
251
+ if (prepared.length === 0) {
252
+ sqlParts.push(`-- skip ${asset.id} (no rows)`);
253
+ continue;
254
+ }
255
+ const sqlType = resolveSqlType(payload, asset);
256
+ let columnUdts = payload.columnUdts && Object.keys(payload.columnUdts).length > 0
257
+ ? payload.columnUdts
258
+ : undefined;
259
+ if (sqlType === "table" &&
260
+ metaClient &&
261
+ (!columnUdts || Object.keys(columnUdts).length === 0)) {
262
+ const pubTable = publicTableFromSnapshotTarget(payload.function);
263
+ if (pubTable) {
264
+ if (!udtCache.has(pubTable)) {
265
+ udtCache.set(pubTable, await fetchPublicTableColumnUdts(metaClient, pubTable));
266
+ }
267
+ columnUdts = udtCache.get(pubTable);
268
+ }
269
+ }
270
+ const pubTable = sqlType === "table" ? publicTableFromSnapshotTarget(payload.function) : undefined;
271
+ if (metaClient && pubTable) {
272
+ if (!identityAlwaysCache.has(pubTable)) {
273
+ identityAlwaysCache.set(pubTable, await fetchPublicTableIdentityAlwaysColumns(metaClient, pubTable));
274
+ }
275
+ if (!generatedStoredCache.has(pubTable)) {
276
+ generatedStoredCache.set(pubTable, await fetchPublicTableGeneratedStoredColumnNames(metaClient, pubTable));
277
+ }
278
+ }
279
+ const identityAlwaysCols = pubTable ? (identityAlwaysCache.get(pubTable) ?? []) : [];
280
+ const generatedStoredCols = pubTable ? (generatedStoredCache.get(pubTable) ?? []) : [];
281
+ if (generatedStoredCols.length > 0) {
282
+ prepared = stripGeneratedStoredColumnsFromPrepared(prepared, generatedStoredCols);
283
+ }
284
+ const isPaymentProviders = payload.function === "payment_providers";
285
+ /** Older node snapshots upserted on `id` but DBs often have `UNIQUE (node_code)` — 23505 when codes collide. */
286
+ const nodesLegacyUpsert = payload.function === "nodes" &&
287
+ sqlType === "table" &&
288
+ (!payload.primaryKey?.length ||
289
+ (payload.primaryKey.length === 1 && payload.primaryKey[0] === "id"));
290
+ const excludeFromConflictUpdateMerged = [
291
+ ...(payload.conflictUpdateExclude ?? []),
292
+ ...(isPaymentProviders ? ["id"] : []),
293
+ ...(nodesLegacyUpsert && !(payload.conflictUpdateExclude ?? []).includes("id") ? ["id"] : []),
294
+ ...identityAlwaysCols,
295
+ ...generatedStoredCols,
296
+ ];
297
+ const excludeForUpsert = excludeFromConflictUpdateMerged.length > 0 ? excludeFromConflictUpdateMerged : undefined;
298
+ let fragment;
299
+ if (payload.function === "payment_providers" && !payload.conflictWhere) {
300
+ const globalRows = prepared.filter((r) => r.row.location_id === null || r.row.location_id === undefined);
301
+ const scopedRows = prepared.filter((r) => r.row.location_id !== null && r.row.location_id !== undefined);
302
+ const chunks = [];
303
+ if (globalRows.length > 0) {
304
+ chunks.push(jsonToSql(globalRows, "payment_providers", sqlType, {
305
+ conflictColumns: ["provider_type"],
306
+ conflictWhere: "location_id IS NULL",
307
+ excludeFromConflictUpdate: excludeForUpsert,
308
+ columnUdts,
309
+ overridingSystemValue: preparedTouchesIdentityAlwaysColumns(globalRows, identityAlwaysCols),
310
+ }));
311
+ }
312
+ if (scopedRows.length > 0) {
313
+ chunks.push(jsonToSql(scopedRows, "payment_providers", sqlType, {
314
+ conflictColumns: ["id"],
315
+ excludeFromConflictUpdate: excludeForUpsert,
316
+ columnUdts,
317
+ overridingSystemValue: preparedTouchesIdentityAlwaysColumns(scopedRows, identityAlwaysCols),
318
+ }));
319
+ }
320
+ fragment = chunks.join("\n\n");
321
+ }
322
+ else {
323
+ fragment = jsonToSql(prepared, payload.function, sqlType, {
324
+ conflictColumns: nodesLegacyUpsert
325
+ ? ["node_code"]
326
+ : (payload.primaryKey ?? (isPaymentProviders ? ["provider_type"] : undefined)),
327
+ excludeFromConflictUpdate: excludeForUpsert,
328
+ conflictWhere: payload.conflictWhere,
329
+ columnUdts,
330
+ overridingSystemValue: preparedTouchesIdentityAlwaysColumns(prepared, identityAlwaysCols),
331
+ });
332
+ }
333
+ sqlParts.push(`-- ${payload.assetId} (${prepared.length} rows, ${sqlType})`);
334
+ sqlParts.push(fragment);
335
+ if (asset.function === "public.audit" && sqlType === "table") {
336
+ sqlParts.push([
337
+ "-- Resync audit.id sequence after bulk restore (triggers use nextval; without this, duplicate audit_pkey)",
338
+ "SELECT setval(",
339
+ " pg_get_serial_sequence('public.audit', 'id'),",
340
+ " COALESCE((SELECT MAX(id) FROM public.audit), 1)",
341
+ ");",
342
+ ].join("\n"));
343
+ }
344
+ sqlParts.push(``);
345
+ }
346
+ }
347
+ finally {
348
+ if (metaClient) {
349
+ await metaClient.end();
350
+ }
351
+ }
352
+ const bundled = sqlParts.join("\n");
353
+ if (opts.dryRun) {
354
+ console.log(bundled);
355
+ return;
356
+ }
357
+ await runSqlContent(bundled, {
358
+ name: `snapshot:${manifest.instance}`,
359
+ path: snapshotDir,
360
+ version: "unknown",
361
+ }, url);
362
+ }
363
+ //# sourceMappingURL=apply.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apply.js","sourceRoot":"","sources":["../../../src/commands/data/apply.ts"],"names":[],"mappings":"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"}