import { DataTypes, QueryTypes, type Sequelize } from "sequelize"; export async function migrateMailboxes(database: Sequelize) { const query = database.getQueryInterface(); const tables = await database.query<{ name: string }>( "SELECT TABLE_NAME AS name FROM information_schema.TABLES WHERE TABLE_SCHEMA=DATABASE()", { type: QueryTypes.SELECT } ); const fk = (table: string, nullable = false) => ({ type: DataTypes.UUID, allowNull: nullable, references: { model: table, key: "id" }, onDelete: "RESTRICT", }); const root = { id: { type: DataTypes.UUID, primaryKey: true }, companyId: fk("companies"), values: { type: DataTypes.JSON, allowNull: false }, }; for (const [table, columns] of [ [ "mailboxes", { ...root, accountId: fk("access_items", true), addressKey: { type: DataTypes.STRING(300), allowNull: false, unique: true }, }, ], ["mailbox_uses", { ...root, mailboxId: fk("mailboxes"), personId: fk("company_contacts") }], [ "mailbox_revisions", { id: root.id, itemId: fk("mailboxes"), position: { type: DataTypes.INTEGER, allowNull: false }, values: root.values, actorId: fk("users"), recordedAt: { type: DataTypes.STRING(24), allowNull: false }, }, ], [ "mailbox_use_revisions", { id: root.id, itemId: fk("mailbox_uses"), position: { type: DataTypes.INTEGER, allowNull: false }, values: root.values, actorId: fk("users"), recordedAt: { type: DataTypes.STRING(24), allowNull: false }, }, ], ] as const) { if (!tables.some((row) => row.name === table)) { await query.createTable(table, columns); } } for (const table of ["mailbox_revisions", "mailbox_use_revisions"]) { const indexes = await database.query<{ name: string }>( "SELECT DISTINCT INDEX_NAME AS name FROM information_schema.STATISTICS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME=:table", { replacements: { table }, type: QueryTypes.SELECT } ); if (!indexes.some((item) => item.name === `${table}_position`)) { await query.addIndex(table, ["itemId", "position"], { unique: true, name: `${table}_position`, }); } } }