import { bigint, boolean, index, integer, jsonb, pgTable, text, timestamp, uniqueIndex, uuid, } from "drizzle-orm/pg-core" import { tenants } from "./tenants" import { authUsers } from "./auth_users" import { userCredentials } from "./user_credentials" export const emailMailboxes = pgTable( "email_mailboxes", { id: uuid("id").primaryKey().defaultRandom(), tenantId: bigint("tenant_id", { mode: "number" }) .notNull() .references(() => tenants.id, { onDelete: "cascade", onUpdate: "cascade" }), userId: uuid("user_id") .notNull() .references(() => authUsers.id, { onDelete: "cascade", onUpdate: "cascade" }), accountId: uuid("account_id") .notNull() .references(() => userCredentials.id, { onDelete: "cascade", onUpdate: "cascade" }), path: text("path").notNull(), delimiter: text("delimiter"), name: text("name").notNull(), specialUse: text("special_use"), flags: jsonb("flags").$type(), exists: integer("exists").notNull().default(0), unseen: integer("unseen").notNull().default(0), createdAt: timestamp("created_at", { withTimezone: true }) .notNull() .defaultNow(), updatedAt: timestamp("updated_at", { withTimezone: true }), }, (table) => ({ accountPathKey: uniqueIndex("email_mailboxes_account_path_key") .on(table.accountId, table.path), tenantAccountIdx: index("email_mailboxes_tenant_account_idx") .on(table.tenantId, table.accountId), }), ) export const emailMessages = pgTable( "email_messages", { id: uuid("id").primaryKey().defaultRandom(), tenantId: bigint("tenant_id", { mode: "number" }) .notNull() .references(() => tenants.id, { onDelete: "cascade", onUpdate: "cascade" }), userId: uuid("user_id") .notNull() .references(() => authUsers.id, { onDelete: "cascade", onUpdate: "cascade" }), accountId: uuid("account_id") .notNull() .references(() => userCredentials.id, { onDelete: "cascade", onUpdate: "cascade" }), mailboxId: uuid("mailbox_id") .notNull() .references(() => emailMailboxes.id, { onDelete: "cascade", onUpdate: "cascade" }), mailboxPath: text("mailbox_path").notNull(), uid: bigint("uid", { mode: "number" }).notNull(), emailId: text("email_id"), messageId: text("message_id"), inReplyTo: text("in_reply_to"), threadId: text("thread_id"), subject: text("subject"), from: jsonb("from").$type>(), to: jsonb("to").$type>(), cc: jsonb("cc").$type>(), bcc: jsonb("bcc").$type>(), replyTo: jsonb("reply_to").$type>(), preview: text("preview"), flags: jsonb("flags").$type(), seen: boolean("seen").notNull().default(false), flagged: boolean("flagged").notNull().default(false), hasAttachments: boolean("has_attachments").notNull().default(false), size: bigint("size", { mode: "number" }), sentAt: timestamp("sent_at", { withTimezone: true }), receivedAt: timestamp("received_at", { withTimezone: true }), createdAt: timestamp("created_at", { withTimezone: true }) .notNull() .defaultNow(), updatedAt: timestamp("updated_at", { withTimezone: true }), }, (table) => ({ mailboxUidKey: uniqueIndex("email_messages_mailbox_uid_key") .on(table.mailboxId, table.uid), accountMailboxIdx: index("email_messages_account_mailbox_idx") .on(table.accountId, table.mailboxPath), receivedIdx: index("email_messages_received_idx") .on(table.receivedAt), messageIdIdx: index("email_messages_message_id_idx") .on(table.messageId), threadIdx: index("email_messages_thread_idx") .on(table.threadId), }), ) export const emailMessageBodies = pgTable("email_message_bodies", { messageId: uuid("message_id") .primaryKey() .references(() => emailMessages.id, { onDelete: "cascade", onUpdate: "cascade" }), text: text("text"), html: text("html"), createdAt: timestamp("created_at", { withTimezone: true }) .notNull() .defaultNow(), updatedAt: timestamp("updated_at", { withTimezone: true }), }) export const emailAttachments = pgTable( "email_attachments", { id: uuid("id").primaryKey().defaultRandom(), messageId: uuid("message_id") .notNull() .references(() => emailMessages.id, { onDelete: "cascade", onUpdate: "cascade" }), filename: text("filename"), contentType: text("content_type"), contentId: text("content_id"), disposition: text("disposition"), size: bigint("size", { mode: "number" }), checksum: text("checksum"), storageKey: text("storage_key"), createdAt: timestamp("created_at", { withTimezone: true }) .notNull() .defaultNow(), }, (table) => ({ messageIdx: index("email_attachments_message_idx") .on(table.messageId), }), ) export const emailSyncState = pgTable( "email_sync_state", { id: uuid("id").primaryKey().defaultRandom(), tenantId: bigint("tenant_id", { mode: "number" }) .notNull() .references(() => tenants.id, { onDelete: "cascade", onUpdate: "cascade" }), userId: uuid("user_id") .notNull() .references(() => authUsers.id, { onDelete: "cascade", onUpdate: "cascade" }), accountId: uuid("account_id") .notNull() .references(() => userCredentials.id, { onDelete: "cascade", onUpdate: "cascade" }), mailboxId: uuid("mailbox_id") .notNull() .references(() => emailMailboxes.id, { onDelete: "cascade", onUpdate: "cascade" }), mailboxPath: text("mailbox_path").notNull(), uidValidity: bigint("uid_validity", { mode: "number" }), highestUid: bigint("highest_uid", { mode: "number" }).notNull().default(0), modSeq: text("mod_seq"), lastSyncedAt: timestamp("last_synced_at", { withTimezone: true }), syncError: text("sync_error"), createdAt: timestamp("created_at", { withTimezone: true }) .notNull() .defaultNow(), updatedAt: timestamp("updated_at", { withTimezone: true }), }, (table) => ({ mailboxKey: uniqueIndex("email_sync_state_mailbox_key") .on(table.accountId, table.mailboxPath), tenantAccountIdx: index("email_sync_state_tenant_account_idx") .on(table.tenantId, table.accountId), }), ) export type EmailMailbox = typeof emailMailboxes.$inferSelect export type NewEmailMailbox = typeof emailMailboxes.$inferInsert export type EmailMessage = typeof emailMessages.$inferSelect export type NewEmailMessage = typeof emailMessages.$inferInsert export type EmailMessageBody = typeof emailMessageBodies.$inferSelect export type NewEmailMessageBody = typeof emailMessageBodies.$inferInsert export type EmailAttachment = typeof emailAttachments.$inferSelect export type NewEmailAttachment = typeof emailAttachments.$inferInsert export type EmailSyncState = typeof emailSyncState.$inferSelect export type NewEmailSyncState = typeof emailSyncState.$inferInsert