Import other modules into monorepo
Some checks failed
continuous-integration/drone/push Build is failing
Some checks failed
continuous-integration/drone/push Build is failing
This commit is contained in:
44
src/di/factory/AbstractFactory.ts
Normal file
44
src/di/factory/AbstractFactory.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import {DependencyRequirement, PropertyDependency} from "../types";
|
||||
import { Collection } from "../../util";
|
||||
|
||||
/**
|
||||
* Abstract base class for dependency container factories.
|
||||
* @abstract
|
||||
*/
|
||||
export abstract class AbstractFactory {
|
||||
protected constructor(
|
||||
/**
|
||||
* Token that was registered for this factory. In most cases, this is the static
|
||||
* form of the item that is to be produced by this factory.
|
||||
* @var
|
||||
* @protected
|
||||
*/
|
||||
protected token: any
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Produce an instance of the token.
|
||||
* @param {Array} dependencies - the resolved dependencies, in order
|
||||
* @param {Array} parameters - the bound constructor parameters, in order
|
||||
*/
|
||||
abstract produce(dependencies: any[], parameters: any[]): any
|
||||
|
||||
/**
|
||||
* Should return true if the given identifier matches the token for this factory.
|
||||
* @param something
|
||||
* @return boolean
|
||||
*/
|
||||
abstract match(something: any): boolean
|
||||
|
||||
/**
|
||||
* Get the dependency requirements required by this factory's token.
|
||||
* @return Collection<DependencyRequirement>
|
||||
*/
|
||||
abstract getDependencyKeys(): Collection<DependencyRequirement>
|
||||
|
||||
/**
|
||||
* Get the property dependencies that should be injected to the created instance.
|
||||
* @return Collection<PropertyDependency>
|
||||
*/
|
||||
abstract getInjectedProperties(): Collection<PropertyDependency>
|
||||
}
|
||||
43
src/di/factory/ClosureFactory.ts
Normal file
43
src/di/factory/ClosureFactory.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import {AbstractFactory} from "./AbstractFactory";
|
||||
import {DependencyRequirement, PropertyDependency, StaticClass} from "../types";
|
||||
import {Collection} from "../../util";
|
||||
|
||||
/**
|
||||
* A factory whose token is produced by calling a function.
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* let i = 0
|
||||
* const fact = new ClosureFactory('someName', () => {
|
||||
* i += 1
|
||||
* return i * 2
|
||||
* })
|
||||
*
|
||||
* fact.produce([], []) // => 2
|
||||
* fact.produce([], []) // => 4
|
||||
* ```
|
||||
*/
|
||||
export class ClosureFactory extends AbstractFactory {
|
||||
constructor(
|
||||
protected readonly name: string | StaticClass<any, any>,
|
||||
protected readonly token: () => any,
|
||||
) {
|
||||
super(token)
|
||||
}
|
||||
|
||||
produce(dependencies: any[], parameters: any[]): any {
|
||||
return this.token()
|
||||
}
|
||||
|
||||
match(something: any) {
|
||||
return something === this.name
|
||||
}
|
||||
|
||||
getDependencyKeys(): Collection<DependencyRequirement> {
|
||||
return new Collection<DependencyRequirement>()
|
||||
}
|
||||
|
||||
getInjectedProperties(): Collection<PropertyDependency> {
|
||||
return new Collection<PropertyDependency>()
|
||||
}
|
||||
}
|
||||
65
src/di/factory/Factory.ts
Normal file
65
src/di/factory/Factory.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
import {AbstractFactory} from "./AbstractFactory";
|
||||
import {
|
||||
DEPENDENCY_KEYS_METADATA_KEY,
|
||||
DEPENDENCY_KEYS_PROPERTY_METADATA_KEY,
|
||||
DependencyRequirement,
|
||||
Instantiable,
|
||||
PropertyDependency
|
||||
} from "../types";
|
||||
import {Collection} from "../../util";
|
||||
import 'reflect-metadata'
|
||||
|
||||
/**
|
||||
* Standard static-class factory. The token of this factory is a reference to a
|
||||
* static class that is instantiated when the factory produces.
|
||||
*
|
||||
* Dependency keys are inferred from injection metadata on the constructor's params,
|
||||
* as are the injected properties.
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* class A {
|
||||
* constructor(
|
||||
* protected readonly myService: MyService
|
||||
* ) { }
|
||||
* }
|
||||
*
|
||||
* const fact = new Factory(A)
|
||||
*
|
||||
* fact.produce([myServiceInstance], []) // => A { myService: myServiceInstance }
|
||||
* ```
|
||||
*/
|
||||
export class Factory extends AbstractFactory {
|
||||
constructor(
|
||||
protected readonly token: Instantiable<any>
|
||||
) {
|
||||
super(token)
|
||||
}
|
||||
|
||||
produce(dependencies: any[], parameters: any[]): any {
|
||||
return new this.token(...dependencies, ...parameters)
|
||||
}
|
||||
|
||||
match(something: any) {
|
||||
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
|
||||
return new Collection<DependencyRequirement>()
|
||||
}
|
||||
|
||||
getInjectedProperties(): Collection<PropertyDependency> {
|
||||
const meta = new Collection<PropertyDependency>()
|
||||
let currentToken = this.token
|
||||
|
||||
do {
|
||||
const loadedMeta = Reflect.getMetadata(DEPENDENCY_KEYS_PROPERTY_METADATA_KEY, currentToken)
|
||||
if ( loadedMeta ) meta.concat(loadedMeta)
|
||||
currentToken = Object.getPrototypeOf(currentToken)
|
||||
} while (Object.getPrototypeOf(currentToken) !== Function.prototype && Object.getPrototypeOf(currentToken) !== Object.prototype)
|
||||
|
||||
return meta
|
||||
}
|
||||
}
|
||||
29
src/di/factory/NamedFactory.ts
Normal file
29
src/di/factory/NamedFactory.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
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 {
|
||||
constructor(
|
||||
/**
|
||||
* The name identifying this factory in the container.
|
||||
* @type {string}
|
||||
*/
|
||||
protected name: string,
|
||||
|
||||
/**
|
||||
* The token to be instantiated.
|
||||
* @type {Instantiable}
|
||||
*/
|
||||
protected token: Instantiable<any>,
|
||||
) {
|
||||
super(token)
|
||||
}
|
||||
|
||||
match(something: any) {
|
||||
return something === this.name
|
||||
}
|
||||
}
|
||||
54
src/di/factory/SingletonFactory.ts
Normal file
54
src/di/factory/SingletonFactory.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
import { Factory } from './Factory'
|
||||
import { Collection } from '../../util'
|
||||
import {DependencyRequirement, PropertyDependency} from "../types";
|
||||
|
||||
/**
|
||||
* Container factory which returns its token as its value, without attempting
|
||||
* to instantiate anything. This is used to register already-produced-singletons
|
||||
* with the container.
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* class A {}
|
||||
* const exactlyThisInstanceOfA = new A()
|
||||
*
|
||||
* const fact = new SingletonFactory(A, a)
|
||||
*
|
||||
* fact.produce([], []) // => exactlyThisInstanceOfA
|
||||
* ```
|
||||
*
|
||||
* @extends Factory
|
||||
*/
|
||||
export default class SingletonFactory extends Factory {
|
||||
constructor(
|
||||
/**
|
||||
* Instantiated value of this factory.
|
||||
* @type FunctionConstructor
|
||||
*/
|
||||
protected token: FunctionConstructor,
|
||||
|
||||
/**
|
||||
* String name of this singleton identifying it in the container.
|
||||
* @type string
|
||||
*/
|
||||
protected key: string,
|
||||
) {
|
||||
super(token)
|
||||
}
|
||||
|
||||
produce(dependencies: any[], parameters: any[]) {
|
||||
return this.token
|
||||
}
|
||||
|
||||
match(something: any) {
|
||||
return something === this.key
|
||||
}
|
||||
|
||||
getDependencyKeys(): Collection<DependencyRequirement> {
|
||||
return new Collection<DependencyRequirement>()
|
||||
}
|
||||
|
||||
getInjectedProperties(): Collection<PropertyDependency> {
|
||||
return new Collection<PropertyDependency>()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user