// Phase 5 — live features: message edits/deletes, reactions, read state. /** @param {import('node-pg-migrate').MigrationBuilder} pgm */ exports.up = (pgm) => { pgm.addColumns('messages', { edited_at: { type: 'timestamptz' }, deleted_at: { type: 'timestamptz' }, }); pgm.createTable('reactions', { message_id: { type: 'uuid', notNull: true, references: 'messages', onDelete: 'CASCADE' }, user_id: { type: 'uuid', notNull: true, references: 'users', onDelete: 'CASCADE' }, emoji: { type: 'text', notNull: true }, created_at: { type: 'timestamptz', notNull: true, default: pgm.func('now()') }, }); pgm.addConstraint('reactions', 'reactions_pkey', { primaryKey: ['message_id', 'user_id', 'emoji'], }); pgm.createIndex('reactions', 'message_id'); pgm.createTable('read_state', { conversation_id: { type: 'uuid', notNull: true, references: 'conversations', onDelete: 'CASCADE', }, user_id: { type: 'uuid', notNull: true, references: 'users', onDelete: 'CASCADE' }, last_read_seq: { type: 'bigint', notNull: true, default: 0 }, updated_at: { type: 'timestamptz', notNull: true, default: pgm.func('now()') }, }); pgm.addConstraint('read_state', 'read_state_pkey', { primaryKey: ['conversation_id', 'user_id'], }); }; /** @param {import('node-pg-migrate').MigrationBuilder} pgm */ exports.down = (pgm) => { pgm.dropTable('read_state'); pgm.dropTable('reactions'); pgm.dropColumns('messages', ['edited_at', 'deleted_at']); };