From fb950ce3da0f026c5ddba4a49d9300ce65ecff7a Mon Sep 17 00:00:00 2001 From: xenobytezero Date: Tue, 30 Apr 2024 11:04:23 +0100 Subject: [PATCH 1/3] fix: plugin no longer crashes in rollup only scenarios --- package.json | 1 + pnpm-lock.yaml | 5 ++++- src/builder.ts | 33 +++++++++++++++------------------ src/helpers.ts | 22 ++++++++++++++-------- src/index.ts | 7 ++++++- 5 files changed, 40 insertions(+), 28 deletions(-) diff --git a/package.json b/package.json index 7e9aa25..4588799 100644 --- a/package.json +++ b/package.json @@ -67,6 +67,7 @@ "@commitlint/cli": "19.2.2", "@commitlint/config-conventional": "19.2.2", "@types/node": "20.12.7", + "@types/normalize-package-data": "^2.4.4", "@typescript-eslint/eslint-plugin": "7.7.0", "@typescript-eslint/parser": "7.7.0", "@vitest/coverage-v8": "1.5.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 72f9f82..df076b3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -24,6 +24,9 @@ importers: '@types/node': specifier: 20.12.7 version: 20.12.7 + '@types/normalize-package-data': + specifier: ^2.4.4 + version: 2.4.4 '@typescript-eslint/eslint-plugin': specifier: 7.7.0 version: 7.7.0(@typescript-eslint/parser@7.7.0(eslint@8.56.0)(typescript@5.4.5))(eslint@8.56.0)(typescript@5.4.5) @@ -3966,7 +3969,7 @@ snapshots: '@babel/helper-module-imports@7.22.15': dependencies: - '@babel/types': 7.23.3 + '@babel/types': 7.24.0 '@babel/helper-module-transforms@7.23.3(@babel/core@7.23.3)': dependencies: diff --git a/src/builder.ts b/src/builder.ts index 53e1032..70b1155 100644 --- a/src/builder.ts +++ b/src/builder.ts @@ -1,8 +1,7 @@ -import { dirname } from "node:path"; import { createRequire } from "node:module"; import { type Builders, type Models, type Factories } from "@cyclonedx/cyclonedx-library"; -import { getPackageJson } from "./helpers"; +import { getCorrespondingPackageFromModuleId } from "./helpers"; const require = createRequire(import.meta.url); @@ -17,24 +16,22 @@ export function registerPackageUrlOnComponent( } export async function registerTools(bom: Models.Bom, builder: Builders.FromNodePackageJson.ToolBuilder) { - // register rollup-plugin-sbom (for vite and rollup) - const pkg = await getPackageJson(dirname(require.resolve("rollup-plugin-sbom"))); - if (pkg) { - const tool = builder.makeTool(pkg); - tool && bom.metadata.tools.add(tool); + async function registerTool(packageName: string) { + try { + const modulePath = require.resolve(packageName); + const pkgJson = await getCorrespondingPackageFromModuleId(modulePath); + if (pkgJson) { + const tool = builder.makeTool(pkgJson); + tool && bom.metadata.tools.add(tool); + } + } catch { + // do nothing + } } - // register vite if available - const vitePkg = await getPackageJson(dirname(require.resolve("vite"))); - if (vitePkg) { - const tool = builder.makeTool(vitePkg); - tool && bom.metadata.tools.add(tool); - } + const knownTools = ["rollup-plugin-sbom", "vite", "rollup"]; - // register rollup if available - const rollupPkg = await getPackageJson(dirname(require.resolve("rollup"))); - if (rollupPkg) { - const tool = builder.makeTool(rollupPkg); - tool && bom.metadata.tools.add(tool); + for (const pkgName of knownTools) { + await registerTool(pkgName); } } diff --git a/src/helpers.ts b/src/helpers.ts index 570ce2f..7968c95 100644 --- a/src/helpers.ts +++ b/src/helpers.ts @@ -34,22 +34,28 @@ export async function getPackageJson(dir: string): Promise { * getPackageRootFromModuleId(moduleId); // "/User/home/.pnpm/react-dom@18.2.0_react@18.2.0/node_modules/react-dom" * ``` */ -export function getCorrespondingPackageFromModuleId(moduleId: string, traversalLimit = 10) { - if (!moduleId.includes("node_modules")) { - return Promise.resolve(null); - } - +export async function getCorrespondingPackageFromModuleId( + modulePath: string, + traversalLimit = 10, +): Promise { if (traversalLimit === 0) { return Promise.resolve(null); } - const folder = dirname(moduleId); + const folder = dirname(modulePath); const potentialPackagePath = join(folder, "./package.json"); + + let pkgJson: Package | null = null; + if (existsSync(potentialPackagePath)) { - return getPackageJson(folder); + pkgJson = await getPackageJson(folder); + } + + if (pkgJson !== null) { + return pkgJson; } - return getCorrespondingPackageFromModuleId(join(folder, ".."), traversalLimit - 1); + return await getCorrespondingPackageFromModuleId(folder, traversalLimit - 1); } /** diff --git a/src/index.ts b/src/index.ts index 170ab97..698a5a1 100644 --- a/src/index.ts +++ b/src/index.ts @@ -97,7 +97,12 @@ export default function rollupPluginSbom(userOptions?: RollupPluginSbomOptions): async moduleParsed(moduleInfo) { const nodeModuleImportedIds = moduleInfo.importedIds.filter((entry) => entry.includes("node_modules")); const potentialComponents = await Promise.all( - nodeModuleImportedIds.map(getCorrespondingPackageFromModuleId), + nodeModuleImportedIds.map((moduleId) => { + if (!moduleId.includes("node_modules")) { + return Promise.resolve(null); + } + return getCorrespondingPackageFromModuleId(moduleId); + }), ); // iterate over all imported unique modules and add them to the BOM From 0afaf42a5d95922d315ed24a4e8710f65cf17341 Mon Sep 17 00:00:00 2001 From: xenobytezero Date: Tue, 30 Apr 2024 11:02:21 +0100 Subject: [PATCH 2/3] fix: moved the known tools list out of function scope --- src/builder.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/builder.ts b/src/builder.ts index 70b1155..cbba557 100644 --- a/src/builder.ts +++ b/src/builder.ts @@ -5,6 +5,8 @@ import { getCorrespondingPackageFromModuleId } from "./helpers"; const require = createRequire(import.meta.url); +const knownTools = ["rollup-plugin-sbom", "vite", "rollup"]; + export function registerPackageUrlOnComponent( component: Models.Component | undefined, factory: Factories.FromNodePackageJson.PackageUrlFactory, @@ -29,8 +31,6 @@ export async function registerTools(bom: Models.Bom, builder: Builders.FromNodeP } } - const knownTools = ["rollup-plugin-sbom", "vite", "rollup"]; - for (const pkgName of knownTools) { await registerTool(pkgName); } From 500fe7417f75983ae804f353dc95aefc8f841681 Mon Sep 17 00:00:00 2001 From: xenobytezero Date: Wed, 1 May 2024 11:08:28 +0100 Subject: [PATCH 3/3] fix: add additional comments + ignore virtual modules when scanning --- src/helpers.ts | 3 +++ src/index.ts | 7 ++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/helpers.ts b/src/helpers.ts index 7968c95..15bfbcf 100644 --- a/src/helpers.ts +++ b/src/helpers.ts @@ -42,6 +42,9 @@ export async function getCorrespondingPackageFromModuleId( return Promise.resolve(null); } + // dirname() will do the equivalent of traversing up the + // directory tree one level when called on a path without + // a file. const folder = dirname(modulePath); const potentialPackagePath = join(folder, "./package.json"); diff --git a/src/index.ts b/src/index.ts index 698a5a1..ac837ed 100644 --- a/src/index.ts +++ b/src/index.ts @@ -95,7 +95,12 @@ export default function rollupPluginSbom(userOptions?: RollupPluginSbomOptions): * Register only the effectively imported third party modules from `node_modules` */ async moduleParsed(moduleInfo) { - const nodeModuleImportedIds = moduleInfo.importedIds.filter((entry) => entry.includes("node_modules")); + // filter out modules that exists in node_modules and + // also are not Rollup virtual modules (starting with \0) + const nodeModuleImportedIds = moduleInfo.importedIds.filter( + (entry) => entry.includes("node_modules") && !entry.startsWith("\0"), + ); + const potentialComponents = await Promise.all( nodeModuleImportedIds.map((moduleId) => { if (!moduleId.includes("node_modules")) {