Setup eslint and enforce rules
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
@@ -1,14 +1,14 @@
|
||||
import {DependencyKey, InstanceRef, Instantiable, isInstantiable, StaticClass} from "./types";
|
||||
import {AbstractFactory} from "./factory/AbstractFactory";
|
||||
import {collect, Collection, globalRegistry, logIfDebugging} from "../util";
|
||||
import {Factory} from "./factory/Factory";
|
||||
import {DuplicateFactoryKeyError} from "./error/DuplicateFactoryKeyError";
|
||||
import {ClosureFactory} from "./factory/ClosureFactory";
|
||||
import NamedFactory from "./factory/NamedFactory";
|
||||
import SingletonFactory from "./factory/SingletonFactory";
|
||||
import {InvalidDependencyKeyError} from "./error/InvalidDependencyKeyError";
|
||||
import {DependencyKey, InstanceRef, Instantiable, isInstantiable} from './types'
|
||||
import {AbstractFactory} from './factory/AbstractFactory'
|
||||
import {collect, Collection, globalRegistry, logIfDebugging} from '../util'
|
||||
import {Factory} from './factory/Factory'
|
||||
import {DuplicateFactoryKeyError} from './error/DuplicateFactoryKeyError'
|
||||
import {ClosureFactory} from './factory/ClosureFactory'
|
||||
import NamedFactory from './factory/NamedFactory'
|
||||
import SingletonFactory from './factory/SingletonFactory'
|
||||
import {InvalidDependencyKeyError} from './error/InvalidDependencyKeyError'
|
||||
|
||||
export type MaybeFactory = AbstractFactory | undefined
|
||||
export type MaybeFactory<T> = AbstractFactory<T> | undefined
|
||||
export type MaybeDependency = any | undefined
|
||||
export type ResolvedDependency = { paramIndex: number, key: DependencyKey, resolved: any }
|
||||
|
||||
@@ -34,7 +34,7 @@ export class Container {
|
||||
* Collection of factories registered with this container.
|
||||
* @type Collection<AbstractFactory>
|
||||
*/
|
||||
protected factories: Collection<AbstractFactory> = new Collection<AbstractFactory>()
|
||||
protected factories: Collection<AbstractFactory<unknown>> = new Collection<AbstractFactory<unknown>>()
|
||||
|
||||
/**
|
||||
* Collection of singleton instances produced by this container.
|
||||
@@ -51,12 +51,14 @@ export class Container {
|
||||
* Register a basic instantiable class as a standard Factory with this container.
|
||||
* @param {Instantiable} dependency
|
||||
*/
|
||||
register(dependency: Instantiable<any>) {
|
||||
if ( this.resolve(dependency) )
|
||||
register(dependency: Instantiable<any>): this {
|
||||
if ( this.resolve(dependency) ) {
|
||||
throw new DuplicateFactoryKeyError(dependency)
|
||||
}
|
||||
|
||||
const factory = new Factory(dependency)
|
||||
this.factories.push(factory)
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -64,12 +66,14 @@ export class Container {
|
||||
* @param {string} name - unique name to identify the factory in the container
|
||||
* @param {function} producer - factory to produce a value
|
||||
*/
|
||||
registerProducer(name: string | StaticClass<any, any>, producer: () => any) {
|
||||
if ( this.resolve(name) )
|
||||
registerProducer(name: DependencyKey, producer: () => any): this {
|
||||
if ( this.resolve(name) ) {
|
||||
throw new DuplicateFactoryKeyError(name)
|
||||
}
|
||||
|
||||
const factory = new ClosureFactory(name, producer)
|
||||
this.factories.push(factory)
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -78,12 +82,14 @@ export class Container {
|
||||
* @param {string} name - unique name to identify the factory in the container
|
||||
* @param {Instantiable} dependency
|
||||
*/
|
||||
registerNamed(name: string, dependency: Instantiable<any>) {
|
||||
if ( this.resolve(name) )
|
||||
registerNamed(name: string, dependency: Instantiable<any>): this {
|
||||
if ( this.resolve(name) ) {
|
||||
throw new DuplicateFactoryKeyError(name)
|
||||
}
|
||||
|
||||
const factory = new NamedFactory(name, dependency)
|
||||
this.factories.push(factory)
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -92,11 +98,13 @@ export class Container {
|
||||
* @param {string} key - unique name to identify the singleton in the container
|
||||
* @param value
|
||||
*/
|
||||
registerSingleton(key: string, value: any) {
|
||||
if ( this.resolve(key) )
|
||||
registerSingleton<T>(key: DependencyKey, value: T): this {
|
||||
if ( this.resolve(key) ) {
|
||||
throw new DuplicateFactoryKeyError(key)
|
||||
}
|
||||
|
||||
this.factories.push(new SingletonFactory(value, key))
|
||||
this.factories.push(new SingletonFactory(key, value))
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -105,24 +113,30 @@ export class Container {
|
||||
* @param staticClass
|
||||
* @param instance
|
||||
*/
|
||||
registerSingletonInstance<T>(staticClass: Instantiable<T>, instance: T) {
|
||||
if ( this.resolve(staticClass) )
|
||||
registerSingletonInstance<T>(staticClass: Instantiable<T>, instance: T): this {
|
||||
if ( this.resolve(staticClass) ) {
|
||||
throw new DuplicateFactoryKeyError(staticClass)
|
||||
}
|
||||
|
||||
this.register(staticClass)
|
||||
this.instances.push({
|
||||
key: staticClass,
|
||||
value: instance,
|
||||
})
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a given factory with the container.
|
||||
* @param {AbstractFactory} factory
|
||||
*/
|
||||
registerFactory(factory: AbstractFactory) {
|
||||
if ( !this.factories.includes(factory) )
|
||||
registerFactory(factory: AbstractFactory<unknown>): this {
|
||||
if ( !this.factories.includes(factory) ) {
|
||||
this.factories.push(factory)
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -138,7 +152,7 @@ export class Container {
|
||||
* @param {DependencyKey} key
|
||||
*/
|
||||
hasKey(key: DependencyKey): boolean {
|
||||
return !!this.resolve(key)
|
||||
return Boolean(this.resolve(key))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -147,17 +161,22 @@ export class Container {
|
||||
*/
|
||||
getExistingInstance(key: DependencyKey): MaybeDependency {
|
||||
const instances = this.instances.where('key', '=', key)
|
||||
if ( instances.isNotEmpty() ) return instances.first()
|
||||
if ( instances.isNotEmpty() ) {
|
||||
return instances.first()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the factory for the given key, if one is registered with this container.
|
||||
* @param {DependencyKey} key
|
||||
*/
|
||||
resolve(key: DependencyKey): MaybeFactory {
|
||||
resolve(key: DependencyKey): MaybeFactory<unknown> {
|
||||
const factory = this.factories.firstWhere(item => item.match(key))
|
||||
if ( factory ) return factory
|
||||
else logIfDebugging('extollo.di.injector', 'unable to resolve factory', factory, this.factories)
|
||||
if ( factory ) {
|
||||
return factory
|
||||
} else {
|
||||
logIfDebugging('extollo.di.injector', 'unable to resolve factory', factory, this.factories)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -172,22 +191,25 @@ export class Container {
|
||||
// If we've already instantiated this, just return that
|
||||
const instance = this.getExistingInstance(key)
|
||||
logIfDebugging('extollo.di.injector', 'resolveAndCreate existing instance?', instance)
|
||||
if ( typeof instance !== 'undefined' ) return instance.value
|
||||
if ( typeof instance !== 'undefined' ) {
|
||||
return instance.value
|
||||
}
|
||||
|
||||
// Otherwise, attempt to create it
|
||||
const factory = this.resolve(key)
|
||||
logIfDebugging('extollo.di.injector', 'resolveAndCreate factory', factory)
|
||||
if ( !factory )
|
||||
if ( !factory ) {
|
||||
throw new InvalidDependencyKeyError(key)
|
||||
}
|
||||
|
||||
// Produce and store a new instance
|
||||
const new_instance = this.produceFactory(factory, parameters)
|
||||
const newInstance = this.produceFactory(factory, parameters)
|
||||
this.instances.push({
|
||||
key,
|
||||
value: new_instance,
|
||||
value: newInstance,
|
||||
})
|
||||
|
||||
return new_instance
|
||||
return newInstance
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -196,7 +218,7 @@ export class Container {
|
||||
* @param {AbstractFactory} factory
|
||||
* @param {array} parameters
|
||||
*/
|
||||
protected produceFactory(factory: AbstractFactory, parameters: any[]) {
|
||||
protected produceFactory<T>(factory: AbstractFactory<T>, parameters: any[]): T {
|
||||
// Create the dependencies for the factory
|
||||
const keys = factory.getDependencyKeys().filter(req => this.hasKey(req.key))
|
||||
const dependencies = keys.map<ResolvedDependency>(req => {
|
||||
@@ -210,20 +232,23 @@ export class Container {
|
||||
// Build the arguments for the factory, using dependencies in the
|
||||
// correct paramIndex positions, or parameters of we don't have
|
||||
// the dependency.
|
||||
const construction_args = []
|
||||
let params = collect(parameters).reverse()
|
||||
const constructorArguments = []
|
||||
const params = collect(parameters).reverse()
|
||||
for ( let i = 0; i <= dependencies.max('paramIndex'); i++ ) {
|
||||
const dep = dependencies.firstWhere('paramIndex', '=', i)
|
||||
if ( dep ) construction_args.push(dep.resolved)
|
||||
else construction_args.push(params.pop())
|
||||
if ( dep ) {
|
||||
constructorArguments.push(dep.resolved)
|
||||
} else {
|
||||
constructorArguments.push(params.pop())
|
||||
}
|
||||
}
|
||||
|
||||
// Produce a new instance
|
||||
const inst = factory.produce(construction_args, params.reverse().all())
|
||||
const inst = factory.produce(constructorArguments, params.reverse().all())
|
||||
|
||||
factory.getInjectedProperties().each(dependency => {
|
||||
if ( dependency.key && inst ) {
|
||||
inst[dependency.property] = this.resolveAndCreate(dependency.key)
|
||||
(inst as any)[dependency.property] = this.resolveAndCreate(dependency.key)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -240,12 +265,13 @@ export class Container {
|
||||
* @param {...any} parameters
|
||||
*/
|
||||
make<T>(target: DependencyKey, ...parameters: any[]): T {
|
||||
if ( this.hasKey(target) )
|
||||
if ( this.hasKey(target) ) {
|
||||
return this.resolveAndCreate(target, ...parameters)
|
||||
else if ( typeof target !== 'string' && isInstantiable(target) )
|
||||
} else if ( typeof target !== 'string' && isInstantiable(target) ) {
|
||||
return this.produceFactory(new Factory(target), parameters)
|
||||
else
|
||||
} else {
|
||||
throw new TypeError(`Invalid or unknown make target: ${target}`)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -255,8 +281,9 @@ export class Container {
|
||||
getDependencies(target: DependencyKey): Collection<DependencyKey> {
|
||||
const factory = this.resolve(target)
|
||||
|
||||
if ( !factory )
|
||||
if ( !factory ) {
|
||||
throw new InvalidDependencyKeyError(target)
|
||||
}
|
||||
|
||||
return factory.getDependencyKeys().pluck('key')
|
||||
}
|
||||
@@ -265,8 +292,9 @@ export class Container {
|
||||
* Given a different container, copy the factories and instances from this container over to it.
|
||||
* @param container
|
||||
*/
|
||||
cloneTo(container: Container) {
|
||||
cloneTo(container: Container): this {
|
||||
container.factories = this.factories.clone()
|
||||
container.instances = this.instances.clone()
|
||||
return this
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import {Container, MaybeDependency, MaybeFactory} from "./Container"
|
||||
import {DependencyKey} from "./types"
|
||||
import {Container, MaybeDependency, MaybeFactory} from './Container'
|
||||
import {DependencyKey} from './types'
|
||||
|
||||
/**
|
||||
* A container that uses some parent container as a base, but
|
||||
@@ -26,8 +26,8 @@ export class ScopedContainer extends Container {
|
||||
* Create a new scoped container based on a parent container instance.
|
||||
* @param container
|
||||
*/
|
||||
public static fromParent(container: Container) {
|
||||
return new ScopedContainer(container);
|
||||
public static fromParent(container: Container): ScopedContainer {
|
||||
return new ScopedContainer(container)
|
||||
}
|
||||
|
||||
constructor(
|
||||
@@ -47,15 +47,19 @@ export class ScopedContainer extends Container {
|
||||
|
||||
getExistingInstance(key: DependencyKey): MaybeDependency {
|
||||
const inst = super.getExistingInstance(key)
|
||||
if ( inst ) return inst;
|
||||
if ( inst ) {
|
||||
return inst
|
||||
}
|
||||
|
||||
return this.parentContainer.getExistingInstance(key);
|
||||
return this.parentContainer.getExistingInstance(key)
|
||||
}
|
||||
|
||||
resolve(key: DependencyKey): MaybeFactory {
|
||||
const factory = super.resolve(key);
|
||||
if ( factory ) return factory;
|
||||
resolve(key: DependencyKey): MaybeFactory<any> {
|
||||
const factory = super.resolve(key)
|
||||
if ( factory ) {
|
||||
return factory
|
||||
}
|
||||
|
||||
return this.parentContainer?.resolve(key);
|
||||
return this.parentContainer?.resolve(key)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'reflect-metadata'
|
||||
import {collect, Collection} from "../../util";
|
||||
import {collect, Collection} from '../../util'
|
||||
import {
|
||||
DependencyKey,
|
||||
DependencyRequirement,
|
||||
@@ -9,16 +9,16 @@ import {
|
||||
InjectionType,
|
||||
DEPENDENCY_KEYS_SERVICE_TYPE_KEY,
|
||||
PropertyDependency,
|
||||
} from "../types";
|
||||
import {Container} from "../Container";
|
||||
} from '../types'
|
||||
import {Container} from '../Container'
|
||||
|
||||
/**
|
||||
* Get a collection of dependency requirements for the given target object.
|
||||
* @param {Object} target
|
||||
* @return Collection<DependencyRequirement>
|
||||
*/
|
||||
function initDependencyMetadata(target: Object): Collection<DependencyRequirement> {
|
||||
const paramTypes = Reflect.getMetadata('design:paramtypes', target)
|
||||
function initDependencyMetadata(target: unknown): Collection<DependencyRequirement> {
|
||||
const paramTypes = Reflect.getMetadata('design:paramtypes', target as any)
|
||||
return collect<DependencyKey>(paramTypes).map<DependencyRequirement>((type, idx) => {
|
||||
return {
|
||||
paramIndex: idx,
|
||||
@@ -37,32 +37,32 @@ export const Injectable = (): ClassDecorator => {
|
||||
return (target) => {
|
||||
const meta = initDependencyMetadata(target)
|
||||
const existing = Reflect.getMetadata(DEPENDENCY_KEYS_METADATA_KEY, target)
|
||||
const new_meta = new Collection<DependencyRequirement>()
|
||||
const newMetadata = new Collection<DependencyRequirement>()
|
||||
|
||||
if ( existing ) {
|
||||
const max_new = meta.max('paramIndex')
|
||||
const max_existing = existing.max('paramIndex')
|
||||
for ( let i = 0; i <= Math.max(max_new, max_existing); i++ ) {
|
||||
const existing_dr = existing.firstWhere('paramIndex', '=', i)
|
||||
const new_dr = meta.firstWhere('paramIndex', '=', i)
|
||||
const maxNew = meta.max('paramIndex')
|
||||
const maxExisting = existing.max('paramIndex')
|
||||
for ( let i = 0; i <= Math.max(maxNew, maxExisting); i++ ) {
|
||||
const existingDR = existing.firstWhere('paramIndex', '=', i)
|
||||
const newDR = meta.firstWhere('paramIndex', '=', i)
|
||||
|
||||
if ( existing_dr && !new_dr ) {
|
||||
new_meta.push(existing_dr)
|
||||
} else if ( new_dr && !existing_dr ) {
|
||||
new_meta.push(new_dr)
|
||||
} else if ( new_dr && existing_dr ) {
|
||||
if ( existing_dr.overridden ) {
|
||||
new_meta.push(existing_dr)
|
||||
if ( existingDR && !newDR ) {
|
||||
newMetadata.push(existingDR)
|
||||
} else if ( newDR && !existingDR ) {
|
||||
newMetadata.push(newDR)
|
||||
} else if ( newDR && existingDR ) {
|
||||
if ( existingDR.overridden ) {
|
||||
newMetadata.push(existingDR)
|
||||
} else {
|
||||
new_meta.push(new_dr)
|
||||
newMetadata.push(newDR)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
new_meta.concat(meta)
|
||||
newMetadata.concat(meta)
|
||||
}
|
||||
|
||||
Reflect.defineMetadata(DEPENDENCY_KEYS_METADATA_KEY, new_meta, target)
|
||||
Reflect.defineMetadata(DEPENDENCY_KEYS_METADATA_KEY, newMetadata, target)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,14 +82,17 @@ export const Inject = (key?: DependencyKey): PropertyDecorator => {
|
||||
}
|
||||
|
||||
const type = Reflect.getMetadata('design:type', target, property)
|
||||
if ( !key && type ) key = type
|
||||
if ( !key && type ) {
|
||||
key = type
|
||||
}
|
||||
|
||||
if ( key ) {
|
||||
const existing = propertyMetadata.firstWhere('property', '=', property)
|
||||
if ( existing ) {
|
||||
existing.key = key
|
||||
} else {
|
||||
propertyMetadata.push({ property, key })
|
||||
propertyMetadata.push({ property,
|
||||
key })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,7 +121,7 @@ export const InjectParam = (key: DependencyKey): ParameterDecorator => {
|
||||
meta.push({
|
||||
paramIndex,
|
||||
key,
|
||||
overridden: true
|
||||
overridden: true,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -135,7 +138,7 @@ export const Singleton = (name?: string): ClassDecorator => {
|
||||
if ( isInstantiable(target) ) {
|
||||
const injectionType: InjectionType = {
|
||||
type: name ? 'named' : 'singleton',
|
||||
...(name ? { name } : {})
|
||||
...(name ? { name } : {}),
|
||||
}
|
||||
|
||||
Reflect.defineMetadata(DEPENDENCY_KEYS_SERVICE_TYPE_KEY, injectionType, target)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {DependencyKey} from "../types";
|
||||
import {DependencyKey} from '../types'
|
||||
|
||||
/**
|
||||
* Error thrown when a factory is registered with a duplicate dependency key.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {DependencyKey} from "../types";
|
||||
import {DependencyKey} from '../types'
|
||||
|
||||
/**
|
||||
* Error thrown when a dependency key that has not been registered is passed to a resolver.
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import {DependencyRequirement, PropertyDependency} from "../types";
|
||||
import { Collection } from "../../util";
|
||||
import {DependencyKey, DependencyRequirement, PropertyDependency} from '../types'
|
||||
import { Collection } from '../../util'
|
||||
|
||||
/**
|
||||
* Abstract base class for dependency container factories.
|
||||
* @abstract
|
||||
*/
|
||||
export abstract class AbstractFactory {
|
||||
export abstract class AbstractFactory<T> {
|
||||
protected constructor(
|
||||
/**
|
||||
* Token that was registered for this factory. In most cases, this is the static
|
||||
@@ -13,7 +13,7 @@ export abstract class AbstractFactory {
|
||||
* @var
|
||||
* @protected
|
||||
*/
|
||||
protected token: any
|
||||
protected token: DependencyKey,
|
||||
) {}
|
||||
|
||||
/**
|
||||
@@ -21,14 +21,14 @@ export abstract class AbstractFactory {
|
||||
* @param {Array} dependencies - the resolved dependencies, in order
|
||||
* @param {Array} parameters - the bound constructor parameters, in order
|
||||
*/
|
||||
abstract produce(dependencies: any[], parameters: any[]): any
|
||||
abstract produce(dependencies: any[], parameters: any[]): T
|
||||
|
||||
/**
|
||||
* Should return true if the given identifier matches the token for this factory.
|
||||
* @param something
|
||||
* @return boolean
|
||||
*/
|
||||
abstract match(something: any): boolean
|
||||
abstract match(something: unknown): boolean
|
||||
|
||||
/**
|
||||
* Get the dependency requirements required by this factory's token.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {AbstractFactory} from "./AbstractFactory";
|
||||
import {DependencyRequirement, PropertyDependency, StaticClass} from "../types";
|
||||
import {Collection} from "../../util";
|
||||
import {AbstractFactory} from './AbstractFactory'
|
||||
import {DependencyKey, DependencyRequirement, PropertyDependency} from '../types'
|
||||
import {Collection} from '../../util'
|
||||
|
||||
/**
|
||||
* A factory whose token is produced by calling a function.
|
||||
@@ -17,19 +17,19 @@ import {Collection} from "../../util";
|
||||
* fact.produce([], []) // => 4
|
||||
* ```
|
||||
*/
|
||||
export class ClosureFactory extends AbstractFactory {
|
||||
export class ClosureFactory<T> extends AbstractFactory<T> {
|
||||
constructor(
|
||||
protected readonly name: string | StaticClass<any, any>,
|
||||
protected readonly token: () => any,
|
||||
protected readonly name: DependencyKey,
|
||||
protected readonly token: () => T,
|
||||
) {
|
||||
super(token)
|
||||
}
|
||||
|
||||
produce(dependencies: any[], parameters: any[]): any {
|
||||
produce(): any {
|
||||
return this.token()
|
||||
}
|
||||
|
||||
match(something: any) {
|
||||
match(something: unknown): boolean {
|
||||
return something === this.name
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import {AbstractFactory} from "./AbstractFactory";
|
||||
import {AbstractFactory} from './AbstractFactory'
|
||||
import {
|
||||
DEPENDENCY_KEYS_METADATA_KEY,
|
||||
DEPENDENCY_KEYS_PROPERTY_METADATA_KEY,
|
||||
DependencyRequirement,
|
||||
Instantiable,
|
||||
PropertyDependency
|
||||
} from "../types";
|
||||
import {Collection} from "../../util";
|
||||
PropertyDependency,
|
||||
} from '../types'
|
||||
import {Collection} from '../../util'
|
||||
import 'reflect-metadata'
|
||||
|
||||
/**
|
||||
@@ -29,9 +29,9 @@ import 'reflect-metadata'
|
||||
* fact.produce([myServiceInstance], []) // => A { myService: myServiceInstance }
|
||||
* ```
|
||||
*/
|
||||
export class Factory extends AbstractFactory {
|
||||
export class Factory<T> extends AbstractFactory<T> {
|
||||
constructor(
|
||||
protected readonly token: Instantiable<any>
|
||||
protected readonly token: Instantiable<T>,
|
||||
) {
|
||||
super(token)
|
||||
}
|
||||
@@ -40,13 +40,15 @@ export class Factory extends AbstractFactory {
|
||||
return new this.token(...dependencies, ...parameters)
|
||||
}
|
||||
|
||||
match(something: any) {
|
||||
match(something: unknown): boolean {
|
||||
return something === this.token // || (something?.name && something.name === this.token.name)
|
||||
}
|
||||
|
||||
getDependencyKeys(): Collection<DependencyRequirement> {
|
||||
const meta = Reflect.getMetadata(DEPENDENCY_KEYS_METADATA_KEY, this.token)
|
||||
if ( meta ) return meta
|
||||
if ( meta ) {
|
||||
return meta
|
||||
}
|
||||
return new Collection<DependencyRequirement>()
|
||||
}
|
||||
|
||||
@@ -56,7 +58,9 @@ export class Factory extends AbstractFactory {
|
||||
|
||||
do {
|
||||
const loadedMeta = Reflect.getMetadata(DEPENDENCY_KEYS_PROPERTY_METADATA_KEY, currentToken)
|
||||
if ( loadedMeta ) meta.concat(loadedMeta)
|
||||
if ( loadedMeta ) {
|
||||
meta.concat(loadedMeta)
|
||||
}
|
||||
currentToken = Object.getPrototypeOf(currentToken)
|
||||
} while (Object.getPrototypeOf(currentToken) !== Function.prototype && Object.getPrototypeOf(currentToken) !== Object.prototype)
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import {Factory} from "./Factory";
|
||||
import {Instantiable} from "../types";
|
||||
import {Factory} from './Factory'
|
||||
import {Instantiable} from '../types'
|
||||
|
||||
/**
|
||||
* Container factory that produces an instance of the token, however the token
|
||||
* is identified by a string name rather than a class reference.
|
||||
* @extends Factory
|
||||
*/
|
||||
export default class NamedFactory extends Factory {
|
||||
export default class NamedFactory<T> extends Factory<T> {
|
||||
constructor(
|
||||
/**
|
||||
* The name identifying this factory in the container.
|
||||
@@ -18,12 +18,12 @@ export default class NamedFactory extends Factory {
|
||||
* The token to be instantiated.
|
||||
* @type {Instantiable}
|
||||
*/
|
||||
protected token: Instantiable<any>,
|
||||
protected token: Instantiable<T>,
|
||||
) {
|
||||
super(token)
|
||||
}
|
||||
|
||||
match(something: any) {
|
||||
match(something: unknown): boolean {
|
||||
return something === this.name
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Factory } from './Factory'
|
||||
import { Collection } from '../../util'
|
||||
import {DependencyRequirement, PropertyDependency} from "../types";
|
||||
import {DependencyKey, DependencyRequirement, PropertyDependency} from '../types'
|
||||
|
||||
/**
|
||||
* Container factory which returns its token as its value, without attempting
|
||||
@@ -19,29 +19,23 @@ import {DependencyRequirement, PropertyDependency} from "../types";
|
||||
*
|
||||
* @extends Factory
|
||||
*/
|
||||
export default class SingletonFactory extends Factory {
|
||||
export default class SingletonFactory<T> extends Factory<T> {
|
||||
constructor(
|
||||
/**
|
||||
* Instantiated value of this factory.
|
||||
* @type FunctionConstructor
|
||||
* Token identifying this singleton.
|
||||
*/
|
||||
protected token: FunctionConstructor,
|
||||
protected token: DependencyKey,
|
||||
|
||||
/**
|
||||
* String name of this singleton identifying it in the container.
|
||||
* @type string
|
||||
* The value of this singleton.
|
||||
*/
|
||||
protected key: string,
|
||||
protected value: T,
|
||||
) {
|
||||
super(token)
|
||||
}
|
||||
|
||||
produce(dependencies: any[], parameters: any[]) {
|
||||
return this.token
|
||||
}
|
||||
|
||||
match(something: any) {
|
||||
return something === this.key
|
||||
produce(): T {
|
||||
return this.value
|
||||
}
|
||||
|
||||
getDependencyKeys(): Collection<DependencyRequirement> {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
export const DEPENDENCY_KEYS_METADATA_KEY = 'extollo:di:dependencies:ctor';
|
||||
export const DEPENDENCY_KEYS_PROPERTY_METADATA_KEY = 'extollo:di:dependencies:properties';
|
||||
export const DEPENDENCY_KEYS_SERVICE_TYPE_KEY = 'extollo:di:service_type';
|
||||
export const DEPENDENCY_KEYS_METADATA_KEY = 'extollo:di:dependencies:ctor'
|
||||
export const DEPENDENCY_KEYS_PROPERTY_METADATA_KEY = 'extollo:di:dependencies:properties'
|
||||
export const DEPENDENCY_KEYS_SERVICE_TYPE_KEY = 'extollo:di:service_type'
|
||||
|
||||
/**
|
||||
* Interface that designates a particular value as able to be constructed.
|
||||
@@ -13,20 +13,26 @@ export interface Instantiable<T> {
|
||||
* Returns true if the given value is instantiable.
|
||||
* @param what
|
||||
*/
|
||||
export function isInstantiable<T>(what: any): what is Instantiable<T> {
|
||||
return (typeof what === 'object' || typeof what === 'function') && 'constructor' in what && typeof what.constructor === 'function'
|
||||
export function isInstantiable<T>(what: unknown): what is Instantiable<T> {
|
||||
return (
|
||||
Boolean(what)
|
||||
&& (typeof what === 'object' || typeof what === 'function')
|
||||
&& (what !== null)
|
||||
&& 'constructor' in what
|
||||
&& typeof what.constructor === 'function'
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Type that identifies a value as a static class, even if it is not instantiable.
|
||||
*/
|
||||
export type StaticClass<T, T2> = Function & {prototype: T} & T2
|
||||
export type StaticClass<T, T2> = Function & {prototype: T} & T2 // eslint-disable-line @typescript-eslint/ban-types
|
||||
|
||||
/**
|
||||
* Returns true if the parameter is a static class.
|
||||
* @param something
|
||||
*/
|
||||
export function isStaticClass<T, T2>(something: any): something is StaticClass<T, T2> {
|
||||
export function isStaticClass<T, T2>(something: unknown): something is StaticClass<T, T2> {
|
||||
return typeof something === 'function' && typeof something.prototype !== 'undefined'
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user