"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.DependencyManager = void 0; /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License * 2.0 and the Server Side Public License, v 1; you may not use this file except * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ class DependencyManager { static orderDependencies(graph) { const cycleInfo = DependencyManager.getSortedDependencies(graph); if (cycleInfo.hasCycle) { const error = DependencyManager.getCyclePathError(cycleInfo.path); DependencyManager.throwCyclicPathError(error); } return cycleInfo.path; } /** * DFS algorithm for checking if graph is a DAG (Directed Acyclic Graph) * and sorting topogy (dependencies) if graph is DAG. * @param {Graph} graph - graph of dependencies. */ static getSortedDependencies(graph = {}) { const sortedVertices = new Set(); const vertices = Object.keys(graph); return vertices.reduce((cycleInfo, srcVertex) => { if (cycleInfo.hasCycle) { return cycleInfo; } return DependencyManager.sortVerticesFrom(srcVertex, graph, sortedVertices, {}, {}, cycleInfo); }, DependencyManager.createCycleInfo()); } /** * Modified DFS algorithm for topological sort. * @param {T extends GraphVertex} srcVertex - a source vertex - the start point of dependencies ordering. * @param {Graph} graph - graph of dependencies, represented in the adjacency list form. * @param {Set} sortedVertices - ordered dependencies path from the free to the dependent vertex. * @param {BreadCrumbs} visited - record of visited vertices. * @param {BreadCrumbs} inpath - record of vertices, which was met in the path. Is used for detecting cycles. */ static sortVerticesFrom(srcVertex, graph, sortedVertices, visited = {}, inpath = {}, cycle) { visited[srcVertex] = true; inpath[srcVertex] = true; const vertexEdges = graph[srcVertex] === undefined || graph[srcVertex] === null ? [] : graph[srcVertex]; cycle = vertexEdges.reduce((info, vertex) => { if (inpath[vertex]) { return { ...info, hasCycle: true }; } else if (!visited[vertex]) { return DependencyManager.sortVerticesFrom(vertex, graph, sortedVertices, visited, inpath, info); } return info; }, cycle); inpath[srcVertex] = false; if (!sortedVertices.has(srcVertex)) { sortedVertices.add(srcVertex); } return { ...cycle, path: [...sortedVertices] }; } static createCycleInfo(path = [], hasCycle = false) { return { hasCycle, path }; } static getCyclePathError(cyclePath) { const cycleString = cyclePath.join(' -> '); return `Circular dependency detected while setting up services: ${cycleString}`; } static throwCyclicPathError(error) { throw new Error(error); } } exports.DependencyManager = DependencyManager;