@cyclonedx/cdxgen 10.4.1 → 10.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -225,7 +225,7 @@ const createDefaultParentComponent = (
225
225
  const parentComponent = {
226
226
  group: options.projectGroup || "",
227
227
  name: options.projectName || dirNameStr,
228
- version: "" + options.projectVersion || "latest",
228
+ version: `${options.projectVersion}` || "latest",
229
229
  type: "application",
230
230
  };
231
231
  const ppurl = new PackageURL(
@@ -245,11 +245,12 @@ const determineParentComponent = (options) => {
245
245
  let parentComponent = undefined;
246
246
  if (options.parentComponent && Object.keys(options.parentComponent).length) {
247
247
  return options.parentComponent;
248
- } else if (options.projectName && options.projectVersion) {
248
+ }
249
+ if (options.projectName && options.projectVersion) {
249
250
  parentComponent = {
250
251
  group: options.projectGroup || "",
251
252
  name: options.projectName,
252
- version: "" + options.projectVersion || "",
253
+ version: `${options.projectVersion}` || "",
253
254
  type: "application",
254
255
  };
255
256
  const ppurl = new PackageURL(
@@ -308,9 +309,8 @@ const addToolsSection = (options, context = {}) => {
308
309
  };
309
310
 
310
311
  const componentToSimpleFullName = (comp) => {
311
- let fullName =
312
- comp.group && comp.group.length ? `${comp.group}/${comp.name}` : comp.name;
313
- if (comp.version && comp.version.length) {
312
+ let fullName = comp.group?.length ? `${comp.group}/${comp.name}` : comp.name;
313
+ if (comp.version?.length) {
314
314
  fullName = `${fullName}@${comp.version}`;
315
315
  }
316
316
  return fullName;
@@ -434,13 +434,13 @@ const addFormulationSection = (options) => {
434
434
  }
435
435
  // Collect build environment details
436
436
  const infoComponents = collectEnvInfo(options.path);
437
- if (infoComponents && infoComponents.length) {
437
+ if (infoComponents?.length) {
438
438
  components = components.concat(infoComponents);
439
439
  }
440
440
  // Should we include the OS crypto libraries
441
441
  if (options.includeCrypto) {
442
442
  const cryptoLibs = collectOSCryptoLibs(options);
443
- if (cryptoLibs && cryptoLibs.length) {
443
+ if (cryptoLibs?.length) {
444
444
  components = components.concat(cryptoLibs);
445
445
  }
446
446
  }
@@ -510,7 +510,7 @@ function addMetadata(parentComponent = {}, options = {}, context = {}) {
510
510
  parentComponent["purl"] = encodeForPurl(parentComponent["bom-ref"]);
511
511
  }
512
512
  }
513
- if (parentComponent && parentComponent.components) {
513
+ if (parentComponent?.components) {
514
514
  const parentFullName = componentToSimpleFullName(parentComponent);
515
515
  const subComponents = [];
516
516
  const addedSubComponents = {};
@@ -529,7 +529,7 @@ function addMetadata(parentComponent = {}, options = {}, context = {}) {
529
529
  fullName !== parentFullName &&
530
530
  !(
531
531
  (comp.name === parentComponent.name ||
532
- comp.name === parentComponent.name + ":latest") &&
532
+ comp.name === `${parentComponent.name}:latest`) &&
533
533
  comp.version === "latest"
534
534
  )
535
535
  ) {
@@ -657,7 +657,7 @@ function addMetadata(parentComponent = {}, options = {}, context = {}) {
657
657
  }
658
658
  }
659
659
  }
660
- if (options.allOSComponentTypes && options.allOSComponentTypes.length) {
660
+ if (options.allOSComponentTypes?.length) {
661
661
  mproperties.push({
662
662
  name: "oci:image:componentTypes",
663
663
  value: options.allOSComponentTypes.join("\\n"),
@@ -689,19 +689,19 @@ function addExternalReferences(opkg) {
689
689
  if (pkg.externalReferences) {
690
690
  externalReferences = externalReferences.concat(pkg.externalReferences);
691
691
  } else {
692
- if (pkg.homepage && pkg.homepage.url) {
692
+ if (pkg.homepage?.url) {
693
693
  externalReferences.push({
694
694
  type: pkg.homepage.url.includes("git") ? "vcs" : "website",
695
695
  url: pkg.homepage.url,
696
696
  });
697
697
  }
698
- if (pkg.bugs && pkg.bugs.url) {
698
+ if (pkg.bugs?.url) {
699
699
  externalReferences.push({
700
700
  type: "issue-tracker",
701
701
  url: pkg.bugs.url,
702
702
  });
703
703
  }
704
- if (pkg.repository && pkg.repository.url) {
704
+ if (pkg.repository?.url) {
705
705
  externalReferences.push({
706
706
  type: "vcs",
707
707
  url: pkg.repository.url,
@@ -777,7 +777,7 @@ function addComponent(
777
777
  encodeForPurl(pkg.subpath),
778
778
  );
779
779
  // There is no purl for cryptographic-asset
780
- if (ptype == "cryptographic-asset") {
780
+ if (ptype === "cryptographic-asset") {
781
781
  purl = undefined;
782
782
  }
783
783
  const purlString = purl.toString();
@@ -787,10 +787,10 @@ function addComponent(
787
787
  const impPkgs = Object.keys(allImports);
788
788
  if (
789
789
  impPkgs.includes(name) ||
790
- impPkgs.includes(group + "/" + name) ||
791
- impPkgs.includes("@" + group + "/" + name) ||
790
+ impPkgs.includes(`${group}/${name}`) ||
791
+ impPkgs.includes(`@${group}/${name}`) ||
792
792
  impPkgs.includes(group) ||
793
- impPkgs.includes("@" + group)
793
+ impPkgs.includes(`@${group}`)
794
794
  ) {
795
795
  compScope = "required";
796
796
  } else if (impPkgs.length) {
@@ -850,10 +850,10 @@ function addComponent(
850
850
  component.tags = pkg.tags;
851
851
  }
852
852
  // Retain any component properties and crypto properties
853
- if (pkg.properties && pkg.properties.length) {
853
+ if (pkg.properties?.length) {
854
854
  component.properties = pkg.properties;
855
855
  }
856
- if (pkg.cryptoProperties && pkg.cryptoProperties.length) {
856
+ if (pkg.cryptoProperties?.length) {
857
857
  component.cryptoProperties = pkg.cryptoProperties;
858
858
  }
859
859
  if (compMap[component.purl]) return; //remove cycles
@@ -904,7 +904,7 @@ function determinePackageType(pkg) {
904
904
  for (const cf of frameworksList.all) {
905
905
  if (
906
906
  pkg.purl.startsWith(cf) ||
907
- (purl.namespace && purl.namespace.includes(cf)) ||
907
+ purl.namespace?.includes(cf) ||
908
908
  purl.name.toLowerCase().includes(cf)
909
909
  ) {
910
910
  return "framework";
@@ -919,10 +919,7 @@ function determinePackageType(pkg) {
919
919
  }
920
920
  }
921
921
  if (Object.prototype.hasOwnProperty.call(pkg, "description")) {
922
- if (
923
- pkg.description &&
924
- pkg.description.toLowerCase().includes("framework")
925
- ) {
922
+ if (pkg.description?.toLowerCase().includes("framework")) {
926
923
  return "framework";
927
924
  }
928
925
  }
@@ -1011,9 +1008,9 @@ const buildBomNSData = (options, pkgInfo, ptype, context) => {
1011
1008
  dependencies: undefined,
1012
1009
  parentComponent: undefined,
1013
1010
  };
1014
- const serialNum = "urn:uuid:" + uuidv4();
1011
+ const serialNum = `urn:uuid:${uuidv4()}`;
1015
1012
  let allImports = {};
1016
- if (context && context.allImports) {
1013
+ if (context?.allImports) {
1017
1014
  allImports = context.allImports;
1018
1015
  }
1019
1016
  const nsMapping = context.nsMapping || {};
@@ -1026,7 +1023,7 @@ const buildBomNSData = (options, pkgInfo, ptype, context) => {
1026
1023
  // CycloneDX 1.5 Json Template
1027
1024
  const jsonTpl = {
1028
1025
  bomFormat: "CycloneDX",
1029
- specVersion: "" + (options.specVersion || "1.5"),
1026
+ specVersion: `${options.specVersion || "1.5"}`,
1030
1027
  serialNumber: serialNum,
1031
1028
  version: 1,
1032
1029
  metadata: metadata,
@@ -1082,14 +1079,14 @@ export async function createJarBom(path, options) {
1082
1079
  } else {
1083
1080
  jarFiles = getAllFiles(
1084
1081
  path,
1085
- (options.multiProject ? "**/" : "") + "*.[jw]ar",
1082
+ `${options.multiProject ? "**/" : ""}*.[jw]ar`,
1086
1083
  options,
1087
1084
  );
1088
1085
  }
1089
1086
  // Jenkins plugins
1090
1087
  const hpiFiles = getAllFiles(
1091
1088
  path,
1092
- (options.multiProject ? "**/" : "") + "*.hpi",
1089
+ `${options.multiProject ? "**/" : ""}*.hpi`,
1093
1090
  options,
1094
1091
  );
1095
1092
  if (hpiFiles.length) {
@@ -1101,7 +1098,7 @@ export async function createJarBom(path, options) {
1101
1098
  console.log(`Parsing ${jar}`);
1102
1099
  }
1103
1100
  const dlist = await extractJarArchive(jar, tempDir);
1104
- if (dlist && dlist.length) {
1101
+ if (dlist?.length) {
1105
1102
  pkgList = pkgList.concat(dlist);
1106
1103
  }
1107
1104
  if (pkgList.length) {
@@ -1109,7 +1106,7 @@ export async function createJarBom(path, options) {
1109
1106
  }
1110
1107
  }
1111
1108
  // Clean up
1112
- if (tempDir && tempDir.startsWith(tmpdir()) && rmSync) {
1109
+ if (tempDir?.startsWith(tmpdir()) && rmSync) {
1113
1110
  rmSync(tempDir, { recursive: true, force: true });
1114
1111
  }
1115
1112
  pkgList = pkgList.concat(convertJarNSToPackages(nsMapping));
@@ -1182,7 +1179,7 @@ export async function createJavaBom(path, options) {
1182
1179
  pkgList = await getMvnMetadata(pkgList);
1183
1180
  }
1184
1181
  // Clean up
1185
- if (tempDir && tempDir.startsWith(tmpdir()) && rmSync) {
1182
+ if (tempDir?.startsWith(tmpdir()) && rmSync) {
1186
1183
  console.log(`Cleaning up ${tempDir}`);
1187
1184
  rmSync(tempDir, { recursive: true, force: true });
1188
1185
  }
@@ -1196,740 +1193,737 @@ export async function createJavaBom(path, options) {
1196
1193
  dependencies,
1197
1194
  parentComponent,
1198
1195
  });
1199
- } else {
1200
- // maven - pom.xml
1201
- const pomFiles = getAllFiles(
1202
- path,
1203
- (options.multiProject ? "**/" : "") + "pom.xml",
1204
- options,
1205
- );
1206
- let bomJsonFiles = [];
1207
- if (
1208
- pomFiles &&
1209
- pomFiles.length &&
1210
- !["scala", "sbt", "gradle"].includes(options.projectType)
1211
- ) {
1212
- const cdxMavenPlugin =
1213
- process.env.CDX_MAVEN_PLUGIN ||
1214
- "org.cyclonedx:cyclonedx-maven-plugin:2.8.0";
1215
- const cdxMavenGoal = process.env.CDX_MAVEN_GOAL || "makeAggregateBom";
1216
- let mvnArgs = [`${cdxMavenPlugin}:${cdxMavenGoal}`, "-DoutputName=bom"];
1217
- if (includeMavenTestScope) {
1218
- mvnArgs.push("-DincludeTestScope=true");
1219
- }
1220
- // By using quiet mode we can reduce the maxBuffer used and avoid crashes
1221
- if (!DEBUG_MODE) {
1222
- mvnArgs.push("-q");
1223
- }
1224
- // Support for passing additional settings and profile to maven
1225
- if (process.env.MVN_ARGS) {
1226
- const addArgs = process.env.MVN_ARGS.split(" ");
1227
- mvnArgs = mvnArgs.concat(addArgs);
1228
- }
1229
- // specVersion 1.4 doesn't support externalReferences.type=disribution-intake
1230
- // so we need to run the plugin with the correct version
1231
- if (options.specVersion === 1.4) {
1232
- mvnArgs = mvnArgs.concat("-DschemaVersion=1.4");
1233
- }
1234
- for (const f of pomFiles) {
1235
- const basePath = dirname(f);
1236
- const settingsXml = join(basePath, "settings.xml");
1237
- if (existsSync(settingsXml)) {
1238
- console.log(
1239
- `maven settings.xml found in ${basePath}. Please set the MVN_ARGS environment variable based on the full mvn build command used for this project.\nExample: MVN_ARGS='--settings ${settingsXml}'`,
1240
- );
1196
+ }
1197
+ // maven - pom.xml
1198
+ const pomFiles = getAllFiles(
1199
+ path,
1200
+ `${options.multiProject ? "**/" : ""}pom.xml`,
1201
+ options,
1202
+ );
1203
+ let bomJsonFiles = [];
1204
+ if (
1205
+ pomFiles?.length &&
1206
+ !["scala", "sbt", "gradle"].includes(options.projectType)
1207
+ ) {
1208
+ const cdxMavenPlugin =
1209
+ process.env.CDX_MAVEN_PLUGIN ||
1210
+ "org.cyclonedx:cyclonedx-maven-plugin:2.8.0";
1211
+ const cdxMavenGoal = process.env.CDX_MAVEN_GOAL || "makeAggregateBom";
1212
+ let mvnArgs = [`${cdxMavenPlugin}:${cdxMavenGoal}`, "-DoutputName=bom"];
1213
+ if (includeMavenTestScope) {
1214
+ mvnArgs.push("-DincludeTestScope=true");
1215
+ }
1216
+ // By using quiet mode we can reduce the maxBuffer used and avoid crashes
1217
+ if (!DEBUG_MODE) {
1218
+ mvnArgs.push("-q");
1219
+ }
1220
+ // Support for passing additional settings and profile to maven
1221
+ if (process.env.MVN_ARGS) {
1222
+ const addArgs = process.env.MVN_ARGS.split(" ");
1223
+ mvnArgs = mvnArgs.concat(addArgs);
1224
+ }
1225
+ // specVersion 1.4 doesn't support externalReferences.type=disribution-intake
1226
+ // so we need to run the plugin with the correct version
1227
+ if (options.specVersion === 1.4) {
1228
+ mvnArgs = mvnArgs.concat("-DschemaVersion=1.4");
1229
+ }
1230
+ for (const f of pomFiles) {
1231
+ const basePath = dirname(f);
1232
+ const settingsXml = join(basePath, "settings.xml");
1233
+ if (existsSync(settingsXml)) {
1234
+ console.log(
1235
+ `maven settings.xml found in ${basePath}. Please set the MVN_ARGS environment variable based on the full mvn build command used for this project.\nExample: MVN_ARGS='--settings ${settingsXml}'`,
1236
+ );
1237
+ }
1238
+ const mavenCmd = getMavenCommand(basePath, path);
1239
+ // Should we attempt to resolve class names
1240
+ if (options.resolveClass || options.deep) {
1241
+ const tmpjarNSMapping = await collectMvnDependencies(
1242
+ mavenCmd,
1243
+ basePath,
1244
+ true,
1245
+ false,
1246
+ );
1247
+ if (tmpjarNSMapping && Object.keys(tmpjarNSMapping).length) {
1248
+ jarNSMapping = { ...jarNSMapping, ...tmpjarNSMapping };
1241
1249
  }
1242
- const mavenCmd = getMavenCommand(basePath, path);
1243
- // Should we attempt to resolve class names
1244
- if (options.resolveClass || options.deep) {
1245
- const tmpjarNSMapping = await collectMvnDependencies(
1246
- mavenCmd,
1247
- basePath,
1248
- true,
1249
- false,
1250
- );
1251
- if (tmpjarNSMapping && Object.keys(tmpjarNSMapping).length) {
1252
- jarNSMapping = { ...jarNSMapping, ...tmpjarNSMapping };
1253
- }
1250
+ }
1251
+ console.log(`Executing '${mavenCmd} ${mvnArgs.join(" ")}' in`, basePath);
1252
+ let result = spawnSync(mavenCmd, mvnArgs, {
1253
+ cwd: basePath,
1254
+ shell: true,
1255
+ encoding: "utf-8",
1256
+ timeout: TIMEOUT_MS,
1257
+ maxBuffer: MAX_BUFFER,
1258
+ });
1259
+ // Check if the cyclonedx plugin created the required bom.json file
1260
+ // Sometimes the plugin fails silently for complex maven projects
1261
+ bomJsonFiles = getAllFiles(path, "**/target/*.json", options);
1262
+ // Check if the bom json files got created in a directory other than target
1263
+ if (!bomJsonFiles.length) {
1264
+ bomJsonFiles = getAllFiles(path, "**/bom*.json", options);
1265
+ }
1266
+ const bomGenerated = bomJsonFiles.length;
1267
+ if (!bomGenerated || result.status !== 0 || result.error) {
1268
+ const tempDir = mkdtempSync(join(tmpdir(), "cdxmvn-"));
1269
+ const tempMvnTree = join(tempDir, "mvn-tree.txt");
1270
+ let mvnTreeArgs = ["dependency:tree", `-DoutputFile=${tempMvnTree}`];
1271
+ if (process.env.MVN_ARGS) {
1272
+ const addArgs = process.env.MVN_ARGS.split(" ");
1273
+ mvnTreeArgs = mvnTreeArgs.concat(addArgs);
1254
1274
  }
1255
1275
  console.log(
1256
- `Executing '${mavenCmd} ${mvnArgs.join(" ")}' in`,
1257
- basePath,
1276
+ `Fallback to executing ${mavenCmd} ${mvnTreeArgs.join(" ")}`,
1258
1277
  );
1259
- let result = spawnSync(mavenCmd, mvnArgs, {
1278
+ result = spawnSync(mavenCmd, mvnTreeArgs, {
1260
1279
  cwd: basePath,
1261
1280
  shell: true,
1262
1281
  encoding: "utf-8",
1263
1282
  timeout: TIMEOUT_MS,
1264
1283
  maxBuffer: MAX_BUFFER,
1265
1284
  });
1266
- // Check if the cyclonedx plugin created the required bom.json file
1267
- // Sometimes the plugin fails silently for complex maven projects
1268
- bomJsonFiles = getAllFiles(path, "**/target/*.json", options);
1269
- // Check if the bom json files got created in a directory other than target
1270
- if (!bomJsonFiles.length) {
1271
- bomJsonFiles = getAllFiles(path, "**/bom*.json", options);
1272
- }
1273
- const bomGenerated = bomJsonFiles.length;
1274
- if (!bomGenerated || result.status !== 0 || result.error) {
1275
- const tempDir = mkdtempSync(join(tmpdir(), "cdxmvn-"));
1276
- const tempMvnTree = join(tempDir, "mvn-tree.txt");
1277
- let mvnTreeArgs = ["dependency:tree", "-DoutputFile=" + tempMvnTree];
1278
- if (process.env.MVN_ARGS) {
1279
- const addArgs = process.env.MVN_ARGS.split(" ");
1280
- mvnTreeArgs = mvnTreeArgs.concat(addArgs);
1281
- }
1282
- console.log(
1283
- `Fallback to executing ${mavenCmd} ${mvnTreeArgs.join(" ")}`,
1284
- );
1285
- result = spawnSync(mavenCmd, mvnTreeArgs, {
1286
- cwd: basePath,
1287
- shell: true,
1288
- encoding: "utf-8",
1289
- timeout: TIMEOUT_MS,
1290
- maxBuffer: MAX_BUFFER,
1291
- });
1292
- if (result.status !== 0 || result.error) {
1293
- // Our approach to recursively invoking the maven plugin for each sub-module is bound to result in failures
1294
- // These could be due to a range of reasons that are covered below.
1295
- if (pomFiles.length === 1 || DEBUG_MODE) {
1296
- console.error(result.stdout, result.stderr);
1285
+ if (result.status !== 0 || result.error) {
1286
+ // Our approach to recursively invoking the maven plugin for each sub-module is bound to result in failures
1287
+ // These could be due to a range of reasons that are covered below.
1288
+ if (pomFiles.length === 1 || DEBUG_MODE) {
1289
+ console.error(result.stdout, result.stderr);
1290
+ console.log(
1291
+ "Resolve the above maven error. This could be due to the following:\n",
1292
+ );
1293
+ if (
1294
+ result.stdout &&
1295
+ (result.stdout.includes("Non-resolvable parent POM") ||
1296
+ result.stdout.includes("points at wrong local POM"))
1297
+ ) {
1297
1298
  console.log(
1298
- "Resolve the above maven error. This could be due to the following:\n",
1299
+ "1. Check if the pom.xml contains valid settings for parent and modules. Some projects can be built only from a specific directory.",
1299
1300
  );
1300
- if (
1301
- result.stdout &&
1302
- (result.stdout.includes("Non-resolvable parent POM") ||
1303
- result.stdout.includes("points at wrong local POM"))
1304
- ) {
1305
- console.log(
1306
- "1. Check if the pom.xml contains valid settings such `parent.relativePath` to make mvn command work from within the sub-directory.",
1307
- );
1308
- } else if (
1309
- result.stdout &&
1310
- (result.stdout.includes("Could not resolve dependencies") ||
1311
- result.stdout.includes("no dependency information available"))
1312
- ) {
1313
- console.log(
1314
- "1. Try building the project with 'mvn package -Dmaven.test.skip=true' using the correct version of Java and maven before invoking cdxgen.",
1315
- );
1316
- } else if (
1317
- result.stdout &&
1318
- result.stdout.includes(
1319
- "Could not resolve target platform specification",
1320
- )
1321
- ) {
1322
- console.log(
1323
- "1. Some projects can be built only from the root directory. Invoke cdxgen with --no-recurse option",
1324
- );
1325
- } else {
1326
- console.log(
1327
- "1. Java version requirement: cdxgen container image bundles Java 21 with maven 3.9 which might be incompatible.",
1328
- );
1329
- }
1301
+ } else if (
1302
+ result.stdout &&
1303
+ (result.stdout.includes("Could not resolve dependencies") ||
1304
+ result.stdout.includes("no dependency information available"))
1305
+ ) {
1330
1306
  console.log(
1331
- "2. Private dependencies cannot be downloaded: Check if any additional arguments must be passed to maven and set them via MVN_ARGS environment variable.",
1307
+ "1. Try building the project with 'mvn package -Dmaven.test.skip=true' using the correct version of Java and maven before invoking cdxgen.",
1332
1308
  );
1309
+ } else if (
1310
+ result.stdout?.includes(
1311
+ "Could not resolve target platform specification",
1312
+ )
1313
+ ) {
1333
1314
  console.log(
1334
- "3. Check if all required environment variables including any maven profile arguments are passed correctly to this tool.",
1315
+ "1. Some projects can be built only from the root directory. Invoke cdxgen with --no-recurse option",
1316
+ );
1317
+ } else {
1318
+ console.log(
1319
+ "1. Java version requirement: cdxgen container image bundles Java 21 with maven 3.9 which might be incompatible. Try running cdxgen with the unofficial JDK11-based image `ghcr.io/appthreat/cdxgen-java:v10`.",
1335
1320
  );
1336
1321
  }
1337
- // Do not fall back to methods that can produce incomplete results when failOnError is set
1338
- options.failOnError && process.exit(1);
1339
1322
  console.log(
1340
- "\nFalling back to manual pom.xml parsing. The result would be incomplete!",
1323
+ "2. Private dependencies cannot be downloaded: Check if any additional arguments must be passed to maven and set them via MVN_ARGS environment variable.",
1324
+ );
1325
+ console.log(
1326
+ "3. Check if all required environment variables including any maven profile arguments are passed correctly to this tool.",
1341
1327
  );
1342
- const dlist = parsePom(f);
1343
- if (dlist && dlist.length) {
1344
- pkgList = pkgList.concat(dlist);
1345
- }
1346
- } else {
1347
- if (existsSync(tempMvnTree)) {
1348
- const mvnTreeString = readFileSync(tempMvnTree, {
1349
- encoding: "utf-8",
1350
- });
1351
- const parsedList = parseMavenTree(mvnTreeString);
1352
- const dlist = parsedList.pkgList;
1353
- parentComponent = dlist.splice(0, 1)[0];
1354
- parentComponent.type = "application";
1355
- if (dlist && dlist.length) {
1356
- pkgList = pkgList.concat(dlist);
1357
- }
1358
- if (parsedList.dependenciesList && parsedList.dependenciesList) {
1359
- dependencies = dependencies.concat(parsedList.dependenciesList);
1360
- }
1361
- unlinkSync(tempMvnTree);
1362
- }
1363
1328
  }
1364
- }
1365
- } // for
1366
- for (const abjson of bomJsonFiles) {
1367
- let bomJsonObj = undefined;
1368
- try {
1369
- if (DEBUG_MODE) {
1370
- console.log(`Extracting data from generated bom file ${abjson}`);
1329
+ // Do not fall back to methods that can produce incomplete results when failOnError is set
1330
+ options.failOnError && process.exit(1);
1331
+ console.log(
1332
+ "\nFalling back to parsing pom.xml files. Only direct dependencies would get included!",
1333
+ );
1334
+ const dlist = parsePom(f);
1335
+ if (dlist?.length) {
1336
+ pkgList = pkgList.concat(dlist);
1371
1337
  }
1372
- bomJsonObj = JSON.parse(
1373
- readFileSync(abjson, {
1338
+ } else {
1339
+ if (existsSync(tempMvnTree)) {
1340
+ const mvnTreeString = readFileSync(tempMvnTree, {
1374
1341
  encoding: "utf-8",
1375
- }),
1376
- );
1377
- if (bomJsonObj) {
1378
- if (
1379
- !tools &&
1380
- bomJsonObj.metadata &&
1381
- bomJsonObj.metadata.tools &&
1382
- Array.isArray(bomJsonObj.metadata.tools)
1383
- ) {
1384
- tools = bomJsonObj.metadata.tools;
1385
- }
1386
- if (
1387
- bomJsonObj.metadata &&
1388
- bomJsonObj.metadata.component &&
1389
- !Object.keys(parentComponent).length
1390
- ) {
1391
- parentComponent = bomJsonObj.metadata.component;
1392
- options.parentComponent = parentComponent;
1393
- pkgList = [];
1394
- }
1395
- if (bomJsonObj.components) {
1396
- pkgList = pkgList.concat(bomJsonObj.components);
1397
- }
1398
- if (bomJsonObj.dependencies) {
1399
- dependencies = mergeDependencies(
1400
- dependencies,
1401
- bomJsonObj.dependencies,
1402
- parentComponent,
1403
- );
1342
+ });
1343
+ const parsedList = parseMavenTree(mvnTreeString);
1344
+ const dlist = parsedList.pkgList;
1345
+ parentComponent = dlist.splice(0, 1)[0];
1346
+ parentComponent.type = "application";
1347
+ if (dlist?.length) {
1348
+ pkgList = pkgList.concat(dlist);
1404
1349
  }
1405
- }
1406
- } catch (err) {
1407
- if (options.failOnError || DEBUG_MODE) {
1408
- console.log(err);
1409
- options.failOnError && process.exit(1);
1410
- }
1411
- }
1412
- }
1413
- if (pkgList) {
1414
- pkgList = trimComponents(pkgList);
1415
- pkgList = await getMvnMetadata(pkgList, jarNSMapping);
1416
- return buildBomNSData(options, pkgList, "maven", {
1417
- src: path,
1418
- filename: pomFiles.join(", "),
1419
- nsMapping: jarNSMapping,
1420
- dependencies,
1421
- parentComponent,
1422
- tools,
1423
- });
1424
- } else if (bomJsonFiles.length) {
1425
- const bomNSData = {};
1426
- bomNSData.bomJsonFiles = bomJsonFiles;
1427
- bomNSData.nsMapping = jarNSMapping;
1428
- bomNSData.dependencies = dependencies;
1429
- bomNSData.parentComponent = parentComponent;
1430
- return bomNSData;
1431
- }
1432
- }
1433
- // gradle
1434
- const gradleFiles = getAllFiles(
1435
- path,
1436
- (options.multiProject ? "**/" : "") + "build.gradle*",
1437
- options,
1438
- );
1439
- const allProjects = [];
1440
- const allProjectsAddedPurls = [];
1441
- const rootDependsOn = [];
1442
- // Execute gradle properties
1443
- if (
1444
- gradleFiles &&
1445
- gradleFiles.length &&
1446
- !["scala", "sbt"].includes(options.projectType)
1447
- ) {
1448
- let retMap = executeGradleProperties(path, null, null);
1449
- const allProjectsStr = retMap.projects || [];
1450
- const rootProject = retMap.rootProject;
1451
- if (rootProject) {
1452
- parentComponent = {
1453
- name: rootProject,
1454
- type: "application",
1455
- ...retMap.metadata,
1456
- };
1457
- const parentPurl = new PackageURL(
1458
- "maven",
1459
- parentComponent.group || "",
1460
- parentComponent.name,
1461
- parentComponent.version,
1462
- { type: "jar" },
1463
- null,
1464
- ).toString();
1465
- parentComponent["purl"] = parentPurl;
1466
- parentComponent["bom-ref"] = decodeURIComponent(parentPurl);
1467
- }
1468
- // Get the sub-project properties and set the root dependencies
1469
- if (allProjectsStr && allProjectsStr.length) {
1470
- for (const spstr of allProjectsStr) {
1471
- retMap = executeGradleProperties(path, null, spstr);
1472
- const rootSubProject = retMap.rootProject;
1473
- if (rootSubProject) {
1474
- const rspName = rootSubProject.replace(/^:/, "");
1475
- const rootSubProjectObj = {
1476
- name: rspName,
1477
- type: "application",
1478
- qualifiers: { type: "jar" },
1479
- ...retMap.metadata,
1480
- };
1481
- const rootSubProjectPurl = new PackageURL(
1482
- "maven",
1483
- rootSubProjectObj.group && rootSubProjectObj.group.length
1484
- ? rootSubProjectObj.group
1485
- : parentComponent.group,
1486
- rootSubProjectObj.name,
1487
- retMap.metadata.version && retMap.metadata.version !== "latest"
1488
- ? retMap.metadata.version
1489
- : parentComponent.version,
1490
- rootSubProjectObj.qualifiers,
1491
- null,
1492
- ).toString();
1493
- rootSubProjectObj["purl"] = rootSubProjectPurl;
1494
- rootSubProjectObj["bom-ref"] =
1495
- decodeURIComponent(rootSubProjectPurl);
1496
- if (!allProjectsAddedPurls.includes(rootSubProjectPurl)) {
1497
- allProjects.push(rootSubProjectObj);
1498
- rootDependsOn.push(rootSubProjectPurl);
1499
- allProjectsAddedPurls.push(rootSubProjectPurl);
1350
+ if (parsedList.dependenciesList && parsedList.dependenciesList) {
1351
+ dependencies = dependencies.concat(parsedList.dependenciesList);
1500
1352
  }
1353
+ unlinkSync(tempMvnTree);
1501
1354
  }
1502
1355
  }
1503
- // Bug #317 fix
1504
- parentComponent.components = allProjects.flatMap((s) => {
1505
- delete s.qualifiers;
1506
- delete s.evidence;
1507
- return s;
1508
- });
1509
- dependencies.push({
1510
- ref: parentComponent["bom-ref"],
1511
- dependsOn: rootDependsOn,
1512
- });
1513
1356
  }
1514
- }
1515
- if (
1516
- gradleFiles &&
1517
- gradleFiles.length &&
1518
- options.installDeps &&
1519
- !["scala", "sbt"].includes(options.projectType)
1520
- ) {
1521
- const gradleCmd = getGradleCommand(path, null);
1522
- const defaultDepTaskArgs = ["-q", "--console", "plain", "--build-cache"];
1523
- allProjects.push(parentComponent);
1524
- let depTaskWithArgs = ["dependencies"];
1525
- if (process.env.GRADLE_DEPENDENCY_TASK) {
1526
- depTaskWithArgs = process.env.GRADLE_DEPENDENCY_TASK.split(" ");
1527
- }
1528
- for (const sp of allProjects) {
1529
- let gradleDepArgs = [
1530
- sp.purl === parentComponent.purl
1531
- ? depTaskWithArgs[0]
1532
- : `:${sp.name}:${depTaskWithArgs[0]}`,
1533
- ];
1534
- gradleDepArgs = gradleDepArgs
1535
- .concat(depTaskWithArgs.slice(1))
1536
- .concat(defaultDepTaskArgs);
1537
- // Support custom GRADLE_ARGS such as --configuration runtimeClassPath (used for all tasks)
1538
- if (process.env.GRADLE_ARGS) {
1539
- const addArgs = process.env.GRADLE_ARGS.split(" ");
1540
- gradleDepArgs = gradleDepArgs.concat(addArgs);
1541
- }
1542
- // gradle args only for the dependencies task
1543
- if (process.env.GRADLE_ARGS_DEPENDENCIES) {
1544
- const addArgs = process.env.GRADLE_ARGS_DEPENDENCIES.split(" ");
1545
- gradleDepArgs = gradleDepArgs.concat(addArgs);
1357
+ } // for
1358
+ for (const abjson of bomJsonFiles) {
1359
+ let bomJsonObj = undefined;
1360
+ try {
1361
+ if (DEBUG_MODE) {
1362
+ console.log(`Extracting data from generated bom file ${abjson}`);
1546
1363
  }
1547
- console.log(
1548
- "Executing",
1549
- gradleCmd,
1550
- gradleDepArgs.join(" "),
1551
- "in",
1552
- path,
1364
+ bomJsonObj = JSON.parse(
1365
+ readFileSync(abjson, {
1366
+ encoding: "utf-8",
1367
+ }),
1553
1368
  );
1554
- const sresult = spawnSync(gradleCmd, gradleDepArgs, {
1555
- cwd: path,
1556
- encoding: "utf-8",
1557
- timeout: TIMEOUT_MS,
1558
- maxBuffer: MAX_BUFFER,
1559
- });
1560
- if (sresult.status !== 0 || sresult.error) {
1561
- if (options.failOnError || DEBUG_MODE) {
1562
- console.error(sresult.stdout, sresult.stderr);
1369
+ if (bomJsonObj) {
1370
+ if (
1371
+ !tools &&
1372
+ bomJsonObj.metadata &&
1373
+ bomJsonObj.metadata.tools &&
1374
+ Array.isArray(bomJsonObj.metadata.tools)
1375
+ ) {
1376
+ tools = bomJsonObj.metadata.tools;
1563
1377
  }
1564
- options.failOnError && process.exit(1);
1565
- }
1566
- const sstdout = sresult.stdout;
1567
- if (sstdout) {
1568
- const cmdOutput = Buffer.from(sstdout).toString();
1569
- const parsedList = parseGradleDep(
1570
- cmdOutput,
1571
- sp.group || parentComponent.group,
1572
- sp.name,
1573
- sp.version && sp.version.length && sp.version !== "latest"
1574
- ? sp.version
1575
- : parentComponent.version,
1576
- );
1577
- const dlist = parsedList.pkgList;
1578
- if (parsedList.dependenciesList && parsedList.dependenciesList) {
1579
- dependencies = mergeDependencies(
1580
- dependencies,
1581
- parsedList.dependenciesList,
1582
- parentComponent,
1583
- );
1378
+ if (
1379
+ bomJsonObj.metadata?.component &&
1380
+ !Object.keys(parentComponent).length
1381
+ ) {
1382
+ parentComponent = bomJsonObj.metadata.component;
1383
+ options.parentComponent = parentComponent;
1384
+ pkgList = [];
1584
1385
  }
1585
- if (dlist && dlist.length) {
1586
- if (DEBUG_MODE) {
1587
- console.log(
1588
- "Found",
1589
- dlist.length,
1590
- "packages in gradle project",
1591
- sp.name,
1592
- );
1386
+ if (bomJsonObj.components) {
1387
+ // Inject evidence into the components. #994
1388
+ if (options.specVersion >= 1.5) {
1389
+ // maven would usually generate a target directory closest to the pom.xml
1390
+ // I am sure there would be cases where this assumption is not true :)
1391
+ const srcPomFile = join(dirname(abjson), "..", "pom.xml");
1392
+ for (const acomp of bomJsonObj.components) {
1393
+ if (!acomp.evidence) {
1394
+ acomp.evidence = {
1395
+ identity: {
1396
+ field: "purl",
1397
+ confidence: 0.8,
1398
+ methods: [
1399
+ {
1400
+ technique: "manifest-analysis",
1401
+ confidence: 0.8,
1402
+ value: srcPomFile,
1403
+ },
1404
+ ],
1405
+ },
1406
+ };
1407
+ }
1408
+ if (!acomp.properties) {
1409
+ acomp.properties = [];
1410
+ }
1411
+ acomp.properties.push({
1412
+ name: "SrcFile",
1413
+ value: srcPomFile,
1414
+ });
1415
+ }
1593
1416
  }
1594
- pkgList = pkgList.concat(dlist);
1417
+ pkgList = pkgList.concat(bomJsonObj.components);
1595
1418
  }
1596
- }
1597
- } // for
1598
- if (pkgList.length) {
1599
- if (parentComponent.components && parentComponent.components.length) {
1600
- for (const subProj of parentComponent.components) {
1601
- pkgList = pkgList.filter(
1602
- (pkg) => pkg["bom-ref"] !== subProj["bom-ref"],
1419
+ if (bomJsonObj.dependencies) {
1420
+ dependencies = mergeDependencies(
1421
+ dependencies,
1422
+ bomJsonObj.dependencies,
1423
+ parentComponent,
1603
1424
  );
1604
1425
  }
1605
1426
  }
1606
- console.log(
1607
- "Obtained",
1608
- pkgList.length,
1609
- "from this gradle project. De-duping this list ...",
1610
- );
1611
- } else {
1612
- console.log(
1613
- "No packages found. Set the environment variable 'CDXGEN_DEBUG_MODE=debug' to troubleshoot any gradle related errors.",
1614
- );
1615
- options.failOnError && process.exit(1);
1616
- }
1617
- // Should we attempt to resolve class names
1618
- if (options.resolveClass || options.deep) {
1619
- const tmpjarNSMapping = await collectJarNS(GRADLE_CACHE_DIR);
1620
- if (tmpjarNSMapping && Object.keys(tmpjarNSMapping).length) {
1621
- jarNSMapping = { ...jarNSMapping, ...tmpjarNSMapping };
1427
+ } catch (err) {
1428
+ if (options.failOnError || DEBUG_MODE) {
1429
+ console.log(err);
1430
+ options.failOnError && process.exit(1);
1622
1431
  }
1623
1432
  }
1433
+ }
1434
+ if (pkgList) {
1435
+ pkgList = trimComponents(pkgList);
1624
1436
  pkgList = await getMvnMetadata(pkgList, jarNSMapping);
1625
1437
  return buildBomNSData(options, pkgList, "maven", {
1626
1438
  src: path,
1627
- filename: gradleFiles.join(", "),
1439
+ filename: pomFiles.join(", "),
1628
1440
  nsMapping: jarNSMapping,
1629
1441
  dependencies,
1630
1442
  parentComponent,
1443
+ tools,
1631
1444
  });
1632
1445
  }
1446
+ if (bomJsonFiles.length) {
1447
+ const bomNSData = {};
1448
+ bomNSData.bomJsonFiles = bomJsonFiles;
1449
+ bomNSData.nsMapping = jarNSMapping;
1450
+ bomNSData.dependencies = dependencies;
1451
+ bomNSData.parentComponent = parentComponent;
1452
+ return bomNSData;
1453
+ }
1454
+ }
1455
+ // gradle
1456
+ const gradleFiles = getAllFiles(
1457
+ path,
1458
+ `${options.multiProject ? "**/" : ""}build.gradle*`,
1459
+ options,
1460
+ );
1461
+ const allProjects = [];
1462
+ const allProjectsAddedPurls = [];
1463
+ const rootDependsOn = [];
1464
+ // Execute gradle properties
1465
+ if (gradleFiles?.length && !["scala", "sbt"].includes(options.projectType)) {
1466
+ let retMap = executeGradleProperties(path, null, null);
1467
+ const allProjectsStr = retMap.projects || [];
1468
+ const rootProject = retMap.rootProject;
1469
+ if (rootProject) {
1470
+ parentComponent = {
1471
+ name: rootProject,
1472
+ type: "application",
1473
+ ...retMap.metadata,
1474
+ };
1475
+ const parentPurl = new PackageURL(
1476
+ "maven",
1477
+ parentComponent.group || "",
1478
+ parentComponent.name,
1479
+ parentComponent.version,
1480
+ { type: "jar" },
1481
+ null,
1482
+ ).toString();
1483
+ parentComponent["purl"] = parentPurl;
1484
+ parentComponent["bom-ref"] = decodeURIComponent(parentPurl);
1485
+ }
1486
+ // Get the sub-project properties and set the root dependencies
1487
+ if (allProjectsStr?.length) {
1488
+ for (const spstr of allProjectsStr) {
1489
+ retMap = executeGradleProperties(path, null, spstr);
1490
+ const rootSubProject = retMap.rootProject;
1491
+ if (rootSubProject) {
1492
+ const rspName = rootSubProject.replace(/^:/, "");
1493
+ const rootSubProjectObj = {
1494
+ name: rspName,
1495
+ type: "application",
1496
+ qualifiers: { type: "jar" },
1497
+ ...retMap.metadata,
1498
+ };
1499
+ const rootSubProjectPurl = new PackageURL(
1500
+ "maven",
1501
+ rootSubProjectObj.group?.length
1502
+ ? rootSubProjectObj.group
1503
+ : parentComponent.group,
1504
+ rootSubProjectObj.name,
1505
+ retMap.metadata.version && retMap.metadata.version !== "latest"
1506
+ ? retMap.metadata.version
1507
+ : parentComponent.version,
1508
+ rootSubProjectObj.qualifiers,
1509
+ null,
1510
+ ).toString();
1511
+ rootSubProjectObj["purl"] = rootSubProjectPurl;
1512
+ rootSubProjectObj["bom-ref"] = decodeURIComponent(rootSubProjectPurl);
1513
+ if (!allProjectsAddedPurls.includes(rootSubProjectPurl)) {
1514
+ allProjects.push(rootSubProjectObj);
1515
+ rootDependsOn.push(rootSubProjectPurl);
1516
+ allProjectsAddedPurls.push(rootSubProjectPurl);
1517
+ }
1518
+ }
1519
+ }
1520
+ // Bug #317 fix
1521
+ parentComponent.components = allProjects.flatMap((s) => {
1522
+ delete s.qualifiers;
1523
+ delete s.evidence;
1524
+ return s;
1525
+ });
1526
+ dependencies.push({
1527
+ ref: parentComponent["bom-ref"],
1528
+ dependsOn: rootDependsOn,
1529
+ });
1530
+ }
1531
+ }
1532
+ if (
1533
+ gradleFiles?.length &&
1534
+ options.installDeps &&
1535
+ !["scala", "sbt"].includes(options.projectType)
1536
+ ) {
1537
+ const gradleCmd = getGradleCommand(path, null);
1538
+ const defaultDepTaskArgs = ["-q", "--console", "plain", "--build-cache"];
1539
+ allProjects.push(parentComponent);
1540
+ let depTaskWithArgs = ["dependencies"];
1541
+ if (process.env.GRADLE_DEPENDENCY_TASK) {
1542
+ depTaskWithArgs = process.env.GRADLE_DEPENDENCY_TASK.split(" ");
1543
+ }
1544
+ for (const sp of allProjects) {
1545
+ let gradleDepArgs = [
1546
+ sp.purl === parentComponent.purl
1547
+ ? depTaskWithArgs[0]
1548
+ : `:${sp.name}:${depTaskWithArgs[0]}`,
1549
+ ];
1550
+ gradleDepArgs = gradleDepArgs
1551
+ .concat(depTaskWithArgs.slice(1))
1552
+ .concat(defaultDepTaskArgs);
1553
+ // Support custom GRADLE_ARGS such as --configuration runtimeClassPath (used for all tasks)
1554
+ if (process.env.GRADLE_ARGS) {
1555
+ const addArgs = process.env.GRADLE_ARGS.split(" ");
1556
+ gradleDepArgs = gradleDepArgs.concat(addArgs);
1557
+ }
1558
+ // gradle args only for the dependencies task
1559
+ if (process.env.GRADLE_ARGS_DEPENDENCIES) {
1560
+ const addArgs = process.env.GRADLE_ARGS_DEPENDENCIES.split(" ");
1561
+ gradleDepArgs = gradleDepArgs.concat(addArgs);
1562
+ }
1563
+ console.log("Executing", gradleCmd, gradleDepArgs.join(" "), "in", path);
1564
+ const sresult = spawnSync(gradleCmd, gradleDepArgs, {
1565
+ cwd: path,
1566
+ encoding: "utf-8",
1567
+ timeout: TIMEOUT_MS,
1568
+ maxBuffer: MAX_BUFFER,
1569
+ });
1570
+ if (sresult.status !== 0 || sresult.error) {
1571
+ if (options.failOnError || DEBUG_MODE) {
1572
+ console.error(sresult.stdout, sresult.stderr);
1573
+ }
1574
+ options.failOnError && process.exit(1);
1575
+ }
1576
+ const sstdout = sresult.stdout;
1577
+ if (sstdout) {
1578
+ const cmdOutput = Buffer.from(sstdout).toString();
1579
+ const parsedList = parseGradleDep(
1580
+ cmdOutput,
1581
+ sp.group || parentComponent.group,
1582
+ sp.name,
1583
+ sp.version?.length && sp.version !== "latest"
1584
+ ? sp.version
1585
+ : parentComponent.version,
1586
+ );
1587
+ const dlist = parsedList.pkgList;
1588
+ if (parsedList.dependenciesList && parsedList.dependenciesList) {
1589
+ dependencies = mergeDependencies(
1590
+ dependencies,
1591
+ parsedList.dependenciesList,
1592
+ parentComponent,
1593
+ );
1594
+ }
1595
+ if (dlist?.length) {
1596
+ if (DEBUG_MODE) {
1597
+ console.log(
1598
+ "Found",
1599
+ dlist.length,
1600
+ "packages in gradle project",
1601
+ sp.name,
1602
+ );
1603
+ }
1604
+ pkgList = pkgList.concat(dlist);
1605
+ }
1606
+ }
1607
+ } // for
1608
+ if (pkgList.length) {
1609
+ if (parentComponent.components?.length) {
1610
+ for (const subProj of parentComponent.components) {
1611
+ pkgList = pkgList.filter(
1612
+ (pkg) => pkg["bom-ref"] !== subProj["bom-ref"],
1613
+ );
1614
+ }
1615
+ }
1616
+ console.log(
1617
+ "Obtained",
1618
+ pkgList.length,
1619
+ "from this gradle project. De-duping this list ...",
1620
+ );
1621
+ } else {
1622
+ console.log(
1623
+ "No packages found. Set the environment variable 'CDXGEN_DEBUG_MODE=debug' to troubleshoot any gradle related errors.",
1624
+ );
1625
+ options.failOnError && process.exit(1);
1626
+ }
1627
+ // Should we attempt to resolve class names
1628
+ if (options.resolveClass || options.deep) {
1629
+ const tmpjarNSMapping = await collectJarNS(GRADLE_CACHE_DIR);
1630
+ if (tmpjarNSMapping && Object.keys(tmpjarNSMapping).length) {
1631
+ jarNSMapping = { ...jarNSMapping, ...tmpjarNSMapping };
1632
+ }
1633
+ }
1634
+ pkgList = await getMvnMetadata(pkgList, jarNSMapping);
1635
+ return buildBomNSData(options, pkgList, "maven", {
1636
+ src: path,
1637
+ filename: gradleFiles.join(", "),
1638
+ nsMapping: jarNSMapping,
1639
+ dependencies,
1640
+ parentComponent,
1641
+ });
1642
+ }
1633
1643
 
1634
- // Bazel
1635
- // Look for the BUILD file only in the root directory
1636
- const bazelFiles = getAllFiles(path, "BUILD", options);
1637
- if (
1638
- bazelFiles &&
1639
- bazelFiles.length &&
1640
- !["scala", "sbt"].includes(options.projectType)
1641
- ) {
1642
- let BAZEL_CMD = "bazel";
1643
- if (process.env.BAZEL_HOME) {
1644
- BAZEL_CMD = join(process.env.BAZEL_HOME, "bin", "bazel");
1645
- }
1646
- for (const f of bazelFiles) {
1647
- const basePath = dirname(f);
1648
- // Invoke bazel build first
1649
- const bazelTarget = process.env.BAZEL_TARGET || ":all";
1644
+ // Bazel
1645
+ // Look for the BUILD file only in the root directory
1646
+ const bazelFiles = getAllFiles(path, "BUILD", options);
1647
+ if (bazelFiles?.length && !["scala", "sbt"].includes(options.projectType)) {
1648
+ let BAZEL_CMD = "bazel";
1649
+ if (process.env.BAZEL_HOME) {
1650
+ BAZEL_CMD = join(process.env.BAZEL_HOME, "bin", "bazel");
1651
+ }
1652
+ for (const f of bazelFiles) {
1653
+ const basePath = dirname(f);
1654
+ // Invoke bazel build first
1655
+ const bazelTarget = process.env.BAZEL_TARGET || ":all";
1656
+ console.log("Executing", BAZEL_CMD, "build", bazelTarget, "in", basePath);
1657
+ let result = spawnSync(BAZEL_CMD, ["build", bazelTarget], {
1658
+ cwd: basePath,
1659
+ shell: true,
1660
+ encoding: "utf-8",
1661
+ timeout: TIMEOUT_MS,
1662
+ maxBuffer: MAX_BUFFER,
1663
+ });
1664
+ if (result.status !== 0 || result.error) {
1665
+ if (result.stderr) {
1666
+ console.error(result.stdout, result.stderr);
1667
+ }
1650
1668
  console.log(
1651
- "Executing",
1652
- BAZEL_CMD,
1653
- "build",
1654
- bazelTarget,
1655
- "in",
1656
- basePath,
1669
+ "1. Check if bazel is installed and available in PATH.\n2. Try building your app with bazel prior to invoking cdxgen",
1657
1670
  );
1658
- let result = spawnSync(BAZEL_CMD, ["build", bazelTarget], {
1671
+ options.failOnError && process.exit(1);
1672
+ } else {
1673
+ const target = process.env.BAZEL_TARGET || "//...";
1674
+ let query;
1675
+ let bazelParser;
1676
+ if (["true", "1"].includes(process.env.BAZEL_USE_ACTION_GRAPH)) {
1677
+ query = ["aquery", `outputs('.*.jar',deps(${target}))`];
1678
+ bazelParser = parseBazelActionGraph;
1679
+ } else {
1680
+ query = ["aquery", "--output=textproto", "--skyframe_state"];
1681
+ bazelParser = parseBazelSkyframe;
1682
+ }
1683
+
1684
+ console.log("Executing", BAZEL_CMD, `${query.join(" ")} in`, basePath);
1685
+ result = spawnSync(BAZEL_CMD, query, {
1659
1686
  cwd: basePath,
1660
- shell: true,
1661
1687
  encoding: "utf-8",
1662
1688
  timeout: TIMEOUT_MS,
1663
1689
  maxBuffer: MAX_BUFFER,
1664
1690
  });
1665
1691
  if (result.status !== 0 || result.error) {
1666
- if (result.stderr) {
1667
- console.error(result.stdout, result.stderr);
1668
- }
1669
- console.log(
1670
- "1. Check if bazel is installed and available in PATH.\n2. Try building your app with bazel prior to invoking cdxgen",
1671
- );
1692
+ console.error(result.stdout, result.stderr);
1672
1693
  options.failOnError && process.exit(1);
1673
- } else {
1674
- const target = process.env.BAZEL_TARGET || "//...";
1675
- let query;
1676
- let bazelParser;
1677
- if (["true", "1"].includes(process.env.BAZEL_USE_ACTION_GRAPH)) {
1678
- query = ["aquery", `outputs('.*.jar',deps(${target}))`];
1679
- bazelParser = parseBazelActionGraph;
1680
- } else {
1681
- query = ["aquery", "--output=textproto", "--skyframe_state"];
1682
- bazelParser = parseBazelSkyframe;
1683
- }
1684
-
1685
- console.log(
1686
- "Executing",
1687
- BAZEL_CMD,
1688
- `${query.join(" ")} in`,
1689
- basePath,
1690
- );
1691
- result = spawnSync(BAZEL_CMD, query, {
1692
- cwd: basePath,
1693
- encoding: "utf-8",
1694
- timeout: TIMEOUT_MS,
1695
- maxBuffer: MAX_BUFFER,
1696
- });
1697
- if (result.status !== 0 || result.error) {
1698
- console.error(result.stdout, result.stderr);
1699
- options.failOnError && process.exit(1);
1700
- }
1701
- const stdout = result.stdout;
1702
- if (stdout) {
1703
- const cmdOutput = Buffer.from(stdout).toString();
1704
- const dlist = bazelParser(cmdOutput);
1705
- if (dlist && dlist.length) {
1706
- pkgList = pkgList.concat(dlist);
1707
- } else {
1708
- console.log(
1709
- "No packages were detected.\n1. Build your project using bazel build command before running cdxgen\n2. Try running the bazel aquery command manually to see if skyframe state can be retrieved.",
1710
- );
1711
- console.log(
1712
- "If your project requires a different query, please file a bug at cyclonedx/cdxgen repo!",
1713
- );
1714
- options.failOnError && process.exit(1);
1715
- }
1694
+ }
1695
+ const stdout = result.stdout;
1696
+ if (stdout) {
1697
+ const cmdOutput = Buffer.from(stdout).toString();
1698
+ const dlist = bazelParser(cmdOutput);
1699
+ if (dlist?.length) {
1700
+ pkgList = pkgList.concat(dlist);
1716
1701
  } else {
1717
- console.log("Bazel unexpectedly didn't produce any output");
1702
+ console.log(
1703
+ "No packages were detected.\n1. Build your project using bazel build command before running cdxgen\n2. Try running the bazel aquery command manually to see if skyframe state can be retrieved.",
1704
+ );
1705
+ console.log(
1706
+ "If your project requires a different query, please file a bug at cyclonedx/cdxgen repo!",
1707
+ );
1718
1708
  options.failOnError && process.exit(1);
1719
1709
  }
1720
- // FIXME: How do we retrieve jarNSMapping for bazel projects?
1721
- pkgList = await getMvnMetadata(pkgList, jarNSMapping);
1722
- return buildBomNSData(options, pkgList, "maven", {
1723
- src: path,
1724
- filename: "BUILD",
1725
- nsMapping: {},
1726
- dependencies,
1727
- parentComponent,
1728
- });
1710
+ } else {
1711
+ console.log("Bazel unexpectedly didn't produce any output");
1712
+ options.failOnError && process.exit(1);
1729
1713
  }
1714
+ // FIXME: How do we retrieve jarNSMapping for bazel projects?
1715
+ pkgList = await getMvnMetadata(pkgList, jarNSMapping);
1716
+ return buildBomNSData(options, pkgList, "maven", {
1717
+ src: path,
1718
+ filename: "BUILD",
1719
+ nsMapping: {},
1720
+ dependencies,
1721
+ parentComponent,
1722
+ });
1730
1723
  }
1731
1724
  }
1725
+ }
1726
+
1727
+ // scala sbt
1728
+ // Identify sbt projects via its `project` directory:
1729
+ // - all SBT project _should_ define build.properties file with sbt version info
1730
+ // - SBT projects _typically_ have some configs/plugins defined in .sbt files
1731
+ // - SBT projects that are still on 0.13.x, can still use the old approach,
1732
+ // where configs are defined via Scala files
1733
+ // Detecting one of those should be enough to determine an SBT project.
1734
+ let sbtProjectFiles = getAllFiles(
1735
+ path,
1736
+ `${
1737
+ options.multiProject ? "**/" : ""
1738
+ }project/{build.properties,*.sbt,*.scala}`,
1739
+ options,
1740
+ );
1732
1741
 
1733
- // scala sbt
1734
- // Identify sbt projects via its `project` directory:
1735
- // - all SBT project _should_ define build.properties file with sbt version info
1736
- // - SBT projects _typically_ have some configs/plugins defined in .sbt files
1737
- // - SBT projects that are still on 0.13.x, can still use the old approach,
1738
- // where configs are defined via Scala files
1739
- // Detecting one of those should be enough to determine an SBT project.
1740
- let sbtProjectFiles = getAllFiles(
1742
+ let sbtProjects = [];
1743
+ for (const i in sbtProjectFiles) {
1744
+ // parent dir of sbtProjectFile is the `project` directory
1745
+ // parent dir of `project` is the sbt root project directory
1746
+ const baseDir = dirname(dirname(sbtProjectFiles[i]));
1747
+ sbtProjects = sbtProjects.concat(baseDir);
1748
+ }
1749
+
1750
+ // Fallback in case sbt's project directory is non-existent
1751
+ if (!sbtProjects.length) {
1752
+ sbtProjectFiles = getAllFiles(
1741
1753
  path,
1742
- (options.multiProject ? "**/" : "") +
1743
- "project/{build.properties,*.sbt,*.scala}",
1754
+ `${options.multiProject ? "**/" : ""}*.sbt`,
1744
1755
  options,
1745
1756
  );
1746
-
1747
- let sbtProjects = [];
1748
1757
  for (const i in sbtProjectFiles) {
1749
- // parent dir of sbtProjectFile is the `project` directory
1750
- // parent dir of `project` is the sbt root project directory
1751
- const baseDir = dirname(dirname(sbtProjectFiles[i]));
1758
+ const baseDir = dirname(sbtProjectFiles[i]);
1752
1759
  sbtProjects = sbtProjects.concat(baseDir);
1753
1760
  }
1761
+ }
1762
+ // eliminate duplicates and ignore project directories
1763
+ sbtProjects = [...new Set(sbtProjects)].filter(
1764
+ (p) => !p.endsWith(`${sep}project`) && !p.includes(`target${sep}`),
1765
+ );
1766
+ const sbtLockFiles = getAllFiles(
1767
+ path,
1768
+ `${options.multiProject ? "**/" : ""}build.sbt.lock`,
1769
+ options,
1770
+ );
1754
1771
 
1755
- // Fallback in case sbt's project directory is non-existent
1756
- if (!sbtProjects.length) {
1757
- sbtProjectFiles = getAllFiles(
1758
- path,
1759
- (options.multiProject ? "**/" : "") + "*.sbt",
1760
- options,
1761
- );
1762
- for (const i in sbtProjectFiles) {
1763
- const baseDir = dirname(sbtProjectFiles[i]);
1764
- sbtProjects = sbtProjects.concat(baseDir);
1765
- }
1766
- }
1767
- // eliminate duplicates and ignore project directories
1768
- sbtProjects = [...new Set(sbtProjects)].filter(
1769
- (p) => !p.endsWith(sep + "project") && !p.includes("target" + sep),
1770
- );
1771
- const sbtLockFiles = getAllFiles(
1772
- path,
1773
- (options.multiProject ? "**/" : "") + "build.sbt.lock",
1774
- options,
1775
- );
1776
-
1777
- if (sbtProjects && sbtProjects.length) {
1778
- let pkgList = [];
1779
- // If the project use sbt lock files
1780
- if (sbtLockFiles && sbtLockFiles.length) {
1781
- for (const f of sbtLockFiles) {
1782
- const dlist = parseSbtLock(f);
1783
- if (dlist && dlist.length) {
1784
- pkgList = pkgList.concat(dlist);
1785
- }
1772
+ if (sbtProjects?.length) {
1773
+ let pkgList = [];
1774
+ // If the project use sbt lock files
1775
+ if (sbtLockFiles?.length) {
1776
+ for (const f of sbtLockFiles) {
1777
+ const dlist = parseSbtLock(f);
1778
+ if (dlist?.length) {
1779
+ pkgList = pkgList.concat(dlist);
1786
1780
  }
1787
- } else {
1788
- const SBT_CMD = process.env.SBT_CMD || "sbt";
1789
- let sbtVersion = determineSbtVersion(path);
1790
- // If can't find sbt version at the root of repository then search in
1791
- // sbt project array too because sometimes the project folder isn't at
1792
- // root of repository
1793
- if (sbtVersion == null) {
1794
- for (const i in sbtProjects) {
1795
- sbtVersion = determineSbtVersion(sbtProjects[i]);
1796
- if (sbtVersion != null) {
1797
- break;
1798
- }
1781
+ }
1782
+ } else {
1783
+ const SBT_CMD = process.env.SBT_CMD || "sbt";
1784
+ let sbtVersion = determineSbtVersion(path);
1785
+ // If can't find sbt version at the root of repository then search in
1786
+ // sbt project array too because sometimes the project folder isn't at
1787
+ // root of repository
1788
+ if (sbtVersion == null) {
1789
+ for (const i in sbtProjects) {
1790
+ sbtVersion = determineSbtVersion(sbtProjects[i]);
1791
+ if (sbtVersion != null) {
1792
+ break;
1799
1793
  }
1800
1794
  }
1801
- if (DEBUG_MODE) {
1802
- console.log("Detected sbt version: " + sbtVersion);
1803
- }
1804
- // Introduced in 1.2.0 https://www.scala-sbt.org/1.x/docs/sbt-1.2-Release-Notes.html#addPluginSbtFile+command,
1805
- // however working properly for real only since 1.3.4: https://github.com/sbt/sbt/releases/tag/v1.3.4
1806
- const standalonePluginFile =
1807
- sbtVersion != null &&
1808
- gte(sbtVersion, "1.3.4") &&
1809
- lte(sbtVersion, "1.4.0");
1810
- const useSlashSyntax = gte(sbtVersion, "1.5.0");
1811
- const isDependencyTreeBuiltIn =
1812
- sbtVersion != null && gte(sbtVersion, "1.4.0");
1813
- const tempDir = mkdtempSync(join(tmpdir(), "cdxsbt-"));
1814
- const tempSbtgDir = mkdtempSync(join(tmpdir(), "cdxsbtg-"));
1815
- mkdirSync(tempSbtgDir, { recursive: true });
1816
- // Create temporary plugins file
1817
- const tempSbtPlugins = join(tempSbtgDir, "dep-plugins.sbt");
1795
+ }
1796
+ if (DEBUG_MODE) {
1797
+ console.log(`Detected sbt version: ${sbtVersion}`);
1798
+ }
1799
+ // Introduced in 1.2.0 https://www.scala-sbt.org/1.x/docs/sbt-1.2-Release-Notes.html#addPluginSbtFile+command,
1800
+ // however working properly for real only since 1.3.4: https://github.com/sbt/sbt/releases/tag/v1.3.4
1801
+ const standalonePluginFile =
1802
+ sbtVersion != null &&
1803
+ gte(sbtVersion, "1.3.4") &&
1804
+ lte(sbtVersion, "1.4.0");
1805
+ const useSlashSyntax = gte(sbtVersion, "1.5.0");
1806
+ const isDependencyTreeBuiltIn =
1807
+ sbtVersion != null && gte(sbtVersion, "1.4.0");
1808
+ const tempDir = mkdtempSync(join(tmpdir(), "cdxsbt-"));
1809
+ const tempSbtgDir = mkdtempSync(join(tmpdir(), "cdxsbtg-"));
1810
+ mkdirSync(tempSbtgDir, { recursive: true });
1811
+ // Create temporary plugins file
1812
+ const tempSbtPlugins = join(tempSbtgDir, "dep-plugins.sbt");
1818
1813
 
1819
- // Requires a custom version of `sbt-dependency-graph` that
1820
- // supports `--append` for `toFile` subtask.
1821
- let sbtPluginDefinition = `\naddSbtPlugin("io.shiftleft" % "sbt-dependency-graph" % "0.10.0-append-to-file3")\n`;
1822
- if (isDependencyTreeBuiltIn) {
1823
- sbtPluginDefinition = `\naddDependencyTreePlugin\n`;
1824
- if (DEBUG_MODE) {
1825
- console.log("Using addDependencyTreePlugin as the custom plugin");
1826
- }
1814
+ // Requires a custom version of `sbt-dependency-graph` that
1815
+ // supports `--append` for `toFile` subtask.
1816
+ let sbtPluginDefinition = `\naddSbtPlugin("io.shiftleft" % "sbt-dependency-graph" % "0.10.0-append-to-file3")\n`;
1817
+ if (isDependencyTreeBuiltIn) {
1818
+ sbtPluginDefinition = "\naddDependencyTreePlugin\n";
1819
+ if (DEBUG_MODE) {
1820
+ console.log("Using addDependencyTreePlugin as the custom plugin");
1827
1821
  }
1828
- writeFileSync(tempSbtPlugins, sbtPluginDefinition);
1829
- for (const i in sbtProjects) {
1830
- const basePath = sbtProjects[i];
1831
- const dlFile = join(tempDir, "dl-" + i + ".tmp");
1832
- let sbtArgs = [];
1833
- let pluginFile = null;
1834
- if (standalonePluginFile) {
1822
+ }
1823
+ writeFileSync(tempSbtPlugins, sbtPluginDefinition);
1824
+ for (const i in sbtProjects) {
1825
+ const basePath = sbtProjects[i];
1826
+ const dlFile = join(tempDir, `dl-${i}.tmp`);
1827
+ let sbtArgs = [];
1828
+ let pluginFile = null;
1829
+ if (standalonePluginFile) {
1830
+ sbtArgs = [
1831
+ `-addPluginSbtFile=${tempSbtPlugins}`,
1832
+ `"dependencyList::toFile ${dlFile} --force"`,
1833
+ ];
1834
+ } else {
1835
+ // write to the existing plugins file
1836
+ if (useSlashSyntax) {
1835
1837
  sbtArgs = [
1836
- `-addPluginSbtFile=${tempSbtPlugins}`,
1837
- `"dependencyList::toFile ${dlFile} --force"`,
1838
+ `'set ThisBuild / asciiGraphWidth := 400' "dependencyTree / toFile ${dlFile} --force"`,
1838
1839
  ];
1839
1840
  } else {
1840
- // write to the existing plugins file
1841
- if (useSlashSyntax) {
1842
- sbtArgs = [
1843
- `'set ThisBuild / asciiGraphWidth := 400' "dependencyTree / toFile ${dlFile} --force"`,
1844
- ];
1845
- } else {
1846
- sbtArgs = [
1847
- `'set asciiGraphWidth in ThisBuild := 400' "dependencyTree::toFile ${dlFile} --force"`,
1848
- ];
1849
- }
1850
- pluginFile = addPlugin(basePath, sbtPluginDefinition);
1841
+ sbtArgs = [
1842
+ `'set asciiGraphWidth in ThisBuild := 400' "dependencyTree::toFile ${dlFile} --force"`,
1843
+ ];
1851
1844
  }
1845
+ pluginFile = addPlugin(basePath, sbtPluginDefinition);
1846
+ }
1847
+ console.log(
1848
+ "Executing",
1849
+ SBT_CMD,
1850
+ sbtArgs.join(" "),
1851
+ "in",
1852
+ basePath,
1853
+ "using plugins",
1854
+ tempSbtgDir,
1855
+ );
1856
+ // Note that the command has to be invoked with `shell: true` to properly execut sbt
1857
+ const result = spawnSync(SBT_CMD, sbtArgs, {
1858
+ cwd: basePath,
1859
+ shell: true,
1860
+ encoding: "utf-8",
1861
+ timeout: TIMEOUT_MS,
1862
+ maxBuffer: MAX_BUFFER,
1863
+ });
1864
+ if (result.status !== 0 || result.error) {
1865
+ console.error(result.stdout, result.stderr);
1852
1866
  console.log(
1853
- "Executing",
1854
- SBT_CMD,
1855
- sbtArgs.join(" "),
1856
- "in",
1857
- basePath,
1858
- "using plugins",
1859
- tempSbtgDir,
1867
+ "1. Check if scala and sbt is installed and available in PATH. Only scala 2.10 + sbt 0.13.6+ and 2.12 + sbt 1.0+ is supported for now.",
1860
1868
  );
1861
- // Note that the command has to be invoked with `shell: true` to properly execut sbt
1862
- const result = spawnSync(SBT_CMD, sbtArgs, {
1863
- cwd: basePath,
1864
- shell: true,
1865
- encoding: "utf-8",
1866
- timeout: TIMEOUT_MS,
1867
- maxBuffer: MAX_BUFFER,
1868
- });
1869
- if (result.status !== 0 || result.error) {
1870
- console.error(result.stdout, result.stderr);
1871
- console.log(
1872
- `1. Check if scala and sbt is installed and available in PATH. Only scala 2.10 + sbt 0.13.6+ and 2.12 + sbt 1.0+ is supported for now.`,
1873
- );
1874
- console.log(
1875
- `2. Check if the plugin net.virtual-void:sbt-dependency-graph 0.10.0-RC1 can be used in the environment`,
1876
- );
1877
- console.log(
1878
- "3. Consider creating a lockfile using sbt-dependency-lock plugin. See https://github.com/stringbean/sbt-dependency-lock",
1879
- );
1880
- options.failOnError && process.exit(1);
1869
+ console.log(
1870
+ "2. Check if the plugin net.virtual-void:sbt-dependency-graph 0.10.0-RC1 can be used in the environment",
1871
+ );
1872
+ console.log(
1873
+ "3. Consider creating a lockfile using sbt-dependency-lock plugin. See https://github.com/stringbean/sbt-dependency-lock",
1874
+ );
1875
+ options.failOnError && process.exit(1);
1876
+ }
1877
+ if (!standalonePluginFile) {
1878
+ cleanupPlugin(basePath, pluginFile);
1879
+ }
1880
+ if (existsSync(dlFile)) {
1881
+ const retMap = parseSbtTree(dlFile);
1882
+ if (retMap.pkgList?.length) {
1883
+ const tmpParentComponent = retMap.pkgList.splice(0, 1)[0];
1884
+ tmpParentComponent.type = "application";
1885
+ pkgList = pkgList.concat(retMap.pkgList);
1886
+ if (!parentComponent || !Object.keys(parentComponent).length) {
1887
+ parentComponent = tmpParentComponent;
1888
+ }
1881
1889
  }
1882
- if (!standalonePluginFile) {
1883
- cleanupPlugin(basePath, pluginFile);
1890
+ if (retMap.dependenciesList) {
1891
+ dependencies = mergeDependencies(
1892
+ dependencies,
1893
+ retMap.dependenciesList,
1894
+ parentComponent,
1895
+ );
1884
1896
  }
1885
- if (existsSync(dlFile)) {
1886
- const retMap = parseSbtTree(dlFile);
1887
- if (retMap.pkgList && retMap.pkgList.length) {
1888
- const tmpParentComponent = retMap.pkgList.splice(0, 1)[0];
1889
- tmpParentComponent.type = "application";
1890
- pkgList = pkgList.concat(retMap.pkgList);
1891
- if (!parentComponent || !Object.keys(parentComponent).length) {
1892
- parentComponent = tmpParentComponent;
1893
- }
1894
- }
1895
- if (retMap.dependenciesList) {
1896
- dependencies = mergeDependencies(
1897
- dependencies,
1898
- retMap.dependenciesList,
1899
- parentComponent,
1900
- );
1901
- }
1902
- } else {
1903
- if (options.failOnError || DEBUG_MODE) {
1904
- console.log(`sbt dependencyList did not yield ${dlFile}`);
1905
- }
1906
- options.failOnError && process.exit(1);
1897
+ } else {
1898
+ if (options.failOnError || DEBUG_MODE) {
1899
+ console.log(`sbt dependencyList did not yield ${dlFile}`);
1907
1900
  }
1901
+ options.failOnError && process.exit(1);
1908
1902
  }
1903
+ }
1909
1904
 
1910
- // Cleanup
1911
- unlinkSync(tempSbtPlugins);
1912
- } // else
1905
+ // Cleanup
1906
+ unlinkSync(tempSbtPlugins);
1907
+ } // else
1913
1908
 
1914
- if (DEBUG_MODE) {
1915
- console.log(`Found ${pkgList.length} packages`);
1916
- }
1917
- // Should we attempt to resolve class names
1918
- if (options.resolveClass || options.deep) {
1919
- const tmpjarNSMapping = await collectJarNS(SBT_CACHE_DIR);
1920
- if (tmpjarNSMapping && Object.keys(tmpjarNSMapping).length) {
1921
- jarNSMapping = { ...jarNSMapping, ...tmpjarNSMapping };
1922
- }
1909
+ if (DEBUG_MODE) {
1910
+ console.log(`Found ${pkgList.length} packages`);
1911
+ }
1912
+ // Should we attempt to resolve class names
1913
+ if (options.resolveClass || options.deep) {
1914
+ const tmpjarNSMapping = await collectJarNS(SBT_CACHE_DIR);
1915
+ if (tmpjarNSMapping && Object.keys(tmpjarNSMapping).length) {
1916
+ jarNSMapping = { ...jarNSMapping, ...tmpjarNSMapping };
1923
1917
  }
1924
- pkgList = await getMvnMetadata(pkgList, jarNSMapping);
1925
- return buildBomNSData(options, pkgList, "maven", {
1926
- src: path,
1927
- filename: sbtProjects.join(", "),
1928
- nsMapping: jarNSMapping,
1929
- dependencies,
1930
- parentComponent,
1931
- });
1932
1918
  }
1919
+ pkgList = await getMvnMetadata(pkgList, jarNSMapping);
1920
+ return buildBomNSData(options, pkgList, "maven", {
1921
+ src: path,
1922
+ filename: sbtProjects.join(", "),
1923
+ nsMapping: jarNSMapping,
1924
+ dependencies,
1925
+ parentComponent,
1926
+ });
1933
1927
  }
1934
1928
  }
1935
1929
 
@@ -1953,7 +1947,7 @@ export async function createNodejsBom(path, options) {
1953
1947
  if (pkgJsonFiles.length) {
1954
1948
  for (const pj of pkgJsonFiles) {
1955
1949
  const dlist = await parsePkgJson(pj);
1956
- if (dlist && dlist.length) {
1950
+ if (dlist?.length) {
1957
1951
  pkgList = pkgList.concat(dlist);
1958
1952
  }
1959
1953
  }
@@ -1982,17 +1976,17 @@ export async function createNodejsBom(path, options) {
1982
1976
  }
1983
1977
  const yarnLockFiles = getAllFiles(
1984
1978
  path,
1985
- (options.multiProject ? "**/" : "") + "yarn.lock",
1979
+ `${options.multiProject ? "**/" : ""}yarn.lock`,
1986
1980
  options,
1987
1981
  );
1988
1982
  const shrinkwrapFiles = getAllFiles(
1989
1983
  path,
1990
- (options.multiProject ? "**/" : "") + "npm-shrinkwrap.json",
1984
+ `${options.multiProject ? "**/" : ""}npm-shrinkwrap.json`,
1991
1985
  options,
1992
1986
  );
1993
1987
  let pkgLockFiles = getAllFiles(
1994
1988
  path,
1995
- (options.multiProject ? "**/" : "") + "package-lock.json",
1989
+ `${options.multiProject ? "**/" : ""}package-lock.json`,
1996
1990
  options,
1997
1991
  );
1998
1992
  if (shrinkwrapFiles.length) {
@@ -2000,40 +1994,40 @@ export async function createNodejsBom(path, options) {
2000
1994
  }
2001
1995
  const pnpmLockFiles = getAllFiles(
2002
1996
  path,
2003
- (options.multiProject ? "**/" : "") + "pnpm-lock.yaml",
1997
+ `${options.multiProject ? "**/" : ""}pnpm-lock.yaml`,
2004
1998
  options,
2005
1999
  );
2006
2000
  const minJsFiles = getAllFiles(
2007
2001
  path,
2008
- (options.multiProject ? "**/" : "") + "*min.js",
2002
+ `${options.multiProject ? "**/" : ""}*min.js`,
2009
2003
  options,
2010
2004
  );
2011
2005
  const bowerFiles = getAllFiles(
2012
2006
  path,
2013
- (options.multiProject ? "**/" : "") + "bower.json",
2007
+ `${options.multiProject ? "**/" : ""}bower.json`,
2014
2008
  options,
2015
2009
  );
2016
2010
  // Parse min js files
2017
- if (minJsFiles && minJsFiles.length) {
2011
+ if (minJsFiles?.length) {
2018
2012
  manifestFiles = manifestFiles.concat(minJsFiles);
2019
2013
  for (const f of minJsFiles) {
2020
2014
  const dlist = await parseMinJs(f);
2021
- if (dlist && dlist.length) {
2015
+ if (dlist?.length) {
2022
2016
  pkgList = pkgList.concat(dlist);
2023
2017
  }
2024
2018
  }
2025
2019
  }
2026
2020
  // Parse bower json files
2027
- if (bowerFiles && bowerFiles.length) {
2021
+ if (bowerFiles?.length) {
2028
2022
  manifestFiles = manifestFiles.concat(bowerFiles);
2029
2023
  for (const f of bowerFiles) {
2030
2024
  const dlist = await parseBowerJson(f);
2031
- if (dlist && dlist.length) {
2025
+ if (dlist?.length) {
2032
2026
  pkgList = pkgList.concat(dlist);
2033
2027
  }
2034
2028
  }
2035
2029
  }
2036
- if (pnpmLockFiles && pnpmLockFiles.length) {
2030
+ if (pnpmLockFiles?.length) {
2037
2031
  manifestFiles = manifestFiles.concat(pnpmLockFiles);
2038
2032
  for (const f of pnpmLockFiles) {
2039
2033
  const basePath = dirname(f);
@@ -2078,7 +2072,7 @@ export async function createNodejsBom(path, options) {
2078
2072
  // Parse the pnpm file
2079
2073
  const parsedList = await parsePnpmLock(f, parentComponent);
2080
2074
  const dlist = parsedList.pkgList;
2081
- if (dlist && dlist.length) {
2075
+ if (dlist?.length) {
2082
2076
  pkgList = pkgList.concat(dlist);
2083
2077
  }
2084
2078
  if (parsedList.dependenciesList && parsedList.dependenciesList) {
@@ -2090,7 +2084,7 @@ export async function createNodejsBom(path, options) {
2090
2084
  }
2091
2085
  }
2092
2086
  }
2093
- if (pkgLockFiles && pkgLockFiles.length) {
2087
+ if (pkgLockFiles?.length) {
2094
2088
  manifestFiles = manifestFiles.concat(pkgLockFiles);
2095
2089
  for (const f of pkgLockFiles) {
2096
2090
  if (DEBUG_MODE) {
@@ -2106,7 +2100,7 @@ export async function createNodejsBom(path, options) {
2106
2100
  } else {
2107
2101
  parentSubComponents.push(tmpParentComponent);
2108
2102
  }
2109
- if (dlist && dlist.length) {
2103
+ if (dlist?.length) {
2110
2104
  pkgList = pkgList.concat(dlist);
2111
2105
  }
2112
2106
  if (parsedList.dependenciesList && parsedList.dependenciesList) {
@@ -2132,7 +2126,7 @@ export async function createNodejsBom(path, options) {
2132
2126
  encoding: "utf-8",
2133
2127
  },
2134
2128
  );
2135
- if (result.status == 1 || result.error) {
2129
+ if (result.status === 1 || result.error) {
2136
2130
  console.error(result.stdout, result.stderr);
2137
2131
  options.failOnError && process.exit(1);
2138
2132
  }
@@ -2162,7 +2156,8 @@ export async function createNodejsBom(path, options) {
2162
2156
  src: path,
2163
2157
  filename: "shrinkwrap-deps.json",
2164
2158
  });
2165
- } else if (existsSync(pnpmLock)) {
2159
+ }
2160
+ if (existsSync(pnpmLock)) {
2166
2161
  let pkgList = await parsePnpmLock(pnpmLock);
2167
2162
  if (allImports && Object.keys(allImports).length) {
2168
2163
  pkgList = await addEvidenceForImports(
@@ -2178,18 +2173,17 @@ export async function createNodejsBom(path, options) {
2178
2173
  src: path,
2179
2174
  filename: "pnpm-lock.yaml",
2180
2175
  });
2181
- } else {
2182
- console.log(
2183
- "Neither shrinkwrap file: ",
2184
- swFile,
2185
- " nor pnpm lockfile",
2186
- pnpmLock,
2187
- "was found!",
2188
- );
2189
- options.failOnError && process.exit(1);
2190
2176
  }
2177
+ console.log(
2178
+ "Neither shrinkwrap file: ",
2179
+ swFile,
2180
+ " nor pnpm lockfile",
2181
+ pnpmLock,
2182
+ "was found!",
2183
+ );
2184
+ options.failOnError && process.exit(1);
2191
2185
  }
2192
- if (yarnLockFiles && yarnLockFiles.length) {
2186
+ if (yarnLockFiles?.length) {
2193
2187
  manifestFiles = manifestFiles.concat(yarnLockFiles);
2194
2188
  for (const f of yarnLockFiles) {
2195
2189
  if (DEBUG_MODE) {
@@ -2248,7 +2242,7 @@ export async function createNodejsBom(path, options) {
2248
2242
  // rush.js could include yarn.lock :(
2249
2243
  const parsedList = await parseYarnLock(f);
2250
2244
  const dlist = parsedList.pkgList;
2251
- if (dlist && dlist.length) {
2245
+ if (dlist?.length) {
2252
2246
  pkgList = pkgList.concat(dlist);
2253
2247
  }
2254
2248
  const rdeplist = [];
@@ -2294,7 +2288,7 @@ export async function createNodejsBom(path, options) {
2294
2288
  manifestFiles = manifestFiles.concat(pkgJsonFiles);
2295
2289
  for (const pkgjf of pkgJsonFiles) {
2296
2290
  const dlist = await parsePkgJson(pkgjf);
2297
- if (dlist && dlist.length) {
2291
+ if (dlist?.length) {
2298
2292
  pkgList = pkgList.concat(dlist);
2299
2293
  }
2300
2294
  }
@@ -2356,20 +2350,20 @@ export async function createPythonBom(path, options) {
2356
2350
  const pipenvMode = existsSync(join(path, "Pipfile"));
2357
2351
  let poetryFiles = getAllFiles(
2358
2352
  path,
2359
- (options.multiProject ? "**/" : "") + "poetry.lock",
2353
+ `${options.multiProject ? "**/" : ""}poetry.lock`,
2360
2354
  options,
2361
2355
  );
2362
2356
  const pdmLockFiles = getAllFiles(
2363
2357
  path,
2364
- (options.multiProject ? "**/" : "") + "pdm.lock",
2358
+ `${options.multiProject ? "**/" : ""}pdm.lock`,
2365
2359
  options,
2366
2360
  );
2367
- if (pdmLockFiles && pdmLockFiles.length) {
2361
+ if (pdmLockFiles?.length) {
2368
2362
  poetryFiles = poetryFiles.concat(pdmLockFiles);
2369
2363
  }
2370
2364
  let reqFiles = getAllFiles(
2371
2365
  path,
2372
- (options.multiProject ? "**/" : "") + "*requirements*.txt",
2366
+ `${options.multiProject ? "**/" : ""}*requirements*.txt`,
2373
2367
  options,
2374
2368
  );
2375
2369
  reqFiles = reqFiles.filter(
@@ -2377,22 +2371,22 @@ export async function createPythonBom(path, options) {
2377
2371
  );
2378
2372
  const reqDirFiles = getAllFiles(
2379
2373
  path,
2380
- (options.multiProject ? "**/" : "") + "requirements/*.txt",
2374
+ `${options.multiProject ? "**/" : ""}requirements/*.txt`,
2381
2375
  options,
2382
2376
  );
2383
2377
  const metadataFiles = getAllFiles(
2384
2378
  path,
2385
- (options.multiProject ? "**/site-packages/**/" : "") + "METADATA",
2379
+ `${options.multiProject ? "**/site-packages/**/" : ""}METADATA`,
2386
2380
  options,
2387
2381
  );
2388
2382
  const whlFiles = getAllFiles(
2389
2383
  path,
2390
- (options.multiProject ? "**/" : "") + "*.whl",
2384
+ `${options.multiProject ? "**/" : ""}*.whl`,
2391
2385
  options,
2392
2386
  );
2393
2387
  const eggInfoFiles = getAllFiles(
2394
2388
  path,
2395
- (options.multiProject ? "**/" : "") + "*.egg-info",
2389
+ `${options.multiProject ? "**/" : ""}*.egg-info`,
2396
2390
  options,
2397
2391
  );
2398
2392
  const setupPy = join(path, "setup.py");
@@ -2400,7 +2394,7 @@ export async function createPythonBom(path, options) {
2400
2394
  const pyProjectMode = existsSync(pyProjectFile);
2401
2395
  if (pyProjectMode) {
2402
2396
  const tmpParentComponent = parsePyProjectToml(pyProjectFile);
2403
- if (tmpParentComponent && tmpParentComponent.name) {
2397
+ if (tmpParentComponent?.name) {
2404
2398
  parentComponent = tmpParentComponent;
2405
2399
  delete parentComponent.homepage;
2406
2400
  delete parentComponent.repository;
@@ -2417,9 +2411,8 @@ export async function createPythonBom(path, options) {
2417
2411
  parentComponent["purl"] = ppurl;
2418
2412
  }
2419
2413
  }
2420
- const requirementsMode =
2421
- (reqFiles && reqFiles.length) || (reqDirFiles && reqDirFiles.length);
2422
- const poetryMode = poetryFiles && poetryFiles.length;
2414
+ const requirementsMode = reqFiles?.length || reqDirFiles?.length;
2415
+ const poetryMode = poetryFiles?.length;
2423
2416
  const setupPyMode = existsSync(setupPy);
2424
2417
  // Poetry sets up its own virtual env containing site-packages so
2425
2418
  // we give preference to poetry lock file. Issue# 129
@@ -2428,11 +2421,11 @@ export async function createPythonBom(path, options) {
2428
2421
  const basePath = dirname(f);
2429
2422
  const lockData = readFileSync(f, { encoding: "utf-8" });
2430
2423
  let retMap = await parsePoetrylockData(lockData, f);
2431
- if (retMap.pkgList && retMap.pkgList.length) {
2424
+ if (retMap.pkgList?.length) {
2432
2425
  pkgList = pkgList.concat(retMap.pkgList);
2433
2426
  pkgList = trimComponents(pkgList);
2434
2427
  }
2435
- if (retMap.dependenciesList && retMap.dependenciesList.length) {
2428
+ if (retMap.dependenciesList?.length) {
2436
2429
  dependencies = mergeDependencies(
2437
2430
  dependencies,
2438
2431
  retMap.dependenciesList,
@@ -2443,7 +2436,7 @@ export async function createPythonBom(path, options) {
2443
2436
  // This is a slow operation
2444
2437
  if (options.deep || !dependencies.length) {
2445
2438
  retMap = getPipFrozenTree(basePath, f, tempDir);
2446
- if (retMap.pkgList && retMap.pkgList.length) {
2439
+ if (retMap.pkgList?.length) {
2447
2440
  pkgList = pkgList.concat(retMap.pkgList);
2448
2441
  }
2449
2442
  if (retMap.dependenciesList) {
@@ -2471,35 +2464,36 @@ export async function createPythonBom(path, options) {
2471
2464
  dependencies,
2472
2465
  parentComponent,
2473
2466
  });
2474
- } else if (metadataFiles && metadataFiles.length) {
2467
+ }
2468
+ if (metadataFiles?.length) {
2475
2469
  // dist-info directories
2476
2470
  for (const mf of metadataFiles) {
2477
2471
  const mData = readFileSync(mf, {
2478
2472
  encoding: "utf-8",
2479
2473
  });
2480
2474
  const dlist = parseBdistMetadata(mData);
2481
- if (dlist && dlist.length) {
2475
+ if (dlist?.length) {
2482
2476
  pkgList = pkgList.concat(dlist);
2483
2477
  }
2484
2478
  }
2485
2479
  }
2486
2480
  // .whl files. Zip file containing dist-info directory
2487
- if (whlFiles && whlFiles.length) {
2481
+ if (whlFiles?.length) {
2488
2482
  for (const wf of whlFiles) {
2489
2483
  const mData = await readZipEntry(wf, "METADATA");
2490
2484
  if (mData) {
2491
2485
  const dlist = parseBdistMetadata(mData);
2492
- if (dlist && dlist.length) {
2486
+ if (dlist?.length) {
2493
2487
  pkgList = pkgList.concat(dlist);
2494
2488
  }
2495
2489
  }
2496
2490
  }
2497
2491
  }
2498
2492
  // .egg-info files
2499
- if (eggInfoFiles && eggInfoFiles.length) {
2493
+ if (eggInfoFiles?.length) {
2500
2494
  for (const ef of eggInfoFiles) {
2501
2495
  const dlist = parseBdistMetadata(readFileSync(ef, { encoding: "utf-8" }));
2502
- if (dlist && dlist.length) {
2496
+ if (dlist?.length) {
2503
2497
  pkgList = pkgList.concat(dlist);
2504
2498
  }
2505
2499
  }
@@ -2511,7 +2505,7 @@ export async function createPythonBom(path, options) {
2511
2505
  if (existsSync(piplockFile)) {
2512
2506
  const lockData = JSON.parse(readFileSync(piplockFile));
2513
2507
  const dlist = await parsePiplockData(lockData);
2514
- if (dlist && dlist.length) {
2508
+ if (dlist?.length) {
2515
2509
  pkgList = pkgList.concat(dlist);
2516
2510
  }
2517
2511
  } else {
@@ -2520,7 +2514,7 @@ export async function createPythonBom(path, options) {
2520
2514
  }
2521
2515
  } else if (requirementsMode) {
2522
2516
  metadataFilename = "requirements.txt";
2523
- if (reqFiles && reqFiles.length) {
2517
+ if (reqFiles?.length) {
2524
2518
  if (options.installDeps && DEBUG_MODE) {
2525
2519
  console.log(
2526
2520
  "cdxgen will now attempt to generate an SBOM for 'build' lifecycle phase for Python. This would take some time ...\nTo speed up this step, invoke cdxgen from within a virtual environment with all the dependencies installed.\nAlternatively, pass the argument '--lifecycle pre-build' to generate a faster but less precise SBOM without installing the dependencies in case of any build issues.",
@@ -2535,7 +2529,7 @@ export async function createPythonBom(path, options) {
2535
2529
  // If there are multiple requirements files then the tree is getting constructed for each one
2536
2530
  // adding to the delay.
2537
2531
  const pkgMap = getPipFrozenTree(basePath, f, tempDir);
2538
- if (pkgMap.pkgList && pkgMap.pkgList.length) {
2532
+ if (pkgMap.pkgList?.length) {
2539
2533
  pkgList = pkgList.concat(pkgMap.pkgList);
2540
2534
  frozen = pkgMap.frozen;
2541
2535
  }
@@ -2556,18 +2550,18 @@ export async function createPythonBom(path, options) {
2556
2550
  }
2557
2551
  reqData = readFileSync(f, { encoding: "utf-8" });
2558
2552
  const dlist = await parseReqFile(reqData, true);
2559
- if (dlist && dlist.length) {
2553
+ if (dlist?.length) {
2560
2554
  pkgList = pkgList.concat(dlist);
2561
2555
  }
2562
2556
  }
2563
2557
  } // for
2564
2558
  metadataFilename = reqFiles.join(", ");
2565
- } else if (reqDirFiles && reqDirFiles.length) {
2559
+ } else if (reqDirFiles?.length) {
2566
2560
  for (const j in reqDirFiles) {
2567
2561
  const f = reqDirFiles[j];
2568
2562
  const reqData = readFileSync(f, { encoding: "utf-8" });
2569
2563
  const dlist = await parseReqFile(reqData, false);
2570
- if (dlist && dlist.length) {
2564
+ if (dlist?.length) {
2571
2565
  pkgList = pkgList.concat(dlist);
2572
2566
  }
2573
2567
  }
@@ -2593,7 +2587,7 @@ export async function createPythonBom(path, options) {
2593
2587
  const parentDependsOn = new Set();
2594
2588
  const retMap = await getPyModules(path, pkgList, options);
2595
2589
  // We need to patch the existing package list to add ImportedModules for evinse to work
2596
- if (retMap.modList && retMap.modList.length) {
2590
+ if (retMap.modList?.length) {
2597
2591
  const iSymbolsMap = {};
2598
2592
  retMap.modList.forEach((v) => {
2599
2593
  iSymbolsMap[v.name] = v.importedSymbols;
@@ -2609,7 +2603,7 @@ export async function createPythonBom(path, options) {
2609
2603
  }
2610
2604
  }
2611
2605
  }
2612
- if (retMap.pkgList && retMap.pkgList.length) {
2606
+ if (retMap.pkgList?.length) {
2613
2607
  pkgList = pkgList.concat(retMap.pkgList);
2614
2608
  for (const p of retMap.pkgList) {
2615
2609
  if (
@@ -2644,7 +2638,7 @@ export async function createPythonBom(path, options) {
2644
2638
  }
2645
2639
  parentDependsOn.add(`pkg:pypi/${p.name}@${p.version}`);
2646
2640
  }
2647
- if (pkgMap.pkgList && pkgMap.pkgList.length) {
2641
+ if (pkgMap.pkgList?.length) {
2648
2642
  pkgList = pkgList.concat(pkgMap.pkgList);
2649
2643
  }
2650
2644
  if (pkgMap.dependenciesList) {
@@ -2677,12 +2671,12 @@ export async function createPythonBom(path, options) {
2677
2671
  if (!pkgList.length && setupPyMode) {
2678
2672
  const setupPyData = readFileSync(setupPy, { encoding: "utf-8" });
2679
2673
  const dlist = await parseSetupPyFile(setupPyData);
2680
- if (dlist && dlist.length) {
2674
+ if (dlist?.length) {
2681
2675
  pkgList = pkgList.concat(dlist);
2682
2676
  }
2683
2677
  }
2684
2678
  // Clean up
2685
- if (tempDir && tempDir.startsWith(tmpdir()) && rmSync) {
2679
+ if (tempDir?.startsWith(tmpdir()) && rmSync) {
2686
2680
  rmSync(tempDir, { recursive: true, force: true });
2687
2681
  }
2688
2682
  if (FETCH_LICENSE) {
@@ -2722,7 +2716,7 @@ export async function createGoBom(path, options) {
2722
2716
  // Read in go.sum and merge all go.sum files.
2723
2717
  const gosumFiles = getAllFiles(
2724
2718
  path,
2725
- (options.multiProject ? "**/" : "") + "go.sum",
2719
+ `${options.multiProject ? "**/" : ""}go.sum`,
2726
2720
  options,
2727
2721
  );
2728
2722
 
@@ -2740,7 +2734,7 @@ export async function createGoBom(path, options) {
2740
2734
  }
2741
2735
  const gosumData = readFileSync(f, { encoding: "utf-8" });
2742
2736
  const dlist = await parseGosumData(gosumData);
2743
- if (dlist && dlist.length) {
2737
+ if (dlist?.length) {
2744
2738
  pkgList = pkgList.concat(dlist);
2745
2739
  }
2746
2740
  }
@@ -2799,7 +2793,7 @@ export async function createGoBom(path, options) {
2799
2793
  // whyPkg would include this package string
2800
2794
  // github.com/golang/protobuf/proto github.com/golang/protobuf
2801
2795
  // golang.org/x/tools/cmd/goimports golang.org/x/tools
2802
- if (whyPkg && whyPkg.includes(pkgFullName)) {
2796
+ if (whyPkg?.includes(pkgFullName)) {
2803
2797
  allImports[pkgFullName] = true;
2804
2798
  }
2805
2799
  doneList[pkgFullName] = true;
@@ -2826,7 +2820,7 @@ export async function createGoBom(path, options) {
2826
2820
  }
2827
2821
  const gosumData = readFileSync(f, { encoding: "utf-8" });
2828
2822
  const dlist = await parseGosumData(gosumData);
2829
- if (dlist && dlist.length) {
2823
+ if (dlist?.length) {
2830
2824
  dlist.forEach((pkg) => {
2831
2825
  gosumMap[`${pkg.name}@${pkg.version}`] = pkg._integrity;
2832
2826
  });
@@ -2837,14 +2831,14 @@ export async function createGoBom(path, options) {
2837
2831
  // Read in data from Gopkg.lock files if they exist
2838
2832
  const gopkgLockFiles = getAllFiles(
2839
2833
  path,
2840
- (options.multiProject ? "**/" : "") + "Gopkg.lock",
2834
+ `${options.multiProject ? "**/" : ""}Gopkg.lock`,
2841
2835
  options,
2842
2836
  );
2843
2837
 
2844
2838
  // Read in go.mod files and parse BOM components with checksums from gosumData
2845
2839
  const gomodFiles = getAllFiles(
2846
2840
  path,
2847
- (options.multiProject ? "**/" : "") + "go.mod",
2841
+ `${options.multiProject ? "**/" : ""}go.mod`,
2848
2842
  options,
2849
2843
  );
2850
2844
  if (gomodFiles.length) {
@@ -2894,7 +2888,7 @@ export async function createGoBom(path, options) {
2894
2888
  if (stdout) {
2895
2889
  let cmdOutput = Buffer.from(stdout).toString();
2896
2890
  const retMap = await parseGoListDep(cmdOutput, gosumMap);
2897
- if (retMap.pkgList && retMap.pkgList.length) {
2891
+ if (retMap.pkgList?.length) {
2898
2892
  pkgList = pkgList.concat(retMap.pkgList);
2899
2893
  }
2900
2894
  // We treat the main module as our parent
@@ -2931,11 +2925,11 @@ export async function createGoBom(path, options) {
2931
2925
  pkgList,
2932
2926
  parentComponent,
2933
2927
  );
2934
- if (retMap.pkgList && retMap.pkgList.length) {
2928
+ if (retMap.pkgList?.length) {
2935
2929
  pkgList = pkgList.concat(retMap.pkgList);
2936
2930
  pkgList = trimComponents(pkgList);
2937
2931
  }
2938
- if (retMap.dependenciesList && retMap.dependenciesList.length) {
2932
+ if (retMap.dependenciesList?.length) {
2939
2933
  dependencies = mergeDependencies(
2940
2934
  dependencies,
2941
2935
  retMap.dependenciesList,
@@ -2973,7 +2967,7 @@ export async function createGoBom(path, options) {
2973
2967
  }
2974
2968
  const gomodData = readFileSync(f, { encoding: "utf-8" });
2975
2969
  const dlist = await parseGoModData(gomodData, gosumMap);
2976
- if (dlist && dlist.length) {
2970
+ if (dlist?.length) {
2977
2971
  pkgList = pkgList.concat(dlist);
2978
2972
  }
2979
2973
  }
@@ -2983,7 +2977,8 @@ export async function createGoBom(path, options) {
2983
2977
  parentComponent,
2984
2978
  filename: gomodFiles.join(", "),
2985
2979
  });
2986
- } else if (gopkgLockFiles.length) {
2980
+ }
2981
+ if (gopkgLockFiles.length) {
2987
2982
  for (const f of gopkgLockFiles) {
2988
2983
  if (DEBUG_MODE) {
2989
2984
  console.log(`Parsing ${f}`);
@@ -2992,7 +2987,7 @@ export async function createGoBom(path, options) {
2992
2987
  encoding: "utf-8",
2993
2988
  });
2994
2989
  const dlist = await parseGopkgData(gopkgData);
2995
- if (dlist && dlist.length) {
2990
+ if (dlist?.length) {
2996
2991
  pkgList = pkgList.concat(dlist);
2997
2992
  }
2998
2993
  }
@@ -3025,7 +3020,7 @@ export async function createRustBom(path, options) {
3025
3020
  if (maybeBinary) {
3026
3021
  const cargoData = getCargoAuditableInfo(path);
3027
3022
  const dlist = await parseCargoAuditableData(cargoData);
3028
- if (dlist && dlist.length) {
3023
+ if (dlist?.length) {
3029
3024
  pkgList = pkgList.concat(dlist);
3030
3025
  }
3031
3026
  // Since this pkg list is derived from the binary mark them as used.
@@ -3042,12 +3037,12 @@ export async function createRustBom(path, options) {
3042
3037
  }
3043
3038
  let cargoLockFiles = getAllFiles(
3044
3039
  path,
3045
- (options.multiProject ? "**/" : "") + "Cargo.lock",
3040
+ `${options.multiProject ? "**/" : ""}Cargo.lock`,
3046
3041
  options,
3047
3042
  );
3048
3043
  const cargoFiles = getAllFiles(
3049
3044
  path,
3050
- (options.multiProject ? "**/" : "") + "Cargo.toml",
3045
+ `${options.multiProject ? "**/" : ""}Cargo.toml`,
3051
3046
  options,
3052
3047
  );
3053
3048
  // This function assumes that the given path is prioritized, i.e that the
@@ -3064,7 +3059,7 @@ export async function createRustBom(path, options) {
3064
3059
  console.log(`Parsing ${f}`);
3065
3060
  }
3066
3061
  const dlist = await parseCargoTomlData(f, cargoLockMode);
3067
- if (dlist && dlist.length) {
3062
+ if (dlist?.length) {
3068
3063
  if (!cargoLockMode) {
3069
3064
  pkgList = pkgList.concat(dlist);
3070
3065
  } else {
@@ -3087,7 +3082,7 @@ export async function createRustBom(path, options) {
3087
3082
  // Get the new lock files
3088
3083
  cargoLockFiles = getAllFiles(
3089
3084
  path,
3090
- (options.multiProject ? "**/" : "") + "Cargo.lock",
3085
+ `${options.multiProject ? "**/" : ""}Cargo.lock`,
3091
3086
  options,
3092
3087
  );
3093
3088
  let dependencyTree = [];
@@ -3097,7 +3092,7 @@ export async function createRustBom(path, options) {
3097
3092
  console.log(`Parsing ${f}`);
3098
3093
  }
3099
3094
  const dlist = await parseCargoData(f);
3100
- if (dlist && dlist.length) {
3095
+ if (dlist?.length) {
3101
3096
  pkgList = pkgList.concat(dlist);
3102
3097
  }
3103
3098
 
@@ -3106,7 +3101,7 @@ export async function createRustBom(path, options) {
3106
3101
  }
3107
3102
  const cargoLockData = readFileSync(f, { encoding: "utf-8" });
3108
3103
  const fileDependencylist = parseCargoDependencyData(cargoLockData);
3109
- if (fileDependencylist && fileDependencylist.length) {
3104
+ if (fileDependencylist?.length) {
3110
3105
  dependencyTree = mergeDependencies(
3111
3106
  dependencyTree,
3112
3107
  fileDependencylist,
@@ -3133,12 +3128,12 @@ export async function createRustBom(path, options) {
3133
3128
  export async function createDartBom(path, options) {
3134
3129
  const pubFiles = getAllFiles(
3135
3130
  path,
3136
- (options.multiProject ? "**/" : "") + "pubspec.lock",
3131
+ `${options.multiProject ? "**/" : ""}pubspec.lock`,
3137
3132
  options,
3138
3133
  );
3139
3134
  const pubSpecYamlFiles = getAllFiles(
3140
3135
  path,
3141
- (options.multiProject ? "**/" : "") + "pubspec.yaml",
3136
+ `${options.multiProject ? "**/" : ""}pubspec.yaml`,
3142
3137
  options,
3143
3138
  );
3144
3139
  let pkgList = [];
@@ -3149,7 +3144,7 @@ export async function createDartBom(path, options) {
3149
3144
  }
3150
3145
  const pubLockData = readFileSync(f, { encoding: "utf-8" });
3151
3146
  const dlist = await parsePubLockData(pubLockData);
3152
- if (dlist && dlist.length) {
3147
+ if (dlist?.length) {
3153
3148
  pkgList = pkgList.concat(dlist);
3154
3149
  }
3155
3150
  }
@@ -3157,14 +3152,15 @@ export async function createDartBom(path, options) {
3157
3152
  src: path,
3158
3153
  filename: pubFiles.join(", "),
3159
3154
  });
3160
- } else if (pubSpecYamlFiles.length) {
3155
+ }
3156
+ if (pubSpecYamlFiles.length) {
3161
3157
  for (const f of pubSpecYamlFiles) {
3162
3158
  if (DEBUG_MODE) {
3163
3159
  console.log(`Parsing ${f}`);
3164
3160
  }
3165
3161
  const pubYamlData = readFileSync(f, { encoding: "utf-8" });
3166
3162
  const dlist = parsePubYamlData(pubYamlData);
3167
- if (dlist && dlist.length) {
3163
+ if (dlist?.length) {
3168
3164
  pkgList = pkgList.concat(dlist);
3169
3165
  }
3170
3166
  }
@@ -3189,36 +3185,36 @@ export function createCppBom(path, options) {
3189
3185
  const addedParentComponentsMap = {};
3190
3186
  const conanLockFiles = getAllFiles(
3191
3187
  path,
3192
- (options.multiProject ? "**/" : "") + "conan.lock",
3188
+ `${options.multiProject ? "**/" : ""}conan.lock`,
3193
3189
  options,
3194
3190
  );
3195
3191
  const conanFiles = getAllFiles(
3196
3192
  path,
3197
- (options.multiProject ? "**/" : "") + "conanfile.txt",
3193
+ `${options.multiProject ? "**/" : ""}conanfile.txt`,
3198
3194
  options,
3199
3195
  );
3200
3196
  let cmakeLikeFiles = [];
3201
3197
  const mesonBuildFiles = getAllFiles(
3202
3198
  path,
3203
- (options.multiProject ? "**/" : "") + "meson.build",
3199
+ `${options.multiProject ? "**/" : ""}meson.build`,
3204
3200
  options,
3205
3201
  );
3206
- if (mesonBuildFiles && mesonBuildFiles.length) {
3202
+ if (mesonBuildFiles?.length) {
3207
3203
  cmakeLikeFiles = cmakeLikeFiles.concat(mesonBuildFiles);
3208
3204
  }
3209
3205
  cmakeLikeFiles = cmakeLikeFiles.concat(
3210
3206
  getAllFiles(
3211
3207
  path,
3212
- (options.multiProject ? "**/" : "") + "CMakeLists.txt",
3208
+ `${options.multiProject ? "**/" : ""}CMakeLists.txt`,
3213
3209
  options,
3214
3210
  ),
3215
3211
  );
3216
3212
  const cmakeFiles = getAllFiles(
3217
3213
  path,
3218
- (options.multiProject ? "**/" : "") + "*.cmake",
3214
+ `${options.multiProject ? "**/" : ""}*.cmake`,
3219
3215
  options,
3220
3216
  );
3221
- if (cmakeFiles && cmakeFiles.length) {
3217
+ if (cmakeFiles?.length) {
3222
3218
  cmakeLikeFiles = cmakeLikeFiles.concat(cmakeFiles);
3223
3219
  }
3224
3220
  let pkgList = [];
@@ -3229,7 +3225,7 @@ export function createCppBom(path, options) {
3229
3225
  }
3230
3226
  const conanLockData = readFileSync(f, { encoding: "utf-8" });
3231
3227
  const dlist = parseConanLockData(conanLockData);
3232
- if (dlist && dlist.length) {
3228
+ if (dlist?.length) {
3233
3229
  pkgList = pkgList.concat(dlist);
3234
3230
  }
3235
3231
  }
@@ -3240,7 +3236,7 @@ export function createCppBom(path, options) {
3240
3236
  }
3241
3237
  const conanData = readFileSync(f, { encoding: "utf-8" });
3242
3238
  const dlist = parseConanData(conanData);
3243
- if (dlist && dlist.length) {
3239
+ if (dlist?.length) {
3244
3240
  pkgList = pkgList.concat(dlist);
3245
3241
  }
3246
3242
  }
@@ -3252,7 +3248,7 @@ export function createCppBom(path, options) {
3252
3248
  }
3253
3249
  const basePath = dirname(f);
3254
3250
  const retMap = parseCmakeLikeFile(f, "generic");
3255
- if (retMap.pkgList && retMap.pkgList.length) {
3251
+ if (retMap.pkgList?.length) {
3256
3252
  pkgList = pkgList.concat(retMap.pkgList);
3257
3253
  }
3258
3254
  if (
@@ -3312,7 +3308,7 @@ export function createCppBom(path, options) {
3312
3308
  results,
3313
3309
  true,
3314
3310
  );
3315
- if (dlist && dlist.length) {
3311
+ if (dlist?.length) {
3316
3312
  osPkgsList = osPkgsList.concat(dlist);
3317
3313
  }
3318
3314
  }
@@ -3320,7 +3316,7 @@ export function createCppBom(path, options) {
3320
3316
  // We pass the current list of packages so that we enhance the current list and replace
3321
3317
  // components inadvertently. For example, we might resolved a name, version and url information already via cmake
3322
3318
  const retMap = getCppModules(path, options, osPkgsList, pkgList);
3323
- if (retMap.pkgList && retMap.pkgList.length) {
3319
+ if (retMap.pkgList?.length) {
3324
3320
  pkgList = pkgList.concat(retMap.pkgList);
3325
3321
  }
3326
3322
  if (retMap.dependenciesList) {
@@ -3366,12 +3362,12 @@ export function createCppBom(path, options) {
3366
3362
  export function createClojureBom(path, options) {
3367
3363
  const ednFiles = getAllFiles(
3368
3364
  path,
3369
- (options.multiProject ? "**/" : "") + "deps.edn",
3365
+ `${options.multiProject ? "**/" : ""}deps.edn`,
3370
3366
  options,
3371
3367
  );
3372
3368
  const leinFiles = getAllFiles(
3373
3369
  path,
3374
- (options.multiProject ? "**/" : "") + "project.clj",
3370
+ `${options.multiProject ? "**/" : ""}project.clj`,
3375
3371
  options,
3376
3372
  );
3377
3373
  let pkgList = [];
@@ -3405,7 +3401,7 @@ export function createClojureBom(path, options) {
3405
3401
  }
3406
3402
  const leinData = readFileSync(f, { encoding: "utf-8" });
3407
3403
  const dlist = parseLeiningenData(leinData);
3408
- if (dlist && dlist.length) {
3404
+ if (dlist?.length) {
3409
3405
  pkgList = pkgList.concat(dlist);
3410
3406
  }
3411
3407
  } else {
@@ -3413,7 +3409,7 @@ export function createClojureBom(path, options) {
3413
3409
  if (stdout) {
3414
3410
  const cmdOutput = Buffer.from(stdout).toString();
3415
3411
  const dlist = parseLeinDep(cmdOutput);
3416
- if (dlist && dlist.length) {
3412
+ if (dlist?.length) {
3417
3413
  pkgList = pkgList.concat(dlist);
3418
3414
  }
3419
3415
  } else {
@@ -3426,7 +3422,8 @@ export function createClojureBom(path, options) {
3426
3422
  src: path,
3427
3423
  filename: leinFiles.join(", "),
3428
3424
  });
3429
- } else if (ednFiles.length) {
3425
+ }
3426
+ if (ednFiles.length) {
3430
3427
  let CLJ_ARGS = ["-Stree"];
3431
3428
  if (process.env.CLJ_ARGS) {
3432
3429
  CLJ_ARGS = process.env.CLJ_ARGS.split(" ");
@@ -3453,7 +3450,7 @@ export function createClojureBom(path, options) {
3453
3450
  }
3454
3451
  const ednData = readFileSync(f, { encoding: "utf-8" });
3455
3452
  const dlist = parseEdnData(ednData);
3456
- if (dlist && dlist.length) {
3453
+ if (dlist?.length) {
3457
3454
  pkgList = pkgList.concat(dlist);
3458
3455
  }
3459
3456
  } else {
@@ -3461,7 +3458,7 @@ export function createClojureBom(path, options) {
3461
3458
  if (stdout) {
3462
3459
  const cmdOutput = Buffer.from(stdout).toString();
3463
3460
  const dlist = parseCljDep(cmdOutput);
3464
- if (dlist && dlist.length) {
3461
+ if (dlist?.length) {
3465
3462
  pkgList = pkgList.concat(dlist);
3466
3463
  }
3467
3464
  } else {
@@ -3488,7 +3485,7 @@ export function createClojureBom(path, options) {
3488
3485
  export function createHaskellBom(path, options) {
3489
3486
  const cabalFiles = getAllFiles(
3490
3487
  path,
3491
- (options.multiProject ? "**/" : "") + "cabal.project.freeze",
3488
+ `${options.multiProject ? "**/" : ""}cabal.project.freeze`,
3492
3489
  options,
3493
3490
  );
3494
3491
  let pkgList = [];
@@ -3499,7 +3496,7 @@ export function createHaskellBom(path, options) {
3499
3496
  }
3500
3497
  const cabalData = readFileSync(f, { encoding: "utf-8" });
3501
3498
  const dlist = parseCabalData(cabalData);
3502
- if (dlist && dlist.length) {
3499
+ if (dlist?.length) {
3503
3500
  pkgList = pkgList.concat(dlist);
3504
3501
  }
3505
3502
  }
@@ -3520,7 +3517,7 @@ export function createHaskellBom(path, options) {
3520
3517
  export function createElixirBom(path, options) {
3521
3518
  const mixFiles = getAllFiles(
3522
3519
  path,
3523
- (options.multiProject ? "**/" : "") + "mix.lock",
3520
+ `${options.multiProject ? "**/" : ""}mix.lock`,
3524
3521
  options,
3525
3522
  );
3526
3523
  let pkgList = [];
@@ -3531,7 +3528,7 @@ export function createElixirBom(path, options) {
3531
3528
  }
3532
3529
  const mixData = readFileSync(f, { encoding: "utf-8" });
3533
3530
  const dlist = parseMixLockData(mixData);
3534
- if (dlist && dlist.length) {
3531
+ if (dlist?.length) {
3535
3532
  pkgList = pkgList.concat(dlist);
3536
3533
  }
3537
3534
  }
@@ -3563,7 +3560,7 @@ export function createGitHubBom(path, options) {
3563
3560
  }
3564
3561
  const ghwData = readFileSync(f, { encoding: "utf-8" });
3565
3562
  const dlist = parseGitHubWorkflowData(ghwData);
3566
- if (dlist && dlist.length) {
3563
+ if (dlist?.length) {
3567
3564
  pkgList = pkgList.concat(dlist);
3568
3565
  }
3569
3566
  }
@@ -3591,7 +3588,7 @@ export function createCloudBuildBom(path, options) {
3591
3588
  }
3592
3589
  const cbwData = readFileSync(f, { encoding: "utf-8" });
3593
3590
  const dlist = parseCloudBuildData(cbwData);
3594
- if (dlist && dlist.length) {
3591
+ if (dlist?.length) {
3595
3592
  pkgList = pkgList.concat(dlist);
3596
3593
  }
3597
3594
  }
@@ -3625,7 +3622,7 @@ export function createOSBom(path, options) {
3625
3622
  results,
3626
3623
  false,
3627
3624
  );
3628
- if (dlist && dlist.length) {
3625
+ if (dlist?.length) {
3629
3626
  if (!Object.keys(parentComponent).length) {
3630
3627
  parentComponent = dlist.splice(0, 1)[0];
3631
3628
  }
@@ -3671,7 +3668,7 @@ export async function createJenkinsBom(path, options) {
3671
3668
  let pkgList = [];
3672
3669
  const hpiFiles = getAllFiles(
3673
3670
  path,
3674
- (options.multiProject ? "**/" : "") + "*.hpi",
3671
+ `${options.multiProject ? "**/" : ""}*.hpi`,
3675
3672
  options,
3676
3673
  );
3677
3674
  const tempDir = mkdtempSync(join(tmpdir(), "hpi-deps-"));
@@ -3681,7 +3678,7 @@ export async function createJenkinsBom(path, options) {
3681
3678
  console.log(`Parsing ${f}`);
3682
3679
  }
3683
3680
  const dlist = await extractJarArchive(f, tempDir);
3684
- if (dlist && dlist.length) {
3681
+ if (dlist?.length) {
3685
3682
  pkgList = pkgList.concat(dlist);
3686
3683
  }
3687
3684
  }
@@ -3693,13 +3690,13 @@ export async function createJenkinsBom(path, options) {
3693
3690
  console.log(`Parsing ${f}`);
3694
3691
  }
3695
3692
  const dlist = await parseMinJs(f);
3696
- if (dlist && dlist.length) {
3693
+ if (dlist?.length) {
3697
3694
  pkgList = pkgList.concat(dlist);
3698
3695
  }
3699
3696
  }
3700
3697
  }
3701
3698
  // Clean up
3702
- if (tempDir && tempDir.startsWith(tmpdir()) && rmSync) {
3699
+ if (tempDir?.startsWith(tmpdir()) && rmSync) {
3703
3700
  console.log(`Cleaning up ${tempDir}`);
3704
3701
  rmSync(tempDir, { recursive: true, force: true });
3705
3702
  }
@@ -3720,7 +3717,7 @@ export function createHelmBom(path, options) {
3720
3717
  let pkgList = [];
3721
3718
  const yamlFiles = getAllFiles(
3722
3719
  path,
3723
- (options.multiProject ? "**/" : "") + "*.yaml",
3720
+ `${options.multiProject ? "**/" : ""}*.yaml`,
3724
3721
  options,
3725
3722
  );
3726
3723
  if (yamlFiles.length) {
@@ -3730,7 +3727,7 @@ export function createHelmBom(path, options) {
3730
3727
  }
3731
3728
  const helmData = readFileSync(f, { encoding: "utf-8" });
3732
3729
  const dlist = parseHelmYamlData(helmData);
3733
- if (dlist && dlist.length) {
3730
+ if (dlist?.length) {
3734
3731
  pkgList = pkgList.concat(dlist);
3735
3732
  }
3736
3733
  }
@@ -3751,12 +3748,12 @@ export function createHelmBom(path, options) {
3751
3748
  export async function createSwiftBom(path, options) {
3752
3749
  const swiftFiles = getAllFiles(
3753
3750
  path,
3754
- (options.multiProject ? "**/" : "") + "Package*.swift",
3751
+ `${options.multiProject ? "**/" : ""}Package*.swift`,
3755
3752
  options,
3756
3753
  );
3757
3754
  const pkgResolvedFiles = getAllFiles(
3758
3755
  path,
3759
- (options.multiProject ? "**/" : "") + "Package.resolved",
3756
+ `${options.multiProject ? "**/" : ""}Package.resolved`,
3760
3757
  options,
3761
3758
  );
3762
3759
  let pkgList = [];
@@ -3772,7 +3769,7 @@ export async function createSwiftBom(path, options) {
3772
3769
  console.log("Parsing", f);
3773
3770
  }
3774
3771
  const dlist = parseSwiftResolved(f);
3775
- if (dlist && dlist.length) {
3772
+ if (dlist?.length) {
3776
3773
  pkgList = pkgList.concat(dlist);
3777
3774
  }
3778
3775
  }
@@ -3801,7 +3798,7 @@ export async function createSwiftBom(path, options) {
3801
3798
  completedPath.push(basePath);
3802
3799
  treeData = Buffer.from(result.stdout).toString();
3803
3800
  const retData = parseSwiftJsonTree(treeData, f);
3804
- if (retData.pkgList && retData.pkgList.length) {
3801
+ if (retData.pkgList?.length) {
3805
3802
  parentComponent = retData.pkgList.splice(0, 1)[0];
3806
3803
  parentComponent.type = "application";
3807
3804
  pkgList = pkgList.concat(retData.pkgList);
@@ -3853,40 +3850,40 @@ export async function createContainerSpecLikeBom(path, options) {
3853
3850
  const origProjectType = options.projectType;
3854
3851
  let dcFiles = getAllFiles(
3855
3852
  path,
3856
- (options.multiProject ? "**/" : "") + "*.yml",
3853
+ `${options.multiProject ? "**/" : ""}*.yml`,
3857
3854
  options,
3858
3855
  );
3859
3856
  const dfFiles = getAllFiles(
3860
3857
  path,
3861
- (options.multiProject ? "**/" : "") + "*Dockerfile*",
3858
+ `${options.multiProject ? "**/" : ""}*Dockerfile*`,
3862
3859
  options,
3863
3860
  );
3864
3861
  const bbPipelineFiles = getAllFiles(
3865
3862
  path,
3866
- (options.multiProject ? "**/" : "") + "bitbucket-pipelines.yml",
3863
+ `${options.multiProject ? "**/" : ""}bitbucket-pipelines.yml`,
3867
3864
  options,
3868
3865
  );
3869
3866
  const cfFiles = getAllFiles(
3870
3867
  path,
3871
- (options.multiProject ? "**/" : "") + "*Containerfile*",
3868
+ `${options.multiProject ? "**/" : ""}*Containerfile*`,
3872
3869
  options,
3873
3870
  );
3874
3871
  const yamlFiles = getAllFiles(
3875
3872
  path,
3876
- (options.multiProject ? "**/" : "") + "*.yaml",
3873
+ `${options.multiProject ? "**/" : ""}*.yaml`,
3877
3874
  options,
3878
3875
  );
3879
3876
  let oapiFiles = getAllFiles(
3880
3877
  path,
3881
- (options.multiProject ? "**/" : "") + "open*.json",
3878
+ `${options.multiProject ? "**/" : ""}open*.json`,
3882
3879
  options,
3883
3880
  );
3884
3881
  const oapiYamlFiles = getAllFiles(
3885
3882
  path,
3886
- (options.multiProject ? "**/" : "") + "open*.yaml",
3883
+ `${options.multiProject ? "**/" : ""}open*.yaml`,
3887
3884
  options,
3888
3885
  );
3889
- if (oapiYamlFiles && oapiYamlFiles.length) {
3886
+ if (oapiYamlFiles?.length) {
3890
3887
  oapiFiles = oapiFiles.concat(oapiYamlFiles);
3891
3888
  }
3892
3889
  if (yamlFiles.length) {
@@ -3918,7 +3915,7 @@ export async function createContainerSpecLikeBom(path, options) {
3918
3915
  imgList = parseContainerFile(dData);
3919
3916
  }
3920
3917
 
3921
- if (imgList && imgList.length) {
3918
+ if (imgList?.length) {
3922
3919
  if (DEBUG_MODE) {
3923
3920
  console.log("Images identified in", f, "are", imgList);
3924
3921
  }
@@ -3999,7 +3996,7 @@ export async function createContainerSpecLikeBom(path, options) {
3999
3996
  group: imageObj.group,
4000
3997
  version:
4001
3998
  imageObj.tag ||
4002
- (imageObj.digest ? "sha256:" + imageObj.digest : "latest"),
3999
+ (imageObj.digest ? `sha256:${imageObj.digest}` : "latest"),
4003
4000
  qualifiers: {},
4004
4001
  properties: commonProperties,
4005
4002
  type: "container",
@@ -4033,17 +4030,13 @@ export async function createContainerSpecLikeBom(path, options) {
4033
4030
  filename: f,
4034
4031
  nsMapping: {},
4035
4032
  });
4036
- if (
4037
- imageBomData &&
4038
- imageBomData.bomJson &&
4039
- imageBomData.bomJson.components
4040
- ) {
4033
+ if (imageBomData?.bomJson?.components) {
4041
4034
  components = components.concat(imageBomData.bomJson.components);
4042
4035
  }
4043
4036
  const bomData = await createBom(img.image, { projectType: "oci" });
4044
4037
  doneimages.push(img.image);
4045
4038
  if (bomData) {
4046
- if (bomData.components && bomData.components.length) {
4039
+ if (bomData.components?.length) {
4047
4040
  // Inject properties
4048
4041
  for (const co of bomData.components) {
4049
4042
  co.properties = commonProperties;
@@ -4067,7 +4060,7 @@ export async function createContainerSpecLikeBom(path, options) {
4067
4060
  }
4068
4061
  const oaData = readFileSync(af, { encoding: "utf-8" });
4069
4062
  const servlist = parseOpenapiSpecData(oaData);
4070
- if (servlist && servlist.length) {
4063
+ if (servlist?.length) {
4071
4064
  // Inject SrcFile property
4072
4065
  for (const se of servlist) {
4073
4066
  se.properties = [
@@ -4131,7 +4124,7 @@ export async function createContainerSpecLikeBom(path, options) {
4131
4124
  multiProject: true,
4132
4125
  });
4133
4126
  if (mbomData) {
4134
- if (mbomData.components && mbomData.components.length) {
4127
+ if (mbomData.components?.length) {
4135
4128
  components = components.concat(mbomData.components);
4136
4129
  }
4137
4130
  // We need to retain the parentComponent. See #527
@@ -4173,7 +4166,7 @@ export function createPHPBom(path, options) {
4173
4166
  let parentComponent = {};
4174
4167
  const composerJsonFiles = getAllFiles(
4175
4168
  path,
4176
- (options.multiProject ? "**/" : "") + "composer.json",
4169
+ `${options.multiProject ? "**/" : ""}composer.json`,
4177
4170
  options,
4178
4171
  );
4179
4172
  if (!options.exclude) {
@@ -4183,7 +4176,7 @@ export function createPHPBom(path, options) {
4183
4176
  options.exclude.push("**/vendor/**");
4184
4177
  let composerLockFiles = getAllFiles(
4185
4178
  path,
4186
- (options.multiProject ? "**/" : "") + "composer.lock",
4179
+ `${options.multiProject ? "**/" : ""}composer.lock`,
4187
4180
  options,
4188
4181
  );
4189
4182
  let pkgList = [];
@@ -4211,7 +4204,7 @@ export function createPHPBom(path, options) {
4211
4204
  console.log("Parsing version", versionResult.stdout);
4212
4205
  }
4213
4206
  const tmpV = undefined;
4214
- if (versionResult && versionResult.stdout) {
4207
+ if (versionResult?.stdout) {
4215
4208
  versionResult.stdout.split(" ");
4216
4209
  }
4217
4210
  if (tmpV && tmpV.length > 1) {
@@ -4240,7 +4233,7 @@ export function createPHPBom(path, options) {
4240
4233
  }
4241
4234
  composerLockFiles = getAllFiles(
4242
4235
  path,
4243
- (options.multiProject ? "**/" : "") + "composer.lock",
4236
+ `${options.multiProject ? "**/" : ""}composer.lock`,
4244
4237
  options,
4245
4238
  );
4246
4239
  if (composerLockFiles.length) {
@@ -4281,7 +4274,7 @@ export function createPHPBom(path, options) {
4281
4274
  }
4282
4275
  }
4283
4276
  const retMap = parseComposerLock(f, rootRequires);
4284
- if (retMap.pkgList && retMap.pkgList.length) {
4277
+ if (retMap.pkgList?.length) {
4285
4278
  pkgList = pkgList.concat(retMap.pkgList);
4286
4279
  }
4287
4280
  if (retMap.dependenciesList) {
@@ -4328,12 +4321,12 @@ export function createPHPBom(path, options) {
4328
4321
  export async function createRubyBom(path, options) {
4329
4322
  const gemFiles = getAllFiles(
4330
4323
  path,
4331
- (options.multiProject ? "**/" : "") + "Gemfile",
4324
+ `${options.multiProject ? "**/" : ""}Gemfile`,
4332
4325
  options,
4333
4326
  );
4334
4327
  let gemLockFiles = getAllFiles(
4335
4328
  path,
4336
- (options.multiProject ? "**/" : "") + "Gemfile*.lock",
4329
+ `${options.multiProject ? "**/" : ""}Gemfile*.lock`,
4337
4330
  options,
4338
4331
  );
4339
4332
  let pkgList = [];
@@ -4361,7 +4354,7 @@ export async function createRubyBom(path, options) {
4361
4354
  }
4362
4355
  gemLockFiles = getAllFiles(
4363
4356
  path,
4364
- (options.multiProject ? "**/" : "") + "Gemfile*.lock",
4357
+ `${options.multiProject ? "**/" : ""}Gemfile*.lock`,
4365
4358
  options,
4366
4359
  );
4367
4360
  if (gemLockFiles.length) {
@@ -4371,18 +4364,18 @@ export async function createRubyBom(path, options) {
4371
4364
  }
4372
4365
  const gemLockData = readFileSync(f, { encoding: "utf-8" });
4373
4366
  const retMap = await parseGemfileLockData(gemLockData, f);
4374
- if (retMap.pkgList && retMap.pkgList.length) {
4367
+ if (retMap.pkgList?.length) {
4375
4368
  pkgList = pkgList.concat(retMap.pkgList);
4376
4369
  pkgList = trimComponents(pkgList);
4377
4370
  }
4378
- if (retMap.dependenciesList && retMap.dependenciesList.length) {
4371
+ if (retMap.dependenciesList?.length) {
4379
4372
  dependencies = mergeDependencies(
4380
4373
  dependencies,
4381
4374
  retMap.dependenciesList,
4382
4375
  parentComponent,
4383
4376
  );
4384
4377
  }
4385
- if (retMap.rootList && retMap.rootList.length) {
4378
+ if (retMap.rootList?.length) {
4386
4379
  rootList = rootList.concat(retMap.rootList);
4387
4380
  }
4388
4381
  }
@@ -4423,58 +4416,46 @@ export async function createCsharpBom(path, options) {
4423
4416
  const parentComponent = createDefaultParentComponent(path, "nuget", options);
4424
4417
  const slnFiles = getAllFiles(
4425
4418
  path,
4426
- (options.multiProject ? "**/" : "") + "*.sln",
4419
+ `${options.multiProject ? "**/" : ""}*.sln`,
4427
4420
  options,
4428
4421
  );
4429
4422
  let csProjFiles = getAllFiles(
4430
4423
  path,
4431
- (options.multiProject ? "**/" : "") + "*.csproj",
4424
+ `${options.multiProject ? "**/" : ""}*.csproj`,
4432
4425
  options,
4433
4426
  );
4434
4427
  csProjFiles = csProjFiles.concat(
4435
- getAllFiles(
4436
- path,
4437
- (options.multiProject ? "**/" : "") + "*.vbproj",
4438
- options,
4439
- ),
4428
+ getAllFiles(path, `${options.multiProject ? "**/" : ""}*.vbproj`, options),
4440
4429
  );
4441
4430
  csProjFiles = csProjFiles.concat(
4442
- getAllFiles(
4443
- path,
4444
- (options.multiProject ? "**/" : "") + "*.vcxproj",
4445
- options,
4446
- ),
4431
+ getAllFiles(path, `${options.multiProject ? "**/" : ""}*.vcxproj`, options),
4447
4432
  );
4448
4433
  csProjFiles = csProjFiles.concat(
4449
- getAllFiles(
4450
- path,
4451
- (options.multiProject ? "**/" : "") + "*.fsproj",
4452
- options,
4453
- ),
4434
+ getAllFiles(path, `${options.multiProject ? "**/" : ""}*.fsproj`, options),
4454
4435
  );
4455
4436
  const pkgConfigFiles = getAllFiles(
4456
4437
  path,
4457
- (options.multiProject ? "**/" : "") + "packages.config",
4438
+ `${options.multiProject ? "**/" : ""}packages.config`,
4458
4439
  options,
4459
4440
  );
4460
4441
  let projAssetsFiles = getAllFiles(
4461
4442
  path,
4462
- (options.multiProject ? "**/" : "") + "project.assets.json",
4443
+ `${options.multiProject ? "**/" : ""}project.assets.json`,
4463
4444
  options,
4464
4445
  );
4465
4446
  const pkgLockFiles = getAllFiles(
4466
4447
  path,
4467
- (options.multiProject ? "**/" : "") + "packages.lock.json",
4448
+ `${options.multiProject ? "**/" : ""}packages.lock.json`,
4468
4449
  options,
4469
4450
  );
4470
4451
  const paketLockFiles = getAllFiles(
4471
4452
  path,
4472
- (options.multiProject ? "**/" : "") + "paket.lock",
4453
+ `${options.multiProject ? "**/" : ""}paket.lock`,
4473
4454
  options,
4474
4455
  );
4475
4456
  const nupkgFiles = getAllFiles(
4476
4457
  path,
4477
- (options.multiProject ? "**/" : "") + "*.nupkg",
4458
+ `${options.multiProject ? "**/" : ""}*.nupkg`,
4478
4459
  options,
4479
4460
  );
4480
4461
  // Support for automatic restore
@@ -4512,7 +4493,7 @@ export async function createCsharpBom(path, options) {
4512
4493
  // Collect the assets file generated from restore
4513
4494
  projAssetsFiles = getAllFiles(
4514
4495
  path,
4515
- (options.multiProject ? "**/" : "") + "project.assets.json",
4496
+ `${options.multiProject ? "**/" : ""}project.assets.json`,
4516
4497
  options,
4517
4498
  );
4518
4499
  }
@@ -4524,7 +4505,7 @@ export async function createCsharpBom(path, options) {
4524
4505
  console.log(`Parsing ${nf}`);
4525
4506
  }
4526
4507
  const dlist = await parseNupkg(nf);
4527
- if (dlist && dlist.length) {
4508
+ if (dlist?.length) {
4528
4509
  pkgList = pkgList.concat(dlist);
4529
4510
  }
4530
4511
  }
@@ -4540,10 +4521,10 @@ export async function createCsharpBom(path, options) {
4540
4521
  const results = parseCsProjAssetsData(pkgData, af);
4541
4522
  const deps = results["dependenciesList"];
4542
4523
  const dlist = results["pkgList"];
4543
- if (dlist && dlist.length) {
4524
+ if (dlist?.length) {
4544
4525
  pkgList = pkgList.concat(dlist);
4545
4526
  }
4546
- if (deps && deps.length) {
4527
+ if (deps?.length) {
4547
4528
  dependencies = mergeDependencies(dependencies, deps, parentComponent);
4548
4529
  }
4549
4530
  }
@@ -4580,15 +4561,15 @@ export async function createCsharpBom(path, options) {
4580
4561
  const deps = results["dependenciesList"];
4581
4562
  const dlist = results["pkgList"];
4582
4563
  const rootList = results["rootList"];
4583
- if (dlist && dlist.length) {
4564
+ if (dlist?.length) {
4584
4565
  pkgList = pkgList.concat(dlist);
4585
4566
  }
4586
- if (deps && deps.length) {
4567
+ if (deps?.length) {
4587
4568
  dependencies = mergeDependencies(dependencies, deps, parentComponent);
4588
4569
  }
4589
4570
  // Keep track of the direct dependencies so that we can construct one complete
4590
4571
  // list after processing all lock files
4591
- if (rootList && rootList.length) {
4572
+ if (rootList?.length) {
4592
4573
  for (const p of rootList) {
4593
4574
  parentDependsOn.add(p["bom-ref"]);
4594
4575
  }
@@ -4613,7 +4594,7 @@ export async function createCsharpBom(path, options) {
4613
4594
  pkgData = pkgData.slice(1);
4614
4595
  }
4615
4596
  const dlist = parseCsPkgData(pkgData);
4616
- if (dlist && dlist.length) {
4597
+ if (dlist?.length) {
4617
4598
  pkgList = pkgList.concat(dlist);
4618
4599
  }
4619
4600
  }
@@ -4629,10 +4610,10 @@ export async function createCsharpBom(path, options) {
4629
4610
  const results = parsePaketLockData(pkgData, f);
4630
4611
  const dlist = results.pkgList;
4631
4612
  const deps = results.dependenciesList;
4632
- if (dlist && dlist.length) {
4613
+ if (dlist?.length) {
4633
4614
  pkgList = pkgList.concat(dlist);
4634
4615
  }
4635
- if (deps && deps.length) {
4616
+ if (deps?.length) {
4636
4617
  dependencies = mergeDependencies(dependencies, deps, parentComponent);
4637
4618
  }
4638
4619
  }
@@ -4650,7 +4631,7 @@ export async function createCsharpBom(path, options) {
4650
4631
  csProjData = csProjData.slice(1);
4651
4632
  }
4652
4633
  const dlist = parseCsProjData(csProjData, f);
4653
- if (dlist && dlist.length) {
4634
+ if (dlist?.length) {
4654
4635
  pkgList = pkgList.concat(dlist);
4655
4636
  }
4656
4637
  }
@@ -4682,7 +4663,7 @@ export async function createCsharpBom(path, options) {
4682
4663
  }
4683
4664
  if (FETCH_LICENSE) {
4684
4665
  const retMap = await getNugetMetadata(pkgList, dependencies);
4685
- if (retMap.dependencies && retMap.dependencies.length) {
4666
+ if (retMap.dependencies?.length) {
4686
4667
  dependencies = mergeDependencies(
4687
4668
  dependencies,
4688
4669
  retMap.dependencies,
@@ -4709,8 +4690,9 @@ export async function createCryptoCertsBom(path, options) {
4709
4690
  const pkgList = [];
4710
4691
  const certFiles = getAllFiles(
4711
4692
  path,
4712
- (options.multiProject ? "**/" : "") +
4713
- "*.{p12,jks,jceks,bks,keystore,key,pem,cer,gpg,pub}",
4693
+ `${
4694
+ options.multiProject ? "**/" : ""
4695
+ }*.{p12,jks,jceks,bks,keystore,key,pem,cer,gpg,pub}`,
4714
4696
  options,
4715
4697
  );
4716
4698
  for (const f of certFiles) {
@@ -4752,10 +4734,9 @@ export function mergeDependencies(
4752
4734
  let providesFound = false;
4753
4735
  const deps_map = {};
4754
4736
  const provides_map = {};
4755
- const parentRef =
4756
- parentComponent && parentComponent["bom-ref"]
4757
- ? parentComponent["bom-ref"]
4758
- : undefined;
4737
+ const parentRef = parentComponent?.["bom-ref"]
4738
+ ? parentComponent["bom-ref"]
4739
+ : undefined;
4759
4740
  const combinedDeps = dependencies.concat(newDependencies || []);
4760
4741
  for (const adep of combinedDeps) {
4761
4742
  if (!deps_map[adep.ref]) {
@@ -4840,14 +4821,14 @@ export function dedupeBom(options, components, parentComponent, dependencies) {
4840
4821
  `BOM includes ${components.length} components and ${dependencies.length} dependencies after dedupe`,
4841
4822
  );
4842
4823
  }
4843
- const serialNum = "urn:uuid:" + uuidv4();
4824
+ const serialNum = `urn:uuid:${uuidv4()}`;
4844
4825
  return {
4845
4826
  options,
4846
4827
  parentComponent,
4847
4828
  components,
4848
4829
  bomJson: {
4849
4830
  bomFormat: "CycloneDX",
4850
- specVersion: "" + (options.specVersion || 1.5),
4831
+ specVersion: `${options.specVersion || 1.5}`,
4851
4832
  serialNumber: serialNum,
4852
4833
  version: 1,
4853
4834
  metadata: addMetadata(parentComponent, options, {}),
@@ -4883,11 +4864,11 @@ export async function createMultiXBom(pathList, options) {
4883
4864
  `Found ${osPackages.length} OS packages at ${options.allLayersExplodedDir}`,
4884
4865
  );
4885
4866
  }
4886
- if (allTypes && allTypes.length) {
4867
+ if (allTypes?.length) {
4887
4868
  options.allOSComponentTypes = allTypes;
4888
4869
  }
4889
4870
  components = components.concat(osPackages);
4890
- if (dependenciesList && dependenciesList.length) {
4871
+ if (dependenciesList?.length) {
4891
4872
  dependencies = dependencies.concat(dependenciesList);
4892
4873
  }
4893
4874
  if (parentComponent && Object.keys(parentComponent).length) {
@@ -4901,7 +4882,7 @@ export async function createMultiXBom(pathList, options) {
4901
4882
  }
4902
4883
  if (options.projectType === "os" && options.bomData) {
4903
4884
  bomData = options.bomData;
4904
- if (bomData && bomData.bomJson && bomData.bomJson.components) {
4885
+ if (bomData?.bomJson?.components) {
4905
4886
  if (DEBUG_MODE) {
4906
4887
  console.log(`Found ${bomData.bomJson.components.length} OS components`);
4907
4888
  }
@@ -4913,12 +4894,7 @@ export async function createMultiXBom(pathList, options) {
4913
4894
  console.log("Scanning", path);
4914
4895
  }
4915
4896
  bomData = await createNodejsBom(path, options);
4916
- if (
4917
- bomData &&
4918
- bomData.bomJson &&
4919
- bomData.bomJson.components &&
4920
- bomData.bomJson.components.length
4921
- ) {
4897
+ if (bomData?.bomJson?.components?.length) {
4922
4898
  if (DEBUG_MODE) {
4923
4899
  console.log(
4924
4900
  `Found ${bomData.bomJson.components.length} npm packages at ${path}`,
@@ -4933,22 +4909,14 @@ export async function createMultiXBom(pathList, options) {
4933
4909
  parentSubComponents.push(bomData.parentComponent);
4934
4910
  }
4935
4911
  // Retain metadata.component.components
4936
- if (
4937
- bomData.parentComponent.components &&
4938
- bomData.parentComponent.components.length
4939
- ) {
4912
+ if (bomData.parentComponent.components?.length) {
4940
4913
  parentSubComponents = parentSubComponents.concat(
4941
4914
  bomData.parentComponent.components,
4942
4915
  );
4943
4916
  }
4944
4917
  }
4945
4918
  bomData = await createJavaBom(path, options);
4946
- if (
4947
- bomData &&
4948
- bomData.bomJson &&
4949
- bomData.bomJson.components &&
4950
- bomData.bomJson.components.length
4951
- ) {
4919
+ if (bomData?.bomJson?.components?.length) {
4952
4920
  if (DEBUG_MODE) {
4953
4921
  console.log(
4954
4922
  `Found ${bomData.bomJson.components.length} java packages at ${path}`,
@@ -4963,22 +4931,14 @@ export async function createMultiXBom(pathList, options) {
4963
4931
  parentSubComponents.push(bomData.parentComponent);
4964
4932
  }
4965
4933
  // Retain metadata.component.components
4966
- if (
4967
- bomData.parentComponent.components &&
4968
- bomData.parentComponent.components.length
4969
- ) {
4934
+ if (bomData.parentComponent.components?.length) {
4970
4935
  parentSubComponents = parentSubComponents.concat(
4971
4936
  bomData.parentComponent.components,
4972
4937
  );
4973
4938
  }
4974
4939
  }
4975
4940
  bomData = await createPythonBom(path, options);
4976
- if (
4977
- bomData &&
4978
- bomData.bomJson &&
4979
- bomData.bomJson.components &&
4980
- bomData.bomJson.components.length
4981
- ) {
4941
+ if (bomData?.bomJson?.components?.length) {
4982
4942
  if (DEBUG_MODE) {
4983
4943
  console.log(
4984
4944
  `Found ${bomData.bomJson.components.length} python packages at ${path}`,
@@ -4994,12 +4954,7 @@ export async function createMultiXBom(pathList, options) {
4994
4954
  }
4995
4955
  }
4996
4956
  bomData = await createGoBom(path, options);
4997
- if (
4998
- bomData &&
4999
- bomData.bomJson &&
5000
- bomData.bomJson.components &&
5001
- bomData.bomJson.components.length
5002
- ) {
4957
+ if (bomData?.bomJson?.components?.length) {
5003
4958
  if (DEBUG_MODE) {
5004
4959
  console.log(
5005
4960
  `Found ${bomData.bomJson.components.length} go packages at ${path}`,
@@ -5015,7 +4970,7 @@ export async function createMultiXBom(pathList, options) {
5015
4970
  }
5016
4971
  }
5017
4972
  bomData = await createRustBom(path, options);
5018
- if (bomData && bomData.bomJson && bomData.bomJson.components) {
4973
+ if (bomData?.bomJson?.components) {
5019
4974
  if (DEBUG_MODE) {
5020
4975
  console.log(
5021
4976
  `Found ${bomData.bomJson.components.length} rust packages at ${path}`,
@@ -5030,17 +4985,14 @@ export async function createMultiXBom(pathList, options) {
5030
4985
  parentSubComponents.push(bomData.parentComponent);
5031
4986
  }
5032
4987
  // Retain metadata.component.components
5033
- if (
5034
- bomData.parentComponent.components &&
5035
- bomData.parentComponent.components.length
5036
- ) {
4988
+ if (bomData.parentComponent.components?.length) {
5037
4989
  parentSubComponents = parentSubComponents.concat(
5038
4990
  bomData.parentComponent.components,
5039
4991
  );
5040
4992
  }
5041
4993
  }
5042
4994
  bomData = createPHPBom(path, options);
5043
- if (bomData && bomData.bomJson && bomData.bomJson.components) {
4995
+ if (bomData?.bomJson?.components) {
5044
4996
  if (DEBUG_MODE) {
5045
4997
  console.log(
5046
4998
  `Found ${bomData.bomJson.components.length} php packages at ${path}`,
@@ -5056,7 +5008,7 @@ export async function createMultiXBom(pathList, options) {
5056
5008
  }
5057
5009
  }
5058
5010
  bomData = await createRubyBom(path, options);
5059
- if (bomData && bomData.bomJson && bomData.bomJson.components) {
5011
+ if (bomData?.bomJson?.components) {
5060
5012
  if (DEBUG_MODE) {
5061
5013
  console.log(
5062
5014
  `Found ${bomData.bomJson.components.length} ruby packages at ${path}`,
@@ -5076,12 +5028,7 @@ export async function createMultiXBom(pathList, options) {
5076
5028
  }
5077
5029
  }
5078
5030
  bomData = await createCsharpBom(path, options);
5079
- if (
5080
- bomData &&
5081
- bomData.bomJson &&
5082
- bomData.bomJson.components &&
5083
- bomData.bomJson.components.length
5084
- ) {
5031
+ if (bomData?.bomJson?.components?.length) {
5085
5032
  if (DEBUG_MODE) {
5086
5033
  console.log(
5087
5034
  `Found ${bomData.bomJson.components.length} csharp packages at ${path}`,
@@ -5097,7 +5044,7 @@ export async function createMultiXBom(pathList, options) {
5097
5044
  }
5098
5045
  }
5099
5046
  bomData = await createDartBom(path, options);
5100
- if (bomData && bomData.bomJson && bomData.bomJson.components) {
5047
+ if (bomData?.bomJson?.components) {
5101
5048
  if (DEBUG_MODE) {
5102
5049
  console.log(
5103
5050
  `Found ${bomData.bomJson.components.length} pub packages at ${path}`,
@@ -5113,7 +5060,7 @@ export async function createMultiXBom(pathList, options) {
5113
5060
  }
5114
5061
  }
5115
5062
  bomData = createHaskellBom(path, options);
5116
- if (bomData && bomData.bomJson && bomData.bomJson.components) {
5063
+ if (bomData?.bomJson?.components) {
5117
5064
  if (DEBUG_MODE) {
5118
5065
  console.log(
5119
5066
  `Found ${bomData.bomJson.components.length} hackage packages at ${path}`,
@@ -5129,7 +5076,7 @@ export async function createMultiXBom(pathList, options) {
5129
5076
  }
5130
5077
  }
5131
5078
  bomData = createElixirBom(path, options);
5132
- if (bomData && bomData.bomJson && bomData.bomJson.components) {
5079
+ if (bomData?.bomJson?.components) {
5133
5080
  if (DEBUG_MODE) {
5134
5081
  console.log(
5135
5082
  `Found ${bomData.bomJson.components.length} mix packages at ${path}`,
@@ -5145,7 +5092,7 @@ export async function createMultiXBom(pathList, options) {
5145
5092
  }
5146
5093
  }
5147
5094
  bomData = createCppBom(path, options);
5148
- if (bomData && bomData.bomJson && bomData.bomJson.components) {
5095
+ if (bomData?.bomJson?.components) {
5149
5096
  if (DEBUG_MODE) {
5150
5097
  console.log(
5151
5098
  `Found ${bomData.bomJson.components.length} cpp packages at ${path}`,
@@ -5161,7 +5108,7 @@ export async function createMultiXBom(pathList, options) {
5161
5108
  }
5162
5109
  }
5163
5110
  bomData = createClojureBom(path, options);
5164
- if (bomData && bomData.bomJson && bomData.bomJson.components) {
5111
+ if (bomData?.bomJson?.components) {
5165
5112
  if (DEBUG_MODE) {
5166
5113
  console.log(
5167
5114
  `Found ${bomData.bomJson.components.length} clojure packages at ${path}`,
@@ -5177,7 +5124,7 @@ export async function createMultiXBom(pathList, options) {
5177
5124
  }
5178
5125
  }
5179
5126
  bomData = createGitHubBom(path, options);
5180
- if (bomData && bomData.bomJson && bomData.bomJson.components) {
5127
+ if (bomData?.bomJson?.components) {
5181
5128
  if (DEBUG_MODE) {
5182
5129
  console.log(
5183
5130
  `Found ${bomData.bomJson.components.length} GitHub action packages at ${path}`,
@@ -5193,7 +5140,7 @@ export async function createMultiXBom(pathList, options) {
5193
5140
  }
5194
5141
  }
5195
5142
  bomData = createCloudBuildBom(path, options);
5196
- if (bomData && bomData.bomJson && bomData.bomJson.components) {
5143
+ if (bomData?.bomJson?.components) {
5197
5144
  if (DEBUG_MODE) {
5198
5145
  console.log(
5199
5146
  `Found ${bomData.bomJson.components.length} CloudBuild configuration at ${path}`,
@@ -5209,12 +5156,7 @@ export async function createMultiXBom(pathList, options) {
5209
5156
  }
5210
5157
  }
5211
5158
  bomData = await createSwiftBom(path, options);
5212
- if (
5213
- bomData &&
5214
- bomData.bomJson &&
5215
- bomData.bomJson.components &&
5216
- bomData.bomJson.components.length
5217
- ) {
5159
+ if (bomData?.bomJson?.components?.length) {
5218
5160
  if (DEBUG_MODE) {
5219
5161
  console.log(
5220
5162
  `Found ${bomData.bomJson.components.length} Swift packages at ${path}`,
@@ -5232,12 +5174,7 @@ export async function createMultiXBom(pathList, options) {
5232
5174
  // Jar scanning is enabled by default
5233
5175
  // See #330
5234
5176
  bomData = createJarBom(path, options);
5235
- if (
5236
- bomData &&
5237
- bomData.bomJson &&
5238
- bomData.bomJson.components &&
5239
- bomData.bomJson.components.length
5240
- ) {
5177
+ if (bomData?.bomJson?.components?.length) {
5241
5178
  if (DEBUG_MODE) {
5242
5179
  console.log(
5243
5180
  `Found ${bomData.bomJson.components.length} jar packages at ${path}`,
@@ -5255,12 +5192,7 @@ export async function createMultiXBom(pathList, options) {
5255
5192
  // Collect any crypto keys
5256
5193
  if (options.specVersion >= 1.6 && options.includeCrypto) {
5257
5194
  bomData = await createCryptoCertsBom(path, options);
5258
- if (
5259
- bomData &&
5260
- bomData.bomJson &&
5261
- bomData.bomJson.components &&
5262
- bomData.bomJson.components.length
5263
- ) {
5195
+ if (bomData?.bomJson?.components?.length) {
5264
5196
  if (DEBUG_MODE) {
5265
5197
  console.log(
5266
5198
  `Found ${bomData.bomJson.components.length} crypto assets at ${path}`,
@@ -5277,12 +5209,7 @@ export async function createMultiXBom(pathList, options) {
5277
5209
  !options.lastWorkingDir.includes("/home/")
5278
5210
  ) {
5279
5211
  bomData = createJarBom(options.lastWorkingDir, options);
5280
- if (
5281
- bomData &&
5282
- bomData.bomJson &&
5283
- bomData.bomJson.components &&
5284
- bomData.bomJson.components.length
5285
- ) {
5212
+ if (bomData?.bomJson?.components?.length) {
5286
5213
  if (DEBUG_MODE) {
5287
5214
  console.log(
5288
5215
  `Found ${bomData.bomJson.components.length} jar packages at ${options.lastWorkingDir}`,
@@ -5310,8 +5237,8 @@ export async function createMultiXBom(pathList, options) {
5310
5237
  );
5311
5238
  parentComponent.components = trimComponents(parentSubComponents);
5312
5239
  if (
5313
- parentComponent.components.length == 1 &&
5314
- parentComponent.components[0].name == parentComponent.name &&
5240
+ parentComponent.components.length === 1 &&
5241
+ parentComponent.components[0].name === parentComponent.name &&
5315
5242
  !parentComponent.purl.startsWith("pkg:container")
5316
5243
  ) {
5317
5244
  parentComponent = parentComponent.components[0];
@@ -5345,19 +5272,19 @@ export async function createXBom(path, options) {
5345
5272
  // maven - pom.xml
5346
5273
  const pomFiles = getAllFiles(
5347
5274
  path,
5348
- (options.multiProject ? "**/" : "") + "pom.xml",
5275
+ `${options.multiProject ? "**/" : ""}pom.xml`,
5349
5276
  options,
5350
5277
  );
5351
5278
  // gradle
5352
5279
  const gradleFiles = getAllFiles(
5353
5280
  path,
5354
- (options.multiProject ? "**/" : "") + "build.gradle*",
5281
+ `${options.multiProject ? "**/" : ""}build.gradle*`,
5355
5282
  options,
5356
5283
  );
5357
5284
  // scala sbt
5358
5285
  const sbtFiles = getAllFiles(
5359
5286
  path,
5360
- (options.multiProject ? "**/" : "") + "{build.sbt,Build.scala}*",
5287
+ `${options.multiProject ? "**/" : ""}{build.sbt,Build.scala}*`,
5361
5288
  options,
5362
5289
  );
5363
5290
  if (pomFiles.length || gradleFiles.length || sbtFiles.length) {
@@ -5373,19 +5300,18 @@ export async function createXBom(path, options) {
5373
5300
  }
5374
5301
  const reqFiles = getAllFiles(
5375
5302
  path,
5376
- (options.multiProject ? "**/" : "") + "*requirements*.txt",
5303
+ `${options.multiProject ? "**/" : ""}*requirements*.txt`,
5377
5304
  options,
5378
5305
  );
5379
5306
  const reqDirFiles = getAllFiles(
5380
5307
  path,
5381
- (options.multiProject ? "**/" : "") + "requirements/*.txt",
5308
+ `${options.multiProject ? "**/" : ""}requirements/*.txt`,
5382
5309
  options,
5383
5310
  );
5384
- const requirementsMode =
5385
- (reqFiles && reqFiles.length) || (reqDirFiles && reqDirFiles.length);
5311
+ const requirementsMode = reqFiles?.length || reqDirFiles?.length;
5386
5312
  const whlFiles = getAllFiles(
5387
5313
  path,
5388
- (options.multiProject ? "**/" : "") + "*.whl",
5314
+ `${options.multiProject ? "**/" : ""}*.whl`,
5389
5315
  options,
5390
5316
  );
5391
5317
  if (requirementsMode || whlFiles.length) {
@@ -5394,17 +5320,17 @@ export async function createXBom(path, options) {
5394
5320
  // go
5395
5321
  const gosumFiles = getAllFiles(
5396
5322
  path,
5397
- (options.multiProject ? "**/" : "") + "go.sum",
5323
+ `${options.multiProject ? "**/" : ""}go.sum`,
5398
5324
  options,
5399
5325
  );
5400
5326
  const gomodFiles = getAllFiles(
5401
5327
  path,
5402
- (options.multiProject ? "**/" : "") + "go.mod",
5328
+ `${options.multiProject ? "**/" : ""}go.mod`,
5403
5329
  options,
5404
5330
  );
5405
5331
  const gopkgLockFiles = getAllFiles(
5406
5332
  path,
5407
- (options.multiProject ? "**/" : "") + "Gopkg.lock",
5333
+ `${options.multiProject ? "**/" : ""}Gopkg.lock`,
5408
5334
  options,
5409
5335
  );
5410
5336
  if (gomodFiles.length || gosumFiles.length || gopkgLockFiles.length) {
@@ -5414,12 +5340,12 @@ export async function createXBom(path, options) {
5414
5340
  // rust
5415
5341
  const cargoLockFiles = getAllFiles(
5416
5342
  path,
5417
- (options.multiProject ? "**/" : "") + "Cargo.lock",
5343
+ `${options.multiProject ? "**/" : ""}Cargo.lock`,
5418
5344
  options,
5419
5345
  );
5420
5346
  const cargoFiles = getAllFiles(
5421
5347
  path,
5422
- (options.multiProject ? "**/" : "") + "Cargo.toml",
5348
+ `${options.multiProject ? "**/" : ""}Cargo.toml`,
5423
5349
  options,
5424
5350
  );
5425
5351
  if (cargoLockFiles.length || cargoFiles.length) {
@@ -5429,12 +5355,12 @@ export async function createXBom(path, options) {
5429
5355
  // php
5430
5356
  const composerJsonFiles = getAllFiles(
5431
5357
  path,
5432
- (options.multiProject ? "**/" : "") + "composer.json",
5358
+ `${options.multiProject ? "**/" : ""}composer.json`,
5433
5359
  options,
5434
5360
  );
5435
5361
  const composerLockFiles = getAllFiles(
5436
5362
  path,
5437
- (options.multiProject ? "**/" : "") + "composer.lock",
5363
+ `${options.multiProject ? "**/" : ""}composer.lock`,
5438
5364
  options,
5439
5365
  );
5440
5366
  if (composerJsonFiles.length || composerLockFiles.length) {
@@ -5444,12 +5370,12 @@ export async function createXBom(path, options) {
5444
5370
  // Ruby
5445
5371
  const gemFiles = getAllFiles(
5446
5372
  path,
5447
- (options.multiProject ? "**/" : "") + "Gemfile",
5373
+ `${options.multiProject ? "**/" : ""}Gemfile`,
5448
5374
  options,
5449
5375
  );
5450
5376
  const gemLockFiles = getAllFiles(
5451
5377
  path,
5452
- (options.multiProject ? "**/" : "") + "Gemfile*.lock",
5378
+ `${options.multiProject ? "**/" : ""}Gemfile*.lock`,
5453
5379
  options,
5454
5380
  );
5455
5381
  if (gemFiles.length || gemLockFiles.length) {
@@ -5459,22 +5385,14 @@ export async function createXBom(path, options) {
5459
5385
  // .Net
5460
5386
  let csProjFiles = getAllFiles(
5461
5387
  path,
5462
- (options.multiProject ? "**/" : "") + "*.csproj",
5388
+ `${options.multiProject ? "**/" : ""}*.csproj`,
5463
5389
  options,
5464
5390
  );
5465
5391
  csProjFiles = csProjFiles.concat(
5466
- getAllFiles(
5467
- path,
5468
- (options.multiProject ? "**/" : "") + "*.vbproj",
5469
- options,
5470
- ),
5392
+ getAllFiles(path, `${options.multiProject ? "**/" : ""}*.vbproj`, options),
5471
5393
  );
5472
5394
  csProjFiles = csProjFiles.concat(
5473
- getAllFiles(
5474
- path,
5475
- (options.multiProject ? "**/" : "") + "*.fsproj",
5476
- options,
5477
- ),
5395
+ getAllFiles(path, `${options.multiProject ? "**/" : ""}*.fsproj`, options),
5478
5396
  );
5479
5397
  if (csProjFiles.length) {
5480
5398
  return await createCsharpBom(path, options);
@@ -5483,12 +5401,12 @@ export async function createXBom(path, options) {
5483
5401
  // Dart
5484
5402
  const pubFiles = getAllFiles(
5485
5403
  path,
5486
- (options.multiProject ? "**/" : "") + "pubspec.lock",
5404
+ `${options.multiProject ? "**/" : ""}pubspec.lock`,
5487
5405
  options,
5488
5406
  );
5489
5407
  const pubSpecFiles = getAllFiles(
5490
5408
  path,
5491
- (options.multiProject ? "**/" : "") + "pubspec.yaml",
5409
+ `${options.multiProject ? "**/" : ""}pubspec.yaml`,
5492
5410
  options,
5493
5411
  );
5494
5412
  if (pubFiles.length || pubSpecFiles.length) {
@@ -5498,7 +5416,7 @@ export async function createXBom(path, options) {
5498
5416
  // Haskell
5499
5417
  const hackageFiles = getAllFiles(
5500
5418
  path,
5501
- (options.multiProject ? "**/" : "") + "cabal.project.freeze",
5419
+ `${options.multiProject ? "**/" : ""}cabal.project.freeze`,
5502
5420
  options,
5503
5421
  );
5504
5422
  if (hackageFiles.length) {
@@ -5508,7 +5426,7 @@ export async function createXBom(path, options) {
5508
5426
  // Elixir
5509
5427
  const mixFiles = getAllFiles(
5510
5428
  path,
5511
- (options.multiProject ? "**/" : "") + "mix.lock",
5429
+ `${options.multiProject ? "**/" : ""}mix.lock`,
5512
5430
  options,
5513
5431
  );
5514
5432
  if (mixFiles.length) {
@@ -5518,22 +5436,22 @@ export async function createXBom(path, options) {
5518
5436
  // cpp
5519
5437
  const conanLockFiles = getAllFiles(
5520
5438
  path,
5521
- (options.multiProject ? "**/" : "") + "conan.lock",
5439
+ `${options.multiProject ? "**/" : ""}conan.lock`,
5522
5440
  options,
5523
5441
  );
5524
5442
  const conanFiles = getAllFiles(
5525
5443
  path,
5526
- (options.multiProject ? "**/" : "") + "conanfile.txt",
5444
+ `${options.multiProject ? "**/" : ""}conanfile.txt`,
5527
5445
  options,
5528
5446
  );
5529
5447
  const cmakeListFiles = getAllFiles(
5530
5448
  path,
5531
- (options.multiProject ? "**/" : "") + "CMakeLists.txt",
5449
+ `${options.multiProject ? "**/" : ""}CMakeLists.txt`,
5532
5450
  options,
5533
5451
  );
5534
5452
  const mesonBuildFiles = getAllFiles(
5535
5453
  path,
5536
- (options.multiProject ? "**/" : "") + "meson.build",
5454
+ `${options.multiProject ? "**/" : ""}meson.build`,
5537
5455
  options,
5538
5456
  );
5539
5457
  if (
@@ -5548,12 +5466,12 @@ export async function createXBom(path, options) {
5548
5466
  // clojure
5549
5467
  const ednFiles = getAllFiles(
5550
5468
  path,
5551
- (options.multiProject ? "**/" : "") + "deps.edn",
5469
+ `${options.multiProject ? "**/" : ""}deps.edn`,
5552
5470
  options,
5553
5471
  );
5554
5472
  const leinFiles = getAllFiles(
5555
5473
  path,
5556
- (options.multiProject ? "**/" : "") + "project.clj",
5474
+ `${options.multiProject ? "**/" : ""}project.clj`,
5557
5475
  options,
5558
5476
  );
5559
5477
  if (ednFiles.length || leinFiles.length) {
@@ -5573,7 +5491,7 @@ export async function createXBom(path, options) {
5573
5491
  // Jenkins plugins
5574
5492
  const hpiFiles = getAllFiles(
5575
5493
  path,
5576
- (options.multiProject ? "**/" : "") + "*.hpi",
5494
+ `${options.multiProject ? "**/" : ""}*.hpi`,
5577
5495
  options,
5578
5496
  );
5579
5497
  if (hpiFiles.length) {
@@ -5583,12 +5501,12 @@ export async function createXBom(path, options) {
5583
5501
  // Helm charts
5584
5502
  const chartFiles = getAllFiles(
5585
5503
  path,
5586
- (options.multiProject ? "**/" : "") + "Chart.yaml",
5504
+ `${options.multiProject ? "**/" : ""}Chart.yaml`,
5587
5505
  options,
5588
5506
  );
5589
5507
  const yamlFiles = getAllFiles(
5590
5508
  path,
5591
- (options.multiProject ? "**/" : "") + "values.yaml",
5509
+ `${options.multiProject ? "**/" : ""}values.yaml`,
5592
5510
  options,
5593
5511
  );
5594
5512
  if (chartFiles.length || yamlFiles.length) {
@@ -5598,27 +5516,27 @@ export async function createXBom(path, options) {
5598
5516
  // Docker compose, dockerfile, containerfile, kubernetes and skaffold
5599
5517
  const dcFiles = getAllFiles(
5600
5518
  path,
5601
- (options.multiProject ? "**/" : "") + "docker-compose*.yml",
5519
+ `${options.multiProject ? "**/" : ""}docker-compose*.yml`,
5602
5520
  options,
5603
5521
  );
5604
5522
  const dfFiles = getAllFiles(
5605
5523
  path,
5606
- (options.multiProject ? "**/" : "") + "*Dockerfile*",
5524
+ `${options.multiProject ? "**/" : ""}*Dockerfile*`,
5607
5525
  options,
5608
5526
  );
5609
5527
  const cfFiles = getAllFiles(
5610
5528
  path,
5611
- (options.multiProject ? "**/" : "") + "*Containerfile*",
5529
+ `${options.multiProject ? "**/" : ""}*Containerfile*`,
5612
5530
  options,
5613
5531
  );
5614
5532
  const skFiles = getAllFiles(
5615
5533
  path,
5616
- (options.multiProject ? "**/" : "") + "skaffold.yaml",
5534
+ `${options.multiProject ? "**/" : ""}skaffold.yaml`,
5617
5535
  options,
5618
5536
  );
5619
5537
  const deplFiles = getAllFiles(
5620
5538
  path,
5621
- (options.multiProject ? "**/" : "") + "deployment.yaml",
5539
+ `${options.multiProject ? "**/" : ""}deployment.yaml`,
5622
5540
  options,
5623
5541
  );
5624
5542
  if (
@@ -5634,7 +5552,7 @@ export async function createXBom(path, options) {
5634
5552
  // Google CloudBuild
5635
5553
  const cbFiles = getAllFiles(
5636
5554
  path,
5637
- (options.multiProject ? "**/" : "") + "cloudbuild.yaml",
5555
+ `${options.multiProject ? "**/" : ""}cloudbuild.yaml`,
5638
5556
  options,
5639
5557
  );
5640
5558
  if (cbFiles.length) {
@@ -5644,12 +5562,12 @@ export async function createXBom(path, options) {
5644
5562
  // Swift
5645
5563
  const swiftFiles = getAllFiles(
5646
5564
  path,
5647
- (options.multiProject ? "**/" : "") + "Package*.swift",
5565
+ `${options.multiProject ? "**/" : ""}Package*.swift`,
5648
5566
  options,
5649
5567
  );
5650
5568
  const pkgResolvedFiles = getAllFiles(
5651
5569
  path,
5652
- (options.multiProject ? "**/" : "") + "Package.resolved",
5570
+ `${options.multiProject ? "**/" : ""}Package.resolved`,
5653
5571
  options,
5654
5572
  );
5655
5573
  if (swiftFiles.length || pkgResolvedFiles.length) {
@@ -5727,8 +5645,7 @@ export async function createBom(path, options) {
5727
5645
  // Create parent component based on the inspect config
5728
5646
  const inspectData = exportData.inspectData;
5729
5647
  if (
5730
- inspectData &&
5731
- inspectData.RepoDigests &&
5648
+ inspectData?.RepoDigests &&
5732
5649
  inspectData.RepoTags &&
5733
5650
  Array.isArray(inspectData.RepoDigests) &&
5734
5651
  Array.isArray(inspectData.RepoTags) &&
@@ -5743,7 +5660,7 @@ export async function createBom(path, options) {
5743
5660
  name: tmpA[0],
5744
5661
  version: tmpA[1],
5745
5662
  type: "container",
5746
- purl: "pkg:oci/" + inspectData.RepoDigests[0],
5663
+ purl: `pkg:oci/${inspectData.RepoDigests[0]}`,
5747
5664
  _integrity: inspectData.RepoDigests[0].replace(
5748
5665
  "sha256:",
5749
5666
  "sha256-",
@@ -5760,7 +5677,7 @@ export async function createBom(path, options) {
5760
5677
  .split("@")[1]
5761
5678
  .replace("sha256:", ""),
5762
5679
  type: "container",
5763
- purl: "pkg:oci/" + inspectData.RepoDigests[0],
5680
+ purl: `pkg:oci/${inspectData.RepoDigests[0]}`,
5764
5681
  _integrity: inspectData.RepoDigests[0].replace("sha256:", "sha256-"),
5765
5682
  };
5766
5683
  options.parentComponent["bom-ref"] = decodeURIComponent(
@@ -5782,10 +5699,7 @@ export async function createBom(path, options) {
5782
5699
  [...new Set(exportData.pkgPathList)],
5783
5700
  options,
5784
5701
  );
5785
- if (
5786
- exportData.allLayersDir &&
5787
- exportData.allLayersDir.startsWith(tmpdir())
5788
- ) {
5702
+ if (exportData.allLayersDir?.startsWith(tmpdir())) {
5789
5703
  if (DEBUG_MODE) {
5790
5704
  console.log(`Cleaning up ${exportData.allLayersDir}`);
5791
5705
  }
@@ -5932,9 +5846,8 @@ export async function createBom(path, options) {
5932
5846
  // https://github.com/cyclonedx/cdxgen/issues/95
5933
5847
  if (options.multiProject) {
5934
5848
  return await createMultiXBom([path], options);
5935
- } else {
5936
- return await createXBom(path, options);
5937
5849
  }
5850
+ return await createXBom(path, options);
5938
5851
  }
5939
5852
  }
5940
5853
 
@@ -5945,7 +5858,7 @@ export async function createBom(path, options) {
5945
5858
  * @param {Object} bomContents BOM Json
5946
5859
  */
5947
5860
  export async function submitBom(args, bomContents) {
5948
- const serverUrl = args.serverUrl.replace(/\/$/, "") + "/api/v1/bom";
5861
+ const serverUrl = `${args.serverUrl.replace(/\/$/, "")}/api/v1/bom`;
5949
5862
  let encodedBomContents = Buffer.from(JSON.stringify(bomContents)).toString(
5950
5863
  "base64",
5951
5864
  );