metis-desk/modules/assets/src/api/infrastructure/persistence/infrastructure-migration.ts

92 lines
3.3 KiB
TypeScript
Raw Normal View History

2026-10-17 15:01:16 +00:00
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",
});
}
}