Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | 16x 1x 15x 6x 2x 3x 5x 5x 1x 4x 3x 1x 5x 4x 1x 4x 4x 6x 7x 8x 4x 1x 3x | // @flow
import CircularDependencyError from '../errors/CircularDependencyError';
import DuplicateError from '../errors/DuplicateError';
import NotFoundError from '../errors/NotFoundError';
export type ComponentDefinition = {
name: string,
constructor: Function,
dependencies: string[],
};
export type ComponentDefinitionMap = {
[string]: ComponentDefinition,
};
export class ComponentContainer {
registered: ComponentDefinitionMap = {};
components = {};
register({ name, constructor, dependencies }: ComponentDefinition): void {
if (this.registered[name]) {
throw new DuplicateError(name);
}
this.registered[name] = {
name,
constructor,
dependencies,
};
}
start(): void {
if (this.areDependenciesCyclic()) {
throw new CircularDependencyError();
}
this.createDependencies();
}
getComponent = (name: string): any => {
const component = this.components[name];
if (component === undefined) {
throw new NotFoundError(name);
}
return component;
}
createDependencies = () => Object.keys(this.registered).forEach(this.createDependency);
createNodeDependencies = (key: string) => {
this.registered[key].dependencies.forEach(this.createDependency);
}
createDependency = (dep: string) => {
if (this.components[dep] === undefined) {
if (this.registered[dep].dependencies.length > 0) {
this.createNodeDependencies(dep);
}
this.components[dep] = new this.registered[dep]
.constructor(...this.getDependenciesFromContainer(this.registered[dep].dependencies));
}
}
getDependenciesFromContainer = (dependencies: string[]): any[] =>
dependencies.map(this.getComponent)
areDependenciesCyclic(): boolean {
return Object.keys(this.registered).some(this.isComponentCyclic);
}
isComponentCyclic = (key: string): boolean => this.registered[key].dependencies.includes(key)
|| this.checkComponentDependencies(key, this.registered[key].dependencies)
checkComponentDependencies(key: string, dependencies: string[]): boolean {
return dependencies.some((dep: string) => {
if (this.registered[dep] === undefined) {
throw new NotFoundError(dep);
}
return dependencies.includes(key)
|| this.checkComponentDependencies(key, this.registered[dep].dependencies);
});
}
}
export default new ComponentContainer();
|