metis-desk/modules/assets/src/api/infrastructure/persistence/asset-relationship-normalization.ts
2026-10-10 11:41:42 +02:00

66 lines
2.3 KiB
TypeScript

import type { Sequelize } from "sequelize";
import { DataTypes, QueryTypes } from "sequelize";
import { RelationshipValuesSchema } from "../../domain/value-objects/asset-relationship-values.vo";
import { LegacyJsonSchema } from "./asset-catalog-relational";
import { removeAssetColumn } from "./asset-relational-sql";
export const relationshipColumns = {
name: { type: DataTypes.STRING(100), allowNull: false },
inverseName: { type: DataTypes.STRING(100), allowNull: false },
symmetric: { type: DataTypes.BOOLEAN, allowNull: false },
notes: { type: DataTypes.TEXT, allowNull: false },
};
export async function normalizeAssetRelationships(database: Sequelize) {
const query = database.getQueryInterface();
const columns = await query.describeTable("asset_relationships");
if (!columns.values) {
return;
}
for (const [column, definition] of Object.entries(relationshipColumns)) {
if (!(column in columns)) {
await query.addColumn("asset_relationships", column, { ...definition, allowNull: true });
}
}
await database.transaction(async (transaction) => {
const rows = await database.query<{
id: string;
sourceId: string;
targetId: string;
typeId: string;
values: unknown;
}>("SELECT id,sourceId,targetId,typeId,`values` FROM asset_relationships", {
type: QueryTypes.SELECT,
transaction,
});
for (const row of rows) {
const values = RelationshipValuesSchema.parse(LegacyJsonSchema.parse(row.values));
if (
values.sourceId !== row.sourceId ||
values.targetId !== row.targetId ||
values.typeId !== row.typeId
) {
throw new Error("Referencias de relación incompatibles con la normalización.");
}
await database.query(
"UPDATE asset_relationships SET name=:name,inverseName=:inverseName,symmetric=:symmetric,notes=:notes WHERE id=:id",
{
replacements: {
id: row.id,
name: values.name,
inverseName: values.inverseName,
symmetric: values.symmetric,
notes: values.notes,
},
transaction,
}
);
}
});
for (const [column, definition] of Object.entries(relationshipColumns)) {
await query.changeColumn("asset_relationships", column, definition);
}
await removeAssetColumn(database, "asset_relationships", "values");
}