import { Identifier, Newable, Container } from './Container'; export interface FinalBinder { transient(): void; } export interface ResolveBinder extends FinalBinder { to(dep: Newable): FinalBinder; toFactory( dep: (container: Container) => Promise | S ): FinalBinder; toValue(value: any): void; } export interface Bind { (identifier: Identifier): ResolveBinder; } export interface InjectorMetaData { scope: 'transient' | 'singleton'; class?: Newable; factory?: (container: Container) => Promise | any; value?: any; } export function createBinder( addBinding: (identifier: Identifier, data: InjectorMetaData) => void, exists: (identifier: Identifier) => boolean ): Bind { return function(identifier: Identifier) { if (exists(identifier)) { throw `${identifier.toString()} already bound`; } const data: InjectorMetaData = { scope: 'singleton' }; addBinding(identifier, data); if (typeof identifier !== 'symbol') { data.class = identifier; } return { to(dep: Newable) { data.class = dep; return this; }, toFactory(dep: (container: Container) => Promise | S) { data.factory = dep; data.class = undefined; return this; }, toValue(value: any) { data.class = undefined; data.value = value; }, transient() { data.scope = 'transient'; } }; }; }