Messenger/packages/backend/migrations/1720000000002_rooms_messages.cjs
Заид Омар Медхат | Zaid Omar Medhat e7f37be62c simple chat init
2026-07-10 15:32:34 +05:00

52 lines
2.3 KiB
JavaScript

// Phase 3 — rooms, membership, and messages.
// Messages use a crypto-agnostic content envelope so E2EE can be layered on
// later with no schema change (content holds plaintext now, ciphertext later).
/** @param {import('node-pg-migrate').MigrationBuilder} pgm */
exports.up = (pgm) => {
pgm.createTable('rooms', {
id: { type: 'uuid', primaryKey: true, default: pgm.func('gen_random_uuid()') },
name: { type: 'text', notNull: true },
created_by: { type: 'uuid', notNull: true, references: 'users', onDelete: 'RESTRICT' },
created_at: { type: 'timestamptz', notNull: true, default: pgm.func('now()') },
});
pgm.createTable('room_members', {
room_id: { type: 'uuid', notNull: true, references: 'rooms', onDelete: 'CASCADE' },
user_id: { type: 'uuid', notNull: true, references: 'users', onDelete: 'CASCADE' },
role: { type: 'text', notNull: true, default: 'member' },
joined_at: { type: 'timestamptz', notNull: true, default: pgm.func('now()') },
});
pgm.addConstraint('room_members', 'room_members_pkey', {
primaryKey: ['room_id', 'user_id'],
});
pgm.createIndex('room_members', 'user_id');
pgm.createTable('messages', {
id: { type: 'uuid', primaryKey: true, default: pgm.func('gen_random_uuid()') },
// Server-assigned monotonic ordering.
seq: { type: 'bigserial', notNull: true },
room_id: { type: 'uuid', notNull: true, references: 'rooms', onDelete: 'CASCADE' },
sender_id: { type: 'uuid', notNull: true, references: 'users', onDelete: 'RESTRICT' },
// Client-generated idempotency / dedupe key.
client_msg_id: { type: 'text', notNull: true },
// Opaque content envelope (see file header).
content: { type: 'text', notNull: true },
content_type: { type: 'text', notNull: true, default: 'text' },
encryption: { type: 'text' },
created_at: { type: 'timestamptz', notNull: true, default: pgm.func('now()') },
});
pgm.createIndex('messages', 'seq', { unique: true });
pgm.createIndex('messages', ['room_id', 'seq']);
// Idempotent sends: one message per (room, sender, client_msg_id).
pgm.addConstraint('messages', 'messages_dedupe_uq', {
unique: ['room_id', 'sender_id', 'client_msg_id'],
});
};
/** @param {import('node-pg-migrate').MigrationBuilder} pgm */
exports.down = (pgm) => {
pgm.dropTable('messages');
pgm.dropTable('room_members');
pgm.dropTable('rooms');
};