import type { Sequelize } from "sequelize"; import { DataTypes, QueryTypes } from "sequelize"; import { supportColumns } from "./asset-support-schema"; export async function migrateSupport(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 = (model: string) => ({ type: DataTypes.UUID, allowNull: false, references: { model, key: "id" }, onDelete: "RESTRICT", }); const definitions = [ [ "asset_support", { id: { type: DataTypes.UUID, primaryKey: true }, companyId: fk("companies"), assetId: fk("assets"), resourceId: { type: DataTypes.UUID, allowNull: false }, ...supportColumns, preferredKey: { type: DataTypes.UUID, allowNull: true, unique: true }, }, ], [ "asset_support_revisions", { id: { type: DataTypes.UUID, primaryKey: true }, connectionId: fk("asset_support"), actorId: fk("users"), resourceId: { type: DataTypes.UUID, allowNull: false }, ...supportColumns, recordedAt: { type: DataTypes.STRING(30), allowNull: false }, position: { type: DataTypes.INTEGER, allowNull: false }, }, ], ] as const; for (const [table, columns] of definitions) { if (!tables.some((item) => item.name === table)) { await query.createTable(table, columns); } } const constraints = await database.query<{ name: string }>( "SELECT CONSTRAINT_NAME AS name FROM information_schema.TABLE_CONSTRAINTS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='asset_support'", { type: QueryTypes.SELECT } ); if (!constraints.some((item) => item.name === "support_asset_company")) { await database.query( "ALTER TABLE asset_support ADD CONSTRAINT support_asset_company FOREIGN KEY (companyId,assetId) REFERENCES assets(companyId,id)" ); } const resourceIndexes = await database.query<{ name: string }>( "SELECT DISTINCT INDEX_NAME AS name FROM information_schema.STATISTICS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='resources'", { type: QueryTypes.SELECT } ); if (!resourceIndexes.some((index) => index.name === "resource_company_identity")) { await query.addIndex("resources", ["companyId", "id"], { unique: true, name: "resource_company_identity", }); } for (const table of ["asset_support", "asset_support_revisions"]) { const existing = await database.query<{ name: string }>( "SELECT CONSTRAINT_NAME AS name FROM information_schema.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA=DATABASE() AND TABLE_NAME=:table", { replacements: { table }, type: QueryTypes.SELECT } ); const name = `${table}_resource_reference`; if (!existing.some((item) => item.name === name)) { await database.query( `ALTER TABLE ${table} ADD CONSTRAINT ${name} FOREIGN KEY (resourceId) REFERENCES resources(id) ON DELETE RESTRICT` ); } if ( table === "asset_support" && !existing.some((item) => item.name === "support_resource_company") ) { await database.query( "ALTER TABLE asset_support ADD CONSTRAINT support_resource_company FOREIGN KEY (companyId,resourceId) REFERENCES resources(companyId,id) ON DELETE RESTRICT" ); } } }