/* eslint-disable camelcase */ import * as _ from 'lodash'; import { Argv } from 'yargs'; import { getApiEnvCommandLineOptions } from '../apiEnv'; import { failedExit, globalCommandLineOptions } from '../cli-utils'; export type OutputMode = 'html' | 'text' | 'json'; export type ParsedArgs = { input_params?: string[]; input_csv?: string[]; input_queries?: string; endpoint: string; extra_params: string[]; method: string; ignored_fields: string[]; response_filter: string; concurrency: number; unchanged: boolean; key_map: string[]; output_mode: OutputMode; output_file: string; input_json_baseline: string; timeout: number; retries: number; _: string[]; }; export const OLD_KEY = 'old'; export const NEW_KEY = 'new'; /** * @param yargs * @param envs */ function createYargs(yargs: Argv, envs: string[]) { _.forEach(globalCommandLineOptions, (val, key) => { yargs.option(key, val); }); // env is "old" + "new" in compare, and just "old" in generate-baseline envs.forEach((env) => { // this is a workaround for some yargs bug yargs.option(env, {}); yargs.hide(env); const envParams = []; _.forEach(getApiEnvCommandLineOptions(), (val, key) => { const envKey = `${env}.${key}`; yargs.option(envKey, { ...val, alias: val.alias ? `${env}.${val.alias}` : null, }); envParams.push(envKey); }); yargs.group(envParams, `Configuration for "${env}" server:`); }); yargs.option('input_params', { type: 'array', description: 'One of more files containing url encoded query params, requires --endpoint', }); yargs.option('extra_params', { type: 'array', default: [], description: 'Extra static parameters that will be added to each query, maybe something like limit=2 to make diffs less noisy', }); yargs.option('input_csv', { type: 'array', description: 'One or more files containing query params in a csv, requires --endpoint. --key_map remaps column names or indexes to query parameter names.', }); yargs.option('endpoint', { description: 'Endpoint to query using query param strings from --input_params', }); yargs.option('input_queries', { type: 'array', description: 'One or more files containing endpoints + queries, one per line', }); yargs.option('input_json_baseline', { type: 'array', description: 'One or more files generated by generate-baseline, with prior queries/results', }); yargs.option('ignored_fields', { type: 'array', default: [], description: 'field names to ignore when diffing responses. geometry latitude longitude are common for geocode compare runs', }); yargs.option('response_filter', { type: 'string', description: 'run the responses through this filter (specified in jsonpath format - https://www.npmjs.com/package/jsonpath) before diffing', }); yargs.option('concurrency', { type: 'number', default: 10, description: 'concurrency of api queries per host to run', }); yargs.option('key_map', { type: 'array', default: [], description: 'a mapping of csv columns to parameter names in the format csv_header1=param1 csv_header2=param2, if all numbers, are assumed to be csv column numbers', }); yargs.option('output_file', { alias: 'o', description: 'output file, if unspecified or -, output to stdout', }); yargs.group( [ 'input_params', 'endpoint', 'input_queries', 'input_csv', 'key_map', 'input_json_baseline', 'method', 'extra_params', ], 'Query reader options:', ); yargs.group(['color', 'output_mode', 'output_file', 'unchanged'], 'Output options:'); yargs.implies('input_csv', 'endpoint'); yargs.implies('input_params', 'endpoint'); } /** * Build / parse command line args with yargs * * @returns {ParsedArgs} parsed commandline args */ export function parseArgv(): ParsedArgs { // Save now if there were any args in argv, because yargs will modify it // And we don't want to exit until after so we can show yargs help. const noArgsSpecified = !_.some(process.argv, (arg) => arg.startsWith('--')); // eslint-disable-next-line @typescript-eslint/no-var-requires, global-require const topLevelYargs = require('yargs').strict(); topLevelYargs.command('generate-baseline', 'generate baseline json for future compare runs', (yargs) => { createYargs(yargs, ['old']); yargs.usage('$0 generate-baseline [args]'); }); const buildCompareYargs = (yargs) => { yargs.option('color', { type: 'boolean', description: 'turns on/off colorized output, defaults to true for stdin, false for redirected output', }); yargs.option('output_mode', { choices: ['html', 'text', 'json'], default: 'text', description: 'what kind of output to generate', }); yargs.option('unchanged', { type: 'boolean', default: false, description: 'whether or not to print all queries, even unchanged ones', }); createYargs(yargs, ['old', 'new']); yargs.usage('$0 [args] or $0 compare [args]'); }; topLevelYargs.command('compare', 'compare two api hosts', buildCompareYargs); topLevelYargs.command('*', 'default command', buildCompareYargs); if (noArgsSpecified) { topLevelYargs.showHelp(); failedExit('No arguments specified'); } return topLevelYargs.argv; }