import { ModelRegistryIndex } from '@travetto/model'; import type { Class } from '@travetto/runtime'; import { castTo, RuntimeError, TypedObject } from '@travetto/runtime'; import { SchemaRegistryIndex } from '@travetto/schema'; import type { SchemaContext } from './types'; export class SQLModelSchemaUtil { static SCHEMA_CACHE = new Map>(); // Schema and Context management static getSchemaContext(modelClass: Class): SchemaContext { if (this.SCHEMA_CACHE.has(modelClass)) { return castTo(this.SCHEMA_CACHE.get(modelClass)!); } const registryConfig = SchemaRegistryIndex.getOptional(modelClass)?.get(); if (!registryConfig) { throw new RuntimeError('Cannot store unregistered models', { category: 'data' }); } const fields = Object.values(registryConfig.fields); const hasModel = ModelRegistryIndex.has(modelClass); if (hasModel && registryConfig.discriminatedBase) { const fieldMap = new Set(fields.map(field => field.name)); for (const subclass of SchemaRegistryIndex.getDiscriminatedClasses(modelClass)) { const subclassConfig = SchemaRegistryIndex.getConfig(subclass); for (const field of TypedObject.values(subclassConfig.fields)) { if (!fieldMap.has(field.name)) { fieldMap.add(field.name); fields.push(field); } } } } const simpleFieldsList = fields.filter(field => !SchemaRegistryIndex.has(field.type) && !field.array); const complexFieldsList = fields.filter(field => SchemaRegistryIndex.has(field.type) || field.array); const simpleFields = new Map(simpleFieldsList.map(field => [field.name, field])); const complexFields = new Map(complexFieldsList.map(field => [field.name, field])); const context: SchemaContext = { cls: modelClass, simpleFields, complexFields, allFields: fields }; this.SCHEMA_CACHE.set(modelClass, context); return context; } static isColumnNotNull(context: SchemaContext, fieldName: string): boolean { const schemaConfig = SchemaRegistryIndex.getOptional(context.cls)?.get(); const fieldConfig = schemaConfig?.fields[fieldName]; if (!fieldConfig || fieldConfig.required?.active === false || fieldConfig.accessor) { return false; } if (ModelRegistryIndex.has(context.cls)) { const modelConfig = ModelRegistryIndex.getConfig(context.cls); if (modelConfig.transientFields?.includes(fieldName)) { return false; } } return true; } }