socket 1.1.104 → 1.1.107

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/CHANGELOG.md CHANGED
@@ -12,6 +12,25 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
12
12
  ### Changed
13
13
  - **Bazel diagnostics** — `socket manifest bazel --verbose` now emits bounded subprocess traces with argv, cwd, duration, exit status, output sizes, and failure stderr tails to make customer log-only triage safer and faster.
14
14
 
15
+ ## [1.1.107](https://github.com/SocketDev/socket-cli/releases/tag/v1.1.107) - 2026-05-28
16
+
17
+ ### Changed
18
+ - **`socket manifest gradle --facts [beta]`** (and its `kotlin` alias) gained `--configs` and `--ignore-unresolved`, matching `socket manifest scala --facts`. `--configs` takes comma-separated glob patterns (e.g. `*CompileClasspath,*RuntimeClasspath`) to restrict resolution to matching Gradle configurations; unresolved dependencies are now a fatal error by default — pass `--ignore-unresolved` for the previous lenient behavior.
19
+ - **`socket manifest scala --facts --configs`** now accepts glob patterns too (e.g. `*Test*`) for consistency with the gradle command. Bare names (no `*`/`?`) keep working as exact-name filters, so existing usages are unchanged.
20
+
21
+ ### Fixed
22
+ - **`socket manifest gradle --facts`** now works on Gradle builds with the configuration cache enabled (default on Gradle 9), which previously failed with `Task.project at execution time` errors.
23
+
24
+ ## [1.1.106](https://github.com/SocketDev/socket-cli/releases/tag/v1.1.106) - 2026-05-27
25
+
26
+ ### Added
27
+ - **`socket manifest scala --facts [beta]`** — Emit a `.socket.facts.json` dependency graph from an sbt build for `socket scan create` to consume as a pregenerated SBOM. Toggle also exposed via the `socket manifest setup` wizard for use with `--auto-manifest`.
28
+
29
+ ## [1.1.105](https://github.com/SocketDev/socket-cli/releases/tag/v1.1.105) - 2026-05-27
30
+
31
+ ### Changed
32
+ - Updated the Coana CLI to v `15.3.11`.
33
+
15
34
  ## [1.1.104](https://github.com/SocketDev/socket-cli/releases/tag/v1.1.104) - 2026-05-26
16
35
 
17
36
  ### Fixed
@@ -25,7 +44,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
25
44
  ## [1.1.98](https://github.com/SocketDev/socket-cli/releases/tag/v1.1.98) - 2026-05-22
26
45
 
27
46
  ### Added
28
- - **`socket manifest gradle --facts [beta]`** (and its `socket manifest kotlin --facts` alias) — Emit a `.socket.facts.json` dependency graph from a Gradle build, consumable by `socket scan create --reach` as pregenerated SBOM input for Tier 1 reachability. Toggle also exposed via the `socket manifest setup` wizard for use with `--auto-manifest`.
47
+ - **`socket manifest gradle --facts [beta]`** (and its `socket manifest kotlin --facts` alias) — Emit a `.socket.facts.json` dependency graph from a Gradle build for `socket scan create` to consume as a pregenerated SBOM. Toggle also exposed via the `socket manifest setup` wizard for use with `--auto-manifest`.
29
48
 
30
49
  ### Changed
31
50
  - Updated the Coana CLI to v `15.3.8`.
package/dist/cli.js CHANGED
@@ -3220,8 +3220,10 @@ async function extractBazelToMaven(opts) {
3220
3220
 
3221
3221
  async function convertGradleToFacts({
3222
3222
  bin,
3223
+ configs,
3223
3224
  cwd,
3224
3225
  gradleOpts,
3226
+ ignoreUnresolved,
3225
3227
  verbose
3226
3228
  }) {
3227
3229
  const rBin = path.resolve(cwd, bin);
@@ -3241,7 +3243,32 @@ async function convertGradleToFacts({
3241
3243
  // The init script is bundled alongside the existing pom-generating one.
3242
3244
  // See .config/rollup.dist.config.mjs:copySocketFactsInitGradle.
3243
3245
  const initLocation = path.join(constants.default.distPath, 'socket-facts.init.gradle');
3244
- const commandArgs = ['--init-script', initLocation, ...gradleOpts, 'socketFacts'];
3246
+ // Disable Gradle's configuration cache for the facts run. The init
3247
+ // script resolves dependencies via the legacy
3248
+ // `Configuration.resolvedConfiguration` API (the only public API that
3249
+ // surfaces classifier + extension metadata) and registers per-
3250
+ // subproject tasks that share a `gradle.ext` accumulator — neither
3251
+ // pattern is compatible with the configuration cache, which would
3252
+ // otherwise be on by default for projects with
3253
+ // `org.gradle.configuration-cache=true` in `gradle.properties`. The
3254
+ // Provider-based CC-safe alternatives (`ResolutionResult` /
3255
+ // `ArtifactView.resolvedArtifacts`) only exist in Gradle 7.4+ and
3256
+ // they don't expose classifier/extension, so they aren't a usable
3257
+ // replacement here. Using `-D` rather than `--no-configuration-cache`
3258
+ // keeps us compatible with older Gradle versions that don't recognize
3259
+ // the flag — the system property is silently ignored when the
3260
+ // feature doesn't exist.
3261
+ // Both knobs are passed as Gradle project properties so the init script
3262
+ // can read them via `rp.findProperty(...)`, matching how
3263
+ // `socket.outputDirectory` / `socket.outputFile` are already wired.
3264
+ const socketProps = [];
3265
+ if (ignoreUnresolved) {
3266
+ socketProps.push('-Psocket.ignoreUnresolved=true');
3267
+ }
3268
+ if (configs) {
3269
+ socketProps.push(`-Psocket.configs=${configs}`);
3270
+ }
3271
+ const commandArgs = ['-Dorg.gradle.configuration-cache=false', ...socketProps, '--init-script', initLocation, ...gradleOpts, 'socketFacts'];
3245
3272
  if (verbose) {
3246
3273
  logger.logger.log('[VERBOSE] Executing:', [bin], ', args:', commandArgs);
3247
3274
  }
@@ -3342,6 +3369,194 @@ async function execGradle$1(bin, commandArgs, cwd, verbose) {
3342
3369
  }
3343
3370
  }
3344
3371
 
3372
+ // Shown when the sbt launcher dies on a modern JDK. sbt 0.13 (and some early
3373
+ // 1.x) install a SecurityManager, which JDK 18+ removed, so the launcher
3374
+ // throws before our plugin runs. We don't pick a JDK for the user — they own
3375
+ // their toolchain — but we point them at the fix.
3376
+ 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>"`.';
3377
+
3378
+ // The socket-owned global base sbt compiles our plugin into. Living under the
3379
+ // app data dir (not the user's `~/.sbt`) means we never mutate their sbt
3380
+ // config, while persisting the compiled plugin between runs. sbt namespaces
3381
+ // the compiled output by Scala/sbt version (`target/scala-2.10/sbt-0.13`,
3382
+ // `target/scala-2.12/sbt-1.0`, ...), so a single base safely serves every sbt
3383
+ // version with no version detection needed.
3384
+ function resolveGlobalBase() {
3385
+ const {
3386
+ socketAppDataPath
3387
+ } = constants.default;
3388
+ return socketAppDataPath ? path.join(path.dirname(socketAppDataPath), 'sbt-facts') : path.join(os.tmpdir(), 'socket-sbt-facts');
3389
+ }
3390
+
3391
+ // Drop the shipped plugin source into `<globalBase>/plugins/`, rewriting only
3392
+ // when its content changed so sbt's incremental compiler can reuse the cache.
3393
+ async function ensurePluginSource(pluginSrcPath, pluginsDir) {
3394
+ const source = await fs$1.promises.readFile(pluginSrcPath, 'utf8');
3395
+ const destPath = path.join(pluginsDir, 'SocketFactsPlugin.scala');
3396
+ let current;
3397
+ if (fs$1.existsSync(destPath)) {
3398
+ current = await fs$1.promises.readFile(destPath, 'utf8');
3399
+ }
3400
+ if (current !== source) {
3401
+ await fs$1.promises.mkdir(pluginsDir, {
3402
+ recursive: true
3403
+ });
3404
+ await fs$1.promises.writeFile(destPath, source, 'utf8');
3405
+ }
3406
+ }
3407
+ async function convertSbtToFacts({
3408
+ bin,
3409
+ configs,
3410
+ cwd,
3411
+ ignoreUnresolved,
3412
+ sbtOpts,
3413
+ verbose
3414
+ }) {
3415
+ logger.logger.group('sbt2facts:');
3416
+ logger.logger.info(`- executing: \`${bin}\``);
3417
+ logger.logger.info(`- src dir: \`${cwd}\``);
3418
+ if (!fs$1.existsSync(cwd)) {
3419
+ logger.logger.warn('Warning: It appears the src dir could not be found. An error might be printed later because of that.');
3420
+ }
3421
+ logger.logger.groupEnd();
3422
+ try {
3423
+ const pluginSrcPath = path.join(constants.default.distPath, 'socket-facts.plugin.scala');
3424
+ const globalBase = resolveGlobalBase();
3425
+ await ensurePluginSource(pluginSrcPath, path.join(globalBase, 'plugins'));
3426
+
3427
+ // `-Dsbt.global.base` points sbt at our isolated plugins dir, so the
3428
+ // source-only plugin activates without touching the user's `~/.sbt`. The
3429
+ // resolution options are passed as JVM system properties the plugin reads.
3430
+ const socketProps = [];
3431
+ if (ignoreUnresolved) {
3432
+ socketProps.push('-Dsocket.ignoreUnresolved=true');
3433
+ }
3434
+ if (configs) {
3435
+ socketProps.push(`-Dsocket.configs=${configs}`);
3436
+ }
3437
+ const commandArgs = [`-Dsbt.global.base=${globalBase}`, ...socketProps, ...sbtOpts, '--batch', 'socketFacts'];
3438
+ if (verbose) {
3439
+ logger.logger.log('[VERBOSE] Executing:', [bin], ', args:', commandArgs);
3440
+ }
3441
+ logger.logger.log(`Generating Socket facts from \`${bin}\` on \`${cwd}\` ...`);
3442
+ const output = await execSbt(bin, commandArgs, cwd, verbose);
3443
+ if (output.code) {
3444
+ process.exitCode = 1;
3445
+ logger.logger.fail(`sbt exited with exit code ${output.code}`);
3446
+ if (!verbose) {
3447
+ const errorLines = extractErrorLines(output.stdout, output.stderr);
3448
+ if (errorLines) {
3449
+ logger.logger.group('sbt output:');
3450
+ logger.logger.error(errorLines);
3451
+ logger.logger.groupEnd();
3452
+ }
3453
+ }
3454
+ if (/security ?manager/i.test(output.stdout + output.stderr)) {
3455
+ logger.logger.warn(JDK_HINT);
3456
+ }
3457
+ return;
3458
+ }
3459
+ logger.logger.success('Executed sbt successfully');
3460
+ if (verbose) {
3461
+ // Output already streamed inline; nothing to re-summarize.
3462
+ logger.logger.log('');
3463
+ logger.logger.log('Next step is to generate a Scan by running the `socket scan create` command on the same directory.');
3464
+ return;
3465
+ }
3466
+ // `spawn` already strips ANSI from captured output, and the plugin prints
3467
+ // these lines bare (via println, no sbt `[info]` prefix), so plain line
3468
+ // matching is stable.
3469
+ const exports = [];
3470
+ for (const m of output.stdout.matchAll(/Socket facts file written to: (.+)/g)) {
3471
+ const reported = m[1]?.trim();
3472
+ if (reported) {
3473
+ exports.push(reported);
3474
+ }
3475
+ }
3476
+ if (exports.length) {
3477
+ logger.logger.log('Reported exports:');
3478
+ for (const fn of exports) {
3479
+ logger.logger.log('- ', fn);
3480
+ }
3481
+ } else {
3482
+ // The plugin skips emission when the build has no resolvable deps.
3483
+ const skipMatch = output.stdout.match(/\[socket-facts\] no resolvable dependencies.*/);
3484
+ if (skipMatch) {
3485
+ logger.logger.warn(skipMatch[0]);
3486
+ }
3487
+ }
3488
+ logger.logger.log('');
3489
+ logger.logger.log('Next step is to generate a Scan by running the `socket scan create` command on the same directory.');
3490
+ } catch (e) {
3491
+ process.exitCode = 1;
3492
+ // A missing sbt launcher is the most common setup failure; surface it
3493
+ // clearly instead of the generic message.
3494
+ if (e instanceof Error && e.code === 'ENOENT') {
3495
+ 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.`);
3496
+ } else {
3497
+ logger.logger.fail('There was an unexpected error while generating Socket facts' + (verbose ? '' : ' (use --verbose for details)'));
3498
+ }
3499
+ if (verbose) {
3500
+ logger.logger.group('[VERBOSE] error:');
3501
+ logger.logger.log(e);
3502
+ logger.logger.groupEnd();
3503
+ }
3504
+ }
3505
+ }
3506
+
3507
+ // Pull the actionable lines out of a noisy sbt run so a failure surfaces the
3508
+ // plugin's own message (and sbt's `[error]` lines) without dumping the whole
3509
+ // resolution log.
3510
+ function extractErrorLines(stdout, stderr) {
3511
+ return `${stdout}\n${stderr}`.split('\n').filter(line => /\[error]|Socket facts|could not resolve|unresolved/i.test(line)).join('\n').trim();
3512
+ }
3513
+ async function execSbt(bin, commandArgs, cwd, verbose) {
3514
+ // When verbose, stream sbt output straight to the terminal so the user can
3515
+ // watch resolution progress; otherwise show a spinner and capture output for
3516
+ // the post-run summary.
3517
+ if (verbose) {
3518
+ logger.logger.info('(Running sbt with output streaming. This can take a while.)');
3519
+ const output = await spawn.spawn(bin, commandArgs, {
3520
+ cwd,
3521
+ stdio: 'inherit'
3522
+ });
3523
+ return {
3524
+ code: output.code,
3525
+ stdout: '',
3526
+ stderr: ''
3527
+ };
3528
+ }
3529
+ const {
3530
+ spinner
3531
+ } = constants.default;
3532
+ let pass = false;
3533
+ try {
3534
+ logger.logger.info('(Running sbt can take a while, depending on the size of the project)');
3535
+ logger.logger.info('(No live output. Pass --verbose to stream sbt output instead.)');
3536
+ spinner.start('Running sbt...');
3537
+ const output = await spawn.spawn(bin, commandArgs, {
3538
+ cwd
3539
+ });
3540
+ pass = true;
3541
+ const {
3542
+ code,
3543
+ stderr,
3544
+ stdout
3545
+ } = output;
3546
+ return {
3547
+ code,
3548
+ stdout,
3549
+ stderr
3550
+ };
3551
+ } finally {
3552
+ if (pass) {
3553
+ spinner.successAndStop('Gracefully completed sbt execution.');
3554
+ } else {
3555
+ spinner.failAndStop('There was an error while trying to run sbt.');
3556
+ }
3557
+ }
3558
+ }
3559
+
3345
3560
  async function convertGradleToMaven({
3346
3561
  bin,
3347
3562
  cwd,
@@ -3799,15 +4014,30 @@ async function generateAutoManifest({
3799
4014
  logger.logger.info(`Using this ${constants.SOCKET_JSON} for defaults:`, sockJson);
3800
4015
  }
3801
4016
  if (!sockJson?.defaults?.manifest?.sbt?.disabled && detected.sbt) {
3802
- logger.logger.log('Detected a Scala sbt build, generating pom files with sbt...');
3803
- await convertSbtToMaven({
3804
- // Note: `sbt` is more likely to be resolved against PATH env
4017
+ // Args shared by both paths. The facts-only knobs (`configs`,
4018
+ // `ignoreUnresolved`) and the pom-only `out` are added per branch so
4019
+ // neither handler is spread properties it doesn't accept.
4020
+ const sbtArgs = {
4021
+ // Note: `sbt` is more likely to be resolved against PATH env.
3805
4022
  bin: sockJson.defaults?.manifest?.sbt?.bin ?? 'sbt',
3806
4023
  cwd,
3807
- out: sockJson.defaults?.manifest?.sbt?.outfile ?? './pom.xml',
3808
4024
  sbtOpts: sockJson.defaults?.manifest?.sbt?.sbtOpts?.split(' ').map(s => s.trim()).filter(Boolean) ?? [],
3809
4025
  verbose: Boolean(sockJson.defaults?.manifest?.sbt?.verbose)
3810
- });
4026
+ };
4027
+ if (sockJson.defaults?.manifest?.sbt?.facts) {
4028
+ logger.logger.log('Detected a Scala sbt build, generating Socket facts...');
4029
+ await convertSbtToFacts({
4030
+ ...sbtArgs,
4031
+ configs: sockJson.defaults?.manifest?.sbt?.configs ?? '',
4032
+ ignoreUnresolved: Boolean(sockJson.defaults?.manifest?.sbt?.ignoreUnresolved)
4033
+ });
4034
+ } else {
4035
+ logger.logger.log('Detected a Scala sbt build, generating pom files with sbt...');
4036
+ await convertSbtToMaven({
4037
+ ...sbtArgs,
4038
+ out: sockJson.defaults?.manifest?.sbt?.outfile ?? './pom.xml'
4039
+ });
4040
+ }
3811
4041
  }
3812
4042
  if (!sockJson?.defaults?.manifest?.gradle?.disabled && detected.gradle) {
3813
4043
  const gradleArgs = {
@@ -3821,7 +4051,11 @@ async function generateAutoManifest({
3821
4051
  };
3822
4052
  if (sockJson.defaults?.manifest?.gradle?.facts) {
3823
4053
  logger.logger.log('Detected a gradle build (Gradle, Kotlin, Scala), generating Socket facts...');
3824
- await convertGradleToFacts(gradleArgs);
4054
+ await convertGradleToFacts({
4055
+ ...gradleArgs,
4056
+ configs: sockJson.defaults?.manifest?.gradle?.configs ?? '',
4057
+ ignoreUnresolved: Boolean(sockJson.defaults?.manifest?.gradle?.ignoreUnresolved)
4058
+ });
3825
4059
  } else {
3826
4060
  logger.logger.log('Detected a gradle build (Gradle, Kotlin, Scala), running default gradle generator...');
3827
4061
  await convertGradleToMaven(gradleArgs);
@@ -8878,6 +9112,14 @@ const config$b = {
8878
9112
  type: 'boolean',
8879
9113
  description: 'Emit a Socket facts JSON file (`.socket.facts.json`) describing the resolved dependency graph instead of generating `pom.xml` files'
8880
9114
  },
9115
+ configs: {
9116
+ type: 'string',
9117
+ 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'
9118
+ },
9119
+ ignoreUnresolved: {
9120
+ type: 'boolean',
9121
+ description: 'With --facts: warn on unresolved dependencies instead of failing the run (unresolved deps are not emitted to the facts file)'
9122
+ },
8881
9123
  gradleOpts: {
8882
9124
  type: 'string',
8883
9125
  description: 'Additional options to pass on to ./gradlew, see `./gradlew --help`'
@@ -8912,11 +9154,20 @@ const config$b = {
8912
9154
 
8913
9155
  - it works with your \`gradlew\` from your repo and local settings and config
8914
9156
 
9157
+ Pass --facts to instead emit a single \`.socket.facts.json\` describing the
9158
+ resolved dependency graph of the whole build (no \`pom.xml\` files). An
9159
+ unresolved dependency is a fatal error. With --facts you can pass
9160
+ --configs=<comma-separated glob patterns> to restrict resolution to
9161
+ matching configurations (e.g. \`*CompileClasspath,*RuntimeClasspath\`),
9162
+ and --ignore-unresolved to warn on unresolved dependencies instead of
9163
+ failing the run.
9164
+
8915
9165
  Support is beta. Please report issues or give us feedback on what's missing.
8916
9166
 
8917
9167
  Examples
8918
9168
 
8919
9169
  $ ${command} .
9170
+ $ ${command} --facts .
8920
9171
  $ ${command} --bin=../gradlew .
8921
9172
  `
8922
9173
  };
@@ -8950,8 +9201,10 @@ async function run$C(argv, importMeta, {
8950
9201
  require$$9.debugFn('inspect', `override: ${constants.SOCKET_JSON} gradle`, sockJson?.defaults?.manifest?.gradle);
8951
9202
  let {
8952
9203
  bin,
9204
+ configs,
8953
9205
  facts,
8954
9206
  gradleOpts,
9207
+ ignoreUnresolved,
8955
9208
  verbose
8956
9209
  } = cli.flags;
8957
9210
 
@@ -8988,6 +9241,31 @@ async function run$C(argv, importMeta, {
8988
9241
  facts = false;
8989
9242
  }
8990
9243
  }
9244
+ if (configs === undefined) {
9245
+ if (sockJson.defaults?.manifest?.gradle?.configs !== undefined) {
9246
+ configs = sockJson.defaults?.manifest?.gradle?.configs;
9247
+ logger.logger.info(`Using default --configs from ${constants.SOCKET_JSON}:`, configs);
9248
+ } else {
9249
+ configs = '';
9250
+ }
9251
+ }
9252
+ if (ignoreUnresolved === undefined) {
9253
+ if (sockJson.defaults?.manifest?.gradle?.ignoreUnresolved !== undefined) {
9254
+ ignoreUnresolved = sockJson.defaults?.manifest?.gradle?.ignoreUnresolved;
9255
+ logger.logger.info(`Using default --ignore-unresolved from ${constants.SOCKET_JSON}:`, ignoreUnresolved);
9256
+ } else {
9257
+ ignoreUnresolved = false;
9258
+ }
9259
+ }
9260
+
9261
+ // `--configs` and `--ignore-unresolved` only affect --facts; the pom path
9262
+ // (the legacy `socketGenerateMaven` task) has no equivalent knobs. Warn
9263
+ // rather than silently ignore an explicitly-passed flag. (socket.json
9264
+ // defaults don't trip this — only a flag actually present on the command
9265
+ // line does.)
9266
+ if (!facts && (cli.flags['configs'] !== undefined || cli.flags['ignoreUnresolved'] !== undefined)) {
9267
+ logger.logger.warn('The `--configs` and `--ignore-unresolved` options only apply with `--facts`; ignoring them.');
9268
+ }
8991
9269
  if (verbose) {
8992
9270
  logger.logger.group('- ', parentName, config$b.commandName, ':');
8993
9271
  logger.logger.group('- flags:', cli.flags);
@@ -9023,8 +9301,10 @@ async function run$C(argv, importMeta, {
9023
9301
  if (facts) {
9024
9302
  await convertGradleToFacts({
9025
9303
  bin: String(bin),
9304
+ configs: String(configs || ''),
9026
9305
  cwd,
9027
9306
  gradleOpts: parsedGradleOpts,
9307
+ ignoreUnresolved: Boolean(ignoreUnresolved),
9028
9308
  verbose: Boolean(verbose)
9029
9309
  });
9030
9310
  return;
@@ -9056,6 +9336,14 @@ const config$a = {
9056
9336
  type: 'boolean',
9057
9337
  description: 'Emit a Socket facts JSON file (`.socket.facts.json`) describing the resolved dependency graph instead of generating `pom.xml` files'
9058
9338
  },
9339
+ configs: {
9340
+ type: 'string',
9341
+ 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'
9342
+ },
9343
+ ignoreUnresolved: {
9344
+ type: 'boolean',
9345
+ description: 'With --facts: warn on unresolved dependencies instead of failing the run (unresolved deps are not emitted to the facts file)'
9346
+ },
9059
9347
  gradleOpts: {
9060
9348
  type: 'string',
9061
9349
  description: 'Additional options to pass on to ./gradlew, see `./gradlew --help`'
@@ -9128,8 +9416,10 @@ async function run$B(argv, importMeta, {
9128
9416
  require$$9.debugFn('inspect', `override: ${constants.SOCKET_JSON} gradle`, sockJson?.defaults?.manifest?.gradle);
9129
9417
  let {
9130
9418
  bin,
9419
+ configs,
9131
9420
  facts,
9132
9421
  gradleOpts,
9422
+ ignoreUnresolved,
9133
9423
  verbose
9134
9424
  } = cli.flags;
9135
9425
 
@@ -9166,6 +9456,25 @@ async function run$B(argv, importMeta, {
9166
9456
  facts = false;
9167
9457
  }
9168
9458
  }
9459
+ if (configs === undefined) {
9460
+ if (sockJson.defaults?.manifest?.gradle?.configs !== undefined) {
9461
+ configs = sockJson.defaults?.manifest?.gradle?.configs;
9462
+ logger.logger.info(`Using default --configs from ${constants.SOCKET_JSON}:`, configs);
9463
+ } else {
9464
+ configs = '';
9465
+ }
9466
+ }
9467
+ if (ignoreUnresolved === undefined) {
9468
+ if (sockJson.defaults?.manifest?.gradle?.ignoreUnresolved !== undefined) {
9469
+ ignoreUnresolved = sockJson.defaults?.manifest?.gradle?.ignoreUnresolved;
9470
+ logger.logger.info(`Using default --ignore-unresolved from ${constants.SOCKET_JSON}:`, ignoreUnresolved);
9471
+ } else {
9472
+ ignoreUnresolved = false;
9473
+ }
9474
+ }
9475
+ if (!facts && (cli.flags['configs'] !== undefined || cli.flags['ignoreUnresolved'] !== undefined)) {
9476
+ logger.logger.warn('The `--configs` and `--ignore-unresolved` options only apply with `--facts`; ignoring them.');
9477
+ }
9169
9478
  if (verbose) {
9170
9479
  logger.logger.group('- ', parentName, config$a.commandName, ':');
9171
9480
  logger.logger.group('- flags:', cli.flags);
@@ -9201,8 +9510,10 @@ async function run$B(argv, importMeta, {
9201
9510
  if (facts) {
9202
9511
  await convertGradleToFacts({
9203
9512
  bin: String(bin),
9513
+ configs: String(configs || ''),
9204
9514
  cwd,
9205
9515
  gradleOpts: parsedGradleOpts,
9516
+ ignoreUnresolved: Boolean(ignoreUnresolved),
9206
9517
  verbose: Boolean(verbose)
9207
9518
  });
9208
9519
  return;
@@ -9225,6 +9536,18 @@ const config$9 = {
9225
9536
  type: 'string',
9226
9537
  description: 'Location of sbt binary to use'
9227
9538
  },
9539
+ facts: {
9540
+ type: 'boolean',
9541
+ description: 'Emit a Socket facts JSON file (`.socket.facts.json`) describing the resolved dependency graph instead of generating `pom.xml` files'
9542
+ },
9543
+ configs: {
9544
+ type: 'string',
9545
+ 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'
9546
+ },
9547
+ ignoreUnresolved: {
9548
+ type: 'boolean',
9549
+ description: 'With --facts: warn on unresolved dependencies instead of failing the run (unresolved deps are not emitted to the facts file)'
9550
+ },
9228
9551
  out: {
9229
9552
  type: 'string',
9230
9553
  description: 'Path of output file; where to store the resulting manifest, see also --stdout'
@@ -9271,6 +9594,15 @@ const config$9 = {
9271
9594
 
9272
9595
  You can specify --bin to override the path to the \`sbt\` binary to invoke.
9273
9596
 
9597
+ Pass --facts to instead emit a single \`.socket.facts.json\` describing the
9598
+ resolved dependency graph of the whole build (no \`pom.xml\` files). It reads
9599
+ dependency metadata only and never downloads artifacts; an unresolved
9600
+ dependency is a fatal error. With --facts you can pass
9601
+ --configs=<comma-separated glob patterns> to choose which sbt configurations
9602
+ to resolve (e.g. \`compile,test\` for exact names or \`*Test*\` for variants),
9603
+ and --ignore-unresolved to warn on unresolved dependencies instead of
9604
+ failing the run.
9605
+
9274
9606
  Support is beta. Please report issues or give us feedback on what's missing.
9275
9607
 
9276
9608
  This is only for SBT. If your Scala setup uses gradle, please see the help
@@ -9279,6 +9611,7 @@ const config$9 = {
9279
9611
  Examples
9280
9612
 
9281
9613
  $ ${command}
9614
+ $ ${command} --facts .
9282
9615
  $ ${command} ./proj --bin=/usr/bin/sbt --file=boot.sbt
9283
9616
  `
9284
9617
  };
@@ -9312,6 +9645,9 @@ async function run$A(argv, importMeta, {
9312
9645
  require$$9.debugFn('inspect', `override: ${constants.SOCKET_JSON} sbt`, sockJson?.defaults?.manifest?.sbt);
9313
9646
  let {
9314
9647
  bin,
9648
+ configs,
9649
+ facts,
9650
+ ignoreUnresolved,
9315
9651
  out,
9316
9652
  sbtOpts,
9317
9653
  stdout,
@@ -9327,6 +9663,30 @@ async function run$A(argv, importMeta, {
9327
9663
  bin = 'sbt';
9328
9664
  }
9329
9665
  }
9666
+ if (facts === undefined) {
9667
+ if (sockJson.defaults?.manifest?.sbt?.facts !== undefined) {
9668
+ facts = sockJson.defaults?.manifest?.sbt?.facts;
9669
+ logger.logger.info(`Using default --facts from ${constants.SOCKET_JSON}:`, facts);
9670
+ } else {
9671
+ facts = false;
9672
+ }
9673
+ }
9674
+ if (configs === undefined) {
9675
+ if (sockJson.defaults?.manifest?.sbt?.configs !== undefined) {
9676
+ configs = sockJson.defaults?.manifest?.sbt?.configs;
9677
+ logger.logger.info(`Using default --configs from ${constants.SOCKET_JSON}:`, configs);
9678
+ } else {
9679
+ configs = '';
9680
+ }
9681
+ }
9682
+ if (ignoreUnresolved === undefined) {
9683
+ if (sockJson.defaults?.manifest?.sbt?.ignoreUnresolved !== undefined) {
9684
+ ignoreUnresolved = sockJson.defaults?.manifest?.sbt?.ignoreUnresolved;
9685
+ logger.logger.info(`Using default --ignore-unresolved from ${constants.SOCKET_JSON}:`, ignoreUnresolved);
9686
+ } else {
9687
+ ignoreUnresolved = false;
9688
+ }
9689
+ }
9330
9690
  if (stdout === undefined && sockJson.defaults?.manifest?.sbt?.stdout !== undefined) {
9331
9691
  stdout = sockJson.defaults?.manifest?.sbt?.stdout;
9332
9692
  logger.logger.info(`Using default --stdout from ${constants.SOCKET_JSON}:`, stdout);
@@ -9355,6 +9715,23 @@ async function run$A(argv, importMeta, {
9355
9715
  } else if (verbose === undefined) {
9356
9716
  verbose = false;
9357
9717
  }
9718
+
9719
+ // `--configs` and `--ignore-unresolved` only affect --facts; the pom path
9720
+ // (`sbt makePom`) has no equivalent knobs. Warn rather than silently ignore
9721
+ // an explicitly-passed flag. (socket.json defaults don't trip this — only a
9722
+ // flag actually present on the command line does.)
9723
+ if (!facts && (cli.flags['configs'] !== undefined || cli.flags['ignoreUnresolved'] !== undefined)) {
9724
+ logger.logger.warn('The `--configs` and `--ignore-unresolved` options only apply with `--facts`; ignoring them.');
9725
+ }
9726
+
9727
+ // Conversely, --out / --stdout only affect the pom path; with --facts the
9728
+ // plugin always writes `.socket.facts.json` to the build root (its
9729
+ // socket.outputDirectory/outputFile JVM props aren't exposed by the CLI), so
9730
+ // warn rather than let `--facts --out custom.json` silently write nothing
9731
+ // there.
9732
+ if (facts && (cli.flags['out'] !== undefined || cli.flags['stdout'] !== undefined)) {
9733
+ logger.logger.warn('The `--out` and `--stdout` options do not apply with `--facts`; the facts file is always written to the build root.');
9734
+ }
9358
9735
  if (verbose) {
9359
9736
  logger.logger.group('- ', parentName, config$9.commandName, ':');
9360
9737
  logger.logger.group('- flags:', cli.flags);
@@ -9387,11 +9764,23 @@ async function run$A(argv, importMeta, {
9387
9764
  logger.logger.log(constants.default.DRY_RUN_BAILING_NOW);
9388
9765
  return;
9389
9766
  }
9767
+ const parsedSbtOpts = String(sbtOpts || '').split(' ').map(s => s.trim()).filter(Boolean);
9768
+ if (facts) {
9769
+ await convertSbtToFacts({
9770
+ bin: String(bin),
9771
+ configs: String(configs || ''),
9772
+ cwd,
9773
+ ignoreUnresolved: Boolean(ignoreUnresolved),
9774
+ sbtOpts: parsedSbtOpts,
9775
+ verbose: Boolean(verbose)
9776
+ });
9777
+ return;
9778
+ }
9390
9779
  await convertSbtToMaven({
9391
9780
  bin: String(bin),
9392
- cwd: cwd,
9781
+ cwd,
9393
9782
  out: String(out),
9394
- sbtOpts: String(sbtOpts).split(' ').map(s => s.trim()).filter(Boolean),
9783
+ sbtOpts: parsedSbtOpts,
9395
9784
  verbose: Boolean(verbose)
9396
9785
  });
9397
9786
  }
@@ -9668,28 +10057,41 @@ async function setupSbt(config) {
9668
10057
  } else {
9669
10058
  delete config.sbtOpts;
9670
10059
  }
9671
- const stdout = await askForStdout(config.stdout);
9672
- if (stdout === undefined) {
10060
+ const facts = await askForFactsFlag(config.facts);
10061
+ if (facts === undefined) {
9673
10062
  return canceledByUser$1();
9674
- } else if (stdout === 'yes') {
9675
- config.stdout = true;
9676
- } else if (stdout === 'no') {
9677
- config.stdout = false;
10063
+ } else if (facts === 'yes' || facts === 'no') {
10064
+ config.facts = facts === 'yes';
9678
10065
  } else {
9679
- delete config.stdout;
10066
+ delete config.facts;
9680
10067
  }
9681
- if (config.stdout !== true) {
9682
- const out = await askForOutputFile(config.outfile || 'sbt.pom.xml');
9683
- if (out === undefined) {
10068
+
10069
+ // --facts emits a .socket.facts.json instead of pom.xml files, so the pom
10070
+ // output questions (stdout/outfile) don't apply when it is enabled.
10071
+ if (config.facts !== true) {
10072
+ const stdout = await askForStdout(config.stdout);
10073
+ if (stdout === undefined) {
9684
10074
  return canceledByUser$1();
9685
- } else if (out === '-') {
10075
+ } else if (stdout === 'yes') {
9686
10076
  config.stdout = true;
10077
+ } else if (stdout === 'no') {
10078
+ config.stdout = false;
9687
10079
  } else {
9688
10080
  delete config.stdout;
9689
- if (out) {
9690
- config.outfile = out;
10081
+ }
10082
+ if (config.stdout !== true) {
10083
+ const out = await askForOutputFile(config.outfile || 'sbt.pom.xml');
10084
+ if (out === undefined) {
10085
+ return canceledByUser$1();
10086
+ } else if (out === '-') {
10087
+ config.stdout = true;
9691
10088
  } else {
9692
- delete config.outfile;
10089
+ delete config.stdout;
10090
+ if (out) {
10091
+ config.outfile = out;
10092
+ } else {
10093
+ delete config.outfile;
10094
+ }
9693
10095
  }
9694
10096
  }
9695
10097
  }
@@ -18619,5 +19021,5 @@ process.on('unhandledRejection', async (reason, promise) => {
18619
19021
  // eslint-disable-next-line n/no-process-exit
18620
19022
  process.exit(1);
18621
19023
  });
18622
- //# debugId=932c44e2-d146-411e-8818-31f6bf237a5b
19024
+ //# debugId=f6378cd8-bbe9-49cb-9f3a-76b5f61b86ed
18623
19025
  //# sourceMappingURL=cli.js.map