// Phase 4 — reshape rooms into a unified "conversations" model (direct + group) // and add contacts. Renames preserve existing group data (existing rooms become // type='group'). /** @param {import('node-pg-migrate').MigrationBuilder} pgm */ exports.up = (pgm) => { // rooms -> conversations pgm.renameTable('rooms', 'conversations'); pgm.renameColumn('conversations', 'name', 'title'); pgm.alterColumn('conversations', 'title', { notNull: false }); pgm.addColumns('conversations', { type: { type: 'text', notNull: true, default: 'group' }, // Canonical sorted user-pair for a direct conversation; unique so a 1:1 is // never duplicated. NULL for groups (Postgres allows many NULLs in UNIQUE). direct_key: { type: 'text' }, last_message_at: { type: 'timestamptz', notNull: true, default: pgm.func('now()') }, }); pgm.addConstraint('conversations', 'conversations_direct_key_uq', { unique: ['direct_key'] }); // room_members -> conversation_members pgm.renameTable('room_members', 'conversation_members'); pgm.renameColumn('conversation_members', 'room_id', 'conversation_id'); // messages.room_id -> conversation_id (indexes + dedupe constraint follow the rename) pgm.renameColumn('messages', 'room_id', 'conversation_id'); pgm.createTable('contacts', { owner_id: { type: 'uuid', notNull: true, references: 'users', onDelete: 'CASCADE' }, contact_id: { type: 'uuid', notNull: true, references: 'users', onDelete: 'CASCADE' }, created_at: { type: 'timestamptz', notNull: true, default: pgm.func('now()') }, }); pgm.addConstraint('contacts', 'contacts_pkey', { primaryKey: ['owner_id', 'contact_id'] }); }; /** @param {import('node-pg-migrate').MigrationBuilder} pgm */ exports.down = (pgm) => { pgm.dropTable('contacts'); pgm.renameColumn('messages', 'conversation_id', 'room_id'); pgm.renameColumn('conversation_members', 'conversation_id', 'room_id'); pgm.renameTable('conversation_members', 'room_members'); pgm.dropConstraint('conversations', 'conversations_direct_key_uq'); pgm.dropColumns('conversations', ['type', 'direct_key', 'last_message_at']); pgm.alterColumn('conversations', 'title', { notNull: true }); pgm.renameColumn('conversations', 'title', 'name'); pgm.renameTable('conversations', 'rooms'); };