UNPKG

@wearesage/schema

Version:

A flexible schema definition and validation system for TypeScript with multi-database support

107 lines (92 loc) 3.37 kB
import "reflect-metadata"; import { MetadataRegistry } from "./MetadataRegistry"; import { EntityOptions, PropertyOptions, RelationshipOptions, Neo4jRelationshipOptions, MongoDBRelationshipOptions, PostgreSQLRelationshipOptions } from "./types"; /** * SchemaBuilder extracts and processes metadata from decorated classes * and registers it with a MetadataRegistry instance. * * This provides a clear separation between: * 1. Schema definition (via decorators that store metadata on classes) * 2. Schema registration (via this builder that processes the metadata) */ export class SchemaBuilder { constructor(private registry: MetadataRegistry) {} /** * Register a class decorated with @Entity and related decorators * This extracts all metadata and registers it with the registry */ registerEntity<T>(entityClass: new (...args: any[]) => T): void { // Register the entity itself const entityMetadata: EntityOptions = Reflect.getMetadata("entity:options", entityClass) || {}; this.registry.registerEntity(entityClass, entityMetadata); // Get all property metadata this.registerEntityProperties(entityClass); // Get all relationship metadata this.registerEntityRelationships(entityClass); } /** * Register multiple entity classes at once */ registerEntities(entityClasses: Array<new (...args: any[]) => any>): void { for (const entityClass of entityClasses) { this.registerEntity(entityClass); } } /** * Extract and register property metadata from an entity class */ private registerEntityProperties(entityClass: Function): void { const prototype = entityClass.prototype; // Get property keys from metadata const propertyKeys: string[] = Reflect.getMetadata("entity:properties", entityClass) || []; // Register each property for (const key of propertyKeys) { const options: PropertyOptions = Reflect.getMetadata("property:options", prototype, key) || {}; this.registry.registerProperty(entityClass, key, options); // Check if this is an ID property const isId = Reflect.getMetadata("property:id", prototype, key); if (isId) { this.registry.registerIdProperty(entityClass, key); } } } /** * Extract and register relationship metadata from an entity class */ private registerEntityRelationships(entityClass: Function): void { const prototype = entityClass.prototype; // Get relationship keys from metadata const relationshipKeys: string[] = Reflect.getMetadata("entity:relationships", entityClass) || []; // Register each relationship for (const key of relationshipKeys) { const baseOptions = Reflect.getMetadata("relationship:options", prototype, key) || {}; const relType = Reflect.getMetadata("relationship:type", prototype, key); // Build full relationship options const options: RelationshipOptions = { ...baseOptions, cardinality: relType === "one-to-many" || relType === "many-to-many" ? "many" : "one" }; this.registry.registerRelationship(entityClass, key, options); } } /** * Get the underlying registry */ getRegistry(): MetadataRegistry { return this.registry; } }