Conversation
| ' Please use "--emulated-form-factor=none" instead.'); | ||
| } | ||
|
|
||
| if (typeof cliFlags.extraHeaders === 'string') { |
There was a problem hiding this comment.
the coerce() functions from yargs gave a perfect place to do this loading/parsing and avoid the awkward type dance. Just moved into cli-flags
| */ | ||
| function getFlags(manualArgv) { | ||
| // @ts-expect-error yargs() is incorrectly typed as not accepting a single string. | ||
| // @ts-expect-error - undocumented, but yargs() supports parsing a single `string`. |
There was a problem hiding this comment.
still undocumented
| }) | ||
|
|
||
| // List of options | ||
| // Logging |
There was a problem hiding this comment.
the slightly weird order of options in here is due to our currently weird order of options. This cli-flags produces exactly the same --help order except --version and --help are switched, and there are more annotated [default: false] at the end of lines.
Happy to reorder.
| }, | ||
| 'enable-error-reporting': { | ||
| type: 'boolean', | ||
| default: undefined, // Explicitly `undefined` so prompted by default. |
There was a problem hiding this comment.
this is the case anyways now, but doesn't hurt to be explicit
| // so for now cast to add yarg's camelCase properties to type. | ||
| const argv = /** @type {typeof rawArgv & CamelCasify<typeof rawArgv>} */ (rawArgv); | ||
|
|
||
| const jobs = Number.isFinite(argv.jobs) ? argv.jobs : undefined; |
There was a problem hiding this comment.
not a big deal, but yargs.number() is less helpful than I'd hoped. --jobs texttext gives argv = { _: [], jobs: NaN} instead of throwing an error to the user like I hoped it would...
| const ROOT_OUTPUT_DIR = `${LH_ROOT}/timings-data`; | ||
|
|
||
| const argv = yargs | ||
| const rawArgv = yargs |
There was a problem hiding this comment.
@connorjclark I tried to minimize the changes needed in here. I don't think I changed any semantics
| chromeFlags: string | string[]; | ||
| /** Output path for the generated results. */ | ||
| outputPath: string; | ||
| outputPath?: string; |
There was a problem hiding this comment.
as far as I can tell, this has always been optional from cli-flags, and we rely on at least the falsy behavior of outputPath for report file naming, so seems ok to document the real type coming out of yargs
|
@brendankenny for documentation purposes, what are the breaking changes in here? |
Actually none that I know of, but my understanding from the eng meeting last week was that it's such a large jump in |
| 'Disable clearing the browser cache and other storage APIs before a run', | ||
| 'emulated-form-factor': 'Controls the emulated device form factor (mobile vs. desktop) if not disabled', | ||
| 'throttling-method': 'Controls throttling method', | ||
| 'throttling.rttMs': 'Controls simulated network RTT (TCP layer)', |
There was a problem hiding this comment.
Why does this need to stay in a describe block?
There was a problem hiding this comment.
Why does this need to stay in a
describeblock?
because object support in yargs is half baked and I was putting off figuring out what to do with these and then I forgot to go back and do something with them :) I'll fix.
lighthouse-cli/cli-flags.js
Outdated
| // TODO: this function does not actually verify the object type. | ||
| if (value === undefined) return value; | ||
| if (typeof value === 'object') return /** @type {LH.SharedFlagsSettings['extraHeaders']} */ (value); | ||
| if (typeof value !== 'string') throw new Error('asdfasf'); |
There was a problem hiding this comment.
Descriptive error message?
| * @return {string} | ||
| */ | ||
| function getProgressBar(i, total = argv.n * argv.urls.length) { | ||
| function getProgressBar(i, total = argv.n * (argv.urls || []).length) { |
There was a problem hiding this comment.
no way to do required arrays?
There was a problem hiding this comment.
no way to do required arrays?
But I think we only want a required array of urls if doing --collect? yargs.implies() can do that, I believe, but it's a little too indirect for the typescript type to infer off of. It might benefit the CLI experience, but a JS check or a default will still have to go somewhere.
I was trying to leave everything mostly untouched so it would all be recognizable when you were next back in here, but happy to commit any suggestions
paulirish
left a comment
There was a problem hiding this comment.
can you also update the --help output in the readme? I think it's a little stale already.
lighthouse-cli/cli-flags.js
Outdated
|
|
||
| // We only have the single string positional argument, the url. | ||
| .option('_', { | ||
| array: true, |
There was a problem hiding this comment.
just curious why is this configured as an array?
There was a problem hiding this comment.
just curious why is this configured as an array?
Really just for types. _ is always an array, but setting the yargs option type to string erases the array part, this puts it back. I added a comment to make that clear.


fixes #11720
Two major parts of the update:
.boolean()no longer defaults tofalse, it defaults toundefined, while we've always relied on the defaultfalse. Also a bunch of other small improvements, like.number()and--versiontaking care of itself, etc@types/yargshas gotten super sophisticated, accumulating type info in each step of the cli flag declarationsThe combo of the two started forcing more options (e.g.
.boolean('flag').default('flag', false)or.option('flag', {type: 'boolean', default: false}), then arrays+strings and choices and descriptions...I eventually just opted to switch everything over to theoptions({flag1: opts, flag2: opts, ...})format, which seems like a popular pattern looking at other projects.DefinitelyTyped is limited to TypeScript 3.2 currently (and to < 4.0 until mid 2022), so types there can't do any manipulation with type names, like representing how yargs turns
--some-flaginto propertysomeFlag...but we aren't limited by that :D This also adds a type transformation to model yarg's behavior. Originally I was going to augment the@types/yargstype to do that but the way yargs is set up it sends the compiler into an infinite loop before it cuts itself off. As a result, it's just a cast for now.It's fancy, but it's really just a checked version of the unchecked cast we were doing from
argvtoLH.CliFlagsbefore. It's all in typescript land, no effect on what's happening at runtime. I can revert to a plain cast if folks don't like it, though.