UNPKG

reactant-di

Version:

A dependency injection lib for Reactant

83 lines (79 loc) 2.18 kB
import { METADATA_KEY } from '../constants'; import { ServiceIdentifier } from '../interfaces'; /** * ## Description * * You can get a decorator `@lazy(serviceIdentifier)` with `getLazyDecorator((serviceIdentifier) => container.get(serviceIdentifier))`, * and use it on any one dependency property that you need to lazily get. * * ## Example * * ```ts * let container: Container; * const lazy = getLazyDecorator((serviceIdentifier) => * container.get(serviceIdentifier) * ); * * @injectable() * class Foo { * public get test() { * return 'test'; * } * } * * @injectable() * class Bar { * @lazy('foo') * foo?: Foo; * } * * container = createContainer({ * ServiceIdentifiers: new Map(), * }); * * const bar = container.get(Bar); * * container.bind('foo').to(Foo); * expect(bar.foo?.test).toBe('test'); * ``` */ export const getLazyDecorator = ( getService: ( serviceIdentifier: ServiceIdentifier<unknown>, target?: object ) => unknown ) => (serviceIdentifier: ServiceIdentifier<unknown>, enableCache = true) => (target: object, key: string | symbol) => { function getter(this: object) { if (enableCache && !Reflect.hasMetadata(METADATA_KEY.lazy, this, key)) { const service = getService(serviceIdentifier, this); if (service !== null) { Reflect.defineMetadata(METADATA_KEY.lazy, service, this, key); } } if (Reflect.hasMetadata(METADATA_KEY.lazy, this, key)) { return Reflect.getMetadata(METADATA_KEY.lazy, this, key); } return getService(serviceIdentifier, this); } function setter(this: object, newVal: unknown) { if (enableCache) { Reflect.defineMetadata(METADATA_KEY.lazy, newVal, this, key); } else { console.warn(` Disable cache and the property ${key.toString()} in class "${ this.constructor.name }" instance failed to set value. `); } } // It should be compatible with the TS decorator and the babel decorator return { configurable: true, enumerable: true, get: getter, set: setter, } as any; };