react-obsidian
Version:
Dependency injection framework for React and React Native applications
62 lines (55 loc) • 2.36 kB
text/typescript
import graphRegistry from './registry/GraphRegistry';
import { Graph } from './Graph';
import providedPropertiesStore from '../ProvidedPropertiesStore';
import { CircularDependenciesDetector } from './CircularDependenciesDetector';
export default class PropertyRetriever {
constructor(private graph: Graph) { }
retrieve(
property: string,
receiver?: unknown,
maybeDetector?: CircularDependenciesDetector,
): unknown | undefined {
const mangledPropertyKey = providedPropertiesStore.getMangledProperty(this.graph, property);
const circularDependenciesDetector = maybeDetector ?? new CircularDependenciesDetector(this.graph.name);
if (
mangledPropertyKey
&& mangledPropertyKey in this.graph
&& circularDependenciesDetector.visit(this.graph.name, property)
) {
const proxiedGraph = new Proxy(this.graph, {
get(graph: Graph, dependencyName: string) {
return graph.retrieve(dependencyName, receiver, circularDependenciesDetector);
},
});
const resolved = Reflect.get(this.graph, mangledPropertyKey, receiver)(proxiedGraph);
circularDependenciesDetector.clear();
return resolved;
}
if (circularDependenciesDetector.hasCircularDependencies()) {
throw new Error(
`Could not resolve ${circularDependenciesDetector.firstDependencyName}`
+ ` from ${circularDependenciesDetector.graphName} because of a circular dependency:`
+ ` ${circularDependenciesDetector.getDependencies().join(' -> ')}`,
);
}
const results = this.getFromSubgraphs(property, circularDependenciesDetector, receiver);
if (results.length === 1) return results[0];
if (results.length > 1) {
throw new Error(
`Multiple subgraphs provide the property ${property}.`
+ 'You should probably provide a unique name to one of the providers: @Provide({name: \'uniqueName\')})',
);
}
return undefined;
}
private getFromSubgraphs(
property: string,
circularDependenciesDetector: CircularDependenciesDetector,
receiver: unknown,
): unknown[] {
const subgraphs = graphRegistry.getSubgraphs(this.graph);
return subgraphs
.map((subgraph: Graph) => subgraph.retrieve(property, receiver, circularDependenciesDetector))
.filter((result) => result !== undefined);
}
}