socket 1.1.113 → 1.1.115

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/dist/cli.js CHANGED
@@ -3738,343 +3738,151 @@ async function extractBazelToMaven(opts) {
3738
3738
  }
3739
3739
  }
3740
3740
 
3741
- async function convertGradleToFacts({
3741
+ // Delegates Socket facts generation for a JVM build tool to the Coana CLI's
3742
+ // `manifest <ecosystem>` command. The build-tool resolution scripts (the Gradle
3743
+ // init script and the sbt plugin) live in Coana now, so socket-cli no longer
3744
+ // runs them itself; it only asks Coana for the uploadable `.socket.facts.json`.
3745
+ //
3746
+ // The resolved artifact-paths sidecar is intentionally NOT requested here: it
3747
+ // only matters for reachability analysis, which is internal to Coana, so Coana
3748
+ // emits it itself when it runs reachability. `socket manifest` only needs the
3749
+ // facts file.
3750
+ //
3751
+ // `spawnCoanaDlx` resolves the Coana CLI via dlx (or a local build when
3752
+ // `SOCKET_CLI_COANA_LOCAL_PATH` is set). `bin` (the gradle/sbt executable) is
3753
+ // always resolved by the caller to a concrete default (`<cwd>/gradlew`, or
3754
+ // `sbt` on PATH) before we get here, so it is forwarded verbatim; the empty
3755
+ // guard below is just a cheap safeguard against passing `--bin ''`.
3756
+ async function runCoanaManifestFacts({
3742
3757
  bin,
3743
- configs,
3758
+ buildOpts,
3759
+ buildOptsFlag,
3744
3760
  cwd,
3745
- gradleOpts,
3761
+ ecosystem,
3762
+ excludeConfigs,
3746
3763
  ignoreUnresolved,
3764
+ includeConfigs,
3747
3765
  verbose
3748
3766
  }) {
3749
- const rBin = path.resolve(cwd, bin);
3750
- const binExists = fs$1.existsSync(rBin);
3751
- const cwdExists = fs$1.existsSync(cwd);
3752
- logger.logger.group('gradle2facts:');
3753
- logger.logger.info(`- executing: \`${rBin}\``);
3754
- if (!binExists) {
3755
- logger.logger.warn(`Warning: It appears the executable could not be found. An error might be printed later because of that.`);
3767
+ // Pin the facts output location explicitly rather than relying on Coana's
3768
+ // "project root" default. `factsPath` is then the single source of truth for
3769
+ // both what we tell Coana to write and what we verify exists below, so the
3770
+ // two can't drift apart if Coana's default ever changes. This is deliberately
3771
+ // NOT user-configurable: Socket facts always land in the project root so that
3772
+ // `socket scan create <project>` finds them (see cmd-manifest-scala.mts, which
3773
+ // rejects --out/--stdout in facts mode).
3774
+ const factsDir = cwd;
3775
+ const factsFile = constants.default.DOT_SOCKET_DOT_FACTS_JSON;
3776
+ const factsPath = path.join(factsDir, factsFile);
3777
+ // `coana manifest <ecosystem> <path>` emits `.socket.facts.json` by default;
3778
+ // there is no `--facts` flag (the artifact-paths sidecar is reachability-
3779
+ // internal and not requested here).
3780
+ const coanaArgs = ['manifest', ecosystem, cwd, '--output-dir', factsDir, '--output-file', factsFile];
3781
+ if (bin) {
3782
+ coanaArgs.push('--bin', bin);
3783
+ }
3784
+ if (includeConfigs) {
3785
+ coanaArgs.push('--include-configs', includeConfigs);
3786
+ }
3787
+ if (excludeConfigs) {
3788
+ coanaArgs.push('--exclude-configs', excludeConfigs);
3789
+ }
3790
+ if (ignoreUnresolved) {
3791
+ coanaArgs.push('--ignore-unresolved');
3756
3792
  }
3757
- logger.logger.info(`- src dir: \`${cwd}\``);
3758
- if (!cwdExists) {
3759
- logger.logger.warn(`Warning: It appears the src dir could not be found. An error might be printed later because of that.`);
3793
+ if (verbose) {
3794
+ coanaArgs.push('--debug');
3760
3795
  }
3761
- logger.logger.groupEnd();
3762
- try {
3763
- // The init script is bundled alongside the existing pom-generating one.
3764
- // See .config/rollup.dist.config.mjs:copySocketFactsInitGradle.
3765
- const initLocation = path.join(constants.default.distPath, 'socket-facts.init.gradle');
3766
- // Disable Gradle's configuration cache for the facts run. The init
3767
- // script resolves dependencies via the legacy
3768
- // `Configuration.resolvedConfiguration` API (the only public API that
3769
- // surfaces classifier + extension metadata) and registers per-
3770
- // subproject tasks that share a `gradle.ext` accumulator — neither
3771
- // pattern is compatible with the configuration cache, which would
3772
- // otherwise be on by default for projects with
3773
- // `org.gradle.configuration-cache=true` in `gradle.properties`. The
3774
- // Provider-based CC-safe alternatives (`ResolutionResult` /
3775
- // `ArtifactView.resolvedArtifacts`) only exist in Gradle 7.4+ and
3776
- // they don't expose classifier/extension, so they aren't a usable
3777
- // replacement here. Using `-D` rather than `--no-configuration-cache`
3778
- // keeps us compatible with older Gradle versions that don't recognize
3779
- // the flag — the system property is silently ignored when the
3780
- // feature doesn't exist.
3781
- // Both knobs are passed as Gradle project properties so the init script
3782
- // can read them via `rp.findProperty(...)`, matching how
3783
- // `socket.outputDirectory` / `socket.outputFile` are already wired.
3784
- const socketProps = [];
3785
- if (ignoreUnresolved) {
3786
- socketProps.push('-Psocket.ignoreUnresolved=true');
3787
- }
3788
- if (configs) {
3789
- socketProps.push(`-Psocket.configs=${configs}`);
3790
- }
3791
- const commandArgs = ['-Dorg.gradle.configuration-cache=false', ...socketProps, '--init-script', initLocation, ...gradleOpts, 'socketFacts'];
3792
- if (verbose) {
3793
- logger.logger.log('[VERBOSE] Executing:', [bin], ', args:', commandArgs);
3794
- }
3795
- logger.logger.log(`Generating Socket facts from \`${bin}\` on \`${cwd}\` ...`);
3796
- const output = await execGradle$1(rBin, commandArgs, cwd, verbose);
3797
- if (output.code) {
3798
- process.exitCode = 1;
3799
- logger.logger.fail(`Gradle exited with exit code ${output.code}`);
3800
- if (!verbose) {
3801
- logger.logger.group('stderr:');
3802
- logger.logger.error(output.stderr);
3803
- logger.logger.groupEnd();
3804
- }
3805
- return;
3806
- }
3807
- logger.logger.success('Executed gradle successfully');
3808
- if (verbose) {
3809
- // Output already streamed; the "Reported exports:" summary lines were
3810
- // visible inline. No need to repeat them from a captured stdout.
3811
- logger.logger.log('');
3812
- logger.logger.log('Next step is to generate a Scan by running the `socket scan create` command on the same directory.');
3813
- return;
3814
- }
3815
- const exports = Array.from(output.stdout.matchAll(/^Socket facts file written to: (.*)/gm), m => m[1]);
3816
- if (exports.length) {
3817
- logger.logger.log('Reported exports:');
3818
- for (const fn of exports) {
3819
- logger.logger.log('- ', fn);
3820
- }
3821
- } else {
3822
- // Gradle script may have skipped emission when no resolvable
3823
- // dependencies were found (see the `components.isEmpty()` branch in
3824
- // socket-facts.init.gradle). Surface the skip reason if present so
3825
- // the user understands why nothing was written.
3826
- const skipMatch = output.stdout.match(/^\[socket-facts\] no resolvable dependencies.*/m);
3827
- if (skipMatch) {
3828
- logger.logger.warn(skipMatch[0]);
3829
- }
3830
- }
3831
- logger.logger.log('');
3832
- logger.logger.log('Next step is to generate a Scan by running the `socket scan create` command on the same directory.');
3833
- } catch (e) {
3834
- process.exitCode = 1;
3835
- logger.logger.fail('There was an unexpected error while generating Socket facts' + (verbose ? '' : ' (use --verbose for details)'));
3836
- if (verbose) {
3837
- logger.logger.group('[VERBOSE] error:');
3838
- logger.logger.log(e);
3839
- logger.logger.groupEnd();
3840
- }
3796
+ // `--gradle-opts` / `--sbt-opts` are variadic on the Coana side; keep them
3797
+ // last so the pass-through values don't swallow any following flags.
3798
+ if (buildOpts.length) {
3799
+ coanaArgs.push(buildOptsFlag, ...buildOpts);
3841
3800
  }
3842
- }
3843
- async function execGradle$1(bin, commandArgs, cwd, verbose) {
3844
- // When verbose, stream gradle stdout/stderr directly to the user's
3845
- // terminal — no spinner, no capture. The trade-off is that the post-run
3846
- // "Reported exports:" summary is skipped (the lines were already visible
3847
- // inline). For huge builds where the user wants to see progress, this is
3848
- // the right default. Non-verbose runs still get the spinner + summary.
3801
+ logger.logger.log(`Generating Socket facts for the ${ecosystem} project at \`${cwd}\` ...`);
3849
3802
  if (verbose) {
3850
- logger.logger.info('(Running gradle with output streaming. This can take a while.)');
3851
- const output = await spawn.spawn(bin, commandArgs, {
3852
- cwd,
3853
- stdio: 'inherit'
3854
- });
3855
- return {
3856
- code: output.code,
3857
- stdout: '',
3858
- stderr: ''
3859
- };
3803
+ logger.logger.log('[VERBOSE] coana args:', coanaArgs);
3860
3804
  }
3861
- const {
3862
- spinner
3863
- } = constants.default;
3864
- let pass = false;
3865
- try {
3866
- logger.logger.info('(Running gradle can take a while, depending on the size of the project)');
3867
- logger.logger.info('(No live output. Pass --verbose to stream gradle output instead.)');
3868
- spinner.start(`Running gradlew...`);
3869
- const output = await spawn.spawn(bin, commandArgs, {
3870
- cwd
3871
- });
3872
- pass = true;
3873
- const {
3874
- code,
3875
- stderr,
3876
- stdout
3877
- } = output;
3878
- return {
3879
- code,
3880
- stdout,
3881
- stderr
3882
- };
3883
- } finally {
3884
- if (pass) {
3885
- spinner.successAndStop('Gracefully completed gradlew execution.');
3886
- } else {
3887
- spinner.failAndStop('There was an error while trying to run gradlew.');
3888
- }
3805
+
3806
+ // Stream Coana's output so the user sees build-tool progress and Coana's own
3807
+ // "Socket facts file written to: ..." line.
3808
+ const result = await utils.spawnCoanaDlx(coanaArgs, undefined, {
3809
+ cwd
3810
+ }, {
3811
+ stdio: 'inherit'
3812
+ });
3813
+ if (!result.ok) {
3814
+ process.exitCode = 1;
3815
+ logger.logger.fail(result.message || 'Coana failed to generate Socket facts');
3816
+ return;
3889
3817
  }
3818
+ // A zero exit code doesn't guarantee a facts file was written: Coana skips
3819
+ // emitting it when there are no resolvable dependencies (e.g. with
3820
+ // --ignore-unresolved). We pinned the output to `factsPath` above, so confirm
3821
+ // it exists before claiming success; otherwise the "next step: socket scan
3822
+ // create" line would mislead.
3823
+ if (!fs$1.existsSync(factsPath)) {
3824
+ logger.logger.warn(`Coana completed but wrote no ${factsFile} (no resolvable dependencies?); nothing to upload.`);
3825
+ return;
3826
+ }
3827
+ logger.logger.success('Generated Socket facts');
3828
+ logger.logger.log('');
3829
+ logger.logger.log('Next step is to generate a Scan by running the `socket scan create` command on the same directory.');
3890
3830
  }
3891
3831
 
3892
- // Shown when the sbt launcher dies on a modern JDK. sbt 0.13 (and some early
3893
- // 1.x) install a SecurityManager, which JDK 18+ removed, so the launcher
3894
- // throws before our plugin runs. We don't pick a JDK for the user — they own
3895
- // their toolchain but we point them at the fix.
3896
- const JDK_HINT = 'Hint: old sbt (0.13.x and early 1.x) cannot run on modern JDKs because the Java Security Manager was removed in JDK 18+. Run with a compatible JDK by setting JAVA_HOME (e.g. Java 11) or passing `--sbt-opts "--java-home <path>"`.';
3897
-
3898
- // The socket-owned global base sbt compiles our plugin into. Living under the
3899
- // app data dir (not the user's `~/.sbt`) means we never mutate their sbt
3900
- // config, while persisting the compiled plugin between runs. sbt namespaces
3901
- // the compiled output by Scala/sbt version (`target/scala-2.10/sbt-0.13`,
3902
- // `target/scala-2.12/sbt-1.0`, ...), so a single base safely serves every sbt
3903
- // version with no version detection needed.
3904
- function resolveGlobalBase() {
3905
- const {
3906
- socketAppDataPath
3907
- } = constants.default;
3908
- return socketAppDataPath ? path.join(path.dirname(socketAppDataPath), 'sbt-facts') : path.join(os.tmpdir(), 'socket-sbt-facts');
3832
+ // Generates a `.socket.facts.json` for a Gradle project by delegating to the
3833
+ // Coana CLI's `manifest gradle` command (which owns the Gradle init script that
3834
+ // resolves the dependency graph). socket-cli no longer runs gradle itself; an
3835
+ // explicit `bin` is forwarded as `--bin`, otherwise Coana defaults to
3836
+ // `./gradlew`.
3837
+ async function convertGradleToFacts({
3838
+ bin,
3839
+ cwd,
3840
+ excludeConfigs,
3841
+ gradleOpts,
3842
+ ignoreUnresolved,
3843
+ includeConfigs,
3844
+ verbose
3845
+ }) {
3846
+ await runCoanaManifestFacts({
3847
+ bin,
3848
+ buildOpts: gradleOpts,
3849
+ buildOptsFlag: '--gradle-opts',
3850
+ cwd,
3851
+ ecosystem: 'gradle',
3852
+ excludeConfigs,
3853
+ ignoreUnresolved,
3854
+ includeConfigs,
3855
+ verbose
3856
+ });
3909
3857
  }
3910
3858
 
3911
- // Drop the shipped plugin source into `<globalBase>/plugins/`, rewriting only
3912
- // when its content changed so sbt's incremental compiler can reuse the cache.
3913
- async function ensurePluginSource(pluginSrcPath, pluginsDir) {
3914
- const source = await fs$1.promises.readFile(pluginSrcPath, 'utf8');
3915
- const destPath = path.join(pluginsDir, 'SocketFactsPlugin.scala');
3916
- let current;
3917
- if (fs$1.existsSync(destPath)) {
3918
- current = await fs$1.promises.readFile(destPath, 'utf8');
3919
- }
3920
- if (current !== source) {
3921
- await fs$1.promises.mkdir(pluginsDir, {
3922
- recursive: true
3923
- });
3924
- await fs$1.promises.writeFile(destPath, source, 'utf8');
3925
- }
3926
- }
3859
+ // Generates a `.socket.facts.json` for an sbt project by delegating to the
3860
+ // Coana CLI's `manifest sbt` command (which owns the sbt plugin that resolves
3861
+ // the dependency graph). socket-cli no longer runs sbt itself; an explicit
3862
+ // `bin` is forwarded as `--bin`, otherwise Coana defaults to `sbt` on PATH.
3863
+ // JDK-compatibility guidance (sbt 0.13/early 1.x cannot run on modern JDKs) is
3864
+ // handled by Coana; pass a compatible JDK via `--sbt-opts "--java-home <path>"`
3865
+ // or `JAVA_HOME`.
3927
3866
  async function convertSbtToFacts({
3928
3867
  bin,
3929
- configs,
3930
3868
  cwd,
3869
+ excludeConfigs,
3931
3870
  ignoreUnresolved,
3871
+ includeConfigs,
3932
3872
  sbtOpts,
3933
3873
  verbose
3934
3874
  }) {
3935
- logger.logger.group('sbt2facts:');
3936
- logger.logger.info(`- executing: \`${bin}\``);
3937
- logger.logger.info(`- src dir: \`${cwd}\``);
3938
- if (!fs$1.existsSync(cwd)) {
3939
- logger.logger.warn('Warning: It appears the src dir could not be found. An error might be printed later because of that.');
3940
- }
3941
- logger.logger.groupEnd();
3942
- try {
3943
- const pluginSrcPath = path.join(constants.default.distPath, 'socket-facts.plugin.scala');
3944
- const globalBase = resolveGlobalBase();
3945
- await ensurePluginSource(pluginSrcPath, path.join(globalBase, 'plugins'));
3946
-
3947
- // `-Dsbt.global.base` points sbt at our isolated plugins dir, so the
3948
- // source-only plugin activates without touching the user's `~/.sbt`. The
3949
- // resolution options are passed as JVM system properties the plugin reads.
3950
- const socketProps = [];
3951
- if (ignoreUnresolved) {
3952
- socketProps.push('-Dsocket.ignoreUnresolved=true');
3953
- }
3954
- if (configs) {
3955
- socketProps.push(`-Dsocket.configs=${configs}`);
3956
- }
3957
- const commandArgs = [`-Dsbt.global.base=${globalBase}`, ...socketProps, ...sbtOpts, '--batch', 'socketFacts'];
3958
- if (verbose) {
3959
- logger.logger.log('[VERBOSE] Executing:', [bin], ', args:', commandArgs);
3960
- }
3961
- logger.logger.log(`Generating Socket facts from \`${bin}\` on \`${cwd}\` ...`);
3962
- const output = await execSbt(bin, commandArgs, cwd, verbose);
3963
- if (output.code) {
3964
- process.exitCode = 1;
3965
- logger.logger.fail(`sbt exited with exit code ${output.code}`);
3966
- if (!verbose) {
3967
- const errorLines = extractErrorLines(output.stdout, output.stderr);
3968
- if (errorLines) {
3969
- logger.logger.group('sbt output:');
3970
- logger.logger.error(errorLines);
3971
- logger.logger.groupEnd();
3972
- }
3973
- }
3974
- if (/security ?manager/i.test(output.stdout + output.stderr)) {
3975
- logger.logger.warn(JDK_HINT);
3976
- }
3977
- return;
3978
- }
3979
- logger.logger.success('Executed sbt successfully');
3980
- if (verbose) {
3981
- // Output already streamed inline; nothing to re-summarize.
3982
- logger.logger.log('');
3983
- logger.logger.log('Next step is to generate a Scan by running the `socket scan create` command on the same directory.');
3984
- return;
3985
- }
3986
- // `spawn` already strips ANSI from captured output, and the plugin prints
3987
- // these lines bare (via println, no sbt `[info]` prefix), so plain line
3988
- // matching is stable.
3989
- const exports = [];
3990
- for (const m of output.stdout.matchAll(/Socket facts file written to: (.+)/g)) {
3991
- const reported = m[1]?.trim();
3992
- if (reported) {
3993
- exports.push(reported);
3994
- }
3995
- }
3996
- if (exports.length) {
3997
- logger.logger.log('Reported exports:');
3998
- for (const fn of exports) {
3999
- logger.logger.log('- ', fn);
4000
- }
4001
- } else {
4002
- // The plugin skips emission when the build has no resolvable deps.
4003
- const skipMatch = output.stdout.match(/\[socket-facts\] no resolvable dependencies.*/);
4004
- if (skipMatch) {
4005
- logger.logger.warn(skipMatch[0]);
4006
- }
4007
- }
4008
- logger.logger.log('');
4009
- logger.logger.log('Next step is to generate a Scan by running the `socket scan create` command on the same directory.');
4010
- } catch (e) {
4011
- process.exitCode = 1;
4012
- // A missing sbt launcher is the most common setup failure; surface it
4013
- // clearly instead of the generic message.
4014
- if (e instanceof Error && e.code === 'ENOENT') {
4015
- logger.logger.fail(`Could not run \`${bin}\`. Make sure sbt is installed and on your PATH, or pass --bin with the path to your sbt launcher.`);
4016
- } else {
4017
- logger.logger.fail('There was an unexpected error while generating Socket facts' + (verbose ? '' : ' (use --verbose for details)'));
4018
- }
4019
- if (verbose) {
4020
- logger.logger.group('[VERBOSE] error:');
4021
- logger.logger.log(e);
4022
- logger.logger.groupEnd();
4023
- }
4024
- }
4025
- }
4026
-
4027
- // Pull the actionable lines out of a noisy sbt run so a failure surfaces the
4028
- // plugin's own message (and sbt's `[error]` lines) without dumping the whole
4029
- // resolution log.
4030
- function extractErrorLines(stdout, stderr) {
4031
- return `${stdout}\n${stderr}`.split('\n').filter(line => /\[error]|Socket facts|could not resolve|unresolved/i.test(line)).join('\n').trim();
4032
- }
4033
- async function execSbt(bin, commandArgs, cwd, verbose) {
4034
- // When verbose, stream sbt output straight to the terminal so the user can
4035
- // watch resolution progress; otherwise show a spinner and capture output for
4036
- // the post-run summary.
4037
- if (verbose) {
4038
- logger.logger.info('(Running sbt with output streaming. This can take a while.)');
4039
- const output = await spawn.spawn(bin, commandArgs, {
4040
- cwd,
4041
- stdio: 'inherit'
4042
- });
4043
- return {
4044
- code: output.code,
4045
- stdout: '',
4046
- stderr: ''
4047
- };
4048
- }
4049
- const {
4050
- spinner
4051
- } = constants.default;
4052
- let pass = false;
4053
- try {
4054
- logger.logger.info('(Running sbt can take a while, depending on the size of the project)');
4055
- logger.logger.info('(No live output. Pass --verbose to stream sbt output instead.)');
4056
- spinner.start('Running sbt...');
4057
- const output = await spawn.spawn(bin, commandArgs, {
4058
- cwd
4059
- });
4060
- pass = true;
4061
- const {
4062
- code,
4063
- stderr,
4064
- stdout
4065
- } = output;
4066
- return {
4067
- code,
4068
- stdout,
4069
- stderr
4070
- };
4071
- } finally {
4072
- if (pass) {
4073
- spinner.successAndStop('Gracefully completed sbt execution.');
4074
- } else {
4075
- spinner.failAndStop('There was an error while trying to run sbt.');
4076
- }
4077
- }
3875
+ await runCoanaManifestFacts({
3876
+ bin,
3877
+ buildOpts: sbtOpts,
3878
+ buildOptsFlag: '--sbt-opts',
3879
+ cwd,
3880
+ ecosystem: 'sbt',
3881
+ excludeConfigs,
3882
+ ignoreUnresolved,
3883
+ includeConfigs,
3884
+ verbose
3885
+ });
4078
3886
  }
4079
3887
 
4080
3888
  async function convertGradleToMaven({
@@ -4534,9 +4342,9 @@ async function generateAutoManifest({
4534
4342
  logger.logger.info(`Using this ${constants.SOCKET_JSON} for defaults:`, sockJson);
4535
4343
  }
4536
4344
  if (!sockJson?.defaults?.manifest?.sbt?.disabled && detected.sbt) {
4537
- // Args shared by both paths. The facts-only knobs (`configs`,
4538
- // `ignoreUnresolved`) and the pom-only `out` are added per branch so
4539
- // neither handler is spread properties it doesn't accept.
4345
+ // Args shared by both paths. The facts-only knobs (`includeConfigs`,
4346
+ // `excludeConfigs`, `ignoreUnresolved`) and the pom-only `out` are added
4347
+ // per branch so neither handler is spread properties it doesn't accept.
4540
4348
  const sbtArgs = {
4541
4349
  // Note: `sbt` is more likely to be resolved against PATH env.
4542
4350
  bin: sockJson.defaults?.manifest?.sbt?.bin ?? 'sbt',
@@ -4544,12 +4352,15 @@ async function generateAutoManifest({
4544
4352
  sbtOpts: sockJson.defaults?.manifest?.sbt?.sbtOpts?.split(' ').map(s => s.trim()).filter(Boolean) ?? [],
4545
4353
  verbose: Boolean(sockJson.defaults?.manifest?.sbt?.verbose)
4546
4354
  };
4547
- if (sockJson.defaults?.manifest?.sbt?.facts) {
4355
+ // Socket facts is the default; opt into pom generation with
4356
+ // `defaults.manifest.sbt.facts: false` in socket.json.
4357
+ if (sockJson.defaults?.manifest?.sbt?.facts !== false) {
4548
4358
  logger.logger.log('Detected a Scala sbt build, generating Socket facts...');
4549
4359
  await convertSbtToFacts({
4550
4360
  ...sbtArgs,
4551
- configs: sockJson.defaults?.manifest?.sbt?.configs ?? '',
4552
- ignoreUnresolved: Boolean(sockJson.defaults?.manifest?.sbt?.ignoreUnresolved)
4361
+ excludeConfigs: sockJson.defaults?.manifest?.sbt?.excludeConfigs ?? '',
4362
+ ignoreUnresolved: Boolean(sockJson.defaults?.manifest?.sbt?.ignoreUnresolved),
4363
+ includeConfigs: sockJson.defaults?.manifest?.sbt?.includeConfigs ?? ''
4553
4364
  });
4554
4365
  } else {
4555
4366
  logger.logger.log('Detected a Scala sbt build, generating pom files with sbt...');
@@ -4569,12 +4380,15 @@ async function generateAutoManifest({
4569
4380
  verbose: Boolean(sockJson.defaults?.manifest?.gradle?.verbose),
4570
4381
  gradleOpts: sockJson.defaults?.manifest?.gradle?.gradleOpts?.split(' ').map(s => s.trim()).filter(Boolean) ?? []
4571
4382
  };
4572
- if (sockJson.defaults?.manifest?.gradle?.facts) {
4383
+ // Socket facts is the default; opt into pom generation with
4384
+ // `defaults.manifest.gradle.facts: false` in socket.json.
4385
+ if (sockJson.defaults?.manifest?.gradle?.facts !== false) {
4573
4386
  logger.logger.log('Detected a gradle build (Gradle, Kotlin, Scala), generating Socket facts...');
4574
4387
  await convertGradleToFacts({
4575
4388
  ...gradleArgs,
4576
- configs: sockJson.defaults?.manifest?.gradle?.configs ?? '',
4577
- ignoreUnresolved: Boolean(sockJson.defaults?.manifest?.gradle?.ignoreUnresolved)
4389
+ excludeConfigs: sockJson.defaults?.manifest?.gradle?.excludeConfigs ?? '',
4390
+ ignoreUnresolved: Boolean(sockJson.defaults?.manifest?.gradle?.ignoreUnresolved),
4391
+ includeConfigs: sockJson.defaults?.manifest?.gradle?.includeConfigs ?? ''
4578
4392
  });
4579
4393
  } else {
4580
4394
  logger.logger.log('Detected a gradle build (Gradle, Kotlin, Scala), running default gradle generator...');
@@ -9793,7 +9607,7 @@ async function run$D(argv, importMeta, {
9793
9607
 
9794
9608
  const config$b = {
9795
9609
  commandName: 'gradle',
9796
- description: '[beta] Use Gradle to generate a manifest file (`pom.xml`) for a Gradle/Java/Kotlin/etc project',
9610
+ description: '[beta] Generate a Socket facts file (or `pom.xml` with --pom) for a Gradle/Java/Kotlin/etc project',
9797
9611
  hidden: false,
9798
9612
  flags: {
9799
9613
  ...flags.commonFlags,
@@ -9803,15 +9617,23 @@ const config$b = {
9803
9617
  },
9804
9618
  facts: {
9805
9619
  type: 'boolean',
9806
- description: 'Emit a Socket facts JSON file (`.socket.facts.json`) describing the resolved dependency graph instead of generating `pom.xml` files'
9620
+ 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'
9621
+ },
9622
+ pom: {
9623
+ type: 'boolean',
9624
+ description: 'Generate `pom.xml` manifest file(s) instead of the default Socket facts file (`.socket.facts.json`)'
9625
+ },
9626
+ includeConfigs: {
9627
+ type: 'string',
9628
+ description: 'When generating facts: comma-separated glob patterns matched against Gradle configuration names (case-sensitive, `*` and `?` wildcards). Only configurations matching at least one pattern are resolved. e.g. `*CompileClasspath,*RuntimeClasspath`. Default: every resolvable configuration except AGP instrumented-test classpaths'
9807
9629
  },
9808
- configs: {
9630
+ excludeConfigs: {
9809
9631
  type: 'string',
9810
- description: 'With --facts: comma-separated glob patterns matched against Gradle configuration names (case-sensitive, `*` and `?` wildcards). e.g. `*CompileClasspath,*RuntimeClasspath` to skip tooling configs. Default: every resolvable configuration except AGP instrumented-test classpaths'
9632
+ description: 'When generating facts: comma-separated glob patterns; Gradle configurations matching any pattern are skipped (applied after --include-configs)'
9811
9633
  },
9812
9634
  ignoreUnresolved: {
9813
9635
  type: 'boolean',
9814
- description: 'With --facts: warn on unresolved dependencies instead of failing the run (unresolved deps are not emitted to the facts file)'
9636
+ description: 'When generating facts: warn on unresolved dependencies instead of failing the run (unresolved deps are not emitted to the facts file)'
9815
9637
  },
9816
9638
  gradleOpts: {
9817
9639
  type: 'string',
@@ -9829,38 +9651,32 @@ const config$b = {
9829
9651
  Options
9830
9652
  ${utils.getFlagListOutput(config.flags)}
9831
9653
 
9832
- Uses gradle, preferably through your local project \`gradlew\`, to generate a
9833
- \`pom.xml\` file for each task. If you have no \`gradlew\` you can try the
9834
- global \`gradle\` binary but that may not work (hard to predict).
9835
-
9836
- The \`pom.xml\` is a manifest file similar to \`package.json\` for npm or
9837
- or ${constants.REQUIREMENTS_TXT} for PyPi), but specifically for Maven, which is Java's
9838
- dependency repository. Languages like Kotlin and Scala piggy back on it too.
9654
+ By default, emits a single \`.socket.facts.json\` describing the resolved
9655
+ dependency graph of the whole build, using gradle (preferably your local
9656
+ \`gradlew\`). An unresolved dependency is a fatal error. You can pass
9657
+ --include-configs / --exclude-configs (comma-separated glob patterns) to
9658
+ control which configurations are resolved (e.g.
9659
+ --include-configs=\`*CompileClasspath,*RuntimeClasspath\`), and
9660
+ --ignore-unresolved to warn on unresolved dependencies instead of failing.
9839
9661
 
9840
- There are some caveats with the gradle to \`pom.xml\` conversion:
9662
+ Pass --pom to instead generate \`pom.xml\` manifest files via gradle (one per
9663
+ task). The \`pom.xml\` is a manifest file similar to \`package.json\` for npm
9664
+ (or ${constants.REQUIREMENTS_TXT} for PyPi), but specifically for Maven, which is
9665
+ Java's dependency repository. Caveats of the \`pom.xml\` conversion:
9841
9666
 
9842
- - each task will generate its own xml file and by default it generates one xml
9843
- for every task. (This may be a good thing!)
9667
+ - each task generates its own xml file (one per task by default)
9844
9668
 
9845
- - it's possible certain features don't translate well into the xml. If you
9846
- think something is missing that could be supported please reach out.
9669
+ - certain features may not translate well into the xml; reach out if
9670
+ something you need is missing
9847
9671
 
9848
9672
  - it works with your \`gradlew\` from your repo and local settings and config
9849
9673
 
9850
- Pass --facts to instead emit a single \`.socket.facts.json\` describing the
9851
- resolved dependency graph of the whole build (no \`pom.xml\` files). An
9852
- unresolved dependency is a fatal error. With --facts you can pass
9853
- --configs=<comma-separated glob patterns> to restrict resolution to
9854
- matching configurations (e.g. \`*CompileClasspath,*RuntimeClasspath\`),
9855
- and --ignore-unresolved to warn on unresolved dependencies instead of
9856
- failing the run.
9857
-
9858
9674
  Support is beta. Please report issues or give us feedback on what's missing.
9859
9675
 
9860
9676
  Examples
9861
9677
 
9862
9678
  $ ${command} .
9863
- $ ${command} --facts .
9679
+ $ ${command} --pom .
9864
9680
  $ ${command} --bin=../gradlew .
9865
9681
  `
9866
9682
  };
@@ -9894,10 +9710,11 @@ async function run$C(argv, importMeta, {
9894
9710
  require$$9.debugFn('inspect', `override: ${constants.SOCKET_JSON} gradle`, sockJson?.defaults?.manifest?.gradle);
9895
9711
  let {
9896
9712
  bin,
9897
- configs,
9713
+ excludeConfigs,
9898
9714
  facts,
9899
9715
  gradleOpts,
9900
9716
  ignoreUnresolved,
9717
+ includeConfigs,
9901
9718
  verbose
9902
9719
  } = cli.flags;
9903
9720
 
@@ -9930,16 +9747,34 @@ async function run$C(argv, importMeta, {
9930
9747
  if (sockJson.defaults?.manifest?.gradle?.facts !== undefined) {
9931
9748
  facts = sockJson.defaults?.manifest?.gradle?.facts;
9932
9749
  logger.logger.info(`Using default --facts from ${constants.SOCKET_JSON}:`, facts);
9750
+ } else {
9751
+ // Socket facts generation is the default; pass --pom to generate poms.
9752
+ facts = true;
9753
+ }
9754
+ }
9755
+ // --pom opts into legacy pom.xml generation. It overrides the facts default
9756
+ // (and the socket.json default) but conflicts with an explicit --facts.
9757
+ if (cli.flags['pom']) {
9758
+ if (cli.flags['facts'] !== undefined) {
9759
+ logger.logger.warn('The `--facts` and `--pom` options are mutually exclusive; generating Socket facts.');
9933
9760
  } else {
9934
9761
  facts = false;
9935
9762
  }
9936
9763
  }
9937
- if (configs === undefined) {
9938
- if (sockJson.defaults?.manifest?.gradle?.configs !== undefined) {
9939
- configs = sockJson.defaults?.manifest?.gradle?.configs;
9940
- logger.logger.info(`Using default --configs from ${constants.SOCKET_JSON}:`, configs);
9764
+ if (includeConfigs === undefined) {
9765
+ if (sockJson.defaults?.manifest?.gradle?.includeConfigs !== undefined) {
9766
+ includeConfigs = sockJson.defaults?.manifest?.gradle?.includeConfigs;
9767
+ logger.logger.info(`Using default --include-configs from ${constants.SOCKET_JSON}:`, includeConfigs);
9941
9768
  } else {
9942
- configs = '';
9769
+ includeConfigs = '';
9770
+ }
9771
+ }
9772
+ if (excludeConfigs === undefined) {
9773
+ if (sockJson.defaults?.manifest?.gradle?.excludeConfigs !== undefined) {
9774
+ excludeConfigs = sockJson.defaults?.manifest?.gradle?.excludeConfigs;
9775
+ logger.logger.info(`Using default --exclude-configs from ${constants.SOCKET_JSON}:`, excludeConfigs);
9776
+ } else {
9777
+ excludeConfigs = '';
9943
9778
  }
9944
9779
  }
9945
9780
  if (ignoreUnresolved === undefined) {
@@ -9951,13 +9786,12 @@ async function run$C(argv, importMeta, {
9951
9786
  }
9952
9787
  }
9953
9788
 
9954
- // `--configs` and `--ignore-unresolved` only affect --facts; the pom path
9955
- // (the legacy `socketGenerateMaven` task) has no equivalent knobs. Warn
9956
- // rather than silently ignore an explicitly-passed flag. (socket.json
9957
- // defaults don't trip this — only a flag actually present on the command
9958
- // line does.)
9959
- if (!facts && (cli.flags['configs'] !== undefined || cli.flags['ignoreUnresolved'] !== undefined)) {
9960
- logger.logger.warn('The `--configs` and `--ignore-unresolved` options only apply with `--facts`; ignoring them.');
9789
+ // `--include-configs`, `--exclude-configs`, and `--ignore-unresolved` only
9790
+ // affect facts generation; the pom path has no equivalent knobs. Warn rather
9791
+ // than silently ignore an explicitly-passed flag. (socket.json defaults don't
9792
+ // trip this — only a flag actually present on the command line does.)
9793
+ if (!facts && (cli.flags['includeConfigs'] !== undefined || cli.flags['excludeConfigs'] !== undefined || cli.flags['ignoreUnresolved'] !== undefined)) {
9794
+ logger.logger.warn('The `--include-configs`, `--exclude-configs`, and `--ignore-unresolved` options only apply when generating Socket facts (not with `--pom`); ignoring them.');
9961
9795
  }
9962
9796
  if (verbose) {
9963
9797
  logger.logger.group('- ', parentName, config$b.commandName, ':');
@@ -9994,10 +9828,11 @@ async function run$C(argv, importMeta, {
9994
9828
  if (facts) {
9995
9829
  await convertGradleToFacts({
9996
9830
  bin: String(bin),
9997
- configs: String(configs || ''),
9998
9831
  cwd,
9832
+ excludeConfigs: String(excludeConfigs || ''),
9999
9833
  gradleOpts: parsedGradleOpts,
10000
9834
  ignoreUnresolved: Boolean(ignoreUnresolved),
9835
+ includeConfigs: String(includeConfigs || ''),
10001
9836
  verbose: Boolean(verbose)
10002
9837
  });
10003
9838
  return;
@@ -10017,7 +9852,7 @@ async function run$C(argv, importMeta, {
10017
9852
  // command. Room for improvement.
10018
9853
  const config$a = {
10019
9854
  commandName: 'kotlin',
10020
- description: '[beta] Use Gradle to generate a manifest file (`pom.xml`) for a Kotlin project',
9855
+ description: '[beta] Generate a Socket facts file (or `pom.xml` with --pom) for a Kotlin project',
10021
9856
  hidden: false,
10022
9857
  flags: {
10023
9858
  ...flags.commonFlags,
@@ -10027,15 +9862,23 @@ const config$a = {
10027
9862
  },
10028
9863
  facts: {
10029
9864
  type: 'boolean',
10030
- description: 'Emit a Socket facts JSON file (`.socket.facts.json`) describing the resolved dependency graph instead of generating `pom.xml` files'
9865
+ 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'
9866
+ },
9867
+ pom: {
9868
+ type: 'boolean',
9869
+ description: 'Generate `pom.xml` manifest file(s) instead of the default Socket facts file (`.socket.facts.json`)'
10031
9870
  },
10032
- configs: {
9871
+ includeConfigs: {
10033
9872
  type: 'string',
10034
- description: 'With --facts: comma-separated glob patterns matched against Gradle configuration names (case-sensitive, `*` and `?` wildcards). e.g. `*CompileClasspath,*RuntimeClasspath` to skip tooling configs. Default: every resolvable configuration except AGP instrumented-test classpaths'
9873
+ description: 'When generating facts: comma-separated glob patterns matched against Gradle configuration names (case-sensitive, `*` and `?` wildcards). Only configurations matching at least one pattern are resolved. e.g. `*CompileClasspath,*RuntimeClasspath`. Default: every resolvable configuration except AGP instrumented-test classpaths'
9874
+ },
9875
+ excludeConfigs: {
9876
+ type: 'string',
9877
+ description: 'When generating facts: comma-separated glob patterns; Gradle configurations matching any pattern are skipped (applied after --include-configs)'
10035
9878
  },
10036
9879
  ignoreUnresolved: {
10037
9880
  type: 'boolean',
10038
- description: 'With --facts: warn on unresolved dependencies instead of failing the run (unresolved deps are not emitted to the facts file)'
9881
+ description: 'When generating facts: warn on unresolved dependencies instead of failing the run (unresolved deps are not emitted to the facts file)'
10039
9882
  },
10040
9883
  gradleOpts: {
10041
9884
  type: 'string',
@@ -10053,21 +9896,23 @@ const config$a = {
10053
9896
  Options
10054
9897
  ${utils.getFlagListOutput(config.flags)}
10055
9898
 
10056
- Uses gradle, preferably through your local project \`gradlew\`, to generate a
10057
- \`pom.xml\` file for each task. If you have no \`gradlew\` you can try the
10058
- global \`gradle\` binary but that may not work (hard to predict).
10059
-
10060
- The \`pom.xml\` is a manifest file similar to \`package.json\` for npm or
10061
- or ${constants.REQUIREMENTS_TXT} for PyPi), but specifically for Maven, which is Java's
10062
- dependency repository. Languages like Kotlin and Scala piggy back on it too.
9899
+ By default, emits a single \`.socket.facts.json\` describing the resolved
9900
+ dependency graph of the whole build, using gradle (preferably your local
9901
+ \`gradlew\`). An unresolved dependency is a fatal error. You can pass
9902
+ --include-configs / --exclude-configs (comma-separated glob patterns) to
9903
+ control which configurations are resolved (e.g.
9904
+ --include-configs=\`*CompileClasspath,*RuntimeClasspath\`), and
9905
+ --ignore-unresolved to warn on unresolved dependencies instead of failing.
10063
9906
 
10064
- There are some caveats with the gradle to \`pom.xml\` conversion:
9907
+ Pass --pom to instead generate \`pom.xml\` manifest files via gradle (one per
9908
+ task). The \`pom.xml\` is a manifest file similar to \`package.json\` for npm
9909
+ (or ${constants.REQUIREMENTS_TXT} for PyPi), but specifically for Maven, which is
9910
+ Java's dependency repository. Caveats of the \`pom.xml\` conversion:
10065
9911
 
10066
- - each task will generate its own xml file and by default it generates one xml
10067
- for every task. (This may be a good thing!)
9912
+ - each task generates its own xml file (one per task by default)
10068
9913
 
10069
- - it's possible certain features don't translate well into the xml. If you
10070
- think something is missing that could be supported please reach out.
9914
+ - certain features may not translate well into the xml; reach out if
9915
+ something you need is missing
10071
9916
 
10072
9917
  - it works with your \`gradlew\` from your repo and local settings and config
10073
9918
 
@@ -10076,6 +9921,7 @@ const config$a = {
10076
9921
  Examples
10077
9922
 
10078
9923
  $ ${command} .
9924
+ $ ${command} --pom .
10079
9925
  $ ${command} --bin=../gradlew .
10080
9926
  `
10081
9927
  };
@@ -10109,10 +9955,11 @@ async function run$B(argv, importMeta, {
10109
9955
  require$$9.debugFn('inspect', `override: ${constants.SOCKET_JSON} gradle`, sockJson?.defaults?.manifest?.gradle);
10110
9956
  let {
10111
9957
  bin,
10112
- configs,
9958
+ excludeConfigs,
10113
9959
  facts,
10114
9960
  gradleOpts,
10115
9961
  ignoreUnresolved,
9962
+ includeConfigs,
10116
9963
  verbose
10117
9964
  } = cli.flags;
10118
9965
 
@@ -10145,16 +9992,34 @@ async function run$B(argv, importMeta, {
10145
9992
  if (sockJson.defaults?.manifest?.gradle?.facts !== undefined) {
10146
9993
  facts = sockJson.defaults?.manifest?.gradle?.facts;
10147
9994
  logger.logger.info(`Using default --facts from ${constants.SOCKET_JSON}:`, facts);
9995
+ } else {
9996
+ // Socket facts generation is the default; pass --pom to generate poms.
9997
+ facts = true;
9998
+ }
9999
+ }
10000
+ // --pom opts into legacy pom.xml generation. It overrides the facts default
10001
+ // (and the socket.json default) but conflicts with an explicit --facts.
10002
+ if (cli.flags['pom']) {
10003
+ if (cli.flags['facts'] !== undefined) {
10004
+ logger.logger.warn('The `--facts` and `--pom` options are mutually exclusive; generating Socket facts.');
10148
10005
  } else {
10149
10006
  facts = false;
10150
10007
  }
10151
10008
  }
10152
- if (configs === undefined) {
10153
- if (sockJson.defaults?.manifest?.gradle?.configs !== undefined) {
10154
- configs = sockJson.defaults?.manifest?.gradle?.configs;
10155
- logger.logger.info(`Using default --configs from ${constants.SOCKET_JSON}:`, configs);
10009
+ if (includeConfigs === undefined) {
10010
+ if (sockJson.defaults?.manifest?.gradle?.includeConfigs !== undefined) {
10011
+ includeConfigs = sockJson.defaults?.manifest?.gradle?.includeConfigs;
10012
+ logger.logger.info(`Using default --include-configs from ${constants.SOCKET_JSON}:`, includeConfigs);
10013
+ } else {
10014
+ includeConfigs = '';
10015
+ }
10016
+ }
10017
+ if (excludeConfigs === undefined) {
10018
+ if (sockJson.defaults?.manifest?.gradle?.excludeConfigs !== undefined) {
10019
+ excludeConfigs = sockJson.defaults?.manifest?.gradle?.excludeConfigs;
10020
+ logger.logger.info(`Using default --exclude-configs from ${constants.SOCKET_JSON}:`, excludeConfigs);
10156
10021
  } else {
10157
- configs = '';
10022
+ excludeConfigs = '';
10158
10023
  }
10159
10024
  }
10160
10025
  if (ignoreUnresolved === undefined) {
@@ -10165,8 +10030,11 @@ async function run$B(argv, importMeta, {
10165
10030
  ignoreUnresolved = false;
10166
10031
  }
10167
10032
  }
10168
- if (!facts && (cli.flags['configs'] !== undefined || cli.flags['ignoreUnresolved'] !== undefined)) {
10169
- logger.logger.warn('The `--configs` and `--ignore-unresolved` options only apply with `--facts`; ignoring them.');
10033
+
10034
+ // `--include-configs`, `--exclude-configs`, and `--ignore-unresolved` only
10035
+ // affect facts generation; the pom path has no equivalent knobs.
10036
+ if (!facts && (cli.flags['includeConfigs'] !== undefined || cli.flags['excludeConfigs'] !== undefined || cli.flags['ignoreUnresolved'] !== undefined)) {
10037
+ logger.logger.warn('The `--include-configs`, `--exclude-configs`, and `--ignore-unresolved` options only apply when generating Socket facts (not with `--pom`); ignoring them.');
10170
10038
  }
10171
10039
  if (verbose) {
10172
10040
  logger.logger.group('- ', parentName, config$a.commandName, ':');
@@ -10203,10 +10071,11 @@ async function run$B(argv, importMeta, {
10203
10071
  if (facts) {
10204
10072
  await convertGradleToFacts({
10205
10073
  bin: String(bin),
10206
- configs: String(configs || ''),
10207
10074
  cwd,
10075
+ excludeConfigs: String(excludeConfigs || ''),
10208
10076
  gradleOpts: parsedGradleOpts,
10209
10077
  ignoreUnresolved: Boolean(ignoreUnresolved),
10078
+ includeConfigs: String(includeConfigs || ''),
10210
10079
  verbose: Boolean(verbose)
10211
10080
  });
10212
10081
  return;
@@ -10221,7 +10090,7 @@ async function run$B(argv, importMeta, {
10221
10090
 
10222
10091
  const config$9 = {
10223
10092
  commandName: 'scala',
10224
- description: "[beta] Generate a manifest file (`pom.xml`) from Scala's `build.sbt` file",
10093
+ description: '[beta] Generate a Socket facts file (or `pom.xml` with --pom) from a Scala `build.sbt` project',
10225
10094
  hidden: false,
10226
10095
  flags: {
10227
10096
  ...flags.commonFlags,
@@ -10231,23 +10100,31 @@ const config$9 = {
10231
10100
  },
10232
10101
  facts: {
10233
10102
  type: 'boolean',
10234
- description: 'Emit a Socket facts JSON file (`.socket.facts.json`) describing the resolved dependency graph instead of generating `pom.xml` files'
10103
+ 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'
10104
+ },
10105
+ pom: {
10106
+ type: 'boolean',
10107
+ description: 'Generate `pom.xml` manifest file(s) instead of the default Socket facts file (`.socket.facts.json`)'
10108
+ },
10109
+ includeConfigs: {
10110
+ type: 'string',
10111
+ description: 'When generating facts: comma-separated glob patterns matched against sbt configuration names (case-sensitive, `*` and `?` wildcards). Only configurations matching at least one pattern are resolved. e.g. `compile,test`. Default: compile,optional,provided,runtime,test'
10235
10112
  },
10236
- configs: {
10113
+ excludeConfigs: {
10237
10114
  type: 'string',
10238
- description: 'With --facts: comma-separated glob patterns matched against sbt configuration names (case-sensitive, `*` and `?` wildcards). Bare names (no wildcards) act as exact-name filters. Default: compile,optional,provided,runtime,test'
10115
+ description: 'When generating facts: comma-separated glob patterns; sbt configurations matching any pattern are skipped (applied after --include-configs)'
10239
10116
  },
10240
10117
  ignoreUnresolved: {
10241
10118
  type: 'boolean',
10242
- description: 'With --facts: warn on unresolved dependencies instead of failing the run (unresolved deps are not emitted to the facts file)'
10119
+ description: 'When generating facts: warn on unresolved dependencies instead of failing the run (unresolved deps are not emitted to the facts file)'
10243
10120
  },
10244
10121
  out: {
10245
10122
  type: 'string',
10246
- description: 'Path of output file; where to store the resulting manifest, see also --stdout'
10123
+ 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`)'
10247
10124
  },
10248
10125
  stdout: {
10249
10126
  type: 'boolean',
10250
- description: 'Print resulting pom.xml to stdout (supersedes --out)'
10127
+ description: 'Only with --pom: print the resulting `pom.xml` to stdout (supersedes --out). Does not apply when generating Socket facts'
10251
10128
  },
10252
10129
  sbtOpts: {
10253
10130
  type: 'string',
@@ -10265,11 +10142,18 @@ const config$9 = {
10265
10142
  Options
10266
10143
  ${utils.getFlagListOutput(config.flags)}
10267
10144
 
10268
- Uses \`sbt makePom\` to generate a \`pom.xml\` from your \`build.sbt\` file.
10269
- This xml file is the dependency manifest (like a package.json
10270
- for Node.js or ${constants.REQUIREMENTS_TXT} for PyPi), but specifically for Scala.
10145
+ By default, emits a single \`.socket.facts.json\` describing the resolved
10146
+ dependency graph of the whole build. It reads dependency metadata only and
10147
+ never downloads artifacts; an unresolved dependency is a fatal error. You
10148
+ can pass --include-configs / --exclude-configs (comma-separated glob
10149
+ patterns) to control which sbt configurations are resolved (e.g.
10150
+ --include-configs=\`compile,test\`), and --ignore-unresolved to warn on
10151
+ unresolved dependencies instead of failing the run.
10271
10152
 
10272
- There are some caveats with \`build.sbt\` to \`pom.xml\` conversion:
10153
+ Pass --pom to instead generate a \`pom.xml\` via \`sbt makePom\` from your
10154
+ \`build.sbt\`. The xml is the dependency manifest (like a package.json for
10155
+ Node.js or ${constants.REQUIREMENTS_TXT} for PyPi), but specifically for Scala.
10156
+ Caveats of the \`build.sbt\` to \`pom.xml\` conversion:
10273
10157
 
10274
10158
  - the xml is exported as pom.xml at the project root so Socket scan picks
10275
10159
  it up; sbt itself first writes it inside your /target/sbt<version> folder
@@ -10287,15 +10171,6 @@ const config$9 = {
10287
10171
 
10288
10172
  You can specify --bin to override the path to the \`sbt\` binary to invoke.
10289
10173
 
10290
- Pass --facts to instead emit a single \`.socket.facts.json\` describing the
10291
- resolved dependency graph of the whole build (no \`pom.xml\` files). It reads
10292
- dependency metadata only and never downloads artifacts; an unresolved
10293
- dependency is a fatal error. With --facts you can pass
10294
- --configs=<comma-separated glob patterns> to choose which sbt configurations
10295
- to resolve (e.g. \`compile,test\` for exact names or \`*Test*\` for variants),
10296
- and --ignore-unresolved to warn on unresolved dependencies instead of
10297
- failing the run.
10298
-
10299
10174
  Support is beta. Please report issues or give us feedback on what's missing.
10300
10175
 
10301
10176
  This is only for SBT. If your Scala setup uses gradle, please see the help
@@ -10304,7 +10179,7 @@ const config$9 = {
10304
10179
  Examples
10305
10180
 
10306
10181
  $ ${command}
10307
- $ ${command} --facts .
10182
+ $ ${command} --pom .
10308
10183
  $ ${command} ./proj --bin=/usr/bin/sbt --file=boot.sbt
10309
10184
  `
10310
10185
  };
@@ -10338,9 +10213,10 @@ async function run$A(argv, importMeta, {
10338
10213
  require$$9.debugFn('inspect', `override: ${constants.SOCKET_JSON} sbt`, sockJson?.defaults?.manifest?.sbt);
10339
10214
  let {
10340
10215
  bin,
10341
- configs,
10216
+ excludeConfigs,
10342
10217
  facts,
10343
10218
  ignoreUnresolved,
10219
+ includeConfigs,
10344
10220
  out,
10345
10221
  sbtOpts,
10346
10222
  stdout,
@@ -10360,16 +10236,34 @@ async function run$A(argv, importMeta, {
10360
10236
  if (sockJson.defaults?.manifest?.sbt?.facts !== undefined) {
10361
10237
  facts = sockJson.defaults?.manifest?.sbt?.facts;
10362
10238
  logger.logger.info(`Using default --facts from ${constants.SOCKET_JSON}:`, facts);
10239
+ } else {
10240
+ // Socket facts generation is the default; pass --pom to generate poms.
10241
+ facts = true;
10242
+ }
10243
+ }
10244
+ // --pom opts into legacy pom.xml generation. It overrides the facts default
10245
+ // (and the socket.json default) but conflicts with an explicit --facts.
10246
+ if (cli.flags['pom']) {
10247
+ if (cli.flags['facts'] !== undefined) {
10248
+ logger.logger.warn('The `--facts` and `--pom` options are mutually exclusive; generating Socket facts.');
10363
10249
  } else {
10364
10250
  facts = false;
10365
10251
  }
10366
10252
  }
10367
- if (configs === undefined) {
10368
- if (sockJson.defaults?.manifest?.sbt?.configs !== undefined) {
10369
- configs = sockJson.defaults?.manifest?.sbt?.configs;
10370
- logger.logger.info(`Using default --configs from ${constants.SOCKET_JSON}:`, configs);
10253
+ if (includeConfigs === undefined) {
10254
+ if (sockJson.defaults?.manifest?.sbt?.includeConfigs !== undefined) {
10255
+ includeConfigs = sockJson.defaults?.manifest?.sbt?.includeConfigs;
10256
+ logger.logger.info(`Using default --include-configs from ${constants.SOCKET_JSON}:`, includeConfigs);
10371
10257
  } else {
10372
- configs = '';
10258
+ includeConfigs = '';
10259
+ }
10260
+ }
10261
+ if (excludeConfigs === undefined) {
10262
+ if (sockJson.defaults?.manifest?.sbt?.excludeConfigs !== undefined) {
10263
+ excludeConfigs = sockJson.defaults?.manifest?.sbt?.excludeConfigs;
10264
+ logger.logger.info(`Using default --exclude-configs from ${constants.SOCKET_JSON}:`, excludeConfigs);
10265
+ } else {
10266
+ excludeConfigs = '';
10373
10267
  }
10374
10268
  }
10375
10269
  if (ignoreUnresolved === undefined) {
@@ -10409,21 +10303,13 @@ async function run$A(argv, importMeta, {
10409
10303
  verbose = false;
10410
10304
  }
10411
10305
 
10412
- // `--configs` and `--ignore-unresolved` only affect --facts; the pom path
10413
- // (`sbt makePom`) has no equivalent knobs. Warn rather than silently ignore
10414
- // an explicitly-passed flag. (socket.json defaults don't trip this only a
10415
- // flag actually present on the command line does.)
10416
- if (!facts && (cli.flags['configs'] !== undefined || cli.flags['ignoreUnresolved'] !== undefined)) {
10417
- logger.logger.warn('The `--configs` and `--ignore-unresolved` options only apply with `--facts`; ignoring them.');
10418
- }
10419
-
10420
- // Conversely, --out / --stdout only affect the pom path; with --facts the
10421
- // plugin always writes `.socket.facts.json` to the build root (its
10422
- // socket.outputDirectory/outputFile JVM props aren't exposed by the CLI), so
10423
- // warn rather than let `--facts --out custom.json` silently write nothing
10424
- // there.
10425
- if (facts && (cli.flags['out'] !== undefined || cli.flags['stdout'] !== undefined)) {
10426
- logger.logger.warn('The `--out` and `--stdout` options do not apply with `--facts`; the facts file is always written to the build root.');
10306
+ // `--include-configs`, `--exclude-configs`, and `--ignore-unresolved` only
10307
+ // affect facts generation; the pom path (`sbt makePom`) has no equivalent
10308
+ // knobs. Warn rather than silently ignore an explicitly-passed flag.
10309
+ // (socket.json defaults don't trip this — only a flag actually present on the
10310
+ // command line does.)
10311
+ if (!facts && (cli.flags['includeConfigs'] !== undefined || cli.flags['excludeConfigs'] !== undefined || cli.flags['ignoreUnresolved'] !== undefined)) {
10312
+ logger.logger.warn('The `--include-configs`, `--exclude-configs`, and `--ignore-unresolved` options only apply when generating Socket facts (not with `--pom`); ignoring them.');
10427
10313
  }
10428
10314
  if (verbose) {
10429
10315
  logger.logger.group('- ', parentName, config$9.commandName, ':');
@@ -10437,11 +10323,20 @@ async function run$A(argv, importMeta, {
10437
10323
  // try, store contents in a file in some folder, target that folder... what
10438
10324
  // would the file name be?
10439
10325
 
10326
+ // --out / --stdout only affect the pom path. Socket facts are always written
10327
+ // to the project root as `.socket.facts.json` so that `socket scan create`
10328
+ // picks them up, so reject these flags in facts mode rather than silently
10329
+ // ignoring an explicitly-passed output location.
10440
10330
  const wasValidInput = utils.checkCommandInput(outputKind, {
10441
10331
  nook: true,
10442
10332
  test: cli.input.length <= 1,
10443
10333
  message: 'Can only accept one DIR (make sure to escape spaces!)',
10444
10334
  fail: 'received ' + cli.input.length
10335
+ }, {
10336
+ nook: true,
10337
+ test: !(facts && (cli.flags['out'] !== undefined || cli.flags['stdout'] !== undefined)),
10338
+ message: 'The `--out` and `--stdout` options only apply with `--pom`; Socket facts are always written to the project root as `.socket.facts.json`',
10339
+ fail: 'remove --out/--stdout, or pass --pom'
10445
10340
  });
10446
10341
  if (!wasValidInput) {
10447
10342
  return;
@@ -10461,9 +10356,10 @@ async function run$A(argv, importMeta, {
10461
10356
  if (facts) {
10462
10357
  await convertSbtToFacts({
10463
10358
  bin: String(bin),
10464
- configs: String(configs || ''),
10465
10359
  cwd,
10360
+ excludeConfigs: String(excludeConfigs || ''),
10466
10361
  ignoreUnresolved: Boolean(ignoreUnresolved),
10362
+ includeConfigs: String(includeConfigs || ''),
10467
10363
  sbtOpts: parsedSbtOpts,
10468
10364
  verbose: Boolean(verbose)
10469
10365
  });
@@ -10524,19 +10420,19 @@ async function setupManifestConfig(cwd, defaultOnReadError = false) {
10524
10420
  }, {
10525
10421
  name: 'Gradle'.padEnd(30, ' '),
10526
10422
  value: 'gradle',
10527
- description: 'Generate pom.xml files through gradle'
10423
+ description: 'Generate a Socket facts file or pom.xml through gradle'
10528
10424
  }, {
10529
10425
  name: 'Kotlin (gradle)'.padEnd(30, ' '),
10530
10426
  value: 'gradle',
10531
- description: 'Generate pom.xml files (for Kotlin) through gradle'
10427
+ description: 'Generate a Socket facts file or pom.xml (for Kotlin) through gradle'
10532
10428
  }, {
10533
10429
  name: 'Scala (gradle)'.padEnd(30, ' '),
10534
10430
  value: 'gradle',
10535
- description: 'Generate pom.xml files (for Scala) through gradle'
10431
+ description: 'Generate a Socket facts file or pom.xml (for Scala) through gradle'
10536
10432
  }, {
10537
10433
  name: 'Scala (sbt)'.padEnd(30, ' '),
10538
10434
  value: 'sbt',
10539
- description: 'Generate pom.xml files through sbt'
10435
+ description: 'Generate a Socket facts file or pom.xml through sbt'
10540
10436
  }];
10541
10437
  choices.forEach(obj => {
10542
10438
  if (detected[obj.value]) {
@@ -10718,6 +10614,15 @@ async function setupGradle(config) {
10718
10614
  } else {
10719
10615
  delete config.facts;
10720
10616
  }
10617
+
10618
+ // The config filters and --ignore-unresolved only apply to facts generation
10619
+ // (the default); skip them when pom generation (--pom) is selected.
10620
+ if (config.facts !== false) {
10621
+ const factsOptions = await setupFactsOptions(config);
10622
+ if (!factsOptions.ok || factsOptions.data.canceled) {
10623
+ return factsOptions;
10624
+ }
10625
+ }
10721
10626
  const verbose = await askForVerboseFlag(config.verbose);
10722
10627
  if (verbose === undefined) {
10723
10628
  return canceledByUser$1();
@@ -10759,9 +10664,10 @@ async function setupSbt(config) {
10759
10664
  delete config.facts;
10760
10665
  }
10761
10666
 
10762
- // --facts emits a .socket.facts.json instead of pom.xml files, so the pom
10763
- // output questions (stdout/outfile) don't apply when it is enabled.
10764
- if (config.facts !== true) {
10667
+ // Socket facts is the default. The pom output questions (stdout/outfile)
10668
+ // only apply when pom generation (--pom) is explicitly selected; otherwise
10669
+ // ask the facts-only options.
10670
+ if (config.facts === false) {
10765
10671
  const stdout = await askForStdout(config.stdout);
10766
10672
  if (stdout === undefined) {
10767
10673
  return canceledByUser$1();
@@ -10787,6 +10693,11 @@ async function setupSbt(config) {
10787
10693
  }
10788
10694
  }
10789
10695
  }
10696
+ } else {
10697
+ const factsOptions = await setupFactsOptions(config);
10698
+ if (!factsOptions.ok || factsOptions.data.canceled) {
10699
+ return factsOptions;
10700
+ }
10790
10701
  }
10791
10702
  const verbose = await askForVerboseFlag(config.verbose);
10792
10703
  if (verbose === undefined) {
@@ -10881,15 +10792,34 @@ async function askForVerboseFlag(current) {
10881
10792
  }
10882
10793
  async function askForFactsFlag(current) {
10883
10794
  return await prompts.select({
10884
- message: '(--facts) Emit a Socket facts JSON file instead of generating pom.xml?',
10795
+ message: '(--facts / --pom) Which manifest should this generate?',
10796
+ choices: [{
10797
+ name: 'Socket facts (default)',
10798
+ value: 'yes',
10799
+ description: 'Generate a .socket.facts.json file describing the resolved dependency graph'
10800
+ }, {
10801
+ name: 'pom.xml',
10802
+ value: 'no',
10803
+ description: 'Generate pom.xml manifest files instead (the --pom path)'
10804
+ }, {
10805
+ name: '(leave default)',
10806
+ value: '',
10807
+ description: 'Do not store a setting; uses the default (Socket facts)'
10808
+ }],
10809
+ default: current === true ? 'yes' : current === false ? 'no' : ''
10810
+ });
10811
+ }
10812
+ async function askForIgnoreUnresolvedFlag(current) {
10813
+ return await prompts.select({
10814
+ message: '(--ignore-unresolved) Warn on unresolved dependencies instead of failing?',
10885
10815
  choices: [{
10886
10816
  name: 'no',
10887
10817
  value: 'no',
10888
- description: 'Generate pom.xml files (default behavior)'
10818
+ description: 'Fail the run when a declared dependency cannot resolve'
10889
10819
  }, {
10890
10820
  name: 'yes',
10891
10821
  value: 'yes',
10892
- description: 'Generate a .socket.facts.json file describing the resolved dependency graph'
10822
+ description: 'Warn and continue; unresolved dependencies are omitted from the facts file'
10893
10823
  }, {
10894
10824
  name: '(leave default)',
10895
10825
  value: '',
@@ -10898,6 +10828,44 @@ async function askForFactsFlag(current) {
10898
10828
  default: current === true ? 'yes' : current === false ? 'no' : ''
10899
10829
  });
10900
10830
  }
10831
+
10832
+ // Prompts for the facts-only options shared by gradle and sbt: the config
10833
+ // include/exclude filters and --ignore-unresolved. Mutates `config` in place.
10834
+ async function setupFactsOptions(config) {
10835
+ const includeConfigs = await prompts.input({
10836
+ message: '(--include-configs) Comma-separated config-name globs to resolve (blank = all configurations)',
10837
+ default: config.includeConfigs || '',
10838
+ required: false
10839
+ });
10840
+ if (includeConfigs === undefined) {
10841
+ return canceledByUser$1();
10842
+ } else if (includeConfigs) {
10843
+ config.includeConfigs = includeConfigs;
10844
+ } else {
10845
+ delete config.includeConfigs;
10846
+ }
10847
+ const excludeConfigs = await prompts.input({
10848
+ message: '(--exclude-configs) Comma-separated config-name globs to skip (blank = none)',
10849
+ default: config.excludeConfigs || '',
10850
+ required: false
10851
+ });
10852
+ if (excludeConfigs === undefined) {
10853
+ return canceledByUser$1();
10854
+ } else if (excludeConfigs) {
10855
+ config.excludeConfigs = excludeConfigs;
10856
+ } else {
10857
+ delete config.excludeConfigs;
10858
+ }
10859
+ const ignoreUnresolved = await askForIgnoreUnresolvedFlag(config.ignoreUnresolved);
10860
+ if (ignoreUnresolved === undefined) {
10861
+ return canceledByUser$1();
10862
+ } else if (ignoreUnresolved === 'yes' || ignoreUnresolved === 'no') {
10863
+ config.ignoreUnresolved = ignoreUnresolved === 'yes';
10864
+ } else {
10865
+ delete config.ignoreUnresolved;
10866
+ }
10867
+ return notCanceled$1();
10868
+ }
10901
10869
  function canceledByUser$1() {
10902
10870
  logger.logger.log('');
10903
10871
  logger.logger.info('User canceled');
@@ -19741,5 +19709,5 @@ process.on('unhandledRejection', async (reason, promise) => {
19741
19709
  // eslint-disable-next-line n/no-process-exit
19742
19710
  process.exit(1);
19743
19711
  });
19744
- //# debugId=614e598d-c01b-4289-b35e-bff2af2ac507
19712
+ //# debugId=b1bb7e64-091d-4be2-bb99-bb2297bb5ec2
19745
19713
  //# sourceMappingURL=cli.js.map