@cyclonedx/cdxgen 11.2.3 → 11.2.5

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/bin/cdxgen.js CHANGED
@@ -56,10 +56,6 @@ if (configPath) {
56
56
  }
57
57
  }
58
58
 
59
- let url = import.meta.url;
60
- if (!url.startsWith("file://")) {
61
- url = new URL(`file://${import.meta.url}`).toString();
62
- }
63
59
  const dirName = dirNameStr;
64
60
 
65
61
  import yargs from "yargs";
@@ -218,6 +214,10 @@ const args = yargs(hideBin(process.argv))
218
214
  default: "semantics.slices.json",
219
215
  hidden: true,
220
216
  })
217
+ .option("openapi-spec-file", {
218
+ description: "Path for the openapi specification file (SaaSBOM).",
219
+ hidden: true,
220
+ })
221
221
  .option("spec-version", {
222
222
  description: "CycloneDX Specification version to use. Defaults to 1.6",
223
223
  default: 1.6,
@@ -993,6 +993,7 @@ const checkPermissions = (filePath, options) => {
993
993
  dataFlowSlicesFile: options.dataFlowSlicesFile,
994
994
  reachablesSlicesFile: options.reachablesSlicesFile,
995
995
  semanticsSlicesFile: options.semanticsSlicesFile,
996
+ openapiSpecFile: options.openapiSpecFile,
996
997
  includeCrypto: options.includeCrypto,
997
998
  specVersion: options.specVersion,
998
999
  profile: options.profile,
package/bin/verify.js CHANGED
@@ -9,10 +9,6 @@ import yargs from "yargs";
9
9
  import { hideBin } from "yargs/helpers";
10
10
  import { dirNameStr } from "../lib/helpers/utils.js";
11
11
 
12
- let url = import.meta.url;
13
- if (!url.startsWith("file://")) {
14
- url = new URL(`file://${import.meta.url}`).toString();
15
- }
16
12
  const dirName = dirNameStr;
17
13
 
18
14
  const args = yargs(hideBin(process.argv))
@@ -0,0 +1,5 @@
1
+ gradle.taskGraph.whenReady {
2
+ gradle.includedBuilds.each { includedBuild ->
3
+ println "<CDXGEN:includedBuild>:${includedBuild.name}"
4
+ }
5
+ }
package/index.cjs ADDED
@@ -0,0 +1,15 @@
1
+ // this file is a wrapper of ./lib/cli/index.js that can be used by commonjs projects importing this module
2
+ // that prefer to use require instead of await import()
3
+ const importPromise = import("./lib/cli/index.js");
4
+
5
+ module.exports = new Proxy(
6
+ {},
7
+ {
8
+ get:
9
+ (_, prop) =>
10
+ async (...args) => {
11
+ const mod = await importPromise;
12
+ return typeof mod[prop] === "function" ? mod[prop](...args) : mod[prop];
13
+ },
14
+ },
15
+ );
package/lib/cli/index.js CHANGED
@@ -33,8 +33,6 @@ import {
33
33
  listFiles,
34
34
  } from "../helpers/envcontext.js";
35
35
  import { thoughtLog } from "../helpers/logger.js";
36
-
37
- import { analyzeBuildSettings } from "../helpers/package_specific/gradleutils.js";
38
36
  import {
39
37
  CARGO_CMD,
40
38
  CLJ_CMD,
@@ -73,6 +71,7 @@ import {
73
71
  getGradleCommand,
74
72
  getLicenses,
75
73
  getMavenCommand,
74
+ getMillCommand,
76
75
  getMvnMetadata,
77
76
  getNugetMetadata,
78
77
  getPipFrozenTree,
@@ -130,6 +129,7 @@ import {
130
129
  parseLeiningenData,
131
130
  parseMakeDFile,
132
131
  parseMavenTree,
132
+ parseMillDependency,
133
133
  parseMinJs,
134
134
  parseMixLockData,
135
135
  parseNodeShrinkwrap,
@@ -180,10 +180,6 @@ import {
180
180
  parseImageName,
181
181
  } from "../managers/docker.js";
182
182
 
183
- let url = import.meta.url;
184
- if (!url.startsWith("file://")) {
185
- url = new URL(`file://${import.meta.url}`).toString();
186
- }
187
183
  const dirName = dirNameStr;
188
184
 
189
185
  const selfPJson = JSON.parse(
@@ -228,6 +224,14 @@ if (process.env.GRADLE_USER_HOME) {
228
224
  );
229
225
  }
230
226
 
227
+ // Construct path to gradle init script
228
+ const GRADLE_INIT_SCRIPT = resolve(
229
+ dirNameStr,
230
+ "data",
231
+ "helpers",
232
+ "init.gradle",
233
+ );
234
+
231
235
  // Construct sbt cache directory
232
236
  const SBT_CACHE_DIR =
233
237
  process.env.SBT_CACHE_DIR || join(homedir(), ".ivy2", "cache");
@@ -416,7 +420,10 @@ const addLifecyclesSection = (options) => {
416
420
  if (inspectData) {
417
421
  lifecycles.push({ phase: "post-build" });
418
422
  }
419
- } else if (options.deep) {
423
+ } else if (
424
+ options?.projectType?.length &&
425
+ options?.projectType?.includes("binary")
426
+ ) {
420
427
  lifecycles.push({ phase: "post-build" });
421
428
  }
422
429
  if (options.projectType?.includes("os")) {
@@ -1393,8 +1400,8 @@ export async function createJarBom(path, options) {
1393
1400
  if (hpiFiles.length) {
1394
1401
  jarFiles = jarFiles.concat(hpiFiles);
1395
1402
  }
1396
- const tempDir = mkdtempSync(join(getTmpDir(), "jar-deps-"));
1397
1403
  for (const jar of jarFiles) {
1404
+ const tempDir = mkdtempSync(join(getTmpDir(), "jar-deps-"));
1398
1405
  if (DEBUG_MODE) {
1399
1406
  console.log(`Parsing ${jar}`);
1400
1407
  }
@@ -1405,10 +1412,10 @@ export async function createJarBom(path, options) {
1405
1412
  if (pkgList.length) {
1406
1413
  pkgList = await getMvnMetadata(pkgList);
1407
1414
  }
1408
- }
1409
- // Clean up
1410
- if (tempDir?.startsWith(getTmpDir()) && rmSync) {
1411
- rmSync(tempDir, { recursive: true, force: true });
1415
+ // Clean up
1416
+ if (tempDir?.startsWith(getTmpDir()) && rmSync) {
1417
+ rmSync(tempDir, { recursive: true, force: true });
1418
+ }
1412
1419
  }
1413
1420
  pkgList = pkgList.concat(convertJarNSToPackages(nsMapping));
1414
1421
  return buildBomNSData(options, pkgList, "maven", {
@@ -1513,10 +1520,20 @@ export async function createJavaBom(path, options) {
1513
1520
  `${options.multiProject ? "**/" : ""}build.gradle*`,
1514
1521
  options,
1515
1522
  );
1523
+ // mill
1524
+ const millFiles = getAllFiles(
1525
+ path,
1526
+ `${options.multiProject ? "**/" : ""}build.mill`,
1527
+ options,
1528
+ );
1516
1529
  let bomJsonFiles = [];
1517
1530
  if (
1518
1531
  pomFiles?.length &&
1519
- isPackageManagerAllowed("maven", ["bazel", "sbt", "gradle"], options)
1532
+ isPackageManagerAllowed(
1533
+ "maven",
1534
+ ["bazel", "sbt", "gradle", "mill"],
1535
+ options,
1536
+ )
1520
1537
  ) {
1521
1538
  if (gradleFiles.length) {
1522
1539
  thoughtLog(
@@ -1942,61 +1959,56 @@ export async function createJavaBom(path, options) {
1942
1959
  // Execute gradle properties
1943
1960
  if (
1944
1961
  gradleFiles?.length &&
1945
- isPackageManagerAllowed("gradle", ["maven", "bazel", "sbt"], options)
1962
+ isPackageManagerAllowed(
1963
+ "gradle",
1964
+ ["maven", "bazel", "sbt", "mill"],
1965
+ options,
1966
+ )
1946
1967
  ) {
1947
- let rootProjects = [null];
1948
1968
  let allProjectsStr = [];
1949
- let rootGradleModule = {};
1950
- let includedProjectsFound = false;
1951
1969
  if (process.env.GRADLE_INCLUDED_BUILDS) {
1952
1970
  // Automatically add the colon prefix
1953
- const includedBuilds = process.env.GRADLE_INCLUDED_BUILDS.split(",").map(
1954
- (b) => (!b.startsWith(":") ? `:${b}` : b),
1971
+ allProjectsStr = process.env.GRADLE_INCLUDED_BUILDS.split(",").map((b) =>
1972
+ !b.startsWith(":") ? `:${b}` : b,
1955
1973
  );
1956
- rootProjects = rootProjects.concat(includedBuilds);
1957
- includedProjectsFound = true;
1958
- } else {
1959
- // Automatically detect included builds
1960
- // Only from the root path for now
1961
- for (const abuildFile of [
1962
- join(gradleRootPath, "build.gradle"),
1963
- join(gradleRootPath, "build.gradle.kts"),
1964
- join(gradleRootPath, "settings.gradle"),
1965
- join(gradleRootPath, "settings.gradle.kts"),
1966
- ]) {
1967
- if (!safeExistsSync(abuildFile)) {
1968
- continue;
1974
+ }
1975
+ let parallelPropTaskOut = executeParallelGradleProperties(
1976
+ gradleRootPath,
1977
+ [null],
1978
+ process.env.GRADLE_INCLUDED_BUILDS
1979
+ ? []
1980
+ : ["--init-script", GRADLE_INIT_SCRIPT],
1981
+ );
1982
+ if (!process.env.GRADLE_INCLUDED_BUILDS) {
1983
+ const outputLines = parallelPropTaskOut.split("\n");
1984
+ for (const [i, line] of outputLines.entries()) {
1985
+ if (line.startsWith("Root project '")) {
1986
+ break;
1969
1987
  }
1970
- const buildSettings = analyzeBuildSettings(abuildFile);
1971
- if (buildSettings?.includedBuilds?.length) {
1972
- for (const aib of buildSettings.includedBuilds) {
1973
- if (!rootProjects.includes(aib)) {
1974
- rootProjects.push(aib);
1975
- includedProjectsFound = true;
1976
- }
1988
+ if (line.startsWith("<CDXGEN:includedBuild>")) {
1989
+ const includedBuild = line.split(">");
1990
+ if (!allProjectsStr.includes(includedBuild[1].trim())) {
1991
+ allProjectsStr.push(includedBuild[1].trim());
1977
1992
  }
1978
- break;
1979
1993
  }
1980
1994
  }
1981
1995
  }
1982
- if (includedProjectsFound) {
1996
+ if (allProjectsStr.length > 0) {
1983
1997
  thoughtLog(
1984
- `Wait, this gradle project uses composite builds. I must carefully process these ${rootProjects.length} projects including the root.`,
1998
+ `Wait, this gradle project uses composite builds. I must carefully process these ${allProjectsStr.length} projects, in addition to the root.`,
1985
1999
  );
1986
2000
  if (DEBUG_MODE) {
1987
- console.log(
1988
- `Additional root projects: ${rootProjects.join(" ").trim()}.`,
1989
- );
2001
+ console.log(`Composite builds: ${allProjectsStr.join(" ").trim()}.`);
1990
2002
  }
2003
+ parallelPropTaskOut = parallelPropTaskOut.concat(
2004
+ "\n",
2005
+ executeParallelGradleProperties(gradleRootPath, allProjectsStr),
2006
+ );
2007
+ allProjectsStr = [];
1991
2008
  }
1992
- const parallelPropTaskOut = executeParallelGradleProperties(
1993
- gradleRootPath,
1994
- rootProjects,
1995
- );
1996
2009
  const splitPropTaskOut = splitOutputByGradleProjects(parallelPropTaskOut, [
1997
2010
  "properties",
1998
2011
  ]);
1999
-
2000
2012
  for (const [key, propTaskOut] of splitPropTaskOut.entries()) {
2001
2013
  const retMap = parseGradleProperties(propTaskOut);
2002
2014
  const rootProject = retMap.rootProject;
@@ -2005,18 +2017,11 @@ export async function createJavaBom(path, options) {
2005
2017
  rootProject,
2006
2018
  retMap.metadata,
2007
2019
  );
2020
+ if (!key.startsWith(":")) {
2021
+ parentComponent = rootComponent;
2022
+ }
2008
2023
  gradleModules.set(key, rootComponent);
2009
- if (!rootProjects.includes(key)) {
2010
- if (rootGradleModule.name) {
2011
- if (DEBUG_MODE) {
2012
- console.log(
2013
- `Received new root component: ${rootComponent.name} with key ${key}. Please verify the value used for included builds. Using the name ${rootGradleModule.name}.`,
2014
- );
2015
- }
2016
- } else {
2017
- rootGradleModule = rootComponent;
2018
- }
2019
- } else if (!allProjectsAddedPurls.includes(rootComponent["purl"])) {
2024
+ if (!allProjectsAddedPurls.includes(rootComponent["purl"])) {
2020
2025
  allProjects.push(rootComponent);
2021
2026
  rootDependsOn.add(rootComponent["bom-ref"]);
2022
2027
  allProjectsAddedPurls.push(rootComponent["purl"]);
@@ -2024,7 +2029,6 @@ export async function createJavaBom(path, options) {
2024
2029
  allProjectsStr = allProjectsStr.concat(retMap.projects);
2025
2030
  }
2026
2031
  }
2027
- parentComponent = rootGradleModule;
2028
2032
  // Get the sub-project properties and set the root dependencies
2029
2033
  if (allProjectsStr?.length) {
2030
2034
  const modulesToSkip = process.env.GRADLE_SKIP_MODULES
@@ -2078,7 +2082,11 @@ export async function createJavaBom(path, options) {
2078
2082
  if (
2079
2083
  gradleFiles?.length &&
2080
2084
  options.installDeps &&
2081
- isPackageManagerAllowed("gradle", ["maven", "bazel", "sbt"], options)
2085
+ isPackageManagerAllowed(
2086
+ "gradle",
2087
+ ["maven", "bazel", "sbt", "mill"],
2088
+ options,
2089
+ )
2082
2090
  ) {
2083
2091
  allProjects.push(parentComponent);
2084
2092
  const gradleCmd = getGradleCommand(gradleRootPath, null);
@@ -2110,32 +2118,36 @@ export async function createJavaBom(path, options) {
2110
2118
  process.env.GRADLE_ARGS_DEPENDENCIES
2111
2119
  ? process.env.GRADLE_ARGS_DEPENDENCIES.split(" ")
2112
2120
  : [],
2121
+ gradleCmd.length,
2113
2122
  );
2114
- if (DEBUG_MODE) {
2115
- console.log(
2116
- "Executing",
2117
- gradleCmd,
2118
- `${gradleArguments.join(" ").substring(0, 150)} ...`,
2119
- "in",
2120
- gradleRootPath,
2123
+ const allOutputs = [];
2124
+ for (const gradleArg of gradleArguments) {
2125
+ if (DEBUG_MODE) {
2126
+ console.log(
2127
+ `Executing ${gradleCmd} with arguments ${gradleArg.join(" ").substring(0, 150)}... in ${gradleRootPath}`,
2128
+ );
2129
+ }
2130
+ thoughtLog(
2131
+ `Let's invoke '${basename(gradleCmd)}' with the arguments '${gradleArg.join(" ").substring(0, 100)} ...'.`,
2121
2132
  );
2122
- }
2123
- thoughtLog(
2124
- `Let's invoke '${basename(gradleCmd)}' with the arguments '${gradleArguments.join(" ").substring(0, 100)} ...'.`,
2125
- );
2126
- const sresult = spawnSync(gradleCmd, gradleArguments, {
2127
- cwd: gradleRootPath,
2128
- encoding: "utf-8",
2129
- timeout: TIMEOUT_MS,
2130
- maxBuffer: MAX_BUFFER,
2131
- });
2132
- if (sresult.status !== 0 || sresult.error) {
2133
- if (options.failOnError || DEBUG_MODE) {
2134
- console.error(sresult.stdout, sresult.stderr);
2133
+ const sresult = spawnSync(gradleCmd, gradleArg, {
2134
+ cwd: gradleRootPath,
2135
+ encoding: "utf-8",
2136
+ shell: isWin,
2137
+ timeout: TIMEOUT_MS,
2138
+ maxBuffer: MAX_BUFFER,
2139
+ });
2140
+ if (sresult.status !== 0 || sresult.error) {
2141
+ if (options.failOnError || DEBUG_MODE) {
2142
+ console.error(sresult.stdout, sresult.stderr);
2143
+ }
2144
+ options.failOnError && process.exit(1);
2145
+ }
2146
+ if (sresult.stdout !== null) {
2147
+ allOutputs.push(sresult.stdout);
2135
2148
  }
2136
- options.failOnError && process.exit(1);
2137
2149
  }
2138
- const sstdout = sresult.stdout;
2150
+ const sstdout = allOutputs.join("\n");
2139
2151
  if (sstdout) {
2140
2152
  const cmdOutput = Buffer.from(sstdout).toString();
2141
2153
  const perProjectOutput = splitOutputByGradleProjects(cmdOutput, [
@@ -2194,6 +2206,29 @@ export async function createJavaBom(path, options) {
2194
2206
  }
2195
2207
  options.failOnError && process.exit(1);
2196
2208
  }
2209
+ if (
2210
+ (!process.env.GRADLE_STOP_DAEMON &&
2211
+ (!process.env.GRADLE_USE_DAEMON ||
2212
+ ["true", "1"].includes(process.env.GRADLE_USE_DAEMON))) ||
2213
+ ["true", "1"].includes(process.env.GRADLE_STOP_DAEMON)
2214
+ ) {
2215
+ if (DEBUG_MODE) {
2216
+ console.log("Stopping gradle daemon...");
2217
+ }
2218
+ const sresult = spawnSync(gradleCmd, ["--stop"], {
2219
+ cwd: gradleRootPath,
2220
+ encoding: "utf-8",
2221
+ shell: isWin,
2222
+ timeout: TIMEOUT_MS,
2223
+ maxBuffer: MAX_BUFFER,
2224
+ });
2225
+ if (sresult.status !== 0 || sresult.error) {
2226
+ if (options.failOnError || DEBUG_MODE) {
2227
+ console.error(sresult.stdout, sresult.stderr);
2228
+ }
2229
+ options.failOnError && process.exit(1);
2230
+ }
2231
+ }
2197
2232
  // Should we attempt to resolve class names
2198
2233
  if (options.resolveClass || options.deep) {
2199
2234
  const tmpjarNSMapping = await collectJarNS(GRADLE_CACHE_DIR);
@@ -2214,7 +2249,11 @@ export async function createJavaBom(path, options) {
2214
2249
  if (
2215
2250
  bazelFiles?.length &&
2216
2251
  !hasAnyProjectType(["docker", "oci", "container", "os"], options, false) &&
2217
- isPackageManagerAllowed("bazel", ["maven", "gradle", "sbt"], options)
2252
+ isPackageManagerAllowed(
2253
+ "bazel",
2254
+ ["maven", "gradle", "sbt", "mill"],
2255
+ options,
2256
+ )
2218
2257
  ) {
2219
2258
  let BAZEL_CMD = "bazel";
2220
2259
  if (process.env.BAZEL_HOME) {
@@ -2356,7 +2395,11 @@ export async function createJavaBom(path, options) {
2356
2395
  safeMkdirSync(tempCacheDir, { recursive: true });
2357
2396
  if (
2358
2397
  sbtProjects?.length &&
2359
- isPackageManagerAllowed("sbt", ["bazel", "maven", "gradle"], options)
2398
+ isPackageManagerAllowed(
2399
+ "sbt",
2400
+ ["bazel", "maven", "gradle", "mill"],
2401
+ options,
2402
+ )
2360
2403
  ) {
2361
2404
  // If the project use sbt lock files
2362
2405
  if (sbtLockFiles?.length) {
@@ -2537,6 +2580,142 @@ export async function createJavaBom(path, options) {
2537
2580
  force: true,
2538
2581
  });
2539
2582
  }
2583
+
2584
+ if (
2585
+ millFiles?.length &&
2586
+ isPackageManagerAllowed(
2587
+ "mill",
2588
+ ["bazel", "sbt", "gradle", "maven"],
2589
+ options,
2590
+ )
2591
+ ) {
2592
+ const millRootPath = dirname(millFiles[0]);
2593
+ parentComponent = createDefaultParentComponent(
2594
+ millRootPath,
2595
+ "maven",
2596
+ options,
2597
+ );
2598
+ const millCmd = getMillCommand(millRootPath);
2599
+ const millCommonArgs = [
2600
+ "--color",
2601
+ "false",
2602
+ "--disable-callgraph",
2603
+ "--disable-prompt",
2604
+ "--keep-going",
2605
+ "--silent",
2606
+ ];
2607
+ if (!["true", "1"].includes(process.env.MILL_USE_SERVER)) {
2608
+ millCommonArgs.unshift("--no-server");
2609
+ }
2610
+ const millArgs = [...millCommonArgs, "__.ivyDepsTree"];
2611
+ if (DEBUG_MODE) {
2612
+ console.log("Executing", millCmd, millArgs.join(" "), "in", millRootPath);
2613
+ }
2614
+ let sresult = spawnSync(millCmd, millArgs, {
2615
+ cwd: millRootPath,
2616
+ encoding: "utf-8",
2617
+ shell: isWin,
2618
+ timeout: TIMEOUT_MS,
2619
+ maxBuffer: MAX_BUFFER * 10,
2620
+ });
2621
+ if (sresult.status !== 0 || sresult.error) {
2622
+ if (options.failOnError || DEBUG_MODE) {
2623
+ console.error(sresult.stdout, sresult.stderr);
2624
+ }
2625
+ options.failOnError && process.exit(1);
2626
+ }
2627
+ const millResolveArgs = [...millCommonArgs, "resolve", "__.ivyDepsTree"];
2628
+ if (DEBUG_MODE) {
2629
+ console.log(
2630
+ "Executing",
2631
+ millCmd,
2632
+ millResolveArgs.join(" "),
2633
+ "in",
2634
+ millRootPath,
2635
+ );
2636
+ }
2637
+ sresult = spawnSync(millCmd, millResolveArgs, {
2638
+ cwd: millRootPath,
2639
+ encoding: "utf-8",
2640
+ shell: isWin,
2641
+ timeout: TIMEOUT_MS,
2642
+ maxBuffer: MAX_BUFFER,
2643
+ });
2644
+ if (sresult.status !== 0 || sresult.error) {
2645
+ if (options.failOnError || DEBUG_MODE) {
2646
+ console.error(sresult.stdout, sresult.stderr);
2647
+ }
2648
+ options.failOnError && process.exit(1);
2649
+ }
2650
+ const sstdout = sresult.stdout;
2651
+ if (sstdout) {
2652
+ parentComponent.components = [];
2653
+ const modules = sstdout
2654
+ .trim()
2655
+ .split("\n")
2656
+ .map((a) => a.substring(0, a.lastIndexOf(".")))
2657
+ .filter((a) =>
2658
+ ["true", "1"].includes(process.env.MILL_EXCLUDE_TEST)
2659
+ ? !a.endsWith(".test")
2660
+ : true,
2661
+ );
2662
+ const moduleBomRefs = [];
2663
+ const packages = new Map();
2664
+ const relations = new Map();
2665
+ relations.set(parentComponent["bom-ref"], []);
2666
+ for (const module of modules) {
2667
+ moduleBomRefs.push(
2668
+ parseMillDependency(module, packages, relations, millRootPath),
2669
+ );
2670
+ }
2671
+ for (const module of moduleBomRefs) {
2672
+ parentComponent.components.push(packages.get(module));
2673
+ relations.get(parentComponent["bom-ref"]).push(module);
2674
+ packages.delete(module);
2675
+ }
2676
+ const newDependencies = [];
2677
+ for (const [ref, dependsOn] of relations.entries()) {
2678
+ newDependencies.push({
2679
+ ref,
2680
+ dependsOn,
2681
+ });
2682
+ }
2683
+ if (DEBUG_MODE) {
2684
+ console.log(
2685
+ `Obtained ${packages.size} components and ${relations.size} dependencies from mill.`,
2686
+ );
2687
+ }
2688
+ pkgList = pkgList.concat(...packages.values());
2689
+ dependencies = mergeDependencies(
2690
+ dependencies,
2691
+ newDependencies,
2692
+ parentComponent,
2693
+ );
2694
+ }
2695
+ if (
2696
+ (!process.env.MILL_SHUTDOWN_SERVER &&
2697
+ ["true", "1"].includes(process.env.MILL_USE_SERVER)) ||
2698
+ ["true", "1"].includes(process.env.MILL_SHUTDOWN_SERVER)
2699
+ ) {
2700
+ if (DEBUG_MODE) {
2701
+ console.log("Shutting down mill server...");
2702
+ }
2703
+ const sresult = spawnSync(millCmd, ["shutdown"], {
2704
+ cwd: millRootPath,
2705
+ encoding: "utf-8",
2706
+ shell: isWin,
2707
+ timeout: TIMEOUT_MS,
2708
+ maxBuffer: MAX_BUFFER,
2709
+ });
2710
+ if (sresult.status !== 0 || sresult.error) {
2711
+ if (options.failOnError || DEBUG_MODE) {
2712
+ console.error(sresult.stdout, sresult.stderr);
2713
+ }
2714
+ options.failOnError && process.exit(1);
2715
+ }
2716
+ }
2717
+ }
2718
+
2540
2719
  pkgList = trimComponents(pkgList);
2541
2720
  pkgList = await getMvnMetadata(pkgList, jarNSMapping, options.deep);
2542
2721
  return buildBomNSData(options, pkgList, "maven", {
@@ -251,7 +251,9 @@ export async function createSlice(
251
251
  ? path.basename(options.output)
252
252
  : path.dirname(options.output);
253
253
  }
254
- const slicesFile = join(sliceOutputDir, `${sliceType}.slices.json`);
254
+ const slicesFile =
255
+ options[`${sliceType}SlicesFile`] ||
256
+ join(sliceOutputDir, `${sliceType}.slices.json`);
255
257
  const openapiSpecFile = basename(
256
258
  options.openapiSpecFile ||
257
259
  process.env?.ATOM_TOOLS_OPENAPI_FILENAME ||