Import other modules into monorepo
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
2021-06-01 20:59:40 -05:00
parent 26d54033af
commit 9be9c44a32
138 changed files with 11544 additions and 139 deletions

View 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>
}

View 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
View 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
}
}

View 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
}
}

View 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>()
}
}