Skip to content

Commit 4f31996

Browse files
Merge pull request #296 from snyk/feat/CSENG-94/add-npm-scope
feat: add npm scope [CSENG-94]
2 parents 57e6278 + 15bf216 commit 4f31996

22 files changed

Lines changed: 867 additions & 21 deletions

lib/dep-graph-builders/npm-lock-v2/index.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
getTopLevelDeps,
1414
parsePkgJson,
1515
PkgNode,
16+
createNodeInfo,
1617
} from '../util';
1718
import { OutOfSyncError } from '../../errors';
1819
import { LockfileType } from '../../parsers';
@@ -38,6 +39,7 @@ export const parseNpmLockV2Project = async (
3839
strictOutOfSync,
3940
includeOptionalDeps,
4041
pruneNpmStrictOutOfSync,
42+
showNpmScope,
4143
} = options;
4244

4345
const pkgJson: PackageJsonBase = parsePkgJson(
@@ -52,6 +54,7 @@ export const parseNpmLockV2Project = async (
5254
includeOptionalDeps,
5355
strictOutOfSync,
5456
pruneNpmStrictOutOfSync,
57+
showNpmScope,
5558
});
5659

5760
return depgraph;
@@ -67,10 +70,12 @@ export const buildDepGraphNpmLockV2 = async (
6770
strictOutOfSync,
6871
includeOptionalDeps,
6972
pruneNpmStrictOutOfSync,
73+
showNpmScope,
7074
} = options;
7175
const depGraphBuilder = new DepGraphBuilder(
7276
{ name: 'npm' },
7377
{ name: pkgJson.name as string, version: pkgJson.version },
78+
createNodeInfo(options),
7479
);
7580

7681
const topLevelDeps = getTopLevelDeps(pkgJson, {
@@ -120,6 +125,7 @@ export const buildDepGraphNpmLockV2 = async (
120125
pkgKeysByName,
121126
pkgJson.overrides,
122127
pruneNpmStrictOutOfSync,
128+
showNpmScope,
123129
);
124130
return depGraphBuilder.build();
125131
};
@@ -144,6 +150,7 @@ const dfsVisit = async (
144150
pkgKeysByName: Map<string, string[]>,
145151
overrides: Overrides | undefined,
146152
pruneNpmStrictOutOfSync?: boolean,
153+
showNpmScope?: boolean,
147154
): Promise<void> => {
148155
visitedMap.add(node.id);
149156

@@ -175,7 +182,7 @@ const dfsVisit = async (
175182
);
176183

177184
if (!visitedMap.has(childNode.id)) {
178-
addPkgNodeToGraph(depGraphBuilder, childNode, {});
185+
addPkgNodeToGraph(depGraphBuilder, childNode, { showNpmScope });
179186
await dfsVisit(
180187
depGraphBuilder,
181188
childNode,
@@ -196,6 +203,8 @@ const dfsVisit = async (
196203
],
197204
pkgKeysByName,
198205
overrides,
206+
undefined,
207+
showNpmScope,
199208
);
200209
}
201210

lib/dep-graph-builders/pnpm/build-dep-graph-pnpm.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { DepGraphBuilder } from '@snyk/dep-graph';
2-
import { getTopLevelDeps } from '../util';
2+
import { createNodeInfo, getTopLevelDeps } from '../util';
33
import type { Overrides, PnpmProjectParseOptions } from '../types';
44
import type { PackageJsonBase } from '../types';
55
import { getPnpmChildNode } from './utils';
@@ -28,11 +28,13 @@ export const buildDepGraphPnpm = async (
2828
includeOptionalDeps,
2929
includeDevDeps,
3030
pruneWithinTopLevelDeps,
31+
showNpmScope,
3132
} = options;
3233

3334
const depGraphBuilder = new DepGraphBuilder(
3435
{ name: 'pnpm' },
3536
{ name: pkgJson.name, version: pkgJson.version || UNDEFINED_VERSION },
37+
createNodeInfo(options),
3638
);
3739

3840
lockFileParser.extractedPackages = lockFileParser.extractPackages();
@@ -84,6 +86,8 @@ export const buildDepGraphPnpm = async (
8486
pkgJson.pnpm?.overrides || {},
8587
pruneWithinTopLevelDeps,
8688
lockFileParser,
89+
undefined,
90+
showNpmScope,
8791
);
8892

8993
return depGraphBuilder.build();
@@ -107,6 +111,7 @@ const dfsVisit = async (
107111
pruneWithinTopLevel: boolean,
108112
lockFileParser: PnpmLockfileParser,
109113
visited?: Set<string>,
114+
showNpmScope?: boolean,
110115
): Promise<void> => {
111116
for (const [name, depInfo] of Object.entries(node.dependencies || {})) {
112117
if (eventLoopSpinner.isStarving()) {
@@ -134,6 +139,9 @@ const dfsVisit = async (
134139
{
135140
labels: {
136141
scope: childNode.isDev ? 'dev' : 'prod',
142+
...(showNpmScope && {
143+
'npm:scope': childNode.isDev ? 'dev' : 'prod',
144+
}),
137145
pruned: 'true',
138146
...(node.missingLockFileEntry && {
139147
missingLockFileEntry: 'true',
@@ -154,6 +162,9 @@ const dfsVisit = async (
154162
{
155163
labels: {
156164
scope: childNode.isDev ? 'dev' : 'prod',
165+
...(showNpmScope && {
166+
'npm:scope': childNode.isDev ? 'dev' : 'prod',
167+
}),
157168
...(node.missingLockFileEntry && {
158169
missingLockFileEntry: 'true',
159170
}),
@@ -174,6 +185,7 @@ const dfsVisit = async (
174185
pruneWithinTopLevel,
175186
lockFileParser,
176187
localVisited,
188+
showNpmScope,
177189
);
178190
}
179191
};

lib/dep-graph-builders/pnpm/parse-project.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export const parsePnpmProject = async (
1717
includeOptionalDeps,
1818
strictOutOfSync,
1919
pruneWithinTopLevelDeps,
20+
showNpmScope,
2021
} = options;
2122
let importer = '';
2223

@@ -47,6 +48,7 @@ export const parsePnpmProject = async (
4748
includePeerDeps,
4849
includeOptionalDeps,
4950
pruneWithinTopLevelDeps,
51+
showNpmScope,
5052
},
5153
importer,
5254
);

lib/dep-graph-builders/pnpm/parse-workspace-project.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export const parsePnpmWorkspaceProject = async (
2020
includeOptionalDeps,
2121
strictOutOfSync,
2222
pruneWithinTopLevelDeps,
23+
showNpmScope,
2324
} = options;
2425

2526
const lockFileParser: PnpmLockfileParser = getPnpmLockfileParser(
@@ -47,6 +48,7 @@ export const parsePnpmWorkspaceProject = async (
4748
strictOutOfSync,
4849
includeOptionalDeps,
4950
pruneWithinTopLevelDeps,
51+
showNpmScope,
5052
},
5153
importer,
5254
);

lib/dep-graph-builders/pnpm/parse-workspace.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ export const parsePnpmWorkspace = async (
5656
strictOutOfSync,
5757
pruneWithinTopLevelDeps,
5858
exclude,
59+
showNpmScope,
5960
} = options;
6061

6162
const pnpmLockfileContents = getFileContents(
@@ -110,6 +111,7 @@ export const parsePnpmWorkspace = async (
110111
strictOutOfSync,
111112
includeOptionalDeps,
112113
pruneWithinTopLevelDeps,
114+
showNpmScope,
113115
},
114116
importer,
115117
);

lib/dep-graph-builders/types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ export type DepGraphBuildOptions = {
4646
includePeerDeps?: boolean;
4747
pruneNpmStrictOutOfSync?: boolean;
4848
honorAliases?: boolean;
49+
showNpmScope?: boolean;
4950
};
5051

5152
export type LockFileParseOptions = {
@@ -69,6 +70,7 @@ export type YarnLockV2ProjectParseOptions = {
6970
strictOutOfSync: boolean;
7071
pruneWithinTopLevelDeps: boolean;
7172
honorAliases?: boolean;
73+
showNpmScope?: boolean;
7274
};
7375

7476
/*
@@ -86,6 +88,7 @@ export type YarnLockV1ProjectParseOptions = {
8688
strictOutOfSync: boolean;
8789
pruneLevel: PruneLevel;
8890
honorAliases?: boolean;
91+
showNpmScope?: boolean;
8992
};
9093

9194
export type Yarn1DepGraphBuildOptions = {
@@ -94,6 +97,7 @@ export type Yarn1DepGraphBuildOptions = {
9497
includePeerDeps: boolean;
9598
strictOutOfSync: boolean;
9699
pruneWithinTopLevelDeps: boolean;
100+
showNpmScope?: boolean;
97101
};
98102

99103
export type PnpmWorkspaceArgs = {
@@ -113,6 +117,7 @@ export type PnpmProjectParseOptions = {
113117
strictOutOfSync: boolean;
114118
pruneWithinTopLevelDeps: boolean;
115119
exclude?: string;
120+
showNpmScope?: boolean;
116121
};
117122

118123
type NodePkgManagers = 'npm' | 'yarn' | 'pnpm';

lib/dep-graph-builders/util.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
import { PackageJsonBase } from './types';
1+
import { DepGraphBuildOptions, PackageJsonBase } from './types';
22
import { DepGraphBuilder } from '@snyk/dep-graph';
3+
import type { NodeInfo } from '@snyk/dep-graph/dist/core/types';
34
import { InvalidUserInputError } from '../errors';
45
import { NormalisedPkgs } from './types';
56
import { OutOfSyncError } from '../errors';
@@ -28,12 +29,27 @@ export interface PkgNode {
2829
};
2930
}
3031

32+
export const createNodeInfo = (
33+
options: DepGraphBuildOptions,
34+
scope = 'unknown',
35+
): NodeInfo | undefined => {
36+
if (options.showNpmScope) {
37+
return {
38+
labels: {
39+
'npm:scope': scope,
40+
},
41+
};
42+
}
43+
return;
44+
};
45+
3146
export const addPkgNodeToGraph = (
3247
depGraphBuilder: DepGraphBuilder,
3348
node: PkgNode,
3449
options: {
3550
isCyclic?: boolean;
3651
isWorkspacePkg?: boolean;
52+
showNpmScope?: boolean;
3753
},
3854
): DepGraphBuilder => {
3955
return depGraphBuilder.addPkgNode(
@@ -42,6 +58,9 @@ export const addPkgNodeToGraph = (
4258
{
4359
labels: {
4460
scope: node.isDev ? 'dev' : 'prod',
61+
...(options.showNpmScope && {
62+
'npm:scope': node.isDev ? 'dev' : 'prod',
63+
}),
4564
...(options.isCyclic && { pruned: 'cyclic' }),
4665
...(options.isWorkspacePkg && { pruned: 'true' }),
4766
...(node.missingLockFileEntry && { missingLockFileEntry: 'true' }),

lib/dep-graph-builders/yarn-lock-v1/build-depgraph-simple-pruned.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
getChildNode,
55
getTopLevelDeps,
66
PkgNode,
7+
createNodeInfo,
78
} from '../util';
89
import type { NormalisedPkgs, PackageJsonBase } from '../types';
910
import type { DepGraphBuildOptions } from '../types';
@@ -19,11 +20,13 @@ export const buildDepGraphYarnLockV1SimpleCyclesPruned = async (
1920
pkgJson: PackageJsonBase,
2021
options: DepGraphBuildOptions,
2122
) => {
22-
const { includeDevDeps, strictOutOfSync, includeOptionalDeps } = options;
23+
const { includeDevDeps, strictOutOfSync, includeOptionalDeps, showNpmScope } =
24+
options;
2325

2426
const depGraphBuilder = new DepGraphBuilder(
2527
{ name: 'yarn' },
2628
{ name: pkgJson.name, version: pkgJson.version },
29+
createNodeInfo(options),
2730
);
2831

2932
const colorMap: Record<string, Color> = {};
@@ -45,6 +48,7 @@ export const buildDepGraphYarnLockV1SimpleCyclesPruned = async (
4548
extractedYarnLockV1Pkgs,
4649
strictOutOfSync,
4750
includeOptionalDeps,
51+
showNpmScope,
4852
);
4953

5054
return depGraphBuilder.build();
@@ -66,6 +70,7 @@ const dfsVisit = async (
6670
extractedYarnLockV1Pkgs: NormalisedPkgs,
6771
strictOutOfSync: boolean,
6872
includeOptionalDeps: boolean,
73+
showNpmScope?: boolean,
6974
): Promise<void> => {
7075
colorMap[node.id] = Color.GRAY;
7176

@@ -84,19 +89,23 @@ const dfsVisit = async (
8489
);
8590

8691
if (!colorMap.hasOwnProperty(childNode.id)) {
87-
addPkgNodeToGraph(depGraphBuilder, childNode, {});
92+
addPkgNodeToGraph(depGraphBuilder, childNode, { showNpmScope });
8893
await dfsVisit(
8994
depGraphBuilder,
9095
childNode,
9196
colorMap,
9297
extractedYarnLockV1Pkgs,
9398
strictOutOfSync,
9499
includeOptionalDeps,
100+
showNpmScope,
95101
);
96102
} else if (colorMap[childNode.id] === Color.GRAY) {
97103
// cycle detected
98104
childNode.id = `${childNode.id}:pruned`;
99-
addPkgNodeToGraph(depGraphBuilder, childNode, { isCyclic: true });
105+
addPkgNodeToGraph(depGraphBuilder, childNode, {
106+
isCyclic: true,
107+
showNpmScope,
108+
});
100109
}
101110

102111
depGraphBuilder.connectDep(node.id, childNode.id);

0 commit comments

Comments
 (0)