import { Class , ParameterPropertyReflection , ClassReflection , TypeOverride , GenericTypeParameterDecorator , GenericTypeArgumentDecorator , TypeDecorator } from "./types" ; import * as decorate from "./decorators" ; import { getMetadata } from "./storage" ; const IsDynamicType = Symbol ( ) ; function useCache < K , P extends any [ ] , R > ( cache , fn , getKey ) { return ( ... args ) => { const key = getKey ( ... args ) ; const result = cache . get ( key ) ; if ( ! ! result ) return result ; else { const newResult = fn ( ... args ) ; cache . set ( key , newResult ) ; return newResult ; } } ; } namespace reflection { export function isParameterProperties ( meta ) { return meta && meta . kind === "Property" && ( meta as ParameterPropertyReflection ) . isParameter ; } export function isCallback ( type ) { return typeof type === "function" && ! type . prototype ; } export function isConstructor ( value ) { return ( "" + value ) . indexOf ( "class" ) == 0 ; } export function isCustomClass ( type ) { switch ( type ) { case Boolean : case String : case Array : case Number : case Object : case Date : return false ; default : return true ; } } export function getMethods ( meta ) { return meta . methods . map ( x => ( { name : x . name , type : x . returnType , pars : x . parameters . map ( p => ( { name : p . name , type : p . type } ) ) } ) ) ; } export function getProperties ( meta ) { return meta . properties . map ( x => ( { name : x . name , type : x . type } ) ) ; } export function getTypeFromDecorator ( decorator ) { const type = reflection . isCallback ( decorator . type ) ? decorator . type ( { } ) : decorator . type ; return [ Array . isArray ( type ) ? type [ 0 ] : type , Array . isArray ( type ) ] ; } } type CustomTypeDefinition = { [ key ] : Class | Class [ ] | { } | { } [ ] ; } ; interface CreateClassOption { extends : Class ; name : string ; genericParams : TypeOverride [ ] ; } function createClass ( definition , opt ? ) { class Base { } const option = { extends : Base , name : "DynamicType" , genericParams : [ ] , ... opt } ; const type = { [ option . name ] : class extends option . extends { } } [ option . name ] ; ( type as any ) [ IsDynamicType ] = true ; for ( const key in definition ) { Reflect . decorate ( [ decorate . type ( definition [ key ] ) ] , type . prototype , key ) ; } if ( option . genericParams . length > 0 ) Reflect . decorate ( [ decorate . generic . argument ( ... option . genericParams ) ] , type ) ; return type ; } export { useCache , reflection , createClass , CustomTypeDefinition , CreateClassOption , IsDynamicType } ;