@wearesage/schema
Version:
A flexible schema definition and validation system for TypeScript with multi-database support
148 lines (126 loc) • 4.14 kB
text/typescript
import { EntityOptions, PropertyOptions, RelationshipOptions } from "./types";
/**
* MetadataRegistry is responsible for storing and retrieving schema metadata
* about entities, properties, and relationships.
*
* This class is designed to be instantiated directly rather than used as a singleton,
* allowing for better testing and composition. It's typically used with a SchemaBuilder
* to register metadata from decorated classes.
*/
export class MetadataRegistry {
private entities = new Map<Function, EntityOptions>();
private properties = new Map<Function, Map<string, PropertyOptions>>();
private ids = new Map<Function, Set<string>>();
private relationships = new Map<Function, Map<string, RelationshipOptions>>();
constructor() {}
// Entity registration
registerEntity(target: Function, options: EntityOptions = {}): void {
this.entities.set(target, options);
}
// Property registration
registerProperty(
target: Function,
propertyKey: string,
options: PropertyOptions = {}
): void {
if (!this.properties.has(target)) {
this.properties.set(target, new Map());
}
this.properties.get(target)!.set(propertyKey, options);
}
// ID registration
registerIdProperty(target: Function, propertyKey: string): void {
if (!this.ids.has(target)) {
this.ids.set(target, new Set());
}
this.ids.get(target)!.add(propertyKey);
}
// Relationship registration
registerRelationship(
target: Function,
propertyKey: string,
options: RelationshipOptions
): void {
if (!this.relationships.has(target)) {
this.relationships.set(target, new Map());
}
this.relationships.get(target)!.set(propertyKey, options);
}
// Getters
getEntityMetadata(target: Function): EntityOptions | undefined {
return this.entities.get(target);
}
getPropertyMetadata(
target: Function,
propertyKey: string
): PropertyOptions | undefined {
return this.properties.get(target)?.get(propertyKey);
}
getAllProperties(target: Function): Map<string, PropertyOptions> | undefined {
return this.properties.get(target);
}
getIdProperties(target: Function): Set<string> | undefined {
return this.ids.get(target);
}
getRelationshipMetadata(
target: Function,
propertyKey: string
): RelationshipOptions | undefined {
return this.relationships.get(target)?.get(propertyKey);
}
getAllRelationships(
target: Function
): Map<string, RelationshipOptions> | undefined {
return this.relationships.get(target);
}
getAllEntities(): Map<Function, EntityOptions> {
return this.entities;
}
/**
* Create a clone of this registry
* Useful for creating modified copies without changing the original
*/
clone(): MetadataRegistry {
const cloned = new MetadataRegistry();
// Clone entities
this.entities.forEach((options, target) => {
cloned.entities.set(target, { ...options });
});
// Clone properties
this.properties.forEach((propertyMap, target) => {
const clonedPropertyMap = new Map<string, PropertyOptions>();
propertyMap.forEach((options, key) => {
clonedPropertyMap.set(key, { ...options });
});
cloned.properties.set(target, clonedPropertyMap);
});
// Clone IDs
this.ids.forEach((idSet, target) => {
cloned.ids.set(target, new Set<string>(idSet));
});
// Clone relationships
this.relationships.forEach((relationshipMap, target) => {
const clonedRelationshipMap = new Map<string, RelationshipOptions>();
relationshipMap.forEach((options, key) => {
clonedRelationshipMap.set(key, { ...options });
});
cloned.relationships.set(target, clonedRelationshipMap);
});
return cloned;
}
/**
* Get all registered entity types
*/
getRegisteredEntities(): Type<any>[] {
return Array.from(this.entities.keys());
}
/**
* Clear all metadata from this registry
*/
clear(): void {
this.entities.clear();
this.properties.clear();
this.ids.clear();
this.relationships.clear();
}
}