Skip to content

Commit 04e2e4a

Browse files
committed
feat: .getDepPkgs() to get all pkgs except root
1 parent 99110fb commit 04e2e4a

File tree

6 files changed

+68
-1
lines changed

6 files changed

+68
-1
lines changed

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,21 @@ export interface DepGraph {
5151
name: string;
5252
version: string | null;
5353
};
54+
// all unique packages in the graph (including root package)
5455
getPkgs(): Array<{
5556
name: string;
5657
version: string | null;
5758
}>;
59+
// all unique packages in the graph, except the root package
60+
getDepPkgs(): Array<{
61+
name: string;
62+
version: string | null;
63+
}>;
5864
pkgPathsToRoot(pkg: Pkg): Array<Array<{
5965
name: string;
6066
version: string | null;
6167
}>>;
68+
countPathsToRoot(pkg: Pkg): number;
6269
toJSON(): DepGraphData;
6370
equals(other: DepGraph, options?: { compareRoot?: boolean }): boolean;
6471
}

src/core/dep-graph.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ class DepGraphImpl implements types.DepGraphInternal {
2323
private _pkgNodes: { [pkgId: string]: Set<string> };
2424

2525
private _pkgList: types.PkgInfo[];
26+
private _depPkgsList: types.PkgInfo[];
2627

2728
private _graph: graphlib.Graph;
2829
private _pkgManager: types.PkgManager;
@@ -50,6 +51,8 @@ class DepGraphImpl implements types.DepGraphInternal {
5051
this._rootPkgId = (graph.node(rootNodeId) as Node).pkgId;
5152

5253
this._pkgList = _.values(pkgs);
54+
this._depPkgsList = this._pkgList
55+
.filter((pkg) => pkg !== this.rootPkg);
5356
}
5457

5558
get pkgManager() {
@@ -68,6 +71,10 @@ class DepGraphImpl implements types.DepGraphInternal {
6871
return this._pkgList;
6972
}
7073

74+
public getDepPkgs(): types.PkgInfo[] {
75+
return this._depPkgsList;
76+
}
77+
7178
public getNode(nodeId: string): types.NodeInfo {
7279
return this.getGraphNode(nodeId).info || {};
7380
}

src/core/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ export interface DepGraph {
8484
readonly pkgManager: PkgManager;
8585
readonly rootPkg: PkgInfo;
8686
getPkgs(): PkgInfo[];
87+
getDepPkgs(): PkgInfo[];
8788
toJSON(): DepGraphData;
8889
pkgPathsToRoot(pkg: Pkg): PkgInfo[][];
8990
countPathsToRoot(pkg: Pkg): number;

test/core/builder.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@ describe('empty graph', () => {
99
expect(depGraph.pkgManager.name).toEqual('pip');
1010
expect(depGraph.rootPkg).toHaveProperty('name');
1111
expect(depGraph.getPkgs()).toHaveLength(1);
12+
expect(depGraph.getDepPkgs()).toHaveLength(0);
1213
});
1314
});

test/core/create-from-json.test.ts

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ describe('fromJSON simple', () => {
1616

1717
});
1818

19-
test('getPkgs', async () => {
19+
test('getPkgs()', async () => {
2020
expect(graph.getPkgs().sort(helpers.depSort)).toEqual([
2121
{ name: 'a', version: '1.0.0' },
2222
{ name: 'b', version: '1.0.0' },
@@ -28,6 +28,17 @@ describe('fromJSON simple', () => {
2828
].sort(helpers.depSort));
2929
});
3030

31+
test('getDepPkgs()', async () => {
32+
expect(graph.getDepPkgs().sort(helpers.depSort)).toEqual([
33+
{ name: 'a', version: '1.0.0' },
34+
{ name: 'b', version: '1.0.0' },
35+
{ name: 'c', version: '1.0.0' },
36+
{ name: 'd', version: '0.0.1' },
37+
{ name: 'd', version: '0.0.2' },
38+
{ name: 'e', version: '5.0.0' },
39+
].sort(helpers.depSort));
40+
});
41+
3142
test('getPathsToRoot', async () => {
3243
expect(graph.pkgPathsToRoot({ name: 'd', version: '0.0.1' })).toHaveLength(1);
3344
expect(graph.countPathsToRoot({ name: 'd', version: '0.0.1' })).toBe(1);
@@ -133,6 +144,9 @@ test('fromJSON a pkg and a node share same id', async () => {
133144
{ name: 'toor', version: '1.0.0' },
134145
{ name: 'foo', version: '2' },
135146
].sort());
147+
expect(depGraph.getDepPkgs()).toEqual([
148+
{ name: 'foo', version: '2' },
149+
]);
136150

137151
expect(depGraph.pkgPathsToRoot({ name: 'foo', version: '2' })).toEqual([[
138152
{ name: 'foo', version: '2' },
@@ -166,6 +180,7 @@ test('fromJSON no deps', async () => {
166180

167181
expect(depGraph.rootPkg).toEqual({ name: 'toor', version: '1.0.0' });
168182
expect(depGraph.getPkgs()).toEqual([{ name: 'toor', version: '1.0.0' }]);
183+
expect(depGraph.getDepPkgs()).toEqual([]);
169184
expect(depGraph.pkgManager.name).toEqual('pip');
170185
});
171186

@@ -176,6 +191,7 @@ test('fromJSON inside schemaVersion', async () => {
176191

177192
const depGraph = depGraphLib.createFromJSON(graphJson);
178193
expect(depGraph.getPkgs()).toHaveLength(7);
194+
expect(depGraph.getDepPkgs()).toHaveLength(6);
179195
});
180196

181197
test('fromJSON too old schemaVersion', async () => {
@@ -342,6 +358,11 @@ test('fromJSON with a cycle', async () => {
342358
{ name: 'bar', version: '3' },
343359
{ name: 'baz', version: '4' },
344360
]);
361+
expect(depGraph.getDepPkgs().sort()).toEqual([
362+
{ name: 'foo', version: '2' },
363+
{ name: 'bar', version: '3' },
364+
{ name: 'baz', version: '4' },
365+
]);
345366

346367
// const convertToDepTree = async () => depGraphLib.legacy.graphToDepTree(depGraph);
347368
// expect(convertToDepTree()).rejects.toThrow(/cycl/);
@@ -631,6 +652,9 @@ test('fromJSON root has several instances', async () => {
631652
{name: 'toor', version: '1.0.0'},
632653
{name: 'foo', version: '2'},
633654
].sort());
655+
expect(depGraph.getDepPkgs().sort()).toEqual([
656+
{name: 'foo', version: '2'},
657+
].sort());
634658
expect(depGraph.countPathsToRoot({name: 'toor', version: '1.0.0'})).toBe(2);
635659
});
636660

@@ -737,6 +761,9 @@ test('fromJSON a pkg missing version field', async () => {
737761
{ name: 'toor', version: '1.0.0' },
738762
{ name: 'foo', version: null },
739763
]);
764+
expect(depGraph.getDepPkgs().sort()).toEqual([
765+
{ name: 'foo', version: null },
766+
]);
740767
});
741768

742769
test('fromJSON pkg-id is not name@version', async () => {

test/legacy/from-dep-tree.test.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,14 @@ describe('depTreeToGraph simple dysmorphic', () => {
3838
{ name: 'e', version: '5.0.0' },
3939
{ name: 'root', version: '0.0.0' },
4040
].sort(helpers.depSort));
41+
expect(depGraph.getDepPkgs().sort(helpers.depSort)).toEqual([
42+
{ name: 'a', version: '1.0.0' },
43+
{ name: 'b', version: '1.0.0' },
44+
{ name: 'c', version: '1.0.0' },
45+
{ name: 'd', version: '0.0.1' },
46+
{ name: 'd', version: '0.0.2' },
47+
{ name: 'e', version: '5.0.0' },
48+
].sort(helpers.depSort));
4149
});
4250

4351
test('getPathsToRoot', async () => {
@@ -113,6 +121,7 @@ describe('depTreeToGraph 0 deps', () => {
113121
const depGraph = await depGraphLib.legacy.depTreeToGraph(depTree, 'npm');
114122

115123
expect(depGraph.getPkgs()).toHaveLength(1);
124+
expect(depGraph.getDepPkgs()).toHaveLength(0);
116125
});
117126
});
118127

@@ -125,6 +134,7 @@ describe('depTreeToGraph goof', () => {
125134
depGraph = await depGraphLib.legacy.depTreeToGraph(depTree, 'npm');
126135

127136
expect(depGraph.getPkgs()).toHaveLength(439);
137+
expect(depGraph.getDepPkgs()).toHaveLength(438);
128138
});
129139

130140
test('check nodes', async () => {
@@ -181,6 +191,7 @@ describe('depTreeToGraph with pkg that that misses a version', () => {
181191
const depGraph = await depGraphLib.legacy.depTreeToGraph(depTree, 'npm');
182192

183193
expect(depGraph.getPkgs()).toHaveLength(3);
194+
expect(depGraph.getDepPkgs()).toHaveLength(2);
184195

185196
const depGraphInternal = depGraph as types.DepGraphInternal;
186197
expect(depGraphInternal.getPkgNodeIds({name: 'bar'} as any)).toEqual(['bar@']);
@@ -210,13 +221,15 @@ describe('depTreeToGraph with funky pipes in the version', () => {
210221
test('create', async () => {
211222
depGraph = await depGraphLib.legacy.depTreeToGraph(depTree, 'composer');
212223
expect(depGraph.getPkgs()).toHaveLength(4);
224+
expect(depGraph.getDepPkgs()).toHaveLength(3);
213225
});
214226

215227
test('convert to JSON and back', async () => {
216228
const graphJson = depGraph.toJSON();
217229
const restoredGraph = await depGraphLib.createFromJSON(graphJson);
218230

219231
expect(restoredGraph.getPkgs().sort()).toEqual(depGraph.getPkgs().sort());
232+
expect(restoredGraph.getDepPkgs().sort()).toEqual(depGraph.getDepPkgs().sort());
220233
});
221234
});
222235

@@ -243,6 +256,12 @@ describe('depTreeToGraph cycle with root', () => {
243256
test('create', async () => {
244257
depGraph = await depGraphLib.legacy.depTreeToGraph(depTree, 'composer');
245258
expect(depGraph.getPkgs()).toHaveLength(3);
259+
// note that despite maple@3 being a dependency of bar@1,
260+
// it's still not returned, as it's the root package.
261+
expect(depGraph.getDepPkgs()).toEqual([
262+
{name: 'bar', version: '1'},
263+
{name: 'foo', version: '2'},
264+
]);
246265

247266
expect(depGraph.countPathsToRoot(depGraph.rootPkg)).toBe(2);
248267
expect(depGraph.pkgPathsToRoot(depGraph.rootPkg)).toEqual([
@@ -262,6 +281,7 @@ describe('depTreeToGraph cycle with root', () => {
262281
const restoredGraph = await depGraphLib.createFromJSON(graphJson);
263282

264283
expect(restoredGraph.getPkgs().sort()).toEqual(depGraph.getPkgs().sort());
284+
expect(restoredGraph.getDepPkgs().sort()).toEqual(depGraph.getDepPkgs().sort());
265285
});
266286
});
267287

@@ -296,6 +316,10 @@ describe('depTreeToGraph with (invalid) null dependency', () => {
296316
{name: 'foo', version: '1'},
297317
{name: 'baz', version: '3'},
298318
], 'name'));
319+
expect(_.sortBy(depGraph.getDepPkgs(), 'name')).toEqual(_.sortBy([
320+
{name: 'foo', version: '1'},
321+
{name: 'baz', version: '3'},
322+
], 'name'));
299323
});
300324
});
301325

0 commit comments

Comments
 (0)