/** * Add Scryfall bulk-data columns to `cards` for richer MTG metadata. * These enable Tagger tag joins (oracle_id, illustration_id), Commander * deck validation (color_identity), format legality checks, keyword * search, and better card detail pages. */ export const shorthands = undefined; export const up = (pgm) => { pgm.addColumns('cards', { oracle_id: { type: 'varchar(36)', comment: 'Stable across printings; joins oracle tags' }, illustration_id: { type: 'varchar(36)', comment: 'Stable per artwork; joins art tags' }, color_identity: { type: 'jsonb', comment: '["W","U","B","R","G"] — includes symbols in rules text' }, keywords: { type: 'jsonb', comment: '["Flying","Trample",...] — searchable mechanics' }, legalities: { type: 'jsonb', comment: '{standard:"legal", modern:"not_legal",...}' }, flavor_text: { type: 'text' }, artist: { type: 'varchar(255)' }, released_at: { type: 'date' }, layout: { type: 'varchar(50)', comment: 'normal, transform, split, mdfc, adventure, etc.' }, edhrec_rank: { type: 'integer', comment: 'Commander popularity — lower is more popular' }, reserved: { type: 'boolean', default: false }, reprint: { type: 'boolean', default: false }, finishes: { type: 'jsonb', comment: '["nonfoil","foil","etched"]' }, }); pgm.createIndex('cards', 'oracle_id'); pgm.createIndex('cards', 'illustration_id'); pgm.createIndex('cards', 'color_identity', { method: 'gin' }); pgm.createIndex('cards', 'keywords', { method: 'gin' }); pgm.createIndex('cards', 'legalities', { method: 'gin' }); pgm.createIndex('cards', 'artist'); pgm.createIndex('cards', 'edhrec_rank'); }; export const down = (pgm) => { pgm.dropColumns('cards', [ 'oracle_id', 'illustration_id', 'color_identity', 'keywords', 'legalities', 'flavor_text', 'artist', 'released_at', 'layout', 'edhrec_rank', 'reserved', 'reprint', 'finishes', ]); };