Skip to content

Fix potential runtime crash and improve applyDefaults validation #738

@justin808

Description

@justin808

Problem

There's a potential runtime crash in runAllBuildsCommand when using --all-builds with --output:

Location: package/configExporter/cli.ts:681

const targetDir = resolvedOptions.saveDir! // Set by applyDefaults

Root Cause:

  • applyDefaults only sets saveDir when !options.stdout && !options.output
  • When --output is present, saveDir remains undefined
  • Line 681 uses saveDir! (non-null assertion) which will fail at runtime

Missing Validation:
The yargs .check() validates --build vs --all-builds but not --output vs --all-builds.

Proposed Fix

Add validation in the yargs .check() block (around line 306):

if (argv['all-builds'] && argv.output) {
  throw new Error(
    "--all-builds and --output are mutually exclusive. Use --save-dir instead."
  )
}

Additional Improvements

1. Test Coverage Gap

The existing test file (test/package/configExporter.test.js) does not test the applyDefaults function directly.

Recommended tests:

  • Default format/annotate for --doctor mode
  • Default format/annotate for file save mode (no --stdout/--output)
  • Default format/annotate for stdout/output modes
  • Default saveDir behavior
  • Immutability property (verify original options object is not mutated)

2. Type Safety Enhancement

Consider creating a ResolvedOptions type to eliminate non-null assertions like resolvedOptions.saveDir!. This would catch potential issues at compile-time rather than runtime.

Example:

type ResolvedOptions = ExportOptions & {
  format: 'yaml' | 'json' | 'inspect'
  annotate: boolean
  saveDir?: string // Make explicit when it's set vs not set
}

3. Code Style Simplification (optional)

The applyDefaults function could potentially be more concise using a functional approach, though the current implementation is clear and maintainable.

Priority

Medium-High: The runtime crash is a real issue that could affect users, but it requires a specific combination of flags that may be uncommon.

Related

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions