From 0427a092bec59c72743e8172002073bfc7b6a9e2 Mon Sep 17 00:00:00 2001 From: Sean Sube Date: Wed, 23 Nov 2022 08:03:10 -0600 Subject: [PATCH] fix(config): make args parser type safe --- src/app.ts | 8 +++--- src/config/args.ts | 64 ++++++++++++++++++++++++---------------------- 2 files changed, 38 insertions(+), 34 deletions(-) diff --git a/src/app.ts b/src/app.ts index 347c0bc..5224c00 100644 --- a/src/app.ts +++ b/src/app.ts @@ -1,4 +1,4 @@ -import { mustGet } from '@apextoaster/js-utils'; +import { mustDefault, mustGet } from '@apextoaster/js-utils'; import { createLogger } from 'bunyan'; import yargs from 'yargs'; @@ -58,9 +58,9 @@ export async function main(argv: Array): Promise { const ctx = new VisitorContext({ logger, schemaOptions: { - coerce: args.coerce, - defaults: args.defaults, - mutate: args.mutate, + coerce: mustDefault(args.coerce, false), + defaults: mustDefault(args.defaults, true), + mutate: mustDefault(args.mutate, true), }, }); diff --git a/src/config/args.ts b/src/config/args.ts index 9b2e745..7bbf480 100644 --- a/src/config/args.ts +++ b/src/config/args.ts @@ -1,4 +1,5 @@ -import yargs, { Options } from 'yargs'; +import { LogLevel } from 'noicejs'; +import yargs from 'yargs'; import { RuleSources } from '../rule/load.js'; import { RuleSelector } from '../rule/resolve.js'; @@ -14,27 +15,14 @@ export enum MODE { export const CONFIG_ARGS_NAME = 'config-name'; export const CONFIG_ARGS_PATH = 'config-path'; -const RULE_OPTION: Options = { - default: [], - group: 'Rules:', - type: 'array', -}; - -export interface Args { - /* eslint-disable-next-line @typescript-eslint/no-explicit-any */ - args: any; - mode: string; -} - export interface ParsedArgs extends RuleSelector, RuleSources { [CONFIG_ARGS_NAME]: string; - [CONFIG_ARGS_PATH]: string; - coerce: boolean; + [CONFIG_ARGS_PATH]: Array; + coerce?: boolean; count: boolean; - defaults: boolean; + defaults?: boolean; dest: string; - mode: string; - mutate: boolean; + mutate?: boolean; reporter: string; source: string; } @@ -50,7 +38,8 @@ export interface ParseResults { export async function parseArgs(argv: Array): Promise { let mode: MODE = MODE.check; - const parser = yargs(argv).usage('Usage: salty-dog [options]') + const parser = yargs(argv) + .usage('Usage: salty-dog [options]') .command({ command: ['check', '*'], describe: 'validate the source documents', @@ -101,7 +90,7 @@ export async function parseArgs(argv: Array): Promise { type: 'string', }, [CONFIG_ARGS_PATH]: { - default: [], + default: [] as Array, group: 'Config:', type: 'array', }, @@ -116,25 +105,43 @@ export async function parseArgs(argv: Array): Promise { default: '-', type: 'string', }, - 'exclude-level': RULE_OPTION, - 'exclude-name': RULE_OPTION, - 'exclude-tag': RULE_OPTION, + 'exclude-level': { + default: [] as Array, + group: 'Rules:', + type: 'array', + }, + 'exclude-name': { + default: [] as Array, + group: 'Rules:', + type: 'array', + }, + 'exclude-tag': { + default: [] as Array, + group: 'Rules:', + type: 'array', + }, 'format': { alias: ['f'], default: 'yaml', type: 'string', }, 'include-level': { - ...RULE_OPTION, alias: ['l', 'level'], + default: [] as Array, + group: 'Rules:', + type: 'array', }, 'include-name': { - ...RULE_OPTION, alias: ['n', 'name'], + default: [] as Array, + group: 'Rules:', + type: 'array', }, 'include-tag': { - ...RULE_OPTION, alias: ['t', 'tag'], + default: [] as Array, + group: 'Rules:', + type: 'array', }, 'reporter': { alias: ['report'], @@ -171,10 +178,7 @@ export async function parseArgs(argv: Array): Promise { .version(VERSION_INFO.package.version) .alias('version', 'v'); - // @TODO: this should not need a cast but the parser's type omits command options and doesn't expose camelCase - /* eslint-disable-next-line @typescript-eslint/no-explicit-any */ - const args = parser.parse(argv) as any; - + const args = await parser.parse(argv); return { args, mode,