File: /home/frenchy/www/french-american.org/current/node_modules/@snyk/dep-graph/dist/core/dep-graph.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var _ = require("lodash");
var graphlib = require("graphlib");
var create_from_json_1 = require("./create-from-json");
var DepGraphImpl = /** @class */ (function () {
function DepGraphImpl(graph, rootNodeId, pkgs, pkgNodes, pkgManager) {
this._countNodePathsToRootCache = new Map();
this._graph = graph;
this._pkgs = pkgs;
this._pkgNodes = pkgNodes;
this._pkgManager = pkgManager;
this._rootNodeId = rootNodeId;
this._rootPkgId = graph.node(rootNodeId).pkgId;
this._pkgList = _.values(pkgs);
}
DepGraphImpl.getPkgId = function (pkg) {
return pkg.name + "@" + (pkg.version || '');
};
Object.defineProperty(DepGraphImpl.prototype, "pkgManager", {
get: function () {
return this._pkgManager;
},
enumerable: true,
configurable: true
});
Object.defineProperty(DepGraphImpl.prototype, "rootPkg", {
get: function () {
return this._pkgs[this._rootPkgId];
},
enumerable: true,
configurable: true
});
Object.defineProperty(DepGraphImpl.prototype, "rootNodeId", {
get: function () {
return this._rootNodeId;
},
enumerable: true,
configurable: true
});
DepGraphImpl.prototype.getPkgs = function () {
return this._pkgList;
};
DepGraphImpl.prototype.getNode = function (nodeId) {
return this.getGraphNode(nodeId).info || {};
};
DepGraphImpl.prototype.getNodePkg = function (nodeId) {
return this._pkgs[this.getGraphNode(nodeId).pkgId];
};
DepGraphImpl.prototype.getPkgNodeIds = function (pkg) {
var pkgId = DepGraphImpl.getPkgId(pkg);
if (!this._pkgs[pkgId]) {
throw new Error("no such pkg: " + pkgId);
}
return Array.from(this._pkgNodes[pkgId]);
};
DepGraphImpl.prototype.getNodeDepsNodeIds = function (nodeId) {
var deps = this._graph.successors(nodeId);
if (!deps) {
throw new Error("no such node: " + nodeId);
}
return deps;
};
DepGraphImpl.prototype.getNodeParentsNodeIds = function (nodeId) {
var parents = this._graph.predecessors(nodeId);
if (!parents) {
throw new Error("no such node: " + nodeId);
}
return parents;
};
DepGraphImpl.prototype.hasCycles = function () {
// `isAcyclic` is expensive, so memoize
if (this._hasCycles === undefined) {
this._hasCycles = !graphlib.alg.isAcyclic(this._graph);
}
return this._hasCycles;
};
DepGraphImpl.prototype.pkgPathsToRoot = function (pkg) {
// TODO: implement cycles support
if (this.hasCycles()) {
throw new Error('pkgPathsToRoot does not support cyclic graphs yet');
}
var pathsToRoot = [];
for (var _i = 0, _a = this.getPkgNodeIds(pkg); _i < _a.length; _i++) {
var id = _a[_i];
pathsToRoot.push.apply(pathsToRoot, this.pathsFromNodeToRoot(id));
}
// note: sorting to get shorter paths first -
// it's nicer - and better resembles older behaviour
return pathsToRoot.sort(function (a, b) { return a.length - b.length; });
};
DepGraphImpl.prototype.countPathsToRoot = function (pkg) {
// TODO: implement cycles support
if (this.hasCycles()) {
throw new Error('countPathsToRoot does not support cyclic graphs yet');
}
var count = 0;
for (var _i = 0, _a = this.getPkgNodeIds(pkg); _i < _a.length; _i++) {
var nodeId = _a[_i];
count += this.countNodePathsToRoot(nodeId);
}
return count;
};
DepGraphImpl.prototype.equals = function (other, _a) {
var _b = (_a === void 0 ? {} : _a).compareRoot, compareRoot = _b === void 0 ? true : _b;
var otherDepGraph;
if (other instanceof DepGraphImpl) {
otherDepGraph = other;
}
else {
// At runtime theoretically we can have multiple versions of
// @snyk/dep-graph. If "other" is not an instance of the same class it is
// safer to rebuild it from JSON.
otherDepGraph = create_from_json_1.createFromJSON(other.toJSON());
}
return this.nodeEquals(this, this.rootNodeId, otherDepGraph, otherDepGraph.rootNodeId, compareRoot);
};
DepGraphImpl.prototype.toJSON = function () {
var _this = this;
var nodeIds = this._graph.nodes();
var nodes = nodeIds.reduce(function (acc, nodeId) {
var deps = (_this._graph.successors(nodeId) || [])
.map(function (depNodeId) { return ({ nodeId: depNodeId }); });
var node = _this._graph.node(nodeId);
var elem = {
nodeId: nodeId,
pkgId: node.pkgId,
deps: deps,
};
if (!_.isEmpty(node.info)) {
elem.info = node.info;
}
acc.push(elem);
return acc;
}, []);
var pkgs = _.keys(this._pkgs)
.map(function (pkgId) { return ({
id: pkgId,
info: _this._pkgs[pkgId],
}); });
return {
schemaVersion: DepGraphImpl.SCHEMA_VERSION,
pkgManager: this._pkgManager,
pkgs: pkgs,
graph: {
rootNodeId: this._rootNodeId,
nodes: nodes,
},
};
};
DepGraphImpl.prototype.nodeEquals = function (graphA, nodeIdA, graphB, nodeIdB, compareRoot, traversedPairs) {
if (traversedPairs === void 0) { traversedPairs = new Set(); }
// Skip root nodes comparision if needed.
if (compareRoot || (nodeIdA !== graphA.rootNodeId && nodeIdB !== graphB.rootNodeId)) {
var pkgA = graphA.getNodePkg(nodeIdA);
var pkgB = graphB.getNodePkg(nodeIdB);
// Compare PkgInfo (name and version).
if (!_.isEqual(pkgA, pkgB)) {
return false;
}
var infoA = graphA.getNode(nodeIdA);
var infoB = graphB.getNode(nodeIdB);
// Compare NodeInfo (VersionProvenance and labels).
if (!_.isEqual(infoA, infoB)) {
return false;
}
}
var depsA = graphA.getNodeDepsNodeIds(nodeIdA);
var depsB = graphB.getNodeDepsNodeIds(nodeIdB);
// Number of dependencies should be the same.
if (depsA.length !== depsB.length) {
return false;
}
// Sort dependencies by name@version string.
var sortFn = function (graph) { return function (idA, idB) {
var pkgA = graph.getNodePkg(idA);
var pkgB = graph.getNodePkg(idB);
return DepGraphImpl.getPkgId(pkgA).localeCompare(DepGraphImpl.getPkgId(pkgB));
}; };
depsA = depsA.sort(sortFn(graphA));
depsB = depsB.sort(sortFn(graphB));
// Compare Each dependency recursively.
for (var i = 0; i < depsA.length; i++) {
var pairKey = depsA[i] + "_" + depsB[i];
// Prevent cycles.
if (traversedPairs.has(pairKey)) {
continue;
}
traversedPairs.add(pairKey);
if (!this.nodeEquals(graphA, depsA[i], graphB, depsB[i], compareRoot, traversedPairs)) {
return false;
}
}
return true;
};
DepGraphImpl.prototype.getGraphNode = function (nodeId) {
var node = this._graph.node(nodeId);
if (!node) {
throw new Error("no such node: " + nodeId);
}
return node;
};
DepGraphImpl.prototype.pathsFromNodeToRoot = function (nodeId) {
var _this = this;
var parentNodesIds = this.getNodeParentsNodeIds(nodeId);
if (parentNodesIds.length === 0) {
return [[this.getNodePkg(nodeId)]];
}
var allPaths = [];
parentNodesIds.map(function (id) {
var out = _this.pathsFromNodeToRoot(id).map(function (path) {
return [_this.getNodePkg(nodeId)].concat(path);
});
allPaths.push.apply(allPaths, out);
});
return allPaths;
};
DepGraphImpl.prototype.countNodePathsToRoot = function (nodeId) {
var _this = this;
if (this._countNodePathsToRootCache.has(nodeId)) {
return this._countNodePathsToRootCache.get(nodeId) || 0;
}
var parentNodesIds = this.getNodeParentsNodeIds(nodeId);
if (parentNodesIds.length === 0) {
this._countNodePathsToRootCache.set(nodeId, 1);
return 1;
}
var count = parentNodesIds.reduce(function (acc, parentNodeId) {
return acc + _this.countNodePathsToRoot(parentNodeId);
}, 0);
this._countNodePathsToRootCache.set(nodeId, count);
return count;
};
DepGraphImpl.SCHEMA_VERSION = '1.2.0';
return DepGraphImpl;
}());
exports.DepGraphImpl = DepGraphImpl;
//# sourceMappingURL=dep-graph.js.map