UNPKG

snyk-nodejs-lockfile-parser

Version:
57 lines 3.03 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.buildDepGraphYarnLockV1SimpleCyclesPruned = void 0; const dep_graph_1 = require("@snyk/dep-graph"); const util_1 = require("../util"); const event_loop_spinner_1 = require("event-loop-spinner"); var Color; (function (Color) { Color[Color["GRAY"] = 0] = "GRAY"; Color[Color["BLACK"] = 1] = "BLACK"; })(Color || (Color = {})); const buildDepGraphYarnLockV1SimpleCyclesPruned = async (extractedYarnLockV1Pkgs, pkgJson, options) => { const { includeDevDeps, strictOutOfSync, includeOptionalDeps } = options; const depGraphBuilder = new dep_graph_1.DepGraphBuilder({ name: 'yarn' }, { name: pkgJson.name, version: pkgJson.version }); const colorMap = {}; const topLevelDeps = (0, util_1.getTopLevelDeps)(pkgJson, { includeDevDeps }); const rootNode = { id: 'root-node', name: pkgJson.name, version: pkgJson.version, dependencies: topLevelDeps, isDev: false, }; await dfsVisit(depGraphBuilder, rootNode, colorMap, extractedYarnLockV1Pkgs, strictOutOfSync, includeOptionalDeps); return depGraphBuilder.build(); }; exports.buildDepGraphYarnLockV1SimpleCyclesPruned = buildDepGraphYarnLockV1SimpleCyclesPruned; /** * Use DFS to add all nodes and edges to the depGraphBuilder and prune cyclic nodes. * The colorMap keep track of the state of node during traversal. * - If a node doesn't exist in the map, it means it hasn't been visited. * - If a node is GRAY, it means it has already been discovered but its subtree hasn't been fully traversed. * - If a node is BLACK, it means its subtree has already been fully traversed. * - When first exploring an edge, if it points to a GRAY node, a cycle is found and the GRAY node is pruned. * - A pruned node has id `${originalId}|1` */ const dfsVisit = async (depGraphBuilder, node, colorMap, extractedYarnLockV1Pkgs, strictOutOfSync, includeOptionalDeps) => { colorMap[node.id] = Color.GRAY; for (const [name, depInfo] of Object.entries(node.dependencies || {})) { if (event_loop_spinner_1.eventLoopSpinner.isStarving()) { await event_loop_spinner_1.eventLoopSpinner.spin(); } const childNode = (0, util_1.getChildNode)(name, depInfo, extractedYarnLockV1Pkgs, strictOutOfSync, includeOptionalDeps); if (!colorMap.hasOwnProperty(childNode.id)) { (0, util_1.addPkgNodeToGraph)(depGraphBuilder, childNode, {}); await dfsVisit(depGraphBuilder, childNode, colorMap, extractedYarnLockV1Pkgs, strictOutOfSync, includeOptionalDeps); } else if (colorMap[childNode.id] === Color.GRAY) { // cycle detected childNode.id = `${childNode.id}:pruned`; (0, util_1.addPkgNodeToGraph)(depGraphBuilder, childNode, { isCyclic: true }); } depGraphBuilder.connectDep(node.id, childNode.id); } colorMap[node.id] = Color.BLACK; }; //# sourceMappingURL=build-depgraph-simple-pruned.js.map