import type { Sequelize } from "sequelize"; import { DataTypes, QueryTypes } from "sequelize"; export async function migrateInfrastructure(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 id = { type: DataTypes.UUID, primaryKey: true }; const fk = (table: string) => ({ type: DataTypes.UUID, allowNull: false, references: { model: table, key: "id" }, onDelete: "RESTRICT", }); const revision = () => ({ ...fk("asset_infrastructure_revisions"), primaryKey: true }); const definitions = [ [ "asset_infrastructure", { id, companyId: fk("companies"), assetId: { ...fk("assets"), unique: true } }, ], [ "asset_infrastructure_revisions", { id, infrastructureId: fk("asset_infrastructure"), actorId: fk("users"), recordedAt: { type: DataTypes.STRING(30), allowNull: false }, position: { type: DataTypes.INTEGER, allowNull: false }, }, ], [ "asset_infrastructure_roles", { revisionId: revision(), role: { type: DataTypes.STRING(30), primaryKey: true } }, ], [ "asset_interface_snapshots", { revisionId: revision(), id, name: { type: DataTypes.STRING(100), allowNull: false }, kind: { type: DataTypes.STRING(12), allowNull: false }, mac: { type: DataTypes.STRING(17), allowNull: false }, notes: { type: DataTypes.TEXT, allowNull: false }, position: { type: DataTypes.INTEGER, allowNull: false }, }, ], [ "asset_interface_address_snapshots", { revisionId: revision(), id, interfaceId: { type: DataTypes.UUID, allowNull: false }, address: { type: DataTypes.STRING(45), allowNull: false }, position: { type: DataTypes.INTEGER, allowNull: false }, }, ], ] as const; for (const [table, columns] of definitions) { if (!tables.some((row) => row.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 IN ('asset_infrastructure','asset_interface_address_snapshots','asset_infrastructure_revisions')", { type: QueryTypes.SELECT } ); if (!constraints.some((row) => row.name === "infrastructure_asset_company")) { await database.query( "ALTER TABLE asset_infrastructure ADD CONSTRAINT infrastructure_asset_company FOREIGN KEY (companyId,assetId) REFERENCES assets(companyId,id)" ); } if (!constraints.some((row) => row.name === "interface_address_owner")) { await database.query( "ALTER TABLE asset_interface_address_snapshots ADD CONSTRAINT interface_address_owner FOREIGN KEY (revisionId,interfaceId) REFERENCES asset_interface_snapshots(revisionId,id)" ); } if (!constraints.some((row) => row.name === "infrastructure_revision_position")) { await query.addConstraint("asset_infrastructure_revisions", { fields: ["infrastructureId", "position"], type: "unique", name: "infrastructure_revision_position", }); } }