diff --git a/apps/backend/drizzle/0008_extend_messages.sql b/apps/backend/drizzle/0008_extend_messages.sql new file mode 100644 index 0000000..8156484 --- /dev/null +++ b/apps/backend/drizzle/0008_extend_messages.sql @@ -0,0 +1,6 @@ +CREATE TYPE "public"."content_type" AS ENUM('text', 'file', 'image', 'video', 'audio', 'system');--> statement-breakpoint +ALTER TABLE "messages" ADD COLUMN "content_type" "content_type" NOT NULL DEFAULT 'text';--> statement-breakpoint +ALTER TABLE "messages" ADD COLUMN "sender_device_id" uuid NOT NULL;--> statement-breakpoint +ALTER TABLE "messages" ADD COLUMN "sequence_number" bigint NOT NULL;--> statement-breakpoint +ALTER TABLE "messages" ADD COLUMN "expires_at" timestamp;--> statement-breakpoint +ALTER TABLE "messages" ADD CONSTRAINT "messages_sender_device_id_user_devices_id_fk" FOREIGN KEY ("sender_device_id") REFERENCES "public"."user_devices"("id") ON DELETE cascade ON UPDATE no action; diff --git a/apps/backend/drizzle/meta/_journal.json b/apps/backend/drizzle/meta/_journal.json index 83106f4..6f5a899 100644 --- a/apps/backend/drizzle/meta/_journal.json +++ b/apps/backend/drizzle/meta/_journal.json @@ -61,8 +61,8 @@ { "idx": 8, "version": "7", - "when": 1782653959991, - "tag": "0008_keen_sway", + "when": 1783000000000, + "tag": "0008_extend_messages", "breakpoints": true } ] diff --git a/apps/backend/src/db/schema.ts b/apps/backend/src/db/schema.ts index 6a85ca0..988f6cb 100644 --- a/apps/backend/src/db/schema.ts +++ b/apps/backend/src/db/schema.ts @@ -8,6 +8,7 @@ import { index, integer, uniqueIndex, + bigint, } from 'drizzle-orm/pg-core'; import { relations, sql } from 'drizzle-orm'; @@ -42,6 +43,15 @@ export const conversations = pgTable('conversations', { createdAt: timestamp('created_at').notNull().defaultNow(), }); +export const contentTypeEnum = pgEnum('content_type', [ + 'text', + 'file', + 'image', + 'video', + 'audio', + 'system', +]); + export const conversationMembers = pgTable('conversation_members', { id: uuid('id').primaryKey().defaultRandom(), conversationId: uuid('conversation_id') @@ -69,6 +79,12 @@ export const messages = pgTable( .notNull() .references(() => users.id, { onDelete: 'cascade' }), content: text('content').notNull(), + contentType: contentTypeEnum('content_type').notNull().default('text'), + senderDeviceId: uuid('sender_device_id') + .notNull() + .references(() => userDevices.id, { onDelete: 'cascade' }), + sequenceNumber: bigint('sequence_number', { mode: 'bigint' }).notNull(), + expiresAt: timestamp('expires_at'), createdAt: timestamp('created_at').notNull().defaultNow(), deletedAt: timestamp('deleted_at'), }, @@ -266,6 +282,10 @@ export const messagesRelations = relations(messages, ({ one }) => ({ references: [conversations.id], }), sender: one(users, { fields: [messages.senderId], references: [users.id] }), + senderDevice: one(userDevices, { + fields: [messages.senderDeviceId], + references: [userDevices.id], + }), })); export const tokenTransfersRelations = relations(tokenTransfers, ({ one }) => ({ @@ -293,6 +313,11 @@ export const oneTimePreKeysRelations = relations(oneTimePreKeys, ({ one }) => ({ device: one(devices, { fields: [oneTimePreKeys.deviceId], references: [devices.id] }), })); +export const userDevicesRelations = relations(userDevices, ({ one, many }) => ({ + user: one(users, { fields: [userDevices.userId], references: [users.id] }), + messages: many(messages), +})); + // ─── Types ──────────────────────────────────────────────────────────────────── export type User = typeof users.$inferSelect; @@ -312,3 +337,5 @@ export type SignedPreKey = typeof signedPreKeys.$inferSelect; export type NewSignedPreKey = typeof signedPreKeys.$inferInsert; export type OneTimePreKey = typeof oneTimePreKeys.$inferSelect; export type NewOneTimePreKey = typeof oneTimePreKeys.$inferInsert; +export type UserDevice = typeof userDevices.$inferSelect; +export type NewUserDevice = typeof userDevices.$inferInsert;