diff --git a/package.json b/package.json index 60a4fa26..d74b9e8e 100644 --- a/package.json +++ b/package.json @@ -74,6 +74,7 @@ "shx": "^0.3.4", "sinon": "^11.1.2", "ts-node": "^9.1.1", + "tsd": "^0.22.0", "typescript": "4.5.5" }, "engines": { diff --git a/src/flags.ts b/src/flags.ts index 339584fb..07268f57 100644 --- a/src/flags.ts +++ b/src/flags.ts @@ -12,7 +12,7 @@ export function option(options: {parse: OptionFlag['parse']} & Partial(options)() } -export function _enum(opts: EnumFlagOptions & {multiple: true} & ({required: true} | { default: Default })): OptionFlag +export function _enum(opts: EnumFlagOptions & {multiple: true} & ({required: true} | { default: Default })): OptionFlag export function _enum(opts: EnumFlagOptions & {multiple: true}): OptionFlag export function _enum(opts: EnumFlagOptions & ({required: true} | { default: Default })): OptionFlag export function _enum(opts: EnumFlagOptions): OptionFlag diff --git a/src/interfaces/parser.ts b/src/interfaces/parser.ts index 5e804a57..ccd24490 100644 --- a/src/interfaces/parser.ts +++ b/src/interfaces/parser.ts @@ -109,10 +109,30 @@ export type FlagProps = { * Shows this flag in a separate list in the help. */ helpGroup?: string; + /** + * Accept an environment variable as input + */ + env?: string; + /** + * If true, the flag will not be shown in the help. + */ hidden?: boolean; + /** + * If true, the flag will be required. + */ required?: boolean; + /** + * List of flags that this flag depends on. + */ dependsOn?: string[]; + /** + * List of flags that cannot be used with this flag. + */ exclusive?: string[]; + /** + * Exactly one of these flags must be provided. + */ + exactlyOne?: string[]; } export type BooleanFlagProps = FlagProps & { @@ -128,36 +148,33 @@ export type OptionFlagProps = FlagProps & { } export type FlagBase = FlagProps & { - exactlyOne?: string[]; - /** - * also accept an environment variable as input - */ - env?: string; parse(input: I, context: any): Promise; } export type BooleanFlag = FlagBase & BooleanFlagProps & { /** - * specifying a default of false is the same not specifying a default + * specifying a default of false is the same as not specifying a default */ default?: Default; } + export type OptionFlag = FlagBase & OptionFlagProps & { - default?: Default; defaultHelp?: DefaultHelp; input: string[]; -} +} & ({ + default?: Default; + multiple: false; +} | { + default?: Default; + multiple: true; +}) export type Definition = { ( - options: { multiple: true } & ({ required: true } | { default: Default }) & - Partial>, + options: { multiple: true } & ({ required: true } | { default: Default }) & Partial, 'default'>> ): OptionFlag; (options: { multiple: true } & Partial>): OptionFlag; - ( - options: ({ required: true } | { default: Default }) & - Partial>, - ): OptionFlag; + (options: ({ required: true } | { default: Default }) & Partial>): OptionFlag; (options?: Partial>): OptionFlag; } diff --git a/src/parser/flags.ts b/src/parser/flags.ts index eaa8bcd8..b6a0734e 100644 --- a/src/parser/flags.ts +++ b/src/parser/flags.ts @@ -8,9 +8,7 @@ import * as fs from 'fs' export function build( defaults: {parse: OptionFlag['parse']} & Partial>, ): Definition -export function build( - defaults: Partial>, -): Definition +export function build(defaults: Partial>): Definition export function build(defaults: Partial>): Definition { return (options: any = {}) => { return { @@ -35,13 +33,19 @@ export function boolean( } as BooleanFlag } -export function integer(opts: Partial> & {min?: number; max?: number } & {multiple: true} & ({required: true} | { default: Default })): OptionFlag -export function integer(opts: Partial> & {min?: number; max?: number } & {multiple: true}): OptionFlag -export function integer(opts: Partial> & {min?: number; max?: number } & ({required: true} | { default: Default })): OptionFlag -export function integer(opts?: Partial> & {min?: number; max?: number }): OptionFlag -export function integer(opts: Partial> & {min?: number; max?: number } = {}): OptionFlag | OptionFlag | OptionFlag | OptionFlag { +type IntegerFlagOptions = Partial> & { + min?: number; + max?: number; +} + +export function integer(opts: IntegerFlagOptions & {multiple: true} & ({required: true} | { default: Default })): OptionFlag +export function integer(opts: IntegerFlagOptions & {multiple: true}): OptionFlag +export function integer(opts: IntegerFlagOptions & ({required: true} | { default: Default })): OptionFlag +export function integer(opts?: IntegerFlagOptions): OptionFlag +export function integer(opts: IntegerFlagOptions = {}): OptionFlag | OptionFlag | OptionFlag | OptionFlag { return build({ ...opts, + // parse thinks it needs an array to be returned, which is not the case parse: async input => { if (!/^-?\d+$/.test(input)) throw new Error(`Expected an integer but received: ${input}`) @@ -50,16 +54,20 @@ export function integer(opts: Partial> & {min?: number; max?: throw new Error(`Expected an integer greater than or equal to ${opts.min} but received: ${input}`) if (opts.max !== undefined && num > opts.max) throw new Error(`Expected an integer less than or equal to ${opts.max} but received: ${input}`) - return opts.parse ? opts.parse(input, 1) : num + return (opts.parse ? opts.parse(input, 1) : num) }, })() } -export function directory(opts: Partial> & { exists?: boolean } & {multiple: true} & ({required: true} | { default: Default })): OptionFlag -export function directory(opts: Partial> & { exists?: boolean } & {multiple: true}): OptionFlag -export function directory(opts: { exists?: boolean } & Partial> & ({required: true} | { default: Default })): OptionFlag -export function directory(opts?: { exists?: boolean } & Partial>): OptionFlag -export function directory(opts: { exists?: boolean } & Partial> = {}): OptionFlag | OptionFlag | OptionFlag | OptionFlag { +type DirectoryFlagOptions = Partial> & { + exists?: boolean; +} + +export function directory(opts: DirectoryFlagOptions & {multiple: true} & ({required: true} | { default: Default })): OptionFlag +export function directory(opts: DirectoryFlagOptions & {multiple: true}): OptionFlag +export function directory(opts: DirectoryFlagOptions & ({required: true} | { default: Default })): OptionFlag +export function directory(opts?: DirectoryFlagOptions): OptionFlag +export function directory(opts: DirectoryFlagOptions = {}): OptionFlag | OptionFlag | OptionFlag | OptionFlag { return build({ ...opts, parse: async (input: string) => { @@ -73,11 +81,15 @@ export function directory(opts: { exists?: boolean } & Partial> & { exists?: boolean } & {multiple: true} & ({required: true} | { default: Default })): OptionFlag -export function file(opts: Partial> & { exists?: boolean } & {multiple: true}): OptionFlag -export function file(opts: { exists?: boolean } & Partial> & ({required: true} | { default: Default })): OptionFlag -export function file(opts?: { exists?: boolean } & Partial>): OptionFlag -export function file(opts: { exists?: boolean } & Partial> = {}): OptionFlag | OptionFlag | OptionFlag | OptionFlag { +type FileFlagOptions = Partial> & { + exists?: boolean; +} + +export function file(opts: FileFlagOptions & {multiple: true} & ({required: true} | { default: Default })): OptionFlag +export function file(opts: FileFlagOptions & {multiple: true}): OptionFlag +export function file(opts: FileFlagOptions & ({required: true} | { default: Default })): OptionFlag +export function file(opts?: FileFlagOptions): OptionFlag +export function file(opts: FileFlagOptions = {}): OptionFlag | OptionFlag | OptionFlag | OptionFlag { return build({ ...opts, parse: async (input: string) => { diff --git a/test/interfaces/flags.test.ts b/test/interfaces/flags.test.ts new file mode 100644 index 00000000..8dc0b1ce --- /dev/null +++ b/test/interfaces/flags.test.ts @@ -0,0 +1,211 @@ +/** + * This test file contains no unit tests but we use the tsd package to ensure that the types are valid when the tests are compiled + */ + +import Command from '../../src/command' +import * as Flags from '../../src/flags' +import * as Interfaces from '../../src/interfaces' +import {expectType, expectNotType} from 'tsd' +import {URL} from 'url' + +abstract class BaseCommand extends Command { + static enableJsonFlag = true + + static globalFlags = { + config: Flags.string({ + description: 'specify config file', + }), + } +} + +type MyFlags = Interfaces.InferredFlags + +enum MyEnum { + 'A' = 'A', + 'B' = 'B', + 'C' = 'C', +} + +type MyType = { + foo: boolean; +} + +class MyCommand extends BaseCommand { + static description = 'describe the command here' + + static examples = [ + '<%= config.bin %> <%= command.id %>', + ] + + static flags = { + requiredString: Flags.string({required: true}), + optionalString: Flags.string(), + defaultString: Flags.string({default: 'default'}), + + requiredMultiString: Flags.string({required: true, multiple: true}), + optionalMultiString: Flags.string({multiple: true}), + defaultMultiString: Flags.string({multiple: true, default: ['default']}), + + requiredBoolean: Flags.boolean({required: true}), + optionalBoolean: Flags.boolean(), + defaultBoolean: Flags.boolean({default: true}), + + optionalEnum: Flags.enum({options: ['a', 'b', 'c']}), + requiredEnum: Flags.enum({options: ['a', 'b', 'c'], required: true}), + defaultEnum: Flags.enum({options: ['a', 'b', 'c'], default: 'a'}), + + optionalMultiEnum: Flags.enum({multiple: true, options: ['a', 'b', 'c']}), + requiredMultiEnum: Flags.enum({multiple: true, options: ['a', 'b', 'c'], required: true}), + defaultMultiEnum: Flags.enum({multiple: true, options: ['a', 'b', 'c'], default: ['a']}), + + optionalTypedEnum: Flags.enum({options: Object.values(MyEnum)}), + requiredTypedEnum: Flags.enum({options: Object.values(MyEnum), required: true}), + defaultTypedEnum: Flags.enum({options: Object.values(MyEnum), default: MyEnum.A}), + + optionalInteger: Flags.integer(), + requiredInteger: Flags.integer({required: true}), + defaultInteger: Flags.integer({default: 1}), + + optionalMultiInteger: Flags.integer({multiple: true}), + requiredMultiInteger: Flags.integer({multiple: true, required: true}), + defaultMultiInteger: Flags.integer({multiple: true, default: [1]}), + + optionalDirectory: Flags.directory(), + requiredDirectory: Flags.directory({required: true}), + defaultDirectory: Flags.directory({default: 'my-dir'}), + + optionalMultiDirectory: Flags.directory({multiple: true}), + requiredMultiDirectory: Flags.directory({multiple: true, required: true}), + defaultMultiDirectory: Flags.directory({multiple: true, default: ['my-dir']}), + + optionalFile: Flags.file(), + requiredFile: Flags.file({required: true}), + defaultFile: Flags.file({default: 'my-file.json'}), + + optionalMultiFile: Flags.file({multiple: true}), + requiredMultiFile: Flags.file({multiple: true, required: true}), + defaultMultiFile: Flags.file({multiple: true, default: ['my-file.json']}), + + optionalUrl: Flags.url(), + requiredUrl: Flags.url({required: true}), + defaultUrl: Flags.url({default: new URL('http://example.com')}), + + optionalMultiUrl: Flags.url({multiple: true}), + requiredMultiUrl: Flags.url({multiple: true, required: true}), + defaultMultiUrl: Flags.url({multiple: true, default: [new URL('http://example.com')]}), + + optionalCustom: Flags.build({ + parse: async () => ({foo: true}), + })(), + requiredCustom: Flags.build({ + parse: async () => ({foo: true}), + })({required: true}), + defaultCustom: Flags.build({ + parse: async () => ({foo: true}), + })({default: {foo: true}}), + } + + public flags!: MyFlags + + public async run(): Promise { + const result = await this.parse(MyCommand) + this.flags = result.flags + expectType(this.flags) + + expectType(this.flags.requiredString) + expectNotType(this.flags.requiredString) + + expectType(this.flags.defaultString) + expectNotType(this.flags.defaultString) + + expectType(this.flags.optionalString) + + expectType(this.flags.requiredMultiString) + expectNotType(this.flags.requiredMultiString) + + expectType(this.flags.optionalMultiString) + expectType(this.flags.defaultMultiString) + expectNotType(this.flags.defaultMultiString) + + expectType(this.flags.requiredBoolean) + expectNotType(this.flags.requiredBoolean) + expectType(this.flags.defaultBoolean) + expectNotType(this.flags.defaultBoolean) + expectType(this.flags.optionalBoolean) + + expectType(this.flags.requiredEnum) + expectNotType(this.flags.requiredEnum) + expectType(this.flags.defaultEnum) + expectNotType(this.flags.defaultEnum) + expectType(this.flags.optionalEnum) + + expectType(this.flags.requiredMultiEnum) + expectNotType(this.flags.requiredMultiEnum) + expectType(this.flags.defaultMultiEnum) + expectNotType(this.flags.defaultMultiEnum) + expectType(this.flags.optionalMultiEnum) + + expectType(this.flags.requiredTypedEnum) + expectNotType(this.flags.requiredTypedEnum) + expectType(this.flags.defaultTypedEnum) + expectNotType(this.flags.defaultTypedEnum) + expectType(this.flags.optionalTypedEnum) + + expectType(this.flags.requiredInteger) + expectNotType(this.flags.requiredInteger) + expectType(this.flags.defaultInteger) + expectNotType(this.flags.defaultInteger) + expectType(this.flags.optionalInteger) + + expectType(this.flags.requiredMultiInteger) + expectNotType(this.flags.requiredMultiInteger) + expectType(this.flags.defaultMultiInteger) + expectNotType(this.flags.defaultMultiInteger) + expectType(this.flags.optionalMultiInteger) + + expectType(this.flags.requiredDirectory) + expectNotType(this.flags.requiredDirectory) + expectType(this.flags.defaultDirectory) + expectNotType(this.flags.defaultDirectory) + expectType(this.flags.optionalDirectory) + + expectType(this.flags.requiredMultiDirectory) + expectNotType(this.flags.requiredMultiDirectory) + expectType(this.flags.defaultMultiDirectory) + expectNotType(this.flags.defaultMultiDirectory) + expectType(this.flags.optionalMultiDirectory) + + expectType(this.flags.requiredFile) + expectNotType(this.flags.requiredFile) + expectType(this.flags.defaultFile) + expectNotType(this.flags.defaultFile) + expectType(this.flags.optionalFile) + + expectType(this.flags.requiredMultiFile) + expectNotType(this.flags.requiredMultiFile) + expectType(this.flags.defaultMultiFile) + expectNotType(this.flags.defaultMultiFile) + expectType(this.flags.optionalMultiFile) + + expectType(this.flags.requiredUrl) + expectNotType(this.flags.requiredUrl) + expectType(this.flags.defaultUrl) + expectNotType(this.flags.defaultUrl) + expectType(this.flags.optionalUrl) + + expectType(this.flags.requiredMultiUrl) + expectNotType(this.flags.requiredMultiUrl) + expectType(this.flags.defaultMultiUrl) + expectNotType(this.flags.defaultMultiUrl) + expectType(this.flags.optionalMultiUrl) + + expectType(this.flags.requiredCustom) + expectNotType(this.flags.requiredCustom) + expectType(this.flags.defaultCustom) + expectNotType(this.flags.defaultCustom) + expectType(this.flags.optionalCustom) + + return result.flags + } +} + diff --git a/tsconfig.json b/tsconfig.json index c994370d..42c61dcd 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -11,7 +11,8 @@ "strict": true, "target": "es2020", "lib": ["es2020"], - "allowSyntheticDefaultImports": true + "allowSyntheticDefaultImports": true, + "noErrorTruncation": true, }, "include": [ "./src/**/*" diff --git a/yarn.lock b/yarn.lock index 8169165d..09e6ab1e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -520,6 +520,11 @@ resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz#8da5c6530915653f3a1f38fd5f101d8c3f8079c5" integrity sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ== +"@tsd/typescript@~4.7.4": + version "4.7.4" + resolved "https://registry.yarnpkg.com/@tsd/typescript/-/typescript-4.7.4.tgz#f1e4e6c3099a174a0cb7aa51cf53f34f6494e528" + integrity sha512-jbtC+RgKZ9Kk65zuRZbKLTACf+tvFW4Rfq0JEMXrlmV3P3yme+Hm+pnb5fJRyt61SjIitcrC810wj7+1tgsEmg== + "@types/ansi-styles@^3.2.1": version "3.2.1" resolved "https://registry.yarnpkg.com/@types/ansi-styles/-/ansi-styles-3.2.1.tgz#49e996bb6e0b7957ca831205df31eb9a0702492c" @@ -563,6 +568,19 @@ resolved "https://registry.yarnpkg.com/@types/ejs/-/ejs-3.1.0.tgz#ab8109208106b5e764e5a6c92b2ba1c625b73020" integrity sha512-DCg+Ka+uDQ31lJ/UtEXVlaeV3d6t81gifaVWKJy4MYVVgvJttyX/viREy+If7fz+tK/gVxTGMtyrFPnm4gjrVA== +"@types/eslint@^7.2.13": + version "7.29.0" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-7.29.0.tgz#e56ddc8e542815272720bb0b4ccc2aff9c3e1c78" + integrity sha512-VNcvioYDH8/FxaeTKkM4/TiTwt6pBV9E3OfGmvaw8tPl0rrHCJ4Ll15HRT+pMiFAf/MLQvAzC+6RzUMEL9Ceng== + dependencies: + "@types/estree" "*" + "@types/json-schema" "*" + +"@types/estree@*": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.0.tgz#5fb2e536c1ae9bf35366eed879e827fa59ca41c2" + integrity sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ== + "@types/fs-extra@^9.0.13": version "9.0.13" resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-9.0.13.tgz#7594fbae04fe7f1918ce8b3d213f74ff44ac1f45" @@ -590,6 +608,11 @@ resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-3.12.7.tgz#330c5d97a3500e9c903210d6e49f02964af04a0e" integrity sha512-S6+8JAYTE1qdsc9HMVsfY7+SgSuUU/Tp6TYTmITW0PZxiyIMvol3Gy//y69Wkhs0ti4py5qgR3uZH6uz/DNzJQ== +"@types/json-schema@*": + version "7.0.11" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" + integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== + "@types/json-schema@^7.0.7": version "7.0.9" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" @@ -813,7 +836,7 @@ ansi-escapes@^3.1.0: resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== -ansi-escapes@^4.3.0, ansi-escapes@^4.3.2: +ansi-escapes@^4.2.1, ansi-escapes@^4.3.0, ansi-escapes@^4.3.2: version "4.3.2" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== @@ -1258,7 +1281,7 @@ decamelize-keys@^1.1.0: decamelize "^1.1.0" map-obj "^1.0.0" -decamelize@^1.1.0: +decamelize@^1.1.0, decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= @@ -1411,6 +1434,20 @@ eslint-config-xo@^0.38.0: dependencies: confusing-browser-globals "1.0.10" +eslint-formatter-pretty@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/eslint-formatter-pretty/-/eslint-formatter-pretty-4.1.0.tgz#7a6877c14ffe2672066c853587d89603e97c7708" + integrity sha512-IsUTtGxF1hrH6lMWiSl1WbGaiP01eT6kzywdY1U+zLc0MP+nwEnUiS9UI8IaOTUhTeQJLlCEWIbXINBH4YJbBQ== + dependencies: + "@types/eslint" "^7.2.13" + ansi-escapes "^4.2.1" + chalk "^4.1.0" + eslint-rule-docs "^1.1.5" + log-symbols "^4.0.0" + plur "^4.0.0" + string-width "^4.2.0" + supports-hyperlinks "^2.0.0" + eslint-plugin-es@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz#75a7cdfdccddc0589934aeeb384175f221c57893" @@ -1457,6 +1494,11 @@ eslint-plugin-unicorn@^36.0.0: safe-regex "^2.1.1" semver "^7.3.5" +eslint-rule-docs@^1.1.5: + version "1.1.235" + resolved "https://registry.yarnpkg.com/eslint-rule-docs/-/eslint-rule-docs-1.1.235.tgz#be6ef1fc3525f17b3c859ae2997fedadc89bfb9b" + integrity sha512-+TQ+x4JdTnDoFEXXb3fDvfGOwnyNV7duH8fXWTPD1ieaBmB8omj7Gw/pMBBu4uI2uJCCU8APDaQJzWuXnTsH4A== + eslint-scope@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" @@ -1824,7 +1866,7 @@ globals@^13.6.0, globals@^13.9.0: dependencies: type-fest "^0.20.2" -globby@^11.0.3, globby@^11.0.4, globby@^11.1.0: +globby@^11.0.1, globby@^11.0.3, globby@^11.0.4, globby@^11.1.0: version "11.1.0" resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== @@ -1963,6 +2005,11 @@ interpret@^1.0.0: resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== +irregular-plurals@^3.2.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/irregular-plurals/-/irregular-plurals-3.3.0.tgz#67d0715d4361a60d9fd9ee80af3881c631a31ee2" + integrity sha512-MVBLKUTangM3EfRPFROhmWQQKRDsrgI83J8GS3jXy+OwYqiR2/aoWndYQ5416jLE3uaGgLH7ncme3X9y09gZ3g== + is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" @@ -2058,6 +2105,11 @@ is-text-path@^1.0.1: dependencies: text-extensions "^1.0.0" +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + is-wsl@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" @@ -2246,6 +2298,14 @@ log-symbols@4.0.0: dependencies: chalk "^4.0.0" +log-symbols@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" + loupe@^2.3.1: version "2.3.4" resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.4.tgz#7e0b9bffc76f148f9be769cb1321d3dcf3cb25f3" @@ -2292,6 +2352,24 @@ meow@^8.0.0: type-fest "^0.18.0" yargs-parser "^20.2.3" +meow@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/meow/-/meow-9.0.0.tgz#cd9510bc5cac9dee7d03c73ee1f9ad959f4ea364" + integrity sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ== + dependencies: + "@types/minimist" "^1.2.0" + camelcase-keys "^6.2.2" + decamelize "^1.2.0" + decamelize-keys "^1.1.0" + hard-rejection "^2.1.0" + minimist-options "4.1.0" + normalize-package-data "^3.0.0" + read-pkg-up "^7.0.1" + redent "^3.0.0" + trim-newlines "^3.0.0" + type-fest "^0.18.0" + yargs-parser "^20.2.3" + merge-descriptors@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" @@ -2617,6 +2695,13 @@ pify@^4.0.1: resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== +plur@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/plur/-/plur-4.0.0.tgz#729aedb08f452645fe8c58ef115bf16b0a73ef84" + integrity sha512-4UGewrYgqDFw9vV6zNV+ADmPAUAfJPKtGvb/VdpQAx25X5f3xXdGdyOEVFwkl8Hl/tl7+xbeHqSEM+D5/TirUg== + dependencies: + irregular-plurals "^3.2.0" + pluralize@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1" @@ -2678,7 +2763,7 @@ randombytes@^2.1.0: dependencies: safe-buffer "^5.1.0" -read-pkg-up@^7.0.1: +read-pkg-up@^7.0.0, read-pkg-up@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507" integrity sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg== @@ -3061,7 +3146,7 @@ supports-color@^7.0.0, supports-color@^7.1.0, supports-color@^7.2.0: dependencies: has-flag "^4.0.0" -supports-hyperlinks@^2.2.0: +supports-hyperlinks@^2.0.0, supports-hyperlinks@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz#4f77b42488765891774b70c79babd87f9bd594bb" integrity sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ== @@ -3137,6 +3222,18 @@ ts-node@^9.1.1: source-map-support "^0.5.17" yn "3.1.1" +tsd@^0.22.0: + version "0.22.0" + resolved "https://registry.yarnpkg.com/tsd/-/tsd-0.22.0.tgz#2ff75cf3adff5136896abee1f2c5540497bf3b54" + integrity sha512-NH+tfEDQ0Ze8gH7TorB6IxYybD+M68EYawe45YNVrbQcydNBfdQHP9IiD0QbnqmwNXrv+l9GAiULT68mo4q/xA== + dependencies: + "@tsd/typescript" "~4.7.4" + eslint-formatter-pretty "^4.1.0" + globby "^11.0.1" + meow "^9.0.0" + path-exists "^4.0.0" + read-pkg-up "^7.0.0" + tslib@^1.8.1: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"