UNPKG

@inversifyjs/core

Version:

InversifyJs core package

101 lines 3.92 kB
"use strict"; 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