@socketsecurity/cli-with-sentry 1.6.2 → 1.8.0

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.
Files changed (45) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +5 -5
  3. package/dist/cli.js +350 -268
  4. package/dist/cli.js.map +1 -1
  5. package/dist/constants.js +4 -4
  6. package/dist/constants.js.map +1 -1
  7. package/dist/manifest-scripts/maven-extension/coana-maven-extension.jar +0 -0
  8. package/dist/manifest-scripts/socket-facts.init.gradle +2 -65
  9. package/dist/manifest-scripts/socket-facts.plugin.scala +75 -41
  10. package/dist/tsconfig.dts.tsbuildinfo +1 -1
  11. package/dist/types/commands/fix/coana-fix.d.mts.map +1 -1
  12. package/dist/types/commands/fix/generated-socket-facts.d.mts +4 -2
  13. package/dist/types/commands/fix/generated-socket-facts.d.mts.map +1 -1
  14. package/dist/types/commands/manifest/cmd-manifest-dynamic-sbom-inference.d.mts.map +1 -1
  15. package/dist/types/commands/manifest/convert-gradle-to-facts.d.mts +2 -1
  16. package/dist/types/commands/manifest/convert-gradle-to-facts.d.mts.map +1 -1
  17. package/dist/types/commands/manifest/convert-maven-to-facts.d.mts +2 -1
  18. package/dist/types/commands/manifest/convert-maven-to-facts.d.mts.map +1 -1
  19. package/dist/types/commands/manifest/convert-sbt-to-facts.d.mts +1 -1
  20. package/dist/types/commands/manifest/convert-sbt-to-facts.d.mts.map +1 -1
  21. package/dist/types/commands/manifest/run-manifest-facts.d.mts +3 -2
  22. package/dist/types/commands/manifest/run-manifest-facts.d.mts.map +1 -1
  23. package/dist/types/commands/manifest/scripts/assemble.d.mts +0 -1
  24. package/dist/types/commands/manifest/scripts/assemble.d.mts.map +1 -1
  25. package/dist/types/commands/manifest/scripts/build-tool.d.mts +2 -0
  26. package/dist/types/commands/manifest/scripts/build-tool.d.mts.map +1 -1
  27. package/dist/types/commands/manifest/scripts/facts.d.mts +15 -9
  28. package/dist/types/commands/manifest/scripts/facts.d.mts.map +1 -1
  29. package/dist/types/commands/manifest/scripts/records.d.mts +6 -7
  30. package/dist/types/commands/manifest/scripts/records.d.mts.map +1 -1
  31. package/dist/types/commands/manifest/scripts/run.d.mts +2 -0
  32. package/dist/types/commands/manifest/scripts/run.d.mts.map +1 -1
  33. package/dist/types/commands/manifest/scripts/sidecar.d.mts +3 -1
  34. package/dist/types/commands/manifest/scripts/sidecar.d.mts.map +1 -1
  35. package/dist/types/commands/scan/handle-create-new-scan.d.mts.map +1 -1
  36. package/dist/types/commands/scan/perform-reachability-analysis.d.mts.map +1 -1
  37. package/dist/types/utils/coana.d.mts +7 -0
  38. package/dist/types/utils/coana.d.mts.map +1 -1
  39. package/dist/utils.js +16 -1
  40. package/dist/utils.js.map +1 -1
  41. package/external/blessed/vendor/tng.js +1 -1
  42. package/external/blessed-contrib/lib/widget/charts/bar.js +2 -2
  43. package/external/blessed-contrib/lib/widget/charts/line.js +2 -2
  44. package/external/blessed-contrib/lib/widget/table.js +3 -3
  45. package/package.json +2 -2
package/dist/cli.js CHANGED
@@ -1857,8 +1857,12 @@ withPaths = true) {
1857
1857
  };
1858
1858
  acc.set(factsFile, {
1859
1859
  components: facts.components.map(paths),
1860
- projects: (facts.projects ?? []).map(proj => ({
1860
+ projects: (facts.projects ?? []).map(({
1861
+ children: _children,
1862
+ ...proj
1863
+ }) => ({
1861
1864
  ...paths(proj),
1865
+ dependencies: [...(artifactPaths.directDependenciesByProject.get(proj.id) ?? [])],
1862
1866
  classpath: [...(artifactPaths.classpathByProject.get(proj.id) ?? [])]
1863
1867
  }))
1864
1868
  });
@@ -1955,15 +1959,13 @@ async function performReachabilityAnalysis(options) {
1955
1959
  }
1956
1960
  const sockSdk = sockSdkCResult.data;
1957
1961
  spinner?.start('Uploading manifests for reachability analysis...');
1962
+ const outputFilePath = outputPath || constants.default.DOT_SOCKET_DOT_FACTS_JSON;
1958
1963
 
1959
1964
  // Ensure uploaded manifest files are relative to analysis target as coana resolves SBOM manifest files relative to this path
1960
- // NOTE: previously stripped any `.socket.facts.json` from packagePaths
1961
- // here to avoid uploading leftover post-reachability output. With the
1962
- // producer flow (`socket manifest gradle --facts`) those files are
1963
- // legitimate INPUT to compute-artifacts, so we now upload them. Stale
1964
- // facts files are cleaned up downstream — see the post-success
1965
- // deletion in handle-create-new-scan.mts.
1966
- const uploadCResult = await utils.handleApiCall(sockSdk.uploadManifestFiles(orgSlug, packagePaths, {
1965
+ const uploadCResult = await utils.handleApiCall(sockSdk.uploadManifestFiles(orgSlug, packagePaths.filter(p => !utils.isReachabilityReportPath(p, {
1966
+ cwd,
1967
+ outputPath: outputFilePath
1968
+ })), {
1967
1969
  pathsRelativeTo: path.resolve(cwd, analysisTarget)
1968
1970
  }), {
1969
1971
  description: 'upload manifests',
@@ -1991,7 +1993,6 @@ async function performReachabilityAnalysis(options) {
1991
1993
  spinner?.success(`Manifests uploaded successfully. Tar hash: ${tarHash}`);
1992
1994
  spinner?.start();
1993
1995
  spinner?.infoAndStop('Running reachability analysis with Coana...');
1994
- const outputFilePath = outputPath || constants.default.DOT_SOCKET_DOT_FACTS_JSON;
1995
1996
 
1996
1997
  // Temp file for --compute-artifacts-sidecar, removed in the finally below.
1997
1998
  // Written even when empty under dynamicSbomInference, since the
@@ -2282,6 +2283,15 @@ const BUILD_TOOL_WRAPPER = {
2282
2283
  maven: 'mvnw'
2283
2284
  };
2284
2285
 
2286
+ // Gradle (8+) and sbt hold one build per directory; Maven builds are addressed
2287
+ // by POM file, so `mvn -f other-pom.xml` puts a second build in the directory.
2288
+ const ADDRESSED_BY_FILE = {
2289
+ __proto__: null,
2290
+ gradle: false,
2291
+ maven: true,
2292
+ sbt: false
2293
+ };
2294
+
2285
2295
  // sbt happily runs in any directory, synthesizing a default project from its
2286
2296
  // name, so an sbt run outside a build yields a plausible but bogus SBOM. Maven
2287
2297
  // and Gradle refuse such a directory themselves.
@@ -2299,6 +2309,14 @@ function resolveBuildToolBin(tool, projectDir, bin) {
2299
2309
  return DEFAULT_BUILD_TOOL_BIN[tool];
2300
2310
  }
2301
2311
 
2312
+ // Distinct for every build sharing a directory.
2313
+ function socketFactsFileName(tool, entryFile) {
2314
+ if (!ADDRESSED_BY_FILE[tool]) {
2315
+ return `${tool}${constants.default.DOT_SOCKET_DOT_FACTS_JSON}`;
2316
+ }
2317
+ return entryFile ? `${path.basename(entryFile)}${constants.default.DOT_SOCKET_DOT_FACTS_JSON}` : undefined;
2318
+ }
2319
+
2302
2320
  // Gradle's variant-aware resolver: distinct exceptions give mutually-exclusive
2303
2321
  // phrasing, so most-specific-first substring checks classify reliably.
2304
2322
  function classifyGradleFailure(detail) {
@@ -2659,13 +2677,14 @@ const PURL_TYPE_MAVEN = 'maven';
2659
2677
  function assembleFacts(parsed, opts = {}) {
2660
2678
  const fileExists = opts.fileExists ?? fs$1.existsSync;
2661
2679
  const perRoot = buildPerRoot(parsed);
2662
- const {
2663
- directByRoot,
2664
- finalNodes
2665
- } = mergeById(perRoot);
2680
+ const finalNodes = mergeById(perRoot);
2681
+ const graphs = buildSubprojectGraphs(perRoot);
2666
2682
  const tool = parsed.tool || 'gradle';
2667
- const components = buildComponents(finalNodes, buildManifestFilesById(parsed, directByRoot, perRoot));
2668
- const projects = opts.emitProjects === false ? [] : buildProjects(parsed, directByRoot, perRoot);
2683
+ const components = buildComponents(finalNodes);
2684
+ const {
2685
+ dependencies,
2686
+ projects
2687
+ } = buildDependencyGraph(parsed, graphs, components);
2669
2688
  const metadata = {
2670
2689
  format: 'socket-facts-sbom',
2671
2690
  tool,
@@ -2677,7 +2696,8 @@ function assembleFacts(parsed, opts = {}) {
2677
2696
  const facts = projects.length ? {
2678
2697
  metadata,
2679
2698
  projects,
2680
- components
2699
+ components,
2700
+ dependencies
2681
2701
  } : {
2682
2702
  metadata,
2683
2703
  components
@@ -2685,7 +2705,7 @@ function assembleFacts(parsed, opts = {}) {
2685
2705
  return {
2686
2706
  facts,
2687
2707
  report: buildReport(parsed),
2688
- artifactPaths: buildArtifactPaths(finalNodes, [...parsed.projects.values()], perRoot, fileExists)
2708
+ artifactPaths: buildArtifactPaths(finalNodes, [...parsed.projects.values()], graphs, fileExists)
2689
2709
  };
2690
2710
  }
2691
2711
 
@@ -2744,17 +2764,15 @@ function buildPerRoot(parsed) {
2744
2764
  // reachability, which needs each subproject's exact classpath.
2745
2765
  function mergeById(perRoot) {
2746
2766
  const finalNodes = new Map();
2747
- const directByRoot = new Map();
2748
- for (const [rootId, {
2767
+ for (const {
2749
2768
  nodes,
2750
2769
  prod
2751
- }] of perRoot) {
2770
+ } of perRoot.values()) {
2752
2771
  for (const [coordId, node] of nodes) {
2753
2772
  let fn = finalNodes.get(coordId);
2754
2773
  if (!fn) {
2755
2774
  fn = {
2756
2775
  coord: node.coord,
2757
- children: new Set(),
2758
2776
  prod: false,
2759
2777
  direct: false,
2760
2778
  project: node.project,
@@ -2768,56 +2786,14 @@ function mergeById(perRoot) {
2768
2786
  if (node.direct) {
2769
2787
  fn.direct = true;
2770
2788
  }
2771
- for (const c of node.children) {
2772
- fn.children.add(c);
2773
- }
2774
2789
  for (const t of node.targets) {
2775
2790
  fn.targets.add(t);
2776
2791
  }
2777
- if (node.direct) {
2778
- let d = directByRoot.get(rootId);
2779
- if (!d) {
2780
- d = new Set();
2781
- directByRoot.set(rootId, d);
2782
- }
2783
- d.add(coordId);
2784
- }
2785
2792
  }
2786
2793
  }
2787
- return {
2788
- finalNodes,
2789
- directByRoot
2790
- };
2791
- }
2792
- function buildManifestFilesById(parsed, directByRoot, perRoot) {
2793
- const buildFilesByCoord = new Map();
2794
- for (const [rootId, ids] of directByRoot) {
2795
- const root = perRoot.get(rootId);
2796
- const project = parsed.projects.get(root?.projectKey ?? '');
2797
- for (const id of ids) {
2798
- let set = buildFilesByCoord.get(id);
2799
- if (!set) {
2800
- set = new Set();
2801
- buildFilesByCoord.set(id, set);
2802
- }
2803
- const coord = root?.nodes.get(id)?.coord;
2804
- // Without a known declaring script, the project's build file, even one
2805
- // absent on disk: its presence marks the dependency direct here.
2806
- const declared = coord && project?.declaredIn.get(`${coord.group}:${coord.name}`);
2807
- const files = declared ?? [...(project?.buildFiles ?? []), ...(project?.missingBuildFiles ?? [])];
2808
- for (const f of files) {
2809
- set.add(f);
2810
- }
2811
- }
2812
- }
2813
- return new Map([...buildFilesByCoord].map(({
2814
- 0: id,
2815
- 1: buildFiles
2816
- }) => [id, [constants.default.DOT_SOCKET_DOT_FACTS_JSON, ...[...buildFiles].sort()].map(file => ({
2817
- file
2818
- }))]));
2794
+ return finalNodes;
2819
2795
  }
2820
- function buildComponents(finalNodes, manifestFilesById) {
2796
+ function buildComponents(finalNodes) {
2821
2797
  return [...finalNodes.keys()].sort().map(id => {
2822
2798
  const fn = finalNodes.get(id);
2823
2799
  const c = fn.coord;
@@ -2851,92 +2827,188 @@ function buildComponents(finalNodes, manifestFilesById) {
2851
2827
  if (fn.project) {
2852
2828
  comp.firstParty = true;
2853
2829
  }
2854
- if (fn.children.size) {
2855
- comp.dependencies = [...fn.children].sort();
2856
- }
2857
- const manifestFiles = manifestFilesById.get(id);
2858
- if (manifestFiles) {
2859
- comp.manifestFiles = manifestFiles;
2860
- }
2861
2830
  return comp;
2862
2831
  });
2863
2832
  }
2864
- function buildProjects(parsed, directByRoot, perRoot) {
2865
- const directByProject = new Map();
2866
- for (const [rootId, ids] of directByRoot) {
2867
- const pk = perRoot.get(rootId)?.projectKey ?? '';
2868
- let set = directByProject.get(pk);
2869
- if (!set) {
2870
- set = new Set();
2871
- directByProject.set(pk, set);
2833
+
2834
+ // One graph per subproject, its configurations merged.
2835
+ function buildSubprojectGraphs(perRoot) {
2836
+ const graphs = new Map();
2837
+ for (const {
2838
+ nodes,
2839
+ projectKey
2840
+ } of perRoot.values()) {
2841
+ let g = graphs.get(projectKey);
2842
+ if (!g) {
2843
+ g = {
2844
+ children: new Map(),
2845
+ direct: new Set()
2846
+ };
2847
+ graphs.set(projectKey, g);
2872
2848
  }
2873
- for (const id of ids) {
2874
- set.add(id);
2849
+ for (const [coordId, node] of nodes) {
2850
+ let set = g.children.get(coordId);
2851
+ if (!set) {
2852
+ set = new Set();
2853
+ g.children.set(coordId, set);
2854
+ }
2855
+ for (const c of node.children) {
2856
+ set.add(c);
2857
+ }
2858
+ if (node.direct) {
2859
+ g.direct.add(coordId);
2860
+ }
2875
2861
  }
2876
2862
  }
2877
- const projects = [...parsed.projects.values()].map(p => {
2878
- const entry = {
2879
- id: p.projectKey,
2880
- type: PURL_TYPE_MAVEN,
2881
- namespace: p.group,
2882
- name: p.name,
2883
- ...(p.version ? {
2884
- version: p.version
2885
- } : {}),
2886
- subprojectDir: p.dir,
2887
- dependencies: [...(directByProject.get(p.projectKey) ?? [])].sort()
2888
- };
2889
- // A project without a build file of its own is defined by the scripts
2890
- // declaring its dependencies, e.g. the root build script.
2891
- const declared = [...new Set([...p.declaredIn.values()].flat())];
2892
- const files = p.buildFiles.length ? p.buildFiles : declared.length ? declared : p.missingBuildFiles;
2893
- if (files.length) {
2894
- entry.manifestFiles = [...files].sort().map(file => ({
2895
- file
2896
- }));
2863
+ return graphs;
2864
+ }
2865
+
2866
+ // Equal subtrees share an entry; partition refinement (coarsest bisimulation)
2867
+ // keeps that exact on cycles too.
2868
+ function buildDependencyGraph(parsed, graphs, components) {
2869
+ const componentIndex = new Map(components.map((c, i) => [c.id, i]));
2870
+ const vertexIds = new Map();
2871
+ const labels = [];
2872
+ const edges = [];
2873
+ const vertex = (projectKey, coordId) => {
2874
+ const key = `${projectKey}\t${coordId}`;
2875
+ let v = vertexIds.get(key);
2876
+ if (v === undefined) {
2877
+ v = labels.length;
2878
+ vertexIds.set(key, v);
2879
+ labels.push(componentIndex.get(coordId));
2880
+ edges.push([]);
2881
+ }
2882
+ return v;
2883
+ };
2884
+ for (const [projectKey, {
2885
+ children
2886
+ }] of graphs) {
2887
+ for (const [coordId, kids] of children) {
2888
+ const v = vertex(projectKey, coordId);
2889
+ for (const c of kids) {
2890
+ edges[v].push(vertex(projectKey, c));
2891
+ }
2897
2892
  }
2898
- return entry;
2899
- });
2900
- projects.sort((a, b) => {
2901
- const ka = `${a.subprojectDir} ${a.namespace}:${a.name}`;
2902
- const kb = `${b.subprojectDir} ${b.namespace}:${b.name}`;
2893
+ }
2894
+
2895
+ // Each round splits blocks by their children's blocks; a round that splits
2896
+ // nothing is stable.
2897
+ let block = [...labels];
2898
+ let blockCount = new Set(block).size;
2899
+ for (;;) {
2900
+ const ids = new Map();
2901
+ block = block.map((b, v) => {
2902
+ const childBlocks = [...new Set(edges[v].map(c => block[c]))].sort((x, y) => x - y);
2903
+ const sig = `${b}:${childBlocks.join(',')}`;
2904
+ let id = ids.get(sig);
2905
+ if (id === undefined) {
2906
+ id = ids.size;
2907
+ ids.set(sig, id);
2908
+ }
2909
+ return id;
2910
+ });
2911
+ if (ids.size === blockCount) {
2912
+ break;
2913
+ }
2914
+ blockCount = ids.size;
2915
+ }
2916
+ const byComponent = (a, b) => componentIndex.get(a) - componentIndex.get(b);
2917
+ const projects = [...parsed.projects.values()].map(p => ({
2918
+ p,
2919
+ roots: treeRoots(p.projectKey, graphs.get(p.projectKey), byComponent)
2920
+ })).sort((a, b) => {
2921
+ const ka = `${a.p.dir} ${a.p.group}:${a.p.name}`;
2922
+ const kb = `${b.p.dir} ${b.p.group}:${b.p.name}`;
2903
2923
  return ka < kb ? -1 : ka > kb ? 1 : 0;
2904
2924
  });
2905
- return projects;
2906
- }
2907
- function buildClasspathByProject(projects, perRoot) {
2908
- const idsByProjectKey = new Map();
2909
- for (const {
2910
- nodes,
2911
- projectKey
2912
- } of perRoot.values()) {
2913
- let set = idsByProjectKey.get(projectKey);
2914
- if (!set) {
2915
- set = new Set();
2916
- idsByProjectKey.set(projectKey, set);
2925
+
2926
+ // Post-order over the sorted projects, so the numbering is stable.
2927
+ const indexOfBlock = new Map();
2928
+ const vertexOfBlock = new Map();
2929
+ const dependencies = [];
2930
+ const visit = v => {
2931
+ const b = block[v];
2932
+ if (vertexOfBlock.has(b)) {
2933
+ return;
2917
2934
  }
2918
- for (const coordId of nodes.keys()) {
2919
- set.add(coordId);
2935
+ vertexOfBlock.set(b, v);
2936
+ for (const c of [...edges[v]].sort((x, y) => labels[x] - labels[y])) {
2937
+ visit(c);
2938
+ }
2939
+ indexOfBlock.set(b, dependencies.length);
2940
+ dependencies.push({
2941
+ component: labels[v]
2942
+ });
2943
+ };
2944
+ const indexOf = v => indexOfBlock.get(block[v]);
2945
+ for (const {
2946
+ p,
2947
+ roots
2948
+ } of projects) {
2949
+ for (const coordId of roots) {
2950
+ visit(vertex(p.projectKey, coordId));
2920
2951
  }
2921
2952
  }
2922
- const classpathByProject = new Map();
2923
- for (const p of projects) {
2924
- const key = p.projectKey;
2925
- let set = classpathByProject.get(key);
2926
- if (!set) {
2927
- set = new Set();
2928
- classpathByProject.set(key, set);
2953
+ for (const [b, v] of vertexOfBlock) {
2954
+ const children = [...new Set(edges[v].map(indexOf))].sort((x, y) => x - y);
2955
+ if (children.length) {
2956
+ dependencies[indexOfBlock.get(b)].children = children;
2929
2957
  }
2930
- for (const id of idsByProjectKey.get(p.projectKey) ?? []) {
2931
- set.add(id);
2958
+ }
2959
+ return {
2960
+ dependencies,
2961
+ projects: projects.map(({
2962
+ p,
2963
+ roots
2964
+ }) => {
2965
+ const entry = {
2966
+ id: p.projectKey,
2967
+ type: PURL_TYPE_MAVEN,
2968
+ namespace: p.group,
2969
+ name: p.name,
2970
+ ...(p.version ? {
2971
+ version: p.version
2972
+ } : {}),
2973
+ subprojectDir: p.dir,
2974
+ children: roots.map(coordId => indexOf(vertex(p.projectKey, coordId))).sort((x, y) => x - y)
2975
+ };
2976
+ if (p.buildFiles.length) {
2977
+ entry.manifestFiles = [...new Set(p.buildFiles)].sort().map(file => ({
2978
+ file
2979
+ }));
2980
+ }
2981
+ return entry;
2982
+ })
2983
+ };
2984
+ }
2985
+ function treeRoots(projectKey, graph, byComponent) {
2986
+ if (!graph) {
2987
+ return [];
2988
+ }
2989
+ const roots = [...graph.direct].sort(byComponent);
2990
+ const reached = new Set();
2991
+ const stack = [...roots];
2992
+ while (stack.length) {
2993
+ const id = stack.pop();
2994
+ if (!reached.has(id)) {
2995
+ reached.add(id);
2996
+ stack.push(...graph.children.get(id));
2932
2997
  }
2933
2998
  }
2934
- return new Map([...classpathByProject].map(({
2935
- 0: key,
2936
- 1: ids
2937
- }) => [key, [...ids].sort()]));
2999
+ const unreached = [...graph.children.keys()].filter(id => !reached.has(id));
3000
+ if (unreached.length) {
3001
+ throw new Error(`Resolved dependencies of ${projectKey} are not reachable from its direct dependencies: ${unreached.sort(byComponent).join(', ')}`);
3002
+ }
3003
+ return roots;
3004
+ }
3005
+ function byProject(projects, graphs, ids) {
3006
+ return new Map(projects.map(p => {
3007
+ const g = graphs.get(p.projectKey);
3008
+ return [p.projectKey, g ? [...ids(g)].sort() : []];
3009
+ }));
2938
3010
  }
2939
- function buildArtifactPaths(finalNodes, projects, perRoot, fileExists) {
3011
+ function buildArtifactPaths(finalNodes, projects, graphs, fileExists) {
2940
3012
  const pathsById = new Map();
2941
3013
  for (const [id, fn] of finalNodes) {
2942
3014
  if (!fn.project) {
@@ -2956,7 +3028,8 @@ function buildArtifactPaths(finalNodes, projects, perRoot, fileExists) {
2956
3028
  }
2957
3029
  return {
2958
3030
  pathsById,
2959
- classpathByProject: buildClasspathByProject(projects, perRoot)
3031
+ classpathByProject: byProject(projects, graphs, g => g.children.keys()),
3032
+ directDependenciesByProject: byProject(projects, graphs, g => g.direct)
2960
3033
  };
2961
3034
  }
2962
3035
  function buildReport(parsed) {
@@ -3128,11 +3201,11 @@ function serializeExcludePathPatterns(paths) {
3128
3201
  //
3129
3202
  // meta tool toolVersion javaVersion
3130
3203
  // buildRoot path (absolute; the facts file's directory)
3204
+ // entry path (file-addressed builds; build-root-relative)
3131
3205
  // project projectKey group name version dir
3132
3206
  // projectSrc projectKey path (--with-files only)
3133
3207
  // projectTgt projectKey path (--with-files only)
3134
- // projectBuild projectKey path [missing] (build-root-relative; `missing`: configured, absent on disk)
3135
- // declared projectKey group name path (script declaring the dependency; build-root-relative)
3208
+ // projectBuild projectKey path (build-root-relative; may be absent on disk)
3136
3209
  // root rootId projectKey config prod(0|1)
3137
3210
  // node rootId coordId group name version ext classifier direct(0|1) project
3138
3211
  // edge rootId parentCoordId childCoordId
@@ -3173,6 +3246,7 @@ function parseRecords(text) {
3173
3246
  toolVersion: '',
3174
3247
  javaVersion: '',
3175
3248
  buildRoot: '',
3249
+ entry: '',
3176
3250
  projects: new Map(),
3177
3251
  roots: new Map(),
3178
3252
  scannedConfigs: [],
@@ -3206,9 +3280,7 @@ function parseRecords(text) {
3206
3280
  dir: '',
3207
3281
  sources: [],
3208
3282
  targets: [],
3209
- buildFiles: [],
3210
- missingBuildFiles: [],
3211
- declaredIn: new Map()
3283
+ buildFiles: []
3212
3284
  };
3213
3285
  result.projects.set(key, p);
3214
3286
  }
@@ -3228,6 +3300,9 @@ function parseRecords(text) {
3228
3300
  case 'buildRoot':
3229
3301
  result.buildRoot = f[1] ?? '';
3230
3302
  break;
3303
+ case 'entry':
3304
+ result.entry = f[1] ?? '';
3305
+ break;
3231
3306
  case 'project':
3232
3307
  {
3233
3308
  const p = project(f[1] ?? '');
@@ -3249,17 +3324,7 @@ function parseRecords(text) {
3249
3324
  break;
3250
3325
  case 'projectBuild':
3251
3326
  if (f[2]) {
3252
- const p = project(f[1] ?? '');
3253
- (f[3] === 'missing' ? p.missingBuildFiles : p.buildFiles).push(f[2]);
3254
- }
3255
- break;
3256
- case 'declared':
3257
- if (f[4]) {
3258
- const {
3259
- declaredIn
3260
- } = project(f[1] ?? '');
3261
- const ga = `${f[2] ?? ''}:${f[3] ?? ''}`;
3262
- declaredIn.set(ga, [...(declaredIn.get(ga) ?? []), f[4]]);
3327
+ project(f[1] ?? '').buildFiles.push(f[2]);
3263
3328
  }
3264
3329
  break;
3265
3330
  case 'root':
@@ -3392,9 +3457,10 @@ async function writeSbtPlugin(globalBase, sourceFilename, destFilename) {
3392
3457
  });
3393
3458
  await fs$1.promises.writeFile(path.join(pluginsDir, destFilename), src);
3394
3459
  }
3395
- async function assembleFromRecords(out, recordsFile) {
3460
+ async function assembleFromRecords(tool, out, recordsFile) {
3396
3461
  const text = fs$1.existsSync(recordsFile) ? await fs$1.promises.readFile(recordsFile, 'utf8') : '';
3397
3462
  const parsed = parseRecords(text);
3463
+ const factsFileName = socketFactsFileName(tool, parsed.entry || undefined);
3398
3464
  const {
3399
3465
  artifactPaths,
3400
3466
  facts,
@@ -3404,6 +3470,7 @@ async function assembleFromRecords(out, recordsFile) {
3404
3470
  buildRoot: parsed.buildRoot || undefined,
3405
3471
  code: out.code,
3406
3472
  facts,
3473
+ factsFileName,
3407
3474
  report,
3408
3475
  artifactPaths,
3409
3476
  stderr: out.stderr,
@@ -3476,7 +3543,7 @@ async function invokeGradle(opts, initScriptFilename, task, tmpDirPrefix) {
3476
3543
  // resolvedConfiguration API and shared accumulator aren't cache-safe.
3477
3544
  const args = ['--init-script', initScript, '-Dorg.gradle.configuration-cache=false', `-Psocket.recordsFile=${recordsFile}`, ...commonProps(opts, '-P'), ...(opts.toolOpts ?? []), task, '--no-daemon', '--console=plain'];
3478
3545
  const out = await runNeverThrow(bin, args, opts);
3479
- return await assembleFromRecords(out, recordsFile);
3546
+ return await assembleFromRecords('gradle', out, recordsFile);
3480
3547
  });
3481
3548
  }
3482
3549
  async function runGradle(opts) {
@@ -3502,7 +3569,7 @@ async function invokeSbtIn(globalBase, opts, pluginSourceFilename, pluginDestFil
3502
3569
  const javaHomeOpt = javaHome && !(opts.toolOpts ?? []).includes('--java-home') ? ['--java-home', javaHome] : [];
3503
3570
  const args = [...javaHomeOpt, ...props, ...(opts.toolOpts ?? []), '--batch', task];
3504
3571
  const out = await runNeverThrow(bin, args, opts);
3505
- return await assembleFromRecords(out, recordsFile);
3572
+ return await assembleFromRecords('sbt', out, recordsFile);
3506
3573
  }
3507
3574
  async function runSbt(opts) {
3508
3575
  const run = globalBase => invokeSbtIn(globalBase, opts, 'socket-facts.plugin.scala', SBT_FACTS_PLUGIN_FILENAME, FACTS_TASK);
@@ -3529,7 +3596,7 @@ async function invokeMaven(opts, coanaTask, tmpDirPrefix) {
3529
3596
  const props = [`-Dmaven.ext.class.path=${jarPath}`, `-Dcoana.task=${coanaTask}`, `-Dsocket.recordsFile=${recordsFile}`, ...commonProps(opts, '-D')];
3530
3597
  const args = [...props, ...(opts.toolOpts ?? []), '--batch-mode', 'validate'];
3531
3598
  const out = await runNeverThrow(bin, args, opts);
3532
- return await assembleFromRecords(out, recordsFile);
3599
+ return await assembleFromRecords('maven', out, recordsFile);
3533
3600
  });
3534
3601
  }
3535
3602
  async function runMaven(opts) {
@@ -3552,8 +3619,9 @@ function tailBuildOutput(stdout, stderr) {
3552
3619
  // `process.exitCode`, which can already be non-zero for an unrelated reason.
3553
3620
 
3554
3621
  // Runs the bundled build-tool resolution script for a JVM project and writes
3555
- // `.socket.facts.json`. `withFiles` (reachability only) additionally folds
3556
- // resolved artifact paths into `sidecarAcc`. A blocking resolution failure sets
3622
+ // its `<entry>.socket.facts.json` (see socketFactsFileName). `withFiles`
3623
+ // (reachability only) additionally folds resolved artifact paths into
3624
+ // `sidecarAcc`. A blocking resolution failure sets
3557
3625
  // a non-zero exit code and returns (matching the `--pom` generator) unless
3558
3626
  // `ignoreUnresolved`; a crashed build — a process failure, not an unresolved
3559
3627
  // dependency — always fails.
@@ -3639,6 +3707,7 @@ async function runManifestFacts({
3639
3707
  buildRoot,
3640
3708
  code,
3641
3709
  facts,
3710
+ factsFileName,
3642
3711
  report,
3643
3712
  stderr,
3644
3713
  stdout
@@ -3697,14 +3766,20 @@ async function runManifestFacts({
3697
3766
  logger.logger.warn(`No resolvable ${ecosystem} dependencies found; nothing to upload.`);
3698
3767
  return;
3699
3768
  }
3700
- if (!buildRoot) {
3769
+ if (!buildRoot || !factsFileName) {
3701
3770
  process.exitCode = 1;
3702
- logger.logger.fail(`The ${ecosystem} build did not report its root directory, so its Socket facts file cannot be placed.`);
3771
+ logger.logger.fail(`The ${ecosystem} build did not report its ${buildRoot ? 'entry build file' : 'root directory'}, so its Socket facts file cannot be placed.`);
3703
3772
  return null;
3704
3773
  }
3705
3774
  // Every path in the facts is relative to the build root, which `-f`/`-p`
3706
3775
  // can move away from cwd.
3707
- const factsPath = path.join(buildRoot, constants.default.DOT_SOCKET_DOT_FACTS_JSON);
3776
+ const factsPath = path.join(buildRoot, factsFileName);
3777
+ // Not a name producers write, so a copy here is stale and would be uploaded
3778
+ // alongside the new file.
3779
+ const legacyFactsPath = path.join(buildRoot, constants.default.DOT_SOCKET_DOT_FACTS_JSON);
3780
+ if (fs$1.existsSync(legacyFactsPath)) {
3781
+ logger.logger.warn(`Found \`${legacyFactsPath}\`, which is uploaded alongside \`${factsFileName}\`. Delete it if an earlier \`socket manifest\` run left it behind.`);
3782
+ }
3708
3783
  const socketCliVersion = constants.default.ENV.INLINED_SOCKET_CLI_VERSION;
3709
3784
  if (facts.metadata && socketCliVersion) {
3710
3785
  facts.metadata.socketCliVersion = socketCliVersion;
@@ -6385,7 +6460,8 @@ async function extractBazelToMaven(opts) {
6385
6460
  }
6386
6461
  }
6387
6462
 
6388
- // Generates `.socket.facts.json` for a Gradle project via the bundled init script.
6463
+ // Generates `gradle.socket.facts.json` for a Gradle project via the bundled
6464
+ // init script.
6389
6465
  async function convertGradleToFacts({
6390
6466
  bin,
6391
6467
  cwd,
@@ -6415,7 +6491,8 @@ async function convertGradleToFacts({
6415
6491
  });
6416
6492
  }
6417
6493
 
6418
- // Generates `.socket.facts.json` for a Maven project via the bundled extension.
6494
+ // Generates `pom.xml.socket.facts.json` (named after the POM Maven runs on)
6495
+ // for a Maven project via the bundled extension.
6419
6496
  async function convertMavenToFacts({
6420
6497
  bin,
6421
6498
  cwd,
@@ -6445,7 +6522,7 @@ async function convertMavenToFacts({
6445
6522
  });
6446
6523
  }
6447
6524
 
6448
- // Generates `.socket.facts.json` for an sbt project via the bundled sbt plugin.
6525
+ // Generates `sbt.socket.facts.json` for an sbt project via the bundled sbt plugin.
6449
6526
  // sbt 0.13/early 1.x can't run on modern JDKs — pass a compatible JDK via
6450
6527
  // `--sbt-opts "--java-home <path>"` or `JAVA_HOME`.
6451
6528
  async function convertSbtToFacts({
@@ -7342,12 +7419,12 @@ async function createNewScan({
7342
7419
  logger.logger.success('Reachability analysis completed successfully');
7343
7420
  reachabilityReport = reachResult.data?.reachabilityReport;
7344
7421
 
7345
- // When using only pre-generated SBOMs, build the scan from those inputs —
7346
- // CycloneDX, SPDX, and Socket facts — matching Coana's
7347
- // `--use-only-pregenerated-sboms` selection. Otherwise drop every facts
7348
- // file; coana's fresh reachability report (appended below) is the
7349
- // authoritative facts file for the scan.
7350
- const pathsForScan = reach.reachUseOnlyPregeneratedSboms ? filterToPregeneratedSboms(packagePaths, supportedFiles) : packagePaths.filter(p => !utils.isSocketFactsFile(p));
7422
+ // Mirror the SBOM inputs Coana analyzed; otherwise its fresh report
7423
+ // (appended below) supersedes every facts file.
7424
+ const pathsForScan = reach.reachUseOnlyPregeneratedSboms ? filterToPregeneratedSboms(packagePaths, supportedFiles).filter(p => !utils.isReachabilityReportPath(p, {
7425
+ cwd,
7426
+ outputPath: constants.default.DOT_SOCKET_DOT_FACTS_JSON
7427
+ })) : packagePaths.filter(p => !utils.isSocketFactsFile(p));
7351
7428
 
7352
7429
  // Append coana's reachability report, but not twice: a pre-generated facts
7353
7430
  // input can resolve to the same path coana wrote its report to.
@@ -7396,17 +7473,8 @@ async function createNewScan({
7396
7473
  logger.logger.warn('Reachability analysis ran but no full application reachability scan ID was found; skipping reachability finalize. The scan was created but its reachability report was not linked.');
7397
7474
  }
7398
7475
 
7399
- // On a successful scan, clean up the `.socket.facts.json` coana wrote at
7400
- // the path we instructed it to write to (via `--socket-mode`). Failed
7401
- // scans leave the file in place for debugging. Producer-written files
7402
- // (e.g. from `socket manifest gradle --facts`) are NOT touched here —
7403
- // those are user-owned input that the user can clean up themselves; in
7404
- // the --reach path coana overwrites that file with its enriched output
7405
- // anyway, so it's the same path that gets removed. `--reach-retain-facts-file`
7406
- // opts out of this cleanup so the report can be inspected; the user is then
7407
- // responsible for deleting it before the next full application reachability
7408
- // scan (a stale file is picked up as pre-generated input and would make those
7409
- // results unreliable).
7476
+ // A scan without --reach would upload a leftover report as an SBOM with
7477
+ // stale reachability results; a failed scan keeps it for debugging.
7410
7478
  if (fullScanCResult.ok && scanId && reachabilityReport && !reach.reachRetainFactsFile) {
7411
7479
  try {
7412
7480
  await fs.unlink(path.resolve(cwd, reachabilityReport));
@@ -8844,49 +8912,75 @@ async function getFixEnv() {
8844
8912
  };
8845
8913
  }
8846
8914
 
8847
- // Backed up so each fix attempt sees the pre-fix build after `git clean`.
8848
- async function generateSocketFactsForFix({
8849
- cwd,
8850
- excludePaths,
8851
- tmpDir
8852
- }) {
8853
- const {
8854
- factsPaths,
8855
- resolvedPathsSidecar
8856
- } = await runDynamicSbomInference({
8857
- cwd,
8858
- excludePaths,
8859
- sbtTmpDir: undefined,
8860
- sidecar: true,
8861
- withFiles: false
8915
+ async function backUp(sources, dir) {
8916
+ await fs.mkdir(dir, {
8917
+ recursive: true
8862
8918
  });
8863
- const sidecarFile = resolvedPathsSidecar ? path.join(tmpDir, 'sidecar.json') : undefined;
8864
- if (sidecarFile) {
8865
- await fs.writeFile(sidecarFile, JSON.stringify(resolvedPathsSidecar));
8866
- }
8867
- const paths = factsPaths.map(p => path.resolve(cwd, p));
8868
- const backups = await Promise.all(paths.map(async (source, index) => {
8869
- const backup = path.join(tmpDir, `${index}.json`);
8919
+ return await Promise.all(sources.map(async (source, index) => {
8920
+ const backup = path.join(dir, `${index}.json`);
8870
8921
  await fs.copyFile(source, backup);
8871
8922
  return {
8872
8923
  backup,
8873
8924
  source
8874
8925
  };
8875
8926
  }));
8927
+ }
8928
+ async function restoreAll(backups) {
8929
+ await Promise.all(backups.map(({
8930
+ backup,
8931
+ source
8932
+ }) => fs.copyFile(backup, source)));
8933
+ }
8934
+
8935
+ // Backed up so each fix attempt sees the pre-fix build after `git clean`, and
8936
+ // facts files already present are left as they were found.
8937
+ async function generateSocketFactsForFix({
8938
+ cwd,
8939
+ excludePaths,
8940
+ findFactsPaths,
8941
+ tmpDir
8942
+ }) {
8943
+ const existingPaths = await findFactsPaths();
8944
+ const originals = await backUp(existingPaths, path.join(tmpDir, 'existing'));
8945
+ const existing = new Set(existingPaths);
8946
+ const reset = async written => {
8947
+ await Promise.all(written.filter(p => !existing.has(p)).map(p => fs.rm(p, {
8948
+ force: true
8949
+ })));
8950
+ await restoreAll(originals);
8951
+ };
8952
+ let paths;
8953
+ let sidecarFile;
8954
+ try {
8955
+ const {
8956
+ factsPaths,
8957
+ resolvedPathsSidecar
8958
+ } = await runDynamicSbomInference({
8959
+ cwd,
8960
+ excludePaths,
8961
+ sbtTmpDir: undefined,
8962
+ sidecar: true,
8963
+ withFiles: false
8964
+ });
8965
+ paths = factsPaths.map(p => path.resolve(cwd, p));
8966
+ if (resolvedPathsSidecar) {
8967
+ sidecarFile = path.join(tmpDir, 'sidecar.json');
8968
+ await fs.writeFile(sidecarFile, JSON.stringify(resolvedPathsSidecar));
8969
+ }
8970
+ } catch (e) {
8971
+ // A failed build root aborts inference after others wrote their facts.
8972
+ await reset(await findFactsPaths());
8973
+ throw e;
8974
+ }
8975
+ const generated = new Set(paths);
8976
+ const backups = [...originals.filter(({
8977
+ source
8978
+ }) => !generated.has(source)), ...(await backUp(paths, path.join(tmpDir, 'generated')))];
8876
8979
  return {
8877
8980
  paths,
8878
8981
  sidecarFile,
8879
- async remove() {
8880
- await Promise.all(paths.map(p => fs.rm(p, {
8881
- force: true
8882
- })));
8883
- },
8884
- async restore() {
8885
- await Promise.all(backups.map(({
8886
- backup,
8887
- source
8888
- }) => fs.copyFile(backup, source)));
8889
- }
8982
+ remove: () => reset(paths),
8983
+ restore: () => restoreAll(backups)
8890
8984
  };
8891
8985
  }
8892
8986
 
@@ -9097,51 +9191,36 @@ async function coanaFixWithFacts(fixConfig, factsSlot) {
9097
9191
  // sibling manifest's references). --exclude stays separate as a hidden
9098
9192
  // legacy escape hatch for the narrower "fix-application only" semantic.
9099
9193
  const coanaExcludePatterns = [...exclude, ...excludePaths];
9100
- const findScanFilepaths = () => utils.getPackageFilesForScan(['.'], supportedFiles, {
9194
+ const findScanFilepaths = async () => (await utils.getPackageFilesForScan(['.'], supportedFiles, {
9101
9195
  additionalIgnores,
9102
9196
  config: socketConfig,
9103
9197
  cwd
9104
- });
9198
+ })).filter(p => !utils.isReachabilityReportPath(p, {
9199
+ cwd,
9200
+ outputPath: constants.DOT_SOCKET_DOT_FACTS_JSON
9201
+ }));
9105
9202
  const scanFilepaths = await findScanFilepaths();
9106
- // Facts files are analysis artifacts and must be removed before re-running fix.
9107
- const factsFiles = scanFilepaths.filter(utils.isSocketFactsFile);
9108
- if (factsFiles.length) {
9109
- if (!silence) {
9110
- spinner?.stop();
9111
- }
9112
- return {
9113
- ok: false,
9114
- message: 'Found Socket facts files in manifest files',
9115
- cause: `Delete the following ${words.pluralize('file', factsFiles.length)} before running socket fix again:\n` + factsFiles.map(p => ` - ${p}`).join('\n')
9116
- };
9117
- }
9118
9203
  if (factsSlot) {
9119
9204
  if (!silence) {
9120
9205
  spinner?.stop();
9121
9206
  logger.logger.info('Generating Socket facts for Gradle, sbt and Maven builds ...');
9122
9207
  }
9123
- try {
9124
- factsSlot.generated = await generateSocketFactsForFix({
9125
- cwd,
9126
- excludePaths,
9127
- tmpDir: factsSlot.tmpDir
9128
- });
9129
- } catch (e) {
9130
- // A failed build root aborts inference after others wrote their facts.
9131
- const partial = (await findScanFilepaths()).filter(utils.isSocketFactsFile);
9132
- await Promise.all(partial.map(p => fs$1.promises.rm(p, {
9133
- force: true
9134
- })));
9135
- throw e;
9136
- }
9137
- scanFilepaths.push(...factsSlot.generated.paths);
9208
+ factsSlot.generated = await generateSocketFactsForFix({
9209
+ cwd,
9210
+ excludePaths,
9211
+ findFactsPaths: async () => (await findScanFilepaths()).filter(utils.isSocketFactsFile),
9212
+ tmpDir: factsSlot.tmpDir
9213
+ });
9214
+ const known = new Set(scanFilepaths);
9215
+ scanFilepaths.push(...factsSlot.generated.paths.filter(p => !known.has(p)));
9138
9216
  if (!silence) {
9139
9217
  spinner?.start();
9140
9218
  }
9141
9219
  }
9142
9220
  const sidecarFile = factsSlot?.generated?.sidecarFile;
9143
- // Discovery only needs which artifacts the facts files resolve; applying
9144
- // fixes also needs each project's exact classpath from the sidecar.
9221
+ // Discovery only needs which artifacts the facts files resolve. Applying
9222
+ // fixes reads each project's tree; a Coana predating facts trees can only
9223
+ // tell from the sidecar's classpaths which projects resolve an artifact.
9145
9224
  const discoveryFlags = factsSlot ? ['--maven-use-only-socket-facts'] : [];
9146
9225
  const factsFlags = [...discoveryFlags, ...(sidecarFile ? ['--compute-artifacts-sidecar', sidecarFile] : [])];
9147
9226
  const uploadCResult = await utils.handleApiCall(sockSdk.uploadManifestFiles(orgSlug, scanFilepaths, {
@@ -9897,7 +9976,7 @@ const reachabilityFlags = {
9897
9976
  reachRetainFactsFile: {
9898
9977
  type: 'boolean',
9899
9978
  default: false,
9900
- description: 'Keep the `.socket.facts.json` reachability report that the analysis writes to the scan directory instead of deleting it after a successful scan. IMPORTANT: you must delete this file before running a fresh full application reachability scan. A stale `.socket.facts.json` left in place is picked up as a pre-generated input and silently overrides fresh analysis, so the new scan results will not be reliable.'
9979
+ description: 'Keep the `.socket.facts.json` reachability report that the analysis writes to the scan directory instead of deleting it after a successful scan. Delete it once inspected: later reachability scans ignore it, but a scan without --reach uploads it as an SBOM carrying stale reachability results.'
9901
9980
  },
9902
9981
  reachSkipCache: {
9903
9982
  type: 'boolean',
@@ -12904,7 +12983,10 @@ const config$d = {
12904
12983
  $ ${command} [options] [CWD=.]
12905
12984
 
12906
12985
  Recursively walks CWD, discovers independent gradle, sbt, and maven build
12907
- roots, and generates a Socket facts SBOM (.socket.facts.json) for each,
12986
+ roots, and generates a Socket facts SBOM for each
12987
+ (pom.xml.socket.facts.json, gradle.socket.facts.json, or
12988
+ sbt.socket.facts.json, so builds sharing a directory never overwrite each
12989
+ other),
12908
12990
  skipping subproject/reactor-module directories a parent build root already
12909
12991
  covers. Unlike \`socket manifest auto\`, this looks beyond CWD itself.
12910
12992
 
@@ -12993,11 +13075,11 @@ const config$c = {
12993
13075
  },
12994
13076
  facts: {
12995
13077
  type: 'boolean',
12996
- description: 'Emit a Socket facts JSON file (`.socket.facts.json`) describing the resolved dependency graph. This is the default; pass `--pom` to generate `pom.xml` files instead'
13078
+ description: 'Emit a Socket facts JSON file (`gradle.socket.facts.json`) describing the resolved dependency graph. This is the default; pass `--pom` to generate `pom.xml` files instead'
12997
13079
  },
12998
13080
  pom: {
12999
13081
  type: 'boolean',
13000
- description: 'Generate `pom.xml` manifest file(s) instead of the default Socket facts file (`.socket.facts.json`)'
13082
+ description: 'Generate `pom.xml` manifest file(s) instead of the default Socket facts file (`gradle.socket.facts.json`)'
13001
13083
  },
13002
13084
  includeConfigs: {
13003
13085
  type: 'string',
@@ -13028,9 +13110,9 @@ const config$c = {
13028
13110
  Options
13029
13111
  ${utils.getFlagListOutput(config.flags)}
13030
13112
 
13031
- By default, emits a single \`.socket.facts.json\` describing the resolved
13032
- dependency graph of the whole build, using gradle (preferably your local
13033
- \`gradlew\`). An unresolved dependency is a fatal error. You can pass
13113
+ By default, emits a single \`gradle.socket.facts.json\` describing the
13114
+ resolved dependency graph of the whole build, using gradle (preferably your
13115
+ local \`gradlew\`). An unresolved dependency is a fatal error. You can pass
13034
13116
  --include-configs / --exclude-configs (comma-separated glob patterns) to
13035
13117
  control which configurations are resolved (e.g.
13036
13118
  --include-configs=\`*CompileClasspath,*RuntimeClasspath\`), and
@@ -13247,11 +13329,11 @@ const config$b = {
13247
13329
  },
13248
13330
  facts: {
13249
13331
  type: 'boolean',
13250
- description: 'Emit a Socket facts JSON file (`.socket.facts.json`) describing the resolved dependency graph. This is the default; pass `--pom` to generate `pom.xml` files instead'
13332
+ description: 'Emit a Socket facts JSON file (`gradle.socket.facts.json`) describing the resolved dependency graph. This is the default; pass `--pom` to generate `pom.xml` files instead'
13251
13333
  },
13252
13334
  pom: {
13253
13335
  type: 'boolean',
13254
- description: 'Generate `pom.xml` manifest file(s) instead of the default Socket facts file (`.socket.facts.json`)'
13336
+ description: 'Generate `pom.xml` manifest file(s) instead of the default Socket facts file (`gradle.socket.facts.json`)'
13255
13337
  },
13256
13338
  includeConfigs: {
13257
13339
  type: 'string',
@@ -13282,9 +13364,9 @@ const config$b = {
13282
13364
  Options
13283
13365
  ${utils.getFlagListOutput(config.flags)}
13284
13366
 
13285
- By default, emits a single \`.socket.facts.json\` describing the resolved
13286
- dependency graph of the whole build, using gradle (preferably your local
13287
- \`gradlew\`). An unresolved dependency is a fatal error. You can pass
13367
+ By default, emits a single \`gradle.socket.facts.json\` describing the
13368
+ resolved dependency graph of the whole build, using gradle (preferably your
13369
+ local \`gradlew\`). An unresolved dependency is a fatal error. You can pass
13288
13370
  --include-configs / --exclude-configs (comma-separated glob patterns) to
13289
13371
  control which configurations are resolved (e.g.
13290
13372
  --include-configs=\`*CompileClasspath,*RuntimeClasspath\`), and
@@ -13521,8 +13603,8 @@ const config$a = {
13521
13603
  Options
13522
13604
  ${utils.getFlagListOutput(config.flags)}
13523
13605
 
13524
- Emits a single \`.socket.facts.json\` describing the resolved dependency
13525
- graph of your Maven project, using maven (\`mvn\` on PATH by default). It
13606
+ Emits a single \`pom.xml.socket.facts.json\` (named after the POM Maven
13607
+ runs on) describing the resolved dependency graph of your Maven project, using maven (\`mvn\` on PATH by default). It
13526
13608
  reads dependency metadata only and never downloads artifacts; an unresolved
13527
13609
  dependency is a fatal error. You can pass --include-configs /
13528
13610
  --exclude-configs (comma-separated glob patterns) to control which Maven
@@ -13685,11 +13767,11 @@ const config$9 = {
13685
13767
  },
13686
13768
  facts: {
13687
13769
  type: 'boolean',
13688
- description: 'Emit a Socket facts JSON file (`.socket.facts.json`) describing the resolved dependency graph. This is the default; pass `--pom` to generate `pom.xml` files instead'
13770
+ description: 'Emit a Socket facts JSON file (`sbt.socket.facts.json`) describing the resolved dependency graph. This is the default; pass `--pom` to generate `pom.xml` files instead'
13689
13771
  },
13690
13772
  pom: {
13691
13773
  type: 'boolean',
13692
- description: 'Generate `pom.xml` manifest file(s) instead of the default Socket facts file (`.socket.facts.json`)'
13774
+ description: 'Generate `pom.xml` manifest file(s) instead of the default Socket facts file (`sbt.socket.facts.json`)'
13693
13775
  },
13694
13776
  includeConfigs: {
13695
13777
  type: 'string',
@@ -13706,7 +13788,7 @@ const config$9 = {
13706
13788
  },
13707
13789
  out: {
13708
13790
  type: 'string',
13709
- description: 'Only with --pom: path of the output `pom.xml`, see also --stdout. Does not apply when generating Socket facts (always written to the project root as `.socket.facts.json`)'
13791
+ description: 'Only with --pom: path of the output `pom.xml`, see also --stdout. Does not apply when generating Socket facts (always written to the project root as `sbt.socket.facts.json`)'
13710
13792
  },
13711
13793
  stdout: {
13712
13794
  type: 'boolean',
@@ -13728,8 +13810,8 @@ const config$9 = {
13728
13810
  Options
13729
13811
  ${utils.getFlagListOutput(config.flags)}
13730
13812
 
13731
- By default, emits a single \`.socket.facts.json\` describing the resolved
13732
- dependency graph of the whole build. It reads dependency metadata only and
13813
+ By default, emits a single \`sbt.socket.facts.json\` describing the
13814
+ resolved dependency graph of the whole build. It reads dependency metadata only and
13733
13815
  never downloads artifacts; an unresolved dependency is a fatal error. You
13734
13816
  can pass --include-configs / --exclude-configs (comma-separated glob
13735
13817
  patterns) to control which sbt configurations are resolved (e.g.
@@ -13910,7 +13992,7 @@ async function run$A(argv, importMeta, {
13910
13992
  // would the file name be?
13911
13993
 
13912
13994
  // --out / --stdout only affect the pom path. Socket facts are always written
13913
- // to the project root as `.socket.facts.json` so that `socket scan create`
13995
+ // to the project root as `sbt.socket.facts.json` so that `socket scan create`
13914
13996
  // picks them up, so reject these flags in facts mode rather than silently
13915
13997
  // ignoring an explicitly-passed output location.
13916
13998
  const wasValidInput = utils.checkCommandInput(outputKind, {
@@ -13921,7 +14003,7 @@ async function run$A(argv, importMeta, {
13921
14003
  }, {
13922
14004
  nook: true,
13923
14005
  test: !(facts && (cli.flags['out'] !== undefined || cli.flags['stdout'] !== undefined)),
13924
- message: 'The `--out` and `--stdout` options only apply with `--pom`; Socket facts are always written to the project root as `.socket.facts.json`',
14006
+ message: 'The `--out` and `--stdout` options only apply with `--pom`; Socket facts are always written to the project root as `sbt.socket.facts.json`',
13925
14007
  fail: 'remove --out/--stdout, or pass --pom'
13926
14008
  });
13927
14009
  if (!wasValidInput) {
@@ -14514,7 +14596,7 @@ async function askForFactsFlag(current) {
14514
14596
  choices: [{
14515
14597
  name: 'Socket facts (default)',
14516
14598
  value: 'yes',
14517
- description: 'Generate a .socket.facts.json file describing the resolved dependency graph'
14599
+ description: 'Generate a Socket facts file (*.socket.facts.json) describing the resolved dependency graph'
14518
14600
  }, {
14519
14601
  name: 'pom.xml',
14520
14602
  value: 'no',
@@ -24478,5 +24560,5 @@ process.on('unhandledRejection', async (reason, promise) => {
24478
24560
  // eslint-disable-next-line n/no-process-exit
24479
24561
  process.exit(1);
24480
24562
  });
24481
- //# debugId=40113ed0-ae58-43eb-a197-d1810801160e
24563
+ //# debugId=e5b43908-d002-4c63-b2f7-4c7336aacdb4
24482
24564
  //# sourceMappingURL=cli.js.map