75 lines
2.6 KiB
TypeScript
75 lines
2.6 KiB
TypeScript
|
|
import type { InferAttributes, InferCreationAttributes, Sequelize } from "sequelize";
|
||
|
|
import { DataTypes, Model, QueryTypes } from "sequelize";
|
||
|
|
export class ResourceModel extends Model<
|
||
|
|
InferAttributes<ResourceModel>,
|
||
|
|
InferCreationAttributes<ResourceModel>
|
||
|
|
> {
|
||
|
|
declare id: string;
|
||
|
|
declare companyId: string;
|
||
|
|
declare templateId: string;
|
||
|
|
declare specification: unknown;
|
||
|
|
declare values: unknown;
|
||
|
|
}
|
||
|
|
export class ResourceRevisionModel extends Model<
|
||
|
|
InferAttributes<ResourceRevisionModel>,
|
||
|
|
InferCreationAttributes<ResourceRevisionModel>
|
||
|
|
> {
|
||
|
|
declare id: string;
|
||
|
|
declare resourceId: string;
|
||
|
|
declare actorId: string;
|
||
|
|
declare recordedAt: string;
|
||
|
|
declare values: unknown;
|
||
|
|
declare position: number;
|
||
|
|
}
|
||
|
|
const id = { type: DataTypes.UUID, primaryKey: true };
|
||
|
|
const fk = (model: string) => ({
|
||
|
|
type: DataTypes.UUID,
|
||
|
|
allowNull: false,
|
||
|
|
references: { model, key: "id" },
|
||
|
|
onDelete: "RESTRICT",
|
||
|
|
});
|
||
|
|
export async function migrateInventory(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 resource = {
|
||
|
|
id,
|
||
|
|
companyId: fk("companies"),
|
||
|
|
templateId: fk("resource_definitions"),
|
||
|
|
specification: { type: DataTypes.JSON, allowNull: false },
|
||
|
|
values: { type: DataTypes.JSON, allowNull: false },
|
||
|
|
};
|
||
|
|
const revision = {
|
||
|
|
id,
|
||
|
|
resourceId: fk("resources"),
|
||
|
|
actorId: fk("users"),
|
||
|
|
recordedAt: { type: DataTypes.STRING(30), allowNull: false },
|
||
|
|
values: { type: DataTypes.JSON, allowNull: false },
|
||
|
|
position: { type: DataTypes.INTEGER, allowNull: false },
|
||
|
|
};
|
||
|
|
if (!tables.some((table) => table.name === "resources")) {
|
||
|
|
await query.createTable("resources", resource);
|
||
|
|
}
|
||
|
|
if (!tables.some((table) => table.name === "resource_revisions")) {
|
||
|
|
await query.createTable("resource_revisions", revision);
|
||
|
|
}
|
||
|
|
const indexes = await database.query<{ name: string }>(
|
||
|
|
"SELECT DISTINCT INDEX_NAME AS name FROM information_schema.STATISTICS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='resource_revisions'",
|
||
|
|
{ type: QueryTypes.SELECT }
|
||
|
|
);
|
||
|
|
if (!indexes.some((index) => index.name === "resource_revision_position_unique")) {
|
||
|
|
await query.addIndex("resource_revisions", ["resourceId", "position"], {
|
||
|
|
unique: true,
|
||
|
|
name: "resource_revision_position_unique",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
ResourceModel.init(resource, { sequelize: database, tableName: "resources", timestamps: false });
|
||
|
|
ResourceRevisionModel.init(revision, {
|
||
|
|
sequelize: database,
|
||
|
|
tableName: "resource_revisions",
|
||
|
|
timestamps: false,
|
||
|
|
});
|
||
|
|
}
|