Folds the union of DDL effects from `scripts/add-user-profile-columns.js`
(#8) and `scripts/add-user-profile-fields.js` (#9) into the migration
history so a brand-new Neon branch reaches structural parity with prod.
Captures:
- 16 ALTER TABLE users ADD COLUMN IF NOT EXISTS (first_name, last_name,
username UNIQUE, profile_image_url, bio, avatar_url, favorite_games,
collection_visibility, preferred_currency, cards_per_page, default_view,
notifications_email, notifications_marketing, two_factor_enabled, theme,
language). Per Finding 2, BOTH profile_image_url and avatar_url are kept
(cleanup deferred to queued unify-user-avatar-column).
- 2 CREATE TABLE IF NOT EXISTS (user_settings, user_avatars) — FK to users
with ON DELETE CASCADE; user_settings has UNIQUE(user_id, setting_key).
- 6 CREATE INDEX IF NOT EXISTS (idx_users_username, idx_users_email,
idx_user_settings_user_id, idx_user_settings_key, idx_user_avatars_user_id,
idx_user_avatars_active).
- 6 CHECK constraints wrapped in DO $$ EXCEPTION WHEN duplicate_object
blocks (Postgres pre-15 has no ADD CONSTRAINT IF NOT EXISTS for CHECK):
check_collection_visibility, check_preferred_currency, check_cards_per_page,
check_default_view, check_theme, check_language.
Defaults-backfill DML from the historical script is intentionally NOT
replicated; column DEFAULTs handle fresh-env semantics and prod rows
already have the values from the historical run.
down() is a hard stub (rolling back would drop columns runtime code reads).
Convoy: reconcile-historical-add-scripts (Brief 5/7).
Co-authored-by: Cursor <cursoragent@cursor.com>