import type { AnyEntity , Dictionary , EntityData } from '../typings' ; import { EntityMetadata } from '../typings' ; import { Utils } from '../utils/Utils' ; import { MetadataError } from '../errors' ; import type { EntityManager } from '../EntityManager' ; import { EntityHelper } from '../entity/EntityHelper' ; import type { EventSubscriber } from '../events' ; export class MetadataStorage { private static readonly metadata : Dictionary < EntityMetadata > = Utils . getGlobalStorage ( 'metadata' ) ; private static readonly subscribers : Dictionary < EventSubscriber > = Utils . getGlobalStorage ( 'subscribers' ) ; private readonly metadata : Dictionary < EntityMetadata > ; constructor ( metadata = { } ) { this . metadata = Utils . copy ( metadata ) ; } static getMetadata ( ) ; static getMetadata < T extends AnyEntity < T > = any > ( entity , path ) ; static getMetadata < T extends AnyEntity < T > = any > ( entity ? , path ? ) { const key = entity && path ? entity + '-' + Utils . hash ( path ) : null ; if ( key && ! MetadataStorage . metadata [ key ] ) { MetadataStorage . metadata [ key ] = new EntityMetadata ( { className : entity , path } ) ; } if ( key ) { return MetadataStorage . metadata [ key ] ; } return MetadataStorage . metadata ; } static isKnownEntity ( name ) { return ! ! Object . values ( this . metadata ) . find ( meta => meta . className === name ) ; } static getMetadataFromDecorator < T = any > ( target ) { const path = Utils . lookupPathFromDecorator ( target . name ) ; const meta = MetadataStorage . getMetadata ( target . name , path ) ; Object . defineProperty ( target , '__path' , { value : path , writable : true } ) ; return meta ; } static getSubscriberMetadata ( ) { return MetadataStorage . subscribers ; } static init ( ) { return new MetadataStorage ( MetadataStorage . metadata ) ; } static clear ( ) { Object . keys ( this . metadata ) . forEach ( k => delete this . metadata [ k ] ) ; Object . keys ( this . subscribers ) . forEach ( k => delete this . subscribers [ k ] ) ; } getAll ( ) { return this . metadata ; } getByDiscriminatorColumn < T > ( meta , data ) { const value = data [ meta . root . discriminatorColumn ! ] ; if ( ! value ) { return undefined ; } const type = meta . root . discriminatorMap ! [ value ] ; return this . metadata [ type ] ; } get < T extends AnyEntity < T > = any > ( entity , init = false , validate = true ) { if ( validate && ! init && entity && ! this . has ( entity ) ) { throw MetadataError . missingMetadata ( entity ) ; } if ( init && ! this . has ( entity ) ) { this . metadata [ entity ] = new EntityMetadata ( ) ; } return this . metadata [ entity ] ; } find < T extends AnyEntity < T > = any > ( entity ) { return this . metadata [ entity ] ; } has ( entity ) { return entity in this . metadata ; } set ( entity , meta ) { return this . metadata [ entity ] = meta ; } reset ( entity ) { delete this . metadata [ entity ] ; } decorate ( em ) { Object . values ( this . metadata ) . filter ( meta => meta . prototype && ! meta . prototype . __meta ) . forEach ( meta => EntityHelper . decorate ( meta , em ) ) ; } }