@oclif/core
Version:
base library for oclif CLIs
464 lines (463 loc) • 15.6 kB
TypeScript
import { Command } from '../command';
import { AlphabetLowercase, AlphabetUppercase } from './alphabet';
export type FlagOutput = {
[name: string]: any;
};
export type ArgOutput = {
[name: string]: any;
};
export type CLIParseErrorOptions = {
parse: {
input?: ParserInput | undefined;
output?: ParserOutput | undefined;
};
exit?: number | undefined;
};
export type OutputArgs<T extends ParserInput['args']> = {
[P in keyof T]: any;
};
export type OutputFlags<T extends ParserInput['flags']> = {
[P in keyof T]: any;
};
export type ParserOutput<TFlags extends OutputFlags<any> = any, BFlags extends OutputFlags<any> = any, TArgs extends OutputFlags<any> = any> = {
flags: TFlags & BFlags & {
json: boolean | undefined;
};
args: TArgs;
argv: unknown[];
raw: ParsingToken[];
metadata: Metadata;
nonExistentFlags: string[];
};
export type ArgToken = {
type: 'arg';
arg: string;
input: string;
};
export type FlagToken = {
type: 'flag';
flag: string;
input: string;
};
export type ParsingToken = ArgToken | FlagToken;
export type FlagUsageOptions = {
displayRequired?: boolean;
};
export type Metadata = {
flags: {
[key: string]: MetadataFlag;
};
};
export type MetadataFlag = {
setFromDefault?: boolean;
defaultHelp?: unknown;
};
export type ListItem = [string, string | undefined];
export type List = ListItem[];
export type CustomOptions = Record<string, unknown>;
export type DefaultContext<T> = {
options: T;
flags: Record<string, string>;
};
/**
* Type to define a default value for a flag.
* @param context The context of the flag.
*/
export type FlagDefault<T, P = CustomOptions> = T | ((context: DefaultContext<P & OptionFlag<T, P>>) => Promise<T>);
/**
* Type to define a defaultHelp value for a flag.
* The defaultHelp value is used in the help output for the flag and when writing a manifest.
* It is also can be used to provide a value for the flag when issuing certain error messages.
*
* @param context The context of the flag.
*/
export type FlagDefaultHelp<T, P = CustomOptions> = T | ((context: DefaultContext<P & OptionFlag<T, P>>) => Promise<string | undefined>);
/**
* Type to define a default value for an arg.
* @param context The context of the arg.
*/
export type ArgDefault<T, P = CustomOptions> = T | ((context: DefaultContext<Arg<T, P>>) => Promise<T>);
/**
* Type to define a defaultHelp value for an arg.
* @param context The context of the arg.
*/
export type ArgDefaultHelp<T, P = CustomOptions> = T | ((context: DefaultContext<Arg<T, P>>) => Promise<string | undefined>);
export type FlagRelationship = string | {
name: string;
when: (flags: Record<string, unknown>) => Promise<boolean>;
};
export type Relationship = {
type: 'all' | 'some' | 'none';
flags: FlagRelationship[];
};
export type Deprecation = {
to?: string;
message?: string;
version?: string | number;
};
export type FlagProps = {
name: string;
char?: AlphabetLowercase | AlphabetUppercase;
/**
* A short summary of flag usage to show in the flag list.
* If not provided, description will be used.
*/
summary?: string;
/**
* A description of flag usage. If summary is provided, the description
* is assumed to be a longer description and will be shown in a separate
* section within help.
*/
description?: string;
/**
* The flag label to show in help. Defaults to "[-<char>] --<name>" where -<char> is
* only displayed if the char is defined.
*/
helpLabel?: string;
/**
* 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[];
/**
* Define complex relationships between flags.
*/
relationships?: Relationship[];
/**
* Make the flag as deprecated.
*/
deprecated?: true | Deprecation;
/**
* Alternate names that can be used for this flag.
*/
aliases?: string[];
/**
* Alternate short chars that can be used for this flag.
*/
charAliases?: (AlphabetLowercase | AlphabetUppercase)[];
/**
* Emit deprecation warning when a flag alias is provided
*/
deprecateAliases?: boolean;
/**
* If true, the value returned by defaultHelp will not be cached in the oclif.manifest.json.
* This is helpful if the default value contains sensitive data that shouldn't be published to npm.
*/
noCacheDefault?: boolean;
/**
* At least one of these flags must be provided.
*/
atLeastOne?: string[];
};
export type ArgProps = {
name: string;
/**
* A description of flag usage. If summary is provided, the description
* is assumed to be a longer description and will be shown in a separate
* section within help.
*/
description?: string;
/**
* If true, the flag will not be shown in the help.
*/
hidden?: boolean;
/**
* If true, the flag will be required.
*/
required?: boolean;
options?: string[];
ignoreStdin?: boolean;
/**
* If true, the value returned by defaultHelp will not be cached in the oclif.manifest.json.
* This is helpful if the default value contains sensitive data that shouldn't be published to npm.
*/
noCacheDefault?: boolean;
};
export type BooleanFlagProps = FlagProps & {
type: 'boolean';
allowNo: boolean;
};
export type OptionFlagProps = FlagProps & {
type: 'option';
helpValue?: string | string[];
options?: readonly string[];
multiple?: boolean;
/**
* Parse one value per flag; allow `-m val1 -m val2`, disallow `-m val1 val2`.
* Set to true to use "multiple: true" flags together with args.
* Only respected if multiple is set to true.
*/
multipleNonGreedy?: boolean;
/**
* Delimiter to separate the values for a multiple value flag.
* Only respected if multiple is set to true. Default behavior is to
* separate on spaces.
*/
delimiter?: ',';
/**
* Allow input value to be read from stdin if the provided value is `-`.
* If set to `only`, the flag will only accept input from stdin.
* Should only be used on one flag at a time.
*/
allowStdin?: boolean | 'only';
};
export type FlagParserContext = Command & {
token: FlagToken;
};
type NonNullableElementOf<T> = [NonNullable<T>] extends [Array<infer U>] ? U : T;
export type FlagParser<T, I extends string | boolean, P = CustomOptions> = (input: I, context: FlagParserContext, opts: P & OptionFlag<T, P>) => Promise<NonNullableElementOf<T> | undefined>;
export type ArgParserContext = Command & {
token: ArgToken;
};
export type ArgParser<T, P = CustomOptions> = (input: string, context: ArgParserContext, opts: P & Arg<T, P>) => Promise<T>;
export type Arg<T, P = CustomOptions> = ArgProps & {
options?: T[];
defaultHelp?: ArgDefaultHelp<T>;
input: string[];
default?: ArgDefault<T | undefined>;
parse: ArgParser<T, P>;
};
export type ArgDefinition<T, P = CustomOptions> = {
(options: P & ({
required: true;
} | {
default: ArgDefault<T>;
}) & Partial<Arg<T, P>>): Arg<T, P>;
(options?: P & Partial<Arg<T, P>>): Arg<T | undefined, P>;
};
export type BooleanFlag<T> = FlagProps & BooleanFlagProps & {
/**
* specifying a default of false is the same as not specifying a default
*/
default?: FlagDefault<boolean>;
parse: (input: boolean, context: FlagParserContext, opts: FlagProps & BooleanFlagProps) => Promise<T>;
};
export type OptionFlag<T, P = CustomOptions> = FlagProps & OptionFlagProps & {
parse: FlagParser<T | undefined, string, P>;
defaultHelp?: FlagDefaultHelp<T, P>;
input: string[];
default?: FlagDefault<T | undefined, P>;
};
type ReturnTypeSwitches = {
multiple: boolean;
requiredOrDefaulted: boolean;
};
/**
* The logic here is as follows:
* - If requiredOrDefaulted is true && multiple is true, then the return type is T[]
* - It's possible that T extends an Array, if so we want to return T so that the return isn't T[][]
* - If requiredOrDefaulted is true && multiple is false, then the return type is T
* - If requiredOrDefaulted is false && multiple is true, then the return type is T[] | undefined
* - It's possible that T extends an Array, if so we want to return T so that the return isn't T[][]
* - If requiredOrDefaulted is false && multiple is false, then the return type is T | undefined
*/
type FlagReturnType<T, R extends ReturnTypeSwitches> = R['requiredOrDefaulted'] extends true ? R['multiple'] extends true ? [T] extends [Array<unknown>] ? T : T[] : T : R['multiple'] extends true ? [T] extends [Array<unknown>] ? T | undefined : T[] | undefined : T | undefined;
/**
* FlagDefinition types a function that takes `options` and returns an OptionFlag<T>.
*
* This is returned by `Flags.custom()` and `Flags.option()`, which each take a `defaults` object
* that mirrors the OptionFlag interface.
*
* The `T` in the `OptionFlag<T>` return type is determined by a combination of the provided defaults for
* `multiple`, `required`, and `default` and the provided options for those same properties. If these properties
* are provided in the options, they override the defaults.
*
* no options or defaults -> T | undefined
* `required` -> T
* `default` -> T
* `multiple` -> T[] | undefined
* `required` + `multiple` -> T[]
* `default` + `multiple` -> T[]
*/
export type FlagDefinition<T, P = CustomOptions, R extends ReturnTypeSwitches = {
multiple: false;
requiredOrDefaulted: false;
}> = {
(options: P & {
multiple: false;
required: true;
} & Partial<OptionFlag<FlagReturnType<T, {
multiple: false;
requiredOrDefaulted: true;
}>, P>>): OptionFlag<FlagReturnType<T, {
multiple: false;
requiredOrDefaulted: true;
}>>;
(options: P & {
multiple: true;
required: false;
} & Partial<OptionFlag<FlagReturnType<T, {
multiple: true;
requiredOrDefaulted: false;
}>, P>>): OptionFlag<FlagReturnType<T, {
multiple: true;
requiredOrDefaulted: false;
}>>;
(options: P & {
multiple: false;
required: false;
} & Partial<OptionFlag<FlagReturnType<T, {
multiple: false;
requiredOrDefaulted: false;
}>, P>>): OptionFlag<FlagReturnType<T, {
multiple: false;
requiredOrDefaulted: false;
}>>;
(options: R['multiple'] extends true ? // `multiple` is defaulted to true and either `required=true` or `default` are provided in options
P & ({
required: true;
} | {
default: OptionFlag<FlagReturnType<T, {
multiple: R['multiple'];
requiredOrDefaulted: true;
}>, P>['default'];
}) & Partial<OptionFlag<FlagReturnType<T, {
multiple: R['multiple'];
requiredOrDefaulted: true;
}>, P>> : // `multiple` is NOT defaulted to true and either `required=true` or `default` are provided in options
P & {
multiple?: false | undefined;
} & ({
required: true;
} | {
default: OptionFlag<FlagReturnType<T, {
multiple: R['multiple'];
requiredOrDefaulted: true;
}>, P>['default'];
}) & Partial<OptionFlag<FlagReturnType<T, {
multiple: R['multiple'];
requiredOrDefaulted: true;
}>, P>>): OptionFlag<FlagReturnType<T, {
multiple: R['multiple'];
requiredOrDefaulted: true;
}>>;
(options: R['multiple'] extends true ? // `multiple` is defaulted to true and either `required=true` or `default` are provided in options
P & ({
required: true;
} | {
default: OptionFlag<FlagReturnType<T, {
multiple: true;
requiredOrDefaulted: true;
}>, P>['default'];
}) & Partial<OptionFlag<FlagReturnType<T, {
multiple: true;
requiredOrDefaulted: true;
}>, P>> : // `multiple` is NOT defaulted to true but `multiple=true` and either `required=true` or `default` are provided in options
P & {
multiple: true;
} & ({
required: true;
} | {
default: OptionFlag<FlagReturnType<T, {
multiple: true;
requiredOrDefaulted: true;
}>, P>['default'];
}) & Partial<OptionFlag<FlagReturnType<T, {
multiple: true;
requiredOrDefaulted: true;
}>, P>>): OptionFlag<FlagReturnType<T, {
multiple: true;
requiredOrDefaulted: true;
}>>;
(options: P & {
multiple?: false | undefined;
} & ({
required: true;
} | {
default: OptionFlag<FlagReturnType<T, {
multiple: R['multiple'];
requiredOrDefaulted: true;
}>, P>['default'];
}) & Partial<OptionFlag<FlagReturnType<T, {
multiple: R['multiple'];
requiredOrDefaulted: true;
}>, P>>): OptionFlag<FlagReturnType<T, {
multiple: R['multiple'];
requiredOrDefaulted: true;
}>>;
(options: P & {
required: false;
} & Partial<OptionFlag<FlagReturnType<T, {
multiple: R['multiple'];
requiredOrDefaulted: false;
}>, P>>): OptionFlag<FlagReturnType<T, {
multiple: R['multiple'];
requiredOrDefaulted: false;
}>>;
(options: P & {
multiple: false;
} & Partial<OptionFlag<FlagReturnType<T, {
multiple: false;
requiredOrDefaulted: R['requiredOrDefaulted'];
}>, P>>): OptionFlag<FlagReturnType<T, {
multiple: false;
requiredOrDefaulted: R['requiredOrDefaulted'];
}>>;
(options?: P & {
multiple?: false | undefined;
} & Partial<OptionFlag<FlagReturnType<T, R>, P>>): OptionFlag<FlagReturnType<T, R>>;
(options: P & {
multiple: true;
} & Partial<OptionFlag<FlagReturnType<T, {
multiple: true;
requiredOrDefaulted: R['requiredOrDefaulted'];
}>, P>>): OptionFlag<FlagReturnType<T, {
multiple: true;
requiredOrDefaulted: R['requiredOrDefaulted'];
}>>;
};
export type Flag<T> = BooleanFlag<T> | OptionFlag<T>;
export type Input<TFlags extends FlagOutput, BFlags extends FlagOutput, AFlags extends ArgOutput> = {
flags?: FlagInput<TFlags>;
baseFlags?: FlagInput<BFlags>;
enableJsonFlag?: true | false;
args?: ArgInput<AFlags>;
strict?: boolean | undefined;
context?: ParserContext;
'--'?: boolean;
};
export type ParserInput = {
argv: string[];
flags: FlagInput<any>;
args: ArgInput<any>;
strict: boolean;
context: ParserContext | undefined;
'--'?: boolean | undefined;
};
export type ParserContext = Command & {
token?: FlagToken | ArgToken | undefined;
};
export type FlagInput<T extends FlagOutput = {
[flag: string]: any;
}> = {
[P in keyof T]: Flag<T[P]>;
};
export type ArgInput<T extends ArgOutput = {
[arg: string]: any;
}> = {
[P in keyof T]: Arg<T[P]>;
};
export {};