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

94 lines
3.4 KiB
TypeScript
Raw Normal View History

2026-10-08 14:43:34 +00:00
import type { Sequelize } from "sequelize";
import { DataTypes, QueryTypes } from "sequelize";
2026-10-10 10:01:58 +00:00
2026-10-10 15:57:05 +00:00
import { supportColumns } from "./asset-support-schema";
2026-10-10 11:32:40 +00:00
2026-10-07 08:16:39 +00:00
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 }
);
2026-10-10 10:01:58 +00:00
2026-10-07 08:16:39 +00:00
const fk = (model: string) => ({
type: DataTypes.UUID,
allowNull: false,
references: { model, key: "id" },
onDelete: "RESTRICT",
});
2026-10-10 10:01:58 +00:00
2026-10-07 08:16:39 +00:00
const definitions = [
[
"asset_support",
{
id: { type: DataTypes.UUID, primaryKey: true },
companyId: fk("companies"),
assetId: fk("assets"),
resourceId: { type: DataTypes.UUID, allowNull: false },
2026-10-10 11:32:40 +00:00
...supportColumns,
2026-10-07 08:16:39 +00:00
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 },
2026-10-10 11:32:40 +00:00
...supportColumns,
2026-10-07 08:16:39 +00:00
recordedAt: { type: DataTypes.STRING(30), allowNull: false },
position: { type: DataTypes.INTEGER, allowNull: false },
},
],
] as const;
2026-10-10 10:01:58 +00:00
2026-10-07 08:16:39 +00:00
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 }
);
2026-10-10 10:01:58 +00:00
2026-10-07 08:16:39 +00:00
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 }
2026-10-07 08:16:39 +00:00
);
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"
);
}
2026-10-07 08:16:39 +00:00
}
}