UNPKG

@wearesage/schema

Version:

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

135 lines (118 loc) 4.01 kB
import { Type } from '../core/types'; /** * Interface for all database adapters */ export interface DatabaseAdapter { /** * Name of the database type (Neo4j, MongoDB, PostgreSQL, etc.) */ readonly type: string; /** * Executes a query against the database * @param entityType The entity class * @param criteria Query criteria * @returns Promise resolving to entity or null */ query<T>(entityType: Type<T>, criteria: object): Promise<T | null>; /** * Executes a query returning multiple results * @param entityType The entity class * @param criteria Query criteria * @returns Promise resolving to array of entities */ queryMany<T>(entityType: Type<T>, criteria: object): Promise<T[]>; /** * Saves an entity to the database * @param entity The entity to save * @returns Promise resolving when save is complete */ save<T extends object>(entity: T): Promise<void>; /** * Deletes an entity from the database * @param entityType The entity class * @param id The entity ID * @returns Promise resolving when delete is complete */ delete<T>(entityType: Type<T>, id: string | number): Promise<void>; /** * Executes a native query specific to this database * @param query The native query string * @param params Parameters to substitute in the query * @returns Promise resolving to query results */ runNativeQuery<T>(query: string, params?: any): Promise<T>; } /** * Decorator for specifying which database an entity extension is for * @param type Database type name */ export function DatabaseAdapter(type: string) { return function <T extends { new (...args: any[]): any }>(target: T): T { // Store the database type on the class Object.defineProperty(target, 'dbType', { value: type, writable: false }); // Automatically register this adapter entity with the shared registry // We need to find the base class it extends const baseEntity = Object.getPrototypeOf(target); if (baseEntity && baseEntity.name) { // Register the adapter entity using the shared instance for backward compatibility DatabaseAdapterRegistry.getInstance().registerAdapterEntity( type, baseEntity, target ); } return target; }; } /** * Registry for database-specific entities */ export class DatabaseAdapterRegistry { private static sharedInstance: DatabaseAdapterRegistry = new DatabaseAdapterRegistry(); private adapterEntities = new Map<string, Map<Function, Function>>(); constructor() {} /** * Get the shared instance of the registry. * This provides backward compatibility for existing code. * New code should prefer direct instantiation when possible. */ static getInstance(): DatabaseAdapterRegistry { return DatabaseAdapterRegistry.sharedInstance; } /** * Register a database-specific entity extension * @param dbType Database type * @param baseEntity Base entity class * @param adapterEntity Database-specific entity class */ registerAdapterEntity( dbType: string, baseEntity: Function, adapterEntity: Function ): void { if (!this.adapterEntities.has(dbType)) { this.adapterEntities.set(dbType, new Map()); } this.adapterEntities.get(dbType)!.set(baseEntity, adapterEntity); } /** * Get a database-specific entity extension * @param dbType Database type * @param baseEntity Base entity class * @returns Database-specific entity class or undefined */ getAdapterEntity(dbType: string, baseEntity: Function): Function | undefined { return this.adapterEntities.get(dbType)?.get(baseEntity); } /** * Get all database-specific entities for a database type * @param dbType Database type * @returns Map of base entities to adapter entities */ getAllAdapterEntities(dbType: string): Map<Function, Function> | undefined { return this.adapterEntities.get(dbType); } }