Skip to content

fix(@angular/cli): handle oneOf when converting schema to yargs options#32554

Open
terencehonles wants to merge 1 commit intoangular:mainfrom
terencehonles:update-yargs-parsing
Open

fix(@angular/cli): handle oneOf when converting schema to yargs options#32554
terencehonles wants to merge 1 commit intoangular:mainfrom
terencehonles:update-yargs-parsing

Conversation

@terencehonles
Copy link

PR Checklist

Please check to confirm your PR fulfills the following requirements:

PR Type

What kind of change does this PR introduce?

  • Bugfix
  • Feature
  • Code style update (formatting, local variables)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • CI related changes
  • Documentation content changes
  • Other... Please describe:

What is the current behavior?

Options such as --allowed-hosts are defined as oneOf([array<string>, boolean]) but the array option is not chosen, even though it is first, because the JSONSchema conversion only supports an array at the root of the option schema.

Issue Number: N/A

What is the new behavior?

This change fixes JSONSchemas where oneOf is placed at the root of the option schema rather than in an array's items. This allows an array to be passed via the command-line, but additional types to be represented via configuration.

Does this PR introduce a breaking change?

  • Yes
  • No

This will affect any commands for each of the options that use oneOf at the root of their schemas. This change does not change the precedence of schema definition, so if there are any changes and they are not wanted then it is just uncovering a bug where the preferred type should have been ordered first.

Other information

@alan-agius4
Copy link
Collaborator

This is a breaking change --no-allowed-hosts will become non-functional.

@terencehonles
Copy link
Author

I forgot --no-allowed-hosts would be one of the accepted forms, but I think it's probably unlikely that allowed hosts are configured but you want to turn that off via the command line. You may be able to use --allowed-hosts "" to fake the same thing, as "" shouldn't match anything.

I looked into how yargs does its parsing and it almost works (it doesn't actually are about the option definition). Using --no-oneOfAtRoot I expected it to return false, but it returns [false] which would fail the validation.

…ions

This change fixes JSONSchemas where `oneOf` is placed at the root of the
schema rather than in an array's `items`. This allows an array to be
passed via the command-line, but additional types to be represented via
configuration.
@terencehonles
Copy link
Author

The change I pushed should handle --no-allowed-hosts as yargs will try to guess you want a boolean in this case, and since the type is not declared as an array, it will return a single boolean value instead of the [false] I was seeing before. It's possible the recursive function I added should just be a default to string, but this will try to find things like an array of numbers (which I just added a test for)

Copy link
Collaborator

@alan-agius4 alan-agius4 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comments


const SUPPORTED_PRIMITIVE_TYPES = new Set(['boolean', 'number', 'string']);
const SUPPORTED_PRIMITIVE_TYPES = new Set(['boolean', 'number', 'string'] as const);
type SupportedPrimitiveType = Parameters<typeof SUPPORTED_PRIMITIVE_TYPES.add>[0];
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider the below, which IMO it's slightly easier to read.

Suggested change
type SupportedPrimitiveType = Parameters<typeof SUPPORTED_PRIMITIVE_TYPES.add>[0];
const types = ['boolean', 'number', 'string'] as const;
const SUPPORTED_PRIMITIVE_TYPES: ReadonlySet<string> = new Set(types);
type SupportedPrimitiveType = (typeof types)[number];

function isSupportedPrimitiveType(value: string): boolean {
return SUPPORTED_PRIMITIVE_TYPES.has(value);
function isSupportedPrimitiveType(value: string): value is SupportedPrimitiveType {
return SUPPORTED_PRIMITIVE_TYPES.has(value as any);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the casting, this is not needed if you change the set type.

Suggested change
return SUPPORTED_PRIMITIVE_TYPES.has(value as any);
return SUPPORTED_PRIMITIVE_TYPES.has(value);

: {
type,
}),
: type === 'array'
Copy link
Collaborator

@alan-agius4 alan-agius4 Feb 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't right as it cause the array type to be replaced by a primitive and forces yargs to parse it as a non array. Example --flag foo bar will now become invalid.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants