@inversifyjs/core
Version:
InversifyJs core package
101 lines • 3.92 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.handleResolveError = handleResolveError;
const common_1 = require("@inversifyjs/common");
const BindingType_1 = require("../../binding/models/BindingType");
const isStackOverflowError_1 = require("../../error/calculations/isStackOverflowError");
const InversifyCoreError_1 = require("../../error/models/InversifyCoreError");
const InversifyCoreErrorKind_1 = require("../../error/models/InversifyCoreErrorKind");
const isPlanServiceRedirectionBindingNode_1 = require("./isPlanServiceRedirectionBindingNode");
const INDEX_NOT_FOUND = -1;
function handleResolveError(params, error) {
if ((0, isStackOverflowError_1.isStackOverflowError)(error)) {
const stringifiedCircularDependencies = stringifyServiceIdentifierTrace(extractLikelyCircularDependency(params));
throw new InversifyCoreError_1.InversifyCoreError(InversifyCoreErrorKind_1.InversifyCoreErrorKind.planning, `Circular dependency found: ${stringifiedCircularDependencies}`, { cause: error });
}
throw error;
}
function extractLikelyCircularDependency(params) {
const root = params.planResult.tree.root;
const stack = [];
function depthFirstSearch(node) {
const existingIndex = stack.indexOf(node);
if (existingIndex !== INDEX_NOT_FOUND) {
const cycleNodes = [
...stack.slice(existingIndex),
node,
];
return cycleNodes.map((n) => n.serviceIdentifier);
}
stack.push(node);
try {
for (const child of getChildServiceNodes(node)) {
const result = depthFirstSearch(child);
if (result !== undefined) {
return result;
}
}
}
finally {
stack.pop();
}
return undefined;
}
const result = depthFirstSearch(root);
return result ?? [];
}
function getChildServiceNodes(serviceNode) {
const children = [];
const bindings = serviceNode.bindings;
if (bindings === undefined) {
return children;
}
const processBindingNode = (bindingNode) => {
if ((0, isPlanServiceRedirectionBindingNode_1.isPlanServiceRedirectionBindingNode)(bindingNode)) {
for (const redirection of bindingNode.redirections) {
processBindingNode(redirection);
}
return;
}
switch (bindingNode.binding.type) {
case BindingType_1.bindingTypeValues.Instance: {
const instanceNode = bindingNode;
for (const ctorParam of instanceNode.constructorParams) {
if (ctorParam !== undefined) {
children.push(ctorParam);
}
}
for (const propParam of instanceNode.propertyParams.values()) {
children.push(propParam);
}
break;
}
case BindingType_1.bindingTypeValues.ResolvedValue: {
const resolvedValueNode = bindingNode;
for (const param of resolvedValueNode.params) {
children.push(param);
}
break;
}
default:
break;
}
};
if (Array.isArray(bindings)) {
for (const bindingNode of bindings) {
processBindingNode(bindingNode);
}
}
else {
processBindingNode(bindings);
}
return children;
}
function stringifyServiceIdentifierTrace(serviceIdentifiers) {
const serviceIdentifiersArray = [...serviceIdentifiers];
if (serviceIdentifiersArray.length === 0) {
return '(No dependency trace)';
}
return serviceIdentifiersArray.map(common_1.stringifyServiceIdentifier).join(' -> ');
}
//# sourceMappingURL=handleResolveError.js.map