/** * Reconcile cards columns missed by initial-schema backfill (B1 of * reconcile-historical-add-scripts convoy). * * Folds the effects of `scripts/add-card-columns.js` into the migration * history. That historical script ran against every long-lived environment * pre-migration-tool and added two columns to the `cards` table that the * initial-schema backfill (`1779853647564_initial-schema.js`) did NOT * capture in its bootstrap `CREATE TABLE cards`: * * - cards.quantity INTEGER DEFAULT 0 * - cards.favorited BOOLEAN DEFAULT false * * Both columns are flagged as "Unused" in docs/SCHEMA_MAP.md § "Known * schema smells" #3 (the live quantity/favorited semantics live on * `user_cards` and `user_favorites`). They are reproduced here verbatim * so a brand-new Neon branch onboarded by `npm run setup-db` ends up * structurally equivalent to prod. The follow-up `drop-dead-cards-columns` * convoy will retire these columns once a query-trace audit confirms zero * readers — see .convoys/reconcile-historical-add-scripts.md § Follow-ups. * * Idempotency (D2): every statement uses `ADD COLUMN IF NOT EXISTS`, so * this migration is safe to run against: * * (a) A fresh Neon branch where initial-schema just ran → columns do * not exist → ALTER adds them. * (b) A long-lived env where `scripts/add-card-columns.js` ran * pre-migration-tool → columns already exist → ALTER is a no-op * (only the `pgmigrations` row insert is recorded). * (c) Re-application of this migration → ALTER is a no-op as in (b). * * Note on overlap with sibling migrations on the `cards` table: * - `1781440700404_add-scryfall-bulk-columns.js` (PR #32, post-architect * plan) adds 13 unrelated Scryfall bulk-data columns to `cards` * (oracle_id, illustration_id, color_identity, keywords, legalities, * flavor_text, artist, released_at, layout, edhrec_rank, reserved, * reprint, finishes). Verified to not include quantity/favorited; * no scope reduction required. * - `add-updated-at-column.js` (script #7 in the convoy inventory) is * already fully captured by initial-schema's `updated_at` column on * `cards` (line 67), so it is intentionally NOT folded here. * * Down-migration is a hard stub. These are reconciliation migrations: the * prod schema state is the source of truth, and rolling back would create * fresh-vs-prod inconsistency. If the columns ever need to be dropped, the * follow-up `drop-dead-cards-columns` convoy will write a new dated * migration with its own real `down()` — do NOT remove this stub. * * @type {import('node-pg-migrate').ColumnDefinitions | undefined} */ export const shorthands = undefined; /** * @param {import('node-pg-migrate').MigrationBuilder} pgm * @returns {void} */ export const up = (pgm) => { pgm.sql(` ALTER TABLE cards ADD COLUMN IF NOT EXISTS quantity INTEGER DEFAULT 0 `); pgm.sql(` ALTER TABLE cards ADD COLUMN IF NOT EXISTS favorited BOOLEAN DEFAULT false `); }; /** * Down-migration is a hard stub. See top-of-file docstring for rationale. * * @returns {void} */ export const down = () => { throw new Error( '[migration:1781000000001_reconcile-cards-columns] Refusing to drop reconciled cards columns. ' + 'This migration folds historical scripts/add-card-columns.js into the migration history; ' + 'rolling it back would create fresh-vs-prod schema inconsistency. If cards.quantity / ' + 'cards.favorited need to be retired, ship a new dated migration via the queued ' + '`drop-dead-cards-columns` convoy (see .convoys/reconcile-historical-add-scripts.md § Follow-ups).' ); };