Add support for --help from globally installed plugins (as long as you include the plugin in add). (#4450)

* Add support for --help from globally installed plugins.

* Disable version and help from first parsing
This commit is contained in:
Peter Hedenskog 2025-03-01 22:03:30 +01:00 committed by GitHub
parent e78200da3e
commit 2cd75d772c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 44 additions and 18 deletions

View File

@ -18,6 +18,7 @@ import { config as slackConfig } from '../plugins/slack/index.js';
import { config as htmlConfig } from '../plugins/html/index.js';
import { messageTypes as matrixMessageTypes } from '../plugins/matrix/index.js';
import { findUpSync } from '../support/fileUtil.js';
import { registerPluginOptions } from './pluginOptions.js';
const metricList = Object.keys(friendlynames);
const require = createRequire(import.meta.url);
@ -25,6 +26,13 @@ const version = require('../../package.json').version;
const configFiles = ['.sitespeed.io.json'];
const addedPlugins = yargs(hideBin(process.argv))
.option('plugins.add', { type: 'array' })
.help(false)
.version(false)
.parse();
const globalPluginsToAdd = addedPlugins.plugins?.add || [];
function fixAndroidArgs(args) {
return args.map(arg => (arg === '--android' ? '--android.enabled' : arg));
}
@ -220,7 +228,7 @@ function validateInput(argv) {
export async function parseCommandLine() {
const fixedArgs = fixAndroidArgs(hideBin(process.argv));
const yargsInstance = yargs(fixedArgs);
let parsed = yargsInstance
yargsInstance
.parserConfiguration({
'camel-case-expansion': false,
'deep-merge-config': true
@ -1160,7 +1168,6 @@ export async function parseCommandLine() {
describe: 'Ignore robots.txt rules of the crawled domain.',
group: 'Crawler'
})
.option('scp.host', {
describe: 'The host.',
group: 'scp'
@ -1346,9 +1353,7 @@ export async function parseCommandLine() {
describe:
'Define which messages to send to Graphite. By default we do not send data per run, but you can change that by adding run as one of the options',
group: 'Graphite'
});
parsed
})
/** Plugins */
.option('plugins.list', {
describe: 'List all configured plugins in the log.',
@ -1454,9 +1459,7 @@ export async function parseCommandLine() {
describe: 'The max size of the screenshot (width and height).',
default: browsertimeConfig.screenshotParams.maxSize,
group: 'Screenshot'
});
parsed
// Metrics
})
.option('metrics.list', {
describe: 'List all possible metrics in the data folder (metrics.txt).',
type: 'boolean',
@ -1801,9 +1804,7 @@ export async function parseCommandLine() {
describe:
'Instead of using the local copy of the hosting database, you can use the latest version through the Green Web Foundation API. This means sitespeed.io will make HTTP GET to the the hosting info.',
group: 'Sustainable'
});
parsed
})
.option('api.key', {
describe: 'The API key to use.',
group: 'API'
@ -1854,9 +1855,7 @@ export async function parseCommandLine() {
.option('api.json', {
describe: 'Output the result as JSON.',
group: 'API'
});
parsed
})
.option('compare.id', {
type: 'string',
describe:
@ -1917,8 +1916,7 @@ export async function parseCommandLine() {
'Selects the method for calculating the Mann-Whitney U test. auto automatically selects between exact and asymptotic based on sample size, exact uses the exact distribution of U, and symptotic uses a normal approximation.',
default: 'auto',
group: 'compare'
});
parsed
})
.option('mobile', {
describe:
'Access pages as mobile a fake mobile device. Set UA and width/height. For Chrome it will use device Moto G4.',
@ -2048,8 +2046,12 @@ export async function parseCommandLine() {
}
return plugins;
}
})
// .describe('browser', 'Specify browser')
});
// .describe('browser', 'Specify browser')
await registerPluginOptions(yargsInstance, globalPluginsToAdd);
let parsed = yargsInstance
.wrap(yargsInstance.terminalWidth())
// .check(validateInput)
.epilog(

24
lib/cli/pluginOptions.js Normal file
View File

@ -0,0 +1,24 @@
import { importGlobalSilent } from 'import-global';
/**
* Dynamically load and register CLI options from plugins.
*
* @param {import('yargs').Argv} yargsInstance - The yargs instance to extend.
* @param {string[]} plugins - Array of plugin module names.
* @returns {Promise<void>}
*/
export async function registerPluginOptions(yargsInstance, plugins) {
for (const pluginName of plugins) {
try {
// Dynamically import the plugin
const plugin = await importGlobalSilent(pluginName);
// If the plugin exports a function to get CLI options, merge them
if (plugin && typeof plugin.getCliOptions === 'function') {
const options = plugin.getCliOptions();
yargsInstance.options(options);
}
} catch {
// Swallow this silent
}
}
}