Skip to content

Commit 47710cf

Browse files
authored
feat: [OSM-1122] use workspaces parser (#16)
1 parent 307cede commit 47710cf

File tree

2 files changed

+23
-131
lines changed

2 files changed

+23
-131
lines changed

lib/workspaces/pnpm-workspaces-parser.ts

+22-130
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,12 @@
11
import * as debugModule from 'debug';
22
import * as pathUtil from 'path';
3+
import * as fs from 'fs';
34

45
const debug = debugModule('snyk-pnpm-workspaces');
56
import * as lockFileParser from 'snyk-nodejs-lockfile-parser';
67
import { MultiProjectResultCustom, ScannedProjectCustom } from '../types';
7-
import { getFileContents, isSubpath, normalizeFilePath } from '../utils';
8-
import {
9-
getWorkspacesMap,
10-
packageJsonBelongsToWorkspace,
11-
sortTargetFiles,
12-
} from './workspace-utils';
13-
import { DepGraph } from '@snyk/dep-graph';
14-
15-
const PNPM_ROOT_FILES = [
16-
'pnpm-workspace.yaml',
17-
'package.json',
18-
'pnpm-lock.yaml',
19-
];
20-
21-
// Compute project versions map
22-
// This is needed because the lockfile doesn't present the version of
23-
// a project that's part of a workspace, we need to retrieve it from
24-
// its corresponding package.json
25-
function computeProjectVersionMaps(root: string, targetFiles) {
26-
const projectsVersionMap = {};
27-
for (const directory of Object.keys(targetFiles)) {
28-
if (!isSubpath(directory, root)) {
29-
continue;
30-
}
31-
const packageJsonFileName = pathUtil.join(directory, 'package.json');
32-
const packageJson = getFileContents(root, packageJsonFileName);
33-
34-
try {
35-
const parsedPkgJson = lockFileParser.parsePkgJson(packageJson.content);
36-
const projectVersion = parsedPkgJson.version;
37-
projectsVersionMap[
38-
normalizeFilePath(pathUtil.relative(root, directory))
39-
] = projectVersion || 'undefined';
40-
} catch (err: any) {
41-
debug(
42-
`Error getting version for project: ${packageJsonFileName}. ERROR: ${err}`,
43-
);
44-
continue;
45-
}
46-
}
47-
return projectsVersionMap;
48-
}
8+
import { sortTargetFiles } from './workspace-utils';
9+
import { ScannedNodeProject } from 'snyk-nodejs-lockfile-parser/dist/dep-graph-builders/types';
4910

5011
export async function processPnpmWorkspaces(
5112
root: string,
@@ -56,7 +17,7 @@ export async function processPnpmWorkspaces(
5617
},
5718
targetFiles: string[],
5819
): Promise<MultiProjectResultCustom> {
59-
const pnpmTargetFiles = sortTargetFiles(targetFiles, PNPM_ROOT_FILES);
20+
const pnpmWorkspaceDirs = sortTargetFiles(targetFiles, ['pnpm-lock.yaml']);
6021

6122
debug(`Processing potential Pnpm workspaces (${targetFiles.length})`);
6223

@@ -68,101 +29,32 @@ export async function processPnpmWorkspaces(
6829
scannedProjects: [],
6930
};
7031

71-
let pnpmWorkspacesMap = {};
72-
const pnpmWorkspacesFilesMap = {};
73-
74-
let rootWorkspaceManifestContent = {};
75-
const projectsVersionMap = {};
76-
7732
// the folders must be ordered highest first
78-
for (const directory of Object.keys(pnpmTargetFiles)) {
33+
for (const directory of Object.keys(pnpmWorkspaceDirs)) {
7934
debug(`Processing ${directory} as a potential Pnpm workspace`);
80-
let isPnpmWorkspacePackage = false;
81-
let isRootPackageJson = false;
82-
const packageJsonFileName = pathUtil.join(directory, 'package.json');
83-
const packageJson = getFileContents(root, packageJsonFileName);
84-
pnpmWorkspacesMap = {
85-
...pnpmWorkspacesMap,
86-
...getWorkspacesMap(root, directory, packageJson),
87-
};
88-
89-
for (const workspaceRoot of Object.keys(pnpmWorkspacesMap)) {
90-
const match = packageJsonBelongsToWorkspace(
91-
packageJsonFileName,
92-
pnpmWorkspacesMap,
93-
workspaceRoot,
94-
);
95-
if (match) {
96-
debug(`${packageJsonFileName} matches an existing workspace pattern`);
97-
pnpmWorkspacesFilesMap[packageJsonFileName] = {
98-
root: workspaceRoot,
99-
};
100-
isPnpmWorkspacePackage = true;
101-
}
102-
if (packageJsonFileName === workspaceRoot) {
103-
isRootPackageJson = true;
104-
const workspaceRootDir = pathUtil.dirname(workspaceRoot);
105-
projectsVersionMap[workspaceRootDir] = computeProjectVersionMaps(
106-
workspaceRootDir,
107-
pnpmTargetFiles,
108-
);
109-
rootWorkspaceManifestContent = JSON.parse(packageJson.content);
110-
}
111-
}
11235

113-
if (!(isPnpmWorkspacePackage || isRootPackageJson)) {
36+
const pnpmWorkspacePath = pathUtil.join(directory, 'pnpm-workspace.yaml');
37+
if (!fs.existsSync(pnpmWorkspacePath)) {
11438
debug(
115-
`${packageJsonFileName} is not part of any detected workspace, skipping`,
39+
`Workspace file not found at ${directory}. Can't be a pnpm workspace root.`,
11640
);
11741
continue;
11842
}
11943

120-
const rootDir = isPnpmWorkspacePackage
121-
? pathUtil.dirname(pnpmWorkspacesFilesMap[packageJsonFileName].root)
122-
: pathUtil.dirname(packageJsonFileName);
123-
124-
try {
125-
const rootPnpmLockfileName = pathUtil.join(rootDir, 'pnpm-lock.yaml');
126-
const pnpmLock = getFileContents(root, rootPnpmLockfileName);
127-
const lockfileVersion = lockFileParser.getPnpmLockfileVersion(
128-
pnpmLock.content,
129-
);
130-
const res: DepGraph = await lockFileParser.parsePnpmProject(
131-
packageJson.content,
132-
pnpmLock.content,
133-
{
134-
includeDevDeps: settings.dev || false,
135-
includeOptionalDeps: settings.optional || true,
136-
pruneWithinTopLevelDeps: true,
137-
strictOutOfSync:
138-
settings.strictOutOfSync === undefined
139-
? true
140-
: settings.strictOutOfSync,
141-
},
142-
lockfileVersion,
143-
{
144-
isWorkspacePkg: true,
145-
workspacePath: normalizeFilePath(
146-
pathUtil.relative(rootDir, directory),
147-
),
148-
isRoot: isRootPackageJson,
149-
projectsVersionMap: projectsVersionMap[rootDir],
150-
rootOverrides: rootWorkspaceManifestContent?.['pnpm.overrides'] || {},
151-
},
152-
);
153-
const project: ScannedProjectCustom = {
154-
packageManager: 'pnpm',
155-
targetFile: pathUtil.relative(root, packageJson.fileName),
156-
depGraph: res as any,
157-
plugin: {
158-
name: 'snyk-nodejs-lockfile-parser',
159-
runtime: process.version,
160-
},
161-
};
162-
result.scannedProjects.push(project);
163-
} catch (e) {
164-
debug(`Error process workspace: ${packageJsonFileName}. ERROR: ${e}`);
165-
}
44+
const scannedProjects: ScannedNodeProject[] =
45+
await lockFileParser.parsePnpmWorkspace(root, directory, {
46+
includeDevDeps: settings.dev || false,
47+
includeOptionalDeps: settings.optional || true,
48+
includePeerDeps: true,
49+
pruneWithinTopLevelDeps: true,
50+
strictOutOfSync:
51+
settings.strictOutOfSync === undefined
52+
? true
53+
: settings.strictOutOfSync,
54+
});
55+
result.scannedProjects = result.scannedProjects.concat(
56+
scannedProjects as ScannedProjectCustom[],
57+
);
16658
}
16759

16860
if (!result.scannedProjects.length) {

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
"lodash.isempty": "^4.4.0",
4343
"lodash.sortby": "^4.7.0",
4444
"micromatch": "4.0.7",
45-
"snyk-nodejs-lockfile-parser": "^1.56.1",
45+
"snyk-nodejs-lockfile-parser": "1.58.5",
4646
"snyk-resolve-deps": "4.8.0"
4747
},
4848
"devDependencies": {

0 commit comments

Comments
 (0)