2026-10-10 15:57:05 +00:00
import type { Sequelize } from "sequelize" ;
import { DataTypes , QueryTypes } from "sequelize" ;
const fk = ( model : string , nullable = false ) = > ( {
type : DataTypes . UUID ,
allowNull : nullable ,
references : { model , key : "id" } ,
onDelete : [ "resource_definitions" , "access_items" ] . includes ( model ) ? "RESTRICT" : "CASCADE" ,
} ) ;
const title = { type : DataTypes . STRING ( 100 ) , allowNull : false } ;
const position = { type : DataTypes . INTEGER , allowNull : false } ;
export const definitionColumns = {
kind : { type : DataTypes . STRING ( 12 ) , allowNull : false } ,
name : title ,
description : { type : DataTypes . TEXT , allowNull : false } ,
2026-10-15 10:32:37 +00:00
icon : { type : DataTypes . STRING ( 30 ) , allowNull : true } ,
2026-10-10 15:57:05 +00:00
fieldType : { type : DataTypes . STRING ( 12 ) , allowNull : true } ,
unit : { type : DataTypes . STRING ( 30 ) , allowNull : true } ,
usage : { type : DataTypes . STRING ( 15 ) , allowNull : true } ,
sectionsDefined : { type : DataTypes . BOOLEAN , allowNull : false , defaultValue : false } ,
} ;
export const inventoryColumns = {
name : title ,
active : { type : DataTypes . BOOLEAN , allowNull : false } ,
notes : { type : DataTypes . TEXT , allowNull : false } ,
integrationKind : { type : DataTypes . STRING ( 10 ) , allowNull : true } ,
addressFieldId : fk ( "resource_definitions" , true ) ,
contextFieldId : fk ( "resource_definitions" , true ) ,
mailboxKind : { type : DataTypes . STRING ( 10 ) , allowNull : true } ,
accountId : fk ( "access_items" , true ) ,
referenceFieldId : fk ( "resource_definitions" , true ) ,
resourceTypeId : fk ( "access_items" , true ) ,
systemId : fk ( "access_items" , true ) ,
environmentId : fk ( "access_items" , true ) ,
} ;
export const specificationColumns = {
templateName : title ,
sectionsDefined : { type : DataTypes . BOOLEAN , allowNull : false , defaultValue : false } ,
} ;
type Columns = Parameters < ReturnType < Sequelize [ " getQueryInterface " ] > [ "createTable" ] > [ 1 ] ;
async function create ( database : Sequelize , name : string , columns : Columns ) {
const tables = await database . query < { name : string } > (
"SELECT TABLE_NAME AS name FROM information_schema.TABLES WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME=:name" ,
{ replacements : { name } , type : QueryTypes . SELECT }
) ;
if ( ! tables . length ) {
await database . getQueryInterface ( ) . createTable ( name , columns ) ;
}
}
export async function initializeResourceCatalogSchema ( database : Sequelize ) {
await create ( database , "resource_field_choices" , {
fieldId : { . . . fk ( "resource_definitions" ) , primaryKey : true } ,
position : { . . . position , primaryKey : true } ,
value : title ,
} ) ;
await create ( database , "resource_template_sections" , {
id : { type : DataTypes . UUID , primaryKey : true } ,
templateId : { . . . fk ( "resource_definitions" ) , primaryKey : true } ,
name : title ,
description : { type : DataTypes . TEXT , allowNull : false } ,
position ,
} ) ;
await constrainSections ( database ) ;
}
export async function initializeResourceInventorySchema ( database : Sequelize ) {
await create ( database , "resource_specification_sections" , {
resourceId : { . . . fk ( "resources" ) , primaryKey : true } ,
id : { type : DataTypes . UUID , primaryKey : true } ,
name : title ,
description : { type : DataTypes . TEXT , allowNull : false } ,
position ,
} ) ;
await create ( database , "resource_specification_fields" , {
resourceId : { . . . fk ( "resources" ) , primaryKey : true } ,
fieldId : { . . . fk ( "resource_definitions" ) , primaryKey : true } ,
name : title ,
fieldType : { type : DataTypes . STRING ( 12 ) , allowNull : false } ,
unit : { type : DataTypes . STRING ( 30 ) , allowNull : false } ,
required : { type : DataTypes . BOOLEAN , allowNull : false } ,
sectionId : { type : DataTypes . UUID , allowNull : true } ,
position ,
} ) ;
await create ( database , "resource_specification_field_choices" , {
resourceId : { . . . fk ( "resources" ) , primaryKey : true } ,
fieldId : { . . . fk ( "resource_definitions" ) , primaryKey : true } ,
position : { . . . position , primaryKey : true } ,
value : title ,
} ) ;
const typedValues = {
fieldId : { . . . fk ( "resource_definitions" ) , primaryKey : true } ,
valueType : { type : DataTypes . STRING ( 12 ) , allowNull : false } ,
textValue : { type : DataTypes . TEXT , allowNull : true } ,
numberValue : { type : DataTypes . DOUBLE , allowNull : true } ,
booleanValue : { type : DataTypes . BOOLEAN , allowNull : true } ,
dateValue : { type : DataTypes . DATEONLY , allowNull : true } ,
} ;
await create ( database , "resource_characteristics" , {
resourceId : { . . . fk ( "resources" ) , primaryKey : true } ,
. . . typedValues ,
} ) ;
await create ( database , "resource_revision_characteristics" , {
revisionId : { . . . fk ( "resource_revisions" ) , primaryKey : true } ,
resourceId : fk ( "resources" ) ,
. . . typedValues ,
} ) ;
}
async function constrainSections ( database : Sequelize ) {
const constraints = await database . query < { name : string } > (
"SELECT CONSTRAINT_NAME AS name FROM information_schema.TABLE_CONSTRAINTS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='resource_template_fields' AND CONSTRAINT_NAME='resource_template_field_section'" ,
{ type : QueryTypes . SELECT }
) ;
if ( ! constraints . length ) {
await database . query (
"ALTER TABLE resource_template_fields ADD CONSTRAINT resource_template_field_section FOREIGN KEY (templateId,sectionId) REFERENCES resource_template_sections(templateId,id)"
) ;
}
}
export async function enforceResourceConstraints ( database : Sequelize ) {
await constrainSections ( database ) ;
}