import { FastifyToken } from './symbols' ; import type { Constructable , IInjectToken } from './types' ; export const serviceTokens = new Map ( ) ; export default class Injector { private readonly injectableMap : Map < Constructable | IInjectToken , any > = new Map ( ) ; private resolve ( constructor ) { let currentInstance = this . injectableMap . get ( constructor ) ; if ( currentInstance ) return currentInstance ; const fastifyInstance = this . injectableMap . get ( FastifyToken ) ; if ( typeof constructor !== 'function' ) { if ( serviceTokens . has ( constructor ) ) { const serviceConstructor = serviceTokens . get ( constructor ) ; const serviceInstance = this . resolve ( serviceConstructor ) ; this . injectableMap . set ( serviceConstructor , serviceInstance ) ; this . injectableMap . set ( constructor , serviceInstance ) ; return serviceInstance ; } return fastifyInstance [ constructor ] ; } const paramTypes = Reflect . getMetadata ( 'design:paramtypes' , constructor ) || [ ] ; const injectedParams = Reflect . getMetadata ( 'fastify-resty:inject:constructor' , constructor ) || new Map ( ) ; const injectedModelParams = Reflect . getMetadata ( 'fastify-resty:inject:constructor:model' , constructor ) || new Map ( ) ; const constructorParams = paramTypes . map ( ( param , index ) => { if ( injectedModelParams . has ( index ) ) { const { Entity , options } = injectedModelParams . get ( index ) as any ; return new fastifyInstance . BaseModel ( Entity , options ) ; } return this . resolve ( injectedParams . get ( index ) || param ) ; } ) ; const injectStaticMap = Reflect . getMetadata ( 'fastify-resty:inject:properties' , constructor ) || new Map ( ) ; for ( const [ property , token ] of injectStaticMap . entries ( ) ) { constructor [ property ] = this . resolve ( token ) ; } const injectModelStaticMap = Reflect . getMetadata ( 'fastify-resty:inject:properties:model' , constructor ) || new Map ( ) ; for ( const [ property , { Entity , options } ] of injectModelStaticMap . entries ( ) ) { constructor [ property ] = new fastifyInstance . BaseModel ( Entity , options ) ; } currentInstance = Reflect . construct ( constructor , constructorParams ) ; const injectPropsMap = Reflect . getMetadata ( 'fastify-resty:inject:properties' , currentInstance ) || new Map ( ) ; for ( const [ property , token ] of injectPropsMap . entries ( ) ) { currentInstance [ property ] = this . resolve ( token ) ; } const injectModelPropsMap = Reflect . getMetadata ( 'fastify-resty:inject:properties:model' , currentInstance ) || new Map ( ) ; for ( const [ property , { Entity , options } ] of injectModelPropsMap . entries ( ) ) { currentInstance [ property ] = new fastifyInstance . BaseModel ( Entity , options ) ; } this . injectableMap . set ( constructor , currentInstance ) ; return currentInstance ; } public getInstance < T > ( constructor ) { return this . resolve ( constructor ) ; } public registerInstance ( key , value ) { this . injectableMap . set ( key , value ) ; } }