Skip to content

Commit

Permalink
feat: add directDepsLeadingTo public method
Browse files Browse the repository at this point in the history
Get the direct deps via which the specified package was introduced
  • Loading branch information
AndreDalcher committed Feb 26, 2020
1 parent fc9ff9a commit 0fa0136
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 0 deletions.
4 changes: 4 additions & 0 deletions README.md
Expand Up @@ -65,6 +65,10 @@ export interface DepGraph {
name: string;
version?: string;
}>>;
directDepsLeadingTo(pkg: Pkg): Array<{
name: string;
version?: string;
}>;
countPathsToRoot(pkg: Pkg): number;
toJSON(): DepGraphData;
equals(other: DepGraph, options?: { compareRoot?: boolean }): boolean;
Expand Down
10 changes: 10 additions & 0 deletions src/core/dep-graph.ts
Expand Up @@ -183,6 +183,16 @@ class DepGraphImpl implements types.DepGraphInternal {
return this.nodeEquals(this, this.rootNodeId, otherDepGraph, otherDepGraph.rootNodeId, compareRoot);
}

public directDepsLeadingTo(pkg: types.Pkg): types.PkgInfo[] {
const pkgNodes = this.getPkgNodeIds(pkg);
const directDeps = this.getNodeDepsNodeIds(this.rootNodeId);
const nodes = directDeps.filter((directDep) => {
const reachableNodes = graphlib.alg.postorder(this._graph, [directDep]);
return reachableNodes.filter((node) => pkgNodes.includes(node)).length;
});
return nodes.map((node) => this.getNodePkg(node));
}

public toJSON(): types.DepGraphData {
const nodeIds = this._graph.nodes();

Expand Down
1 change: 1 addition & 0 deletions src/core/types.ts
Expand Up @@ -94,6 +94,7 @@ export interface DepGraph {
getPkgNodes(pkg: Pkg): Node[];
toJSON(): DepGraphData;
pkgPathsToRoot(pkg: Pkg): PkgInfo[][];
directDepsLeadingTo(pkg: Pkg): PkgInfo[];
countPathsToRoot(pkg: Pkg): number;
equals(other: DepGraph, options?: { compareRoot?: boolean }): boolean;
}
Expand Down
53 changes: 53 additions & 0 deletions test/core/direct-deps-leading-to.test.ts
@@ -0,0 +1,53 @@
import * as depGraphLib from "../../src";
import * as helpers from "../helpers";

describe("directDepsLeadingTo", () => {
const depGraph = depGraphLib.createFromJSON(
helpers.loadFixture("goof-graph.json")
);

test("it gets the package itself if it is a direct dependency", () => {
const pkg = { name: "consolidate", version: "0.14.5" };

expect(depGraph.directDepsLeadingTo(pkg)).toEqual([pkg]);
});

test("it gets the direct deps leading to a package, respecting the version", () => {
const pkgA = { name: "bluebird", version: "2.9.26" };
const pkgB = { name: "bluebird", version: "3.5.2" };

const expectedDepsA = [{ name: "mongoose", version: "4.2.4" }];
const expectedDepsB = [
{ name: "consolidate", version: "0.14.5" },
{ name: "tap", version: "5.8.0" }
];

const directDepsForA = depGraph.directDepsLeadingTo(pkgA);
const directDepsForB = depGraph.directDepsLeadingTo(pkgB);

expect(directDepsForA).toEqual(expectedDepsA);
expect(directDepsForB).toEqual(expectedDepsB);
expect(directDepsForA).not.toEqual(directDepsForB);
});

test("it gets the correct direct deps for a deep dependency", () => {
const pkg = { name: "isarray", version: "0.0.1" };
const expected = [
{ name: "express-fileupload", version: "0.0.5" },
{ name: "mongoose", version: "4.2.4" },
{ name: "tap", version: "5.8.0" }
];

expect(depGraph.directDepsLeadingTo(pkg)).toEqual(expected);
});

test("it works with a cyclic dep-graph", () => {
const cyclic = depGraphLib.createFromJSON(
helpers.loadFixture("cyclic-dep-graph.json")
);
const pkg = { name: "baz", version: "4" };
const expected = [{ name: "foo", version: "2" }];

expect(cyclic.directDepsLeadingTo(pkg)).toEqual(expected);
});
});

0 comments on commit 0fa0136

Please sign in to comment.