import { ignore , noop , parameterProperties , type } from "./decorators" ; import { createClass , reflection , useCache } from "./helpers" ; import * as v from "./analyzer" ; import { parseFunction } from "./parser" ; import { Class , ClassReflection , ObjectReflection , Reflection } from "./types" ; import { walkReflectionMembers , walkTypeMembersRecursive } from "./walker" ; interface TraverseContext { path : any [ ] ; } type Visitor < Ref , Ctx , Ret > = ( r : Ref , c : Ctx ) => Ret ; function pipe < Ref , Ctx , Ret > ( visitors ) { return ( value , ctx ) => visitors . reduce ( ( a , b ) => ! ! a ? b ( a , ctx ) : a , value as any ) ; } function reflectClass ( target ) { const ref = walkTypeMembersRecursive ( target , { target , memberVisitor : pipe ( [ v . addsDesignTypes , v . addsDecorators , v . addsParameterProperties , v . removeIgnored , ] ) , classPath : [ ] } ) ; return walkReflectionMembers ( ref , { classPath : [ ] , target , parent : ref , memberVisitor : pipe ( [ v . addsApplyToDecorator , v . addsTypeByTypeDecorator , v . addsTypeClassification , ] ) } ) ; } function traverseObject ( fn , name , ctx ) { if ( fn === undefined || fn === null ) return ; if ( Array . isArray ( fn ) ) return ; if ( typeof fn === "object" ) { if ( ctx . path . some ( x => x === fn ) ) return ; return reflectObject ( fn , name , { path : ctx . path . concat ( fn ) } ) ; } if ( typeof fn === "function" && reflection . isConstructor ( fn ) ) return reflectClass ( fn ) ; if ( typeof fn === "function" ) return parseFunction ( fn ) ; } function reflectObject ( object , name , ctx ) { return { kind : "Object" , name , members : Object . keys ( object ) . map ( x => traverseObject ( object [ x ] , x , ctx ) ) . filter ( ( x ) : x is Reflection => ! ! x ) } ; } function reflectModuleOrClass ( opt ) { if ( typeof opt === "string" ) { return reflectObject ( require ( opt ) , "module" , { path : [ ] } ) ; } else { return reflectClass ( opt ) ; } } interface ReflectOption { /**
     * Flush cached current module/class metadata before processing.
     */ flushCache ? : true ; } const cacheStore = new Map < string | Class , ClassReflection | ObjectReflection > ( ) ; const reflectCached = useCache ( cacheStore , reflectModuleOrClass , x => x ) ; param path function reflect ( path , opt ? ) ; param classType function reflect ( classType , opt ? ) ; function reflect ( pathOrClass , opt ? ) { if ( opt ?. flushCache ) cacheStore . delete ( pathOrClass ) ; return reflectCached ( pathOrClass ) ; } function flush ( pathOrClass ? ) { if ( pathOrClass ) cacheStore . delete ( pathOrClass ) ; else cacheStore . clear ( ) ; } /**
 * Decorator that do nothing, intended to be able to inspect data type
 */ reflect . noop = noop ; /**
 * Ignore member from metadata generated
 */ reflect . ignore = ignore ; param type param info reflect . type = type ; /**
 * Create class dynamically
 */ reflect . create = createClass ; /**
 * Mark all constructor parameters as properties
 */ reflect . parameterProperties = parameterProperties ; /**
 * Flush metadata cache, call without parameter to clear all
 */ reflect . flush = flush ; export { reflect } ;