@travetto/di
Version:
Dependency registration/management and injection support.
54 lines (48 loc) • 2.11 kB
text/typescript
import { type Any, castTo, type ClassInstance, getClass, type Class } from '@travetto/runtime';
import { CONSTRUCTOR_PROPERTY } from '@travetto/schema';
import type { InjectableCandidate, ResolutionType } from './types.ts';
import { DependencyRegistryIndex } from './registry/registry-index.ts';
const fromInput = <T extends { qualifier?: symbol }>(input?: T | symbol): T =>
typeof input === 'symbol' ? castTo({ qualifier: input }) : (input ?? castTo<T>({}));
/**
* Indicate that a class is able to be injected
* @augments `@travetto/schema:Schema`
* @example opt-in
* @kind decorator
*/
export function Injectable(input?: Partial<InjectableCandidate> | symbol) {
return <T extends Class>(cls: T): void => {
DependencyRegistryIndex.getForRegister(cls).registerClass(fromInput(input));
};
}
export type InjectConfig = { qualifier?: symbol, resolution?: ResolutionType };
/**
* Indicate that a field or parameter is able to be injected
* @augments `@travetto/di:Inject`
* @augments `@travetto/schema:Input`
* @kind decorator
*/
export function Inject(input?: InjectConfig | symbol) {
return (instanceOrCls: Class | ClassInstance, property?: string, idx?: number | PropertyDescriptor): void => {
const config = fromInput(input);
const cls = getClass(instanceOrCls);
const propertyKey = property ?? CONSTRUCTOR_PROPERTY;
if (typeof idx !== 'number') {
DependencyRegistryIndex.registerFieldMetadata(cls, propertyKey, config);
} else {
DependencyRegistryIndex.registerParameterMetadata(cls, propertyKey, idx, config);
}
};
}
/**
* Identifies a static method that is able to produce a dependency
* @augments `@travetto/schema:Method`
* @kind decorator
*/
export function InjectableFactory(input?: Partial<InjectableCandidate> | symbol) {
return <T extends Class>(cls: T, property: string, descriptor: TypedPropertyDescriptor<(...args: Any[]) => Any>): void => {
DependencyRegistryIndex.getForRegister(cls).registerFactory(property, fromInput(input), {
factory: (...params: unknown[]) => descriptor.value!.apply(cls, params),
});
};
}