UNPKG

@clerc/core

Version:
499 lines (487 loc) 17.5 kB
import { Equals, Dict, CamelCase, MaybeArray as MaybeArray$1 } from '@clerc/utils'; import { OmitIndexSignature, LiteralUnion, Simplify } from 'type-fest'; declare const DOUBLE_DASH = "--"; type TypeFunction<ReturnType = any> = (value: any) => ReturnType; type TypeFunctionArray<ReturnType> = readonly [TypeFunction<ReturnType>]; type FlagType<ReturnType = any> = TypeFunction<ReturnType> | TypeFunctionArray<ReturnType>; type FlagSchemaBase<TF> = { /** * Type of the flag as a function that parses the argv string and returns the * parsed value. * * @example * * ``` * type: String; * ``` * * @example Wrap in an array to accept multiple values. `type: [Boolean]` * * @example Custom function type that uses moment.js to parse string as date. * `type: function CustomDate(value: string) { return moment(value).toDate(); * }` */ type: TF; /** * A single-character alias for the flag. * * @example * * ``` * alias: "s"; * ``` */ alias?: string; } & Record<PropertyKey, unknown>; type FlagSchemaDefault<TF, DefaultType = any> = FlagSchemaBase<TF> & { /** * Default value of the flag. Also accepts a function that returns the default * value. [Default: undefined] * * @example * * ``` * default: 'hello' * ``` * * @example * * ``` * default: () => [1, 2, 3] * ``` */ default: DefaultType | (() => DefaultType); }; type FlagSchema<TF = FlagType> = FlagSchemaBase<TF> | FlagSchemaDefault<TF>; type FlagTypeOrSchema<ExtraOptions = Record<string, unknown>> = FlagType | (FlagSchema & ExtraOptions); type Flags$1<ExtraOptions = Record<string, unknown>> = Record<string, FlagTypeOrSchema<ExtraOptions>>; type InferFlagType<Flag extends FlagTypeOrSchema> = Flag extends TypeFunctionArray<infer T> | FlagSchema<TypeFunctionArray<infer T>> ? Flag extends FlagSchemaDefault<TypeFunctionArray<T>, infer D> ? T[] | D : T[] : Flag extends TypeFunction<infer T> | FlagSchema<TypeFunction<infer T>> ? Flag extends FlagSchemaDefault<TypeFunction<T>, infer D> ? T | D : T | undefined : never; interface ParsedFlags<Schemas = Record<string, unknown>> { flags: Schemas; unknownFlags: Record<string, (string | boolean)[]>; _: string[] & { [DOUBLE_DASH]: string[]; }; } type TypeFlag<Schemas extends Flags$1> = ParsedFlags<{ [flag in keyof Schemas]: InferFlagType<Schemas[flag]>; }>; type StripBrackets<Parameter extends string> = Parameter extends `<${infer ParameterName}>` | `[${infer ParameterName}]` ? ParameterName extends `${infer SpreadName}...` ? SpreadName : ParameterName : never; type ParameterType<Parameter extends string> = Parameter extends `<${infer _ParameterName}...>` | `[${infer _ParameterName}...]` ? string[] : Parameter extends `<${infer _ParameterName}>` ? string : Parameter extends `[${infer _ParameterName}]` ? string | undefined : never; type NonNullableParameters<T extends string[] | undefined> = T extends undefined ? [] : NonNullable<T>; type TransformParameters<C extends Command> = { [Parameter in NonNullableParameters<C["parameters"]>[number] as CamelCase<StripBrackets<Parameter>>]: ParameterType<Parameter>; }; type MakeEventMap<T extends Commands> = { [K in keyof T]: [InterceptorContext]; }; type FallbackFlags<F extends Flags | undefined> = Equals<NonNullableFlag<F>["flags"], {}> extends true ? Dict<any> : NonNullableFlag<F>["flags"]; type NonNullableFlag<F extends Flags | undefined> = TypeFlag<NonNullable<F>>; type ParseFlag<C extends Commands, N extends keyof C, GF extends GlobalFlagOptions = {}> = N extends keyof C ? OmitIndexSignature<NonNullableFlag<C[N]["flags"] & GF>["flags"]> : FallbackFlags<C[N]["flags"] & GF>["flags"]; type ParseRaw<C extends Command, GF extends GlobalFlagOptions = {}> = NonNullableFlag<C["flags"] & GF> & { flags: FallbackFlags<C["flags"] & GF>; parameters: string[]; mergedFlags: FallbackFlags<C["flags"] & GF> & NonNullableFlag<C["flags"] & GF>["unknownFlags"]; }; type ParseParameters<C extends Commands = Commands, N extends keyof C = keyof C> = Equals<TransformParameters<C[N]>, {}> extends true ? N extends keyof C ? TransformParameters<C[N]> : Dict<string | string[] | undefined> : TransformParameters<C[N]>; type Locales = Dict<Dict<string>>; type TranslateFn = (name: string, ...args: string[]) => string | undefined; interface I18N { add: (locales: Locales) => void; t: TranslateFn; } interface Plugin<T extends Clerc = Clerc, U extends Clerc = Clerc> { setup: (cli: T) => U; } type CommandType = RootType | string; type FlagOptions = FlagSchema & { description: string; }; type Flag = FlagOptions & { name: string; }; type GlobalFlagOption = FlagSchema; type Flags = Dict<FlagOptions>; type GlobalFlagOptions = Dict<GlobalFlagOption>; declare interface CommandCustomProperties { } interface CommandOptions<P extends string[] = string[], A extends MaybeArray$1<string | RootType> = MaybeArray$1<string | RootType>, F extends Flags = Flags> extends CommandCustomProperties { alias?: A; parameters?: P; flags?: F; } type Command<N extends string | RootType = string, O extends CommandOptions = CommandOptions> = O & { name: N; description: string; }; type CommandAlias<N extends string | RootType = string, O extends CommandOptions = CommandOptions> = Command<N, O> & { __isAlias?: true; }; type CommandWithHandler<N extends string | RootType = string, O extends CommandOptions = CommandOptions> = Command<N, O> & { handler?: HandlerInCommand<HandlerContext<Record<N, Command<N, O>> & Record<never, never>, N>>; }; type Commands = Dict<Command> & { [Root]?: Command; }; interface ParseOptions { argv?: string[]; run?: boolean; } interface HandlerContext<C extends Commands = Commands, N extends keyof C = keyof C, GF extends GlobalFlagOptions = {}> { name?: LiteralUnion<N, string>; called?: string | RootType; resolved: boolean; hasRootOrAlias: boolean; hasRoot: boolean; raw: Simplify<ParseRaw<C[N], GF>>; parameters: Simplify<ParseParameters<C, N>>; unknownFlags: ParsedFlags["unknownFlags"]; flags: Simplify<ParseFlag<C, N, GF> & Record<string, any>>; cli: Clerc<C, GF>; } type Handler<C extends Commands = Commands, K extends keyof C = keyof C, GF extends GlobalFlagOptions = {}> = (ctx: HandlerContext<C, K, GF>) => void; type HandlerInCommand<C extends HandlerContext> = (ctx: { [K in keyof C]: C[K]; }) => void; type FallbackType<T, U> = {} extends T ? U : T; /** * @deprecated This is a typo. Use `InterceptorContext` instead. */ type InspectorContext<C extends Commands = Commands> = InterceptorContext<C>; /** * @deprecated This is a typo. Use `Interceptor` instead. */ type Inspector<C extends Commands = Commands> = Interceptor<C>; /** * @deprecated This is a typo. Use `InspectorFn` instead. */ type InspectorFn<C extends Commands = Commands> = InterceptorFn<C>; /** * @deprecated This is a typo. Use `InspectorObject` instead. */ type InspectorObject<C extends Commands = Commands> = InterceptorObject<C>; type InterceptorContext<C extends Commands = Commands> = HandlerContext<C> & { flags: FallbackType<TypeFlag<NonNullable<C[keyof C]["flags"]>>["flags"], Dict<any>>; }; type Interceptor<C extends Commands = Commands> = InterceptorFn<C> | InterceptorObject<C>; type InterceptorFn<C extends Commands = Commands> = (ctx: InterceptorContext<C>, next: () => void) => void; interface InterceptorObject<C extends Commands = Commands> { enforce?: "pre" | "post"; fn: InterceptorFn<C>; } declare const Root: unique symbol; type RootType = typeof Root; declare class Clerc<C extends Commands = {}, GF extends GlobalFlagOptions = {}> { #private; get i18n(): I18N; private constructor(); get _name(): string; get _scriptName(): string; get _description(): string; get _version(): string; /** * @deprecated This is a typo. Use `_interceptor` instead. */ get _inspectors(): Interceptor[]; get _interceptors(): Interceptor[]; get _commands(): C; get _flags(): GF; /** * Create a new cli * * @example * * ```ts * const cli = Clerc.create(); * ``` * * @param name * @param description * @param version * @returns */ static create(name?: string, description?: string, version?: string): Clerc<{}, {}>; /** * Set the name of the cli * * @example * * ```ts * Clerc.create().name("test"); * ``` * * @param name * @returns */ name(name: string): this; /** * Set the script name of the cli * * @example * * ```ts * Clerc.create().scriptName("test"); * ``` * * @param scriptName * @returns */ scriptName(scriptName: string): this; /** * Set the description of the cli * * @example * * ```ts * Clerc.create().description("test cli"); * ``` * * @param description * @returns */ description(description: string): this; /** * Set the version of the cli * * @example * * ```ts * Clerc.create().version("1.0.0"); * ``` * * @param version * @returns */ version(version: string): this; /** * Set the Locale You must call this method once after you created the Clerc * instance. * * @example * * ```ts * Clerc.create() * .locale("en") * .command(...) * ``` * * @param locale * @returns */ locale(locale: string): this; /** * Set the fallback Locale You must call this method once after you created * the Clerc instance. * * @example * * ```ts * Clerc.create() * .fallbackLocale("en") * .command(...) * ``` * * @param fallbackLocale * @returns */ fallbackLocale(fallbackLocale: string): this; /** * Register a error handler * * @example * * ```ts * Clerc.create().errorHandler((err) => { * console.log(err); * }); * ``` * * @param handler * @returns */ errorHandler(handler: (err: any) => void): this; /** * Register a command * * @example * * ```ts * Clerc.create().command("test", "test command", { * alias: "t", * flags: { * foo: { * alias: "f", * description: "foo flag", * }, * }, * }); * ``` * * @example * * ```ts * Clerc.create().command("", "root", { * flags: { * foo: { * alias: "f", * description: "foo flag", * }, * }, * }); * ``` * * @param name * @param description * @param options * @returns */ command<C extends CommandWithHandler<any, any>[]>(c: [...C]): this; command<N extends string | RootType, O extends CommandOptions<[...P], A, F>, P extends string[] = string[], A extends MaybeArray$1<string | RootType> = MaybeArray$1<string | RootType>, F extends Flags = Flags>(c: CommandWithHandler<N, O & CommandOptions<[...P], A, F>>): this & Clerc<C & Record<N, Command<N, O>>, GF>; command<N extends string | RootType, O extends CommandOptions<[...P], A, F>, P extends string[] = string[], A extends MaybeArray$1<string | RootType> = MaybeArray$1<string | RootType>, F extends Flags = Flags>(name: N, description: string, options?: O & CommandOptions<[...P], A, F>): this & Clerc<C & Record<N, Command<N, O>>, GF>; /** * Register a global flag * * @example * * ```ts * Clerc.create().flag("help", "help", { * alias: "h", * type: Boolean, * }); * ``` * * @param name * @param description * @param options * @returns */ flag<N extends string, O extends GlobalFlagOption>(name: N, description: string, options: O): this & Clerc<C, GF & Record<N, O>>; /** * Register a handler * * @example * * ```ts * Clerc.create() * .command("test", "test command") * .on("test", (ctx) => { * console.log(ctx); * }); * ``` * * @param name * @param handler * @returns */ on<K extends LiteralUnion<keyof CM, string | RootType>, CM extends this["_commands"] = this["_commands"]>(name: K, handler: Handler<CM, K, this["_flags"]>): this; /** * Use a plugin * * @example * * ```ts * Clerc.create().use(plugin); * ``` * * @param plugin * @returns */ use<T extends Clerc, U extends Clerc>(plugin: Plugin<T, U>): this & Clerc<C & U["_commands"]> & U; /** * @deprecated This is a typo. Use `intercetor()` instead. */ inspector(interceptor: Interceptor): this; /** * Register a interceptor * * @example * * ```ts * Clerc.create().interceptor((ctx, next) => { * console.log(ctx); * next(); * }); * ``` * * @param interceptor * @returns */ interceptor(interceptor: Interceptor): this; /** * Parse the command line arguments * * @example * * ```ts * Clerc.create().parse(process.argv.slice(2)); // Optional * ``` * * @param args * @param optionsOrArgv * @returns */ parse(optionsOrArgv?: string[] | ParseOptions): this; /** * Run matched command * * @example * * ```ts * Clerc.create().parse({ run: false }).runMatchedCommand(); * ``` * * @returns */ runMatchedCommand(): this; } declare class CommandExistsError extends Error { commandName: string; constructor(commandName: string, t: TranslateFn); } declare class NoSuchCommandError extends Error { commandName: string; constructor(commandName: string, t: TranslateFn); } declare class NoCommandGivenError extends Error { constructor(t: TranslateFn); } declare class CommandNameConflictError extends Error { n1: string; n2: string; constructor(n1: string, n2: string, t: TranslateFn); } declare class ScriptNameNotSetError extends Error { constructor(t: TranslateFn); } declare class DescriptionNotSetError extends Error { constructor(t: TranslateFn); } declare class VersionNotSetError extends Error { constructor(t: TranslateFn); } declare class InvalidCommandNameError extends Error { commandName: string; constructor(commandName: string, t: TranslateFn); } declare class LocaleNotCalledFirstError extends Error { constructor(t: TranslateFn); } type MaybeArray<T> = T | T[]; declare const definePlugin: <T extends Clerc<{}, {}>, U extends Clerc<{}, {}>>(p: Plugin<T, U>) => Plugin<T, U>; declare const defineHandler: <C extends Clerc<{}, {}>, K extends keyof C["_commands"]>(_cli: C, _key: K, handler: Handler<C["_commands"], K>) => Handler<C["_commands"], K>; declare const defineInterceptor: <C extends Clerc<{}, {}>>(_cli: C, interceptor: Interceptor<C["_commands"]>) => Interceptor<C["_commands"]>; /** * @deprecated This is a typo. Use `defineInterceptor` instead. */ declare const defineInspector: <C extends Clerc<{}, {}>>(_cli: C, interceptor: Interceptor<C["_commands"]>) => Interceptor<C["_commands"]>; declare const defineCommand: <N extends string | typeof Root, O extends CommandOptions<[...P], MaybeArray<string | typeof Root>, Flags>, P extends string[]>(command: Command<N, O & CommandOptions<[...P], MaybeArray<string | typeof Root>, Flags>>, handler?: HandlerInCommand<HandlerContext<Record<N, Command<N, O>> & Record<never, never>, N, {}>> | undefined) => CommandWithHandler<N, O & CommandOptions<[...P], MaybeArray<string | typeof Root>, Flags>>; declare function resolveFlattenCommands(commands: Commands, t: TranslateFn): Map<string[] | typeof Root, CommandAlias>; declare function resolveCommand(commands: Commands, argv: string[], t: TranslateFn): [Command<string | RootType> | undefined, string[] | RootType | undefined]; declare const resolveArgv: () => string[]; declare function compose(interceptors: Interceptor[]): (ctx: InterceptorContext) => void; declare const isValidName: (name: CommandType) => boolean; declare const withBrackets: (s: string, isOptional?: boolean) => string; declare const formatCommandName: (name: string | string[] | RootType) => string; declare const detectLocale: () => string; declare const stripFlags: (argv: string[]) => string[]; export { Clerc, Command, CommandAlias, CommandCustomProperties, CommandExistsError, CommandNameConflictError, CommandOptions, CommandType, CommandWithHandler, Commands, DescriptionNotSetError, FallbackType, Flag, FlagOptions, Flags, GlobalFlagOption, GlobalFlagOptions, Handler, HandlerContext, HandlerInCommand, I18N, Inspector, InspectorContext, InspectorFn, InspectorObject, Interceptor, InterceptorContext, InterceptorFn, InterceptorObject, InvalidCommandNameError, LocaleNotCalledFirstError, Locales, MakeEventMap, NoCommandGivenError, NoSuchCommandError, ParseOptions, Plugin, Root, RootType, ScriptNameNotSetError, TranslateFn, VersionNotSetError, compose, defineCommand, defineHandler, defineInspector, defineInterceptor, definePlugin, detectLocale, formatCommandName, isValidName, resolveArgv, resolveCommand, resolveFlattenCommands, stripFlags, withBrackets };