@drizzle-team/brocli
Advanced tools
Comparing version 0.3.0 to 0.4.0
123
index.d.ts
@@ -12,5 +12,18 @@ /** | ||
type OutputType = string | boolean | number | undefined; | ||
type BuilderConfig = { | ||
type BuilderConfig<TType extends OptionType = OptionType> = { | ||
name?: string | undefined; | ||
aliases: string[]; | ||
type: TType; | ||
description?: string; | ||
default?: OutputType; | ||
isHidden?: boolean; | ||
isRequired?: boolean; | ||
isInt?: boolean; | ||
minVal?: number; | ||
maxVal?: number; | ||
enumVals?: [string, ...string[]]; | ||
}; | ||
type ProcessedBuilderConfig = { | ||
name: string; | ||
aliases: string[]; | ||
type: OptionType; | ||
@@ -26,2 +39,5 @@ description?: string; | ||
}; | ||
type BuilderConfigLimited = BuilderConfig & { | ||
type: Exclude<OptionType, 'positional'>; | ||
}; | ||
declare class OptionBuilderBase<TBuilderConfig extends BuilderConfig = BuilderConfig, TOutput extends OutputType = string, TOmit extends string = '', TEnums extends string | undefined = undefined> { | ||
@@ -39,19 +55,19 @@ _: { | ||
constructor(config?: TBuilderConfig); | ||
string<TName extends string>(name: TName): Omit<OptionBuilderBase<BuilderConfig, string | undefined, TOmit | OptionType | 'min' | 'max' | 'int'>, TOmit | OptionType | 'min' | 'max' | 'int'>; | ||
string(): Omit<OptionBuilderBase<BuilderConfig, string | undefined, TOmit | OptionType | 'min' | 'max' | 'int'>, TOmit | OptionType | 'min' | 'max' | 'int'>; | ||
number<TName extends string>(name: TName): Omit<OptionBuilderBase<BuilderConfig, number | undefined, TOmit | OptionType | 'enum'>, TOmit | OptionType | 'enum'>; | ||
number(): Omit<OptionBuilderBase<BuilderConfig, string | undefined, TOmit | OptionType | 'enum'>, TOmit | OptionType | 'enum'>; | ||
boolean<TName extends string>(name: TName): Omit<OptionBuilderBase<BuilderConfig, boolean | undefined, TOmit | OptionType | 'min' | 'max' | 'enum' | 'int'>, TOmit | OptionType | 'min' | 'max' | 'enum' | 'int'>; | ||
boolean(): Omit<OptionBuilderBase<BuilderConfig, boolean | undefined, TOmit | OptionType | 'min' | 'max' | 'enum' | 'int'>, TOmit | OptionType | 'min' | 'max' | 'enum' | 'int'>; | ||
positional<TName extends string>(displayName: TName): Omit<OptionBuilderBase<BuilderConfig, string | undefined, TOmit | OptionType | 'min' | 'max' | 'int' | 'alias'>, TOmit | OptionType | 'min' | 'max' | 'int' | 'alias'>; | ||
positional(): Omit<OptionBuilderBase<BuilderConfig, string | undefined, TOmit | OptionType | 'min' | 'max' | 'int' | 'alias'>, TOmit | OptionType | 'min' | 'max' | 'int' | 'alias'>; | ||
alias(...aliases: string[]): Omit<OptionBuilderBase<BuilderConfig, TOutput, TOmit | 'alias'>, TOmit | 'alias'>; | ||
desc<TDescription extends string>(description: TDescription): Omit<OptionBuilderBase<BuilderConfig, TOutput, TOmit | 'desc'>, TOmit | 'desc'>; | ||
hidden(): Omit<OptionBuilderBase<BuilderConfig, TOutput, TOmit | 'hidden'>, TOmit | 'hidden'>; | ||
required(): Omit<OptionBuilderBase<BuilderConfig, Exclude<TOutput, undefined>, TOmit | 'required' | 'default'>, TOmit | 'required' | 'default'>; | ||
default<TDefVal extends TEnums extends undefined ? Exclude<TOutput, undefined> : TEnums>(value: TDefVal): Omit<OptionBuilderBase<BuilderConfig, Exclude<TOutput, undefined>, TOmit | 'enum' | 'required' | 'default', TEnums>, TOmit | 'enum' | 'required' | 'default'>; | ||
enum<TValues extends [string, ...string[]]>(...values: TValues): Omit<OptionBuilderBase<BuilderConfig, TValues[number], TOmit | 'enum', TValues[number]>, TOmit | 'enum'>; | ||
min(value: number): Omit<OptionBuilderBase<BuilderConfig, TOutput, TOmit | 'min'>, TOmit | 'min'>; | ||
max(value: number): Omit<OptionBuilderBase<BuilderConfig, TOutput, TOmit | 'max'>, TOmit | 'max'>; | ||
int(): Omit<OptionBuilderBase<BuilderConfig, TOutput, TOmit | 'int'>, TOmit | 'int'>; | ||
string<TName extends string>(name: TName): Omit<OptionBuilderBase<BuilderConfig<'string'>, string | undefined, TOmit | OptionType | 'min' | 'max' | 'int'>, TOmit | OptionType | 'min' | 'max' | 'int'>; | ||
string(): Omit<OptionBuilderBase<BuilderConfig<'string'>, string | undefined, TOmit | OptionType | 'min' | 'max' | 'int'>, TOmit | OptionType | 'min' | 'max' | 'int'>; | ||
number<TName extends string>(name: TName): Omit<OptionBuilderBase<BuilderConfig<'number'>, number | undefined, TOmit | OptionType | 'enum'>, TOmit | OptionType | 'enum'>; | ||
number(): Omit<OptionBuilderBase<BuilderConfig<'number'>, string | undefined, TOmit | OptionType | 'enum'>, TOmit | OptionType | 'enum'>; | ||
boolean<TName extends string>(name: TName): Omit<OptionBuilderBase<BuilderConfig<'boolean'>, boolean | undefined, TOmit | OptionType | 'min' | 'max' | 'enum' | 'int'>, TOmit | OptionType | 'min' | 'max' | 'enum' | 'int'>; | ||
boolean(): Omit<OptionBuilderBase<BuilderConfig<'boolean'>, boolean | undefined, TOmit | OptionType | 'min' | 'max' | 'enum' | 'int'>, TOmit | OptionType | 'min' | 'max' | 'enum' | 'int'>; | ||
positional<TName extends string>(displayName: TName): Omit<OptionBuilderBase<BuilderConfig<'positional'>, string | undefined, TOmit | OptionType | 'min' | 'max' | 'int' | 'alias'>, TOmit | OptionType | 'min' | 'max' | 'int' | 'alias'>; | ||
positional(): Omit<OptionBuilderBase<BuilderConfig<'positional'>, string | undefined, TOmit | OptionType | 'min' | 'max' | 'int' | 'alias'>, TOmit | OptionType | 'min' | 'max' | 'int' | 'alias'>; | ||
alias(...aliases: string[]): Omit<OptionBuilderBase<TBuilderConfig, TOutput, TOmit | 'alias'>, TOmit | 'alias'>; | ||
desc<TDescription extends string>(description: TDescription): Omit<OptionBuilderBase<TBuilderConfig, TOutput, TOmit | 'desc'>, TOmit | 'desc'>; | ||
hidden(): Omit<OptionBuilderBase<TBuilderConfig, TOutput, TOmit | 'hidden'>, TOmit | 'hidden'>; | ||
required(): Omit<OptionBuilderBase<TBuilderConfig, Exclude<TOutput, undefined>, TOmit | 'required' | 'default'>, TOmit | 'required' | 'default'>; | ||
default<TDefVal extends TEnums extends undefined ? Exclude<TOutput, undefined> : TEnums>(value: TDefVal): Omit<OptionBuilderBase<TBuilderConfig, Exclude<TOutput, undefined>, TOmit | 'enum' | 'required' | 'default', TEnums>, TOmit | 'enum' | 'required' | 'default'>; | ||
enum<TValues extends [string, ...string[]]>(...values: TValues): Omit<OptionBuilderBase<TBuilderConfig, TValues[number], TOmit | 'enum', TValues[number]>, TOmit | 'enum'>; | ||
min(value: number): Omit<OptionBuilderBase<TBuilderConfig, TOutput, TOmit | 'min'>, TOmit | 'min'>; | ||
max(value: number): Omit<OptionBuilderBase<TBuilderConfig, TOutput, TOmit | 'max'>, TOmit | 'max'>; | ||
int(): Omit<OptionBuilderBase<TBuilderConfig, TOutput, TOmit | 'int'>, TOmit | 'int'>; | ||
} | ||
@@ -70,9 +86,17 @@ type GenericBuilderInternalsFields = { | ||
}; | ||
type AssignConfigName<TConfig extends BuilderConfig, TName extends string> = TConfig['name'] extends undefined ? Omit<TConfig, 'name'> & { | ||
name: TName; | ||
} : TConfig; | ||
type GenericProcessedOptions = ProcessedOptions<Record<string, GenericBuilderInternals>>; | ||
type GenericBuilderInternalsFieldsLimited = { | ||
/** | ||
* Type-level only field | ||
* | ||
* Do not attempt to access at a runtime | ||
*/ | ||
$output: OutputType; | ||
config: BuilderConfigLimited; | ||
}; | ||
type GenericBuilderInternalsLimited = { | ||
_: GenericBuilderInternalsFieldsLimited; | ||
}; | ||
type ProcessedOptions<TOptionConfig extends Record<string, GenericBuilderInternals> = Record<string, GenericBuilderInternals>> = { | ||
[K in keyof TOptionConfig]: K extends string ? { | ||
config: AssignConfigName<TOptionConfig[K]['_']['config'], K>; | ||
config: ProcessedBuilderConfig; | ||
/** | ||
@@ -92,10 +116,10 @@ * Type-level only field | ||
}>; | ||
declare function string<TName extends string>(name: TName): Omit<OptionBuilderBase<BuilderConfig, string | undefined, OptionType | 'min' | 'max' | 'int'>, OptionType | 'min' | 'max' | 'int'>; | ||
declare function string(): Omit<OptionBuilderBase<BuilderConfig, string | undefined, OptionType | 'min' | 'max' | 'int'>, OptionType | 'min' | 'max' | 'int'>; | ||
declare function number<TName extends string>(name: TName): Omit<OptionBuilderBase<BuilderConfig, number | undefined, OptionType | 'enum'>, OptionType | 'enum'>; | ||
declare function number(): Omit<OptionBuilderBase<BuilderConfig, number | undefined, OptionType | 'enum'>, OptionType | 'enum'>; | ||
declare function boolean<TName extends string>(name: TName): Omit<OptionBuilderBase<BuilderConfig, boolean | undefined, OptionType | 'min' | 'max' | 'int' | 'enum'>, OptionType | 'min' | 'max' | 'int' | 'enum'>; | ||
declare function boolean(): Omit<OptionBuilderBase<BuilderConfig, boolean | undefined, OptionType | 'min' | 'max' | 'int' | 'enum'>, OptionType | 'min' | 'max' | 'int' | 'enum'>; | ||
declare function positional<TName extends string>(displayName: TName): Omit<OptionBuilderBase<BuilderConfig, string | undefined, OptionType | 'min' | 'max' | 'int' | 'alias'>, OptionType | 'min' | 'max' | 'int' | 'alias'>; | ||
declare function positional(): Omit<OptionBuilderBase<BuilderConfig, string | undefined, OptionType | 'min' | 'max' | 'int' | 'alias'>, OptionType | 'min' | 'max' | 'int' | 'alias'>; | ||
declare function string<TName extends string>(name: TName): Omit<OptionBuilderBase<BuilderConfig<'string'>, string | undefined, OptionType | 'min' | 'max' | 'int'>, OptionType | 'min' | 'max' | 'int'>; | ||
declare function string(): Omit<OptionBuilderBase<BuilderConfig<'string'>, string | undefined, OptionType | 'min' | 'max' | 'int'>, OptionType | 'min' | 'max' | 'int'>; | ||
declare function number<TName extends string>(name: TName): Omit<OptionBuilderBase<BuilderConfig<'number'>, number | undefined, OptionType | 'enum'>, OptionType | 'enum'>; | ||
declare function number(): Omit<OptionBuilderBase<BuilderConfig<'number'>, number | undefined, OptionType | 'enum'>, OptionType | 'enum'>; | ||
declare function boolean<TName extends string>(name: TName): Omit<OptionBuilderBase<BuilderConfig<'boolean'>, boolean | undefined, OptionType | 'min' | 'max' | 'int' | 'enum'>, OptionType | 'min' | 'max' | 'int' | 'enum'>; | ||
declare function boolean(): Omit<OptionBuilderBase<BuilderConfig<'boolean'>, boolean | undefined, OptionType | 'min' | 'max' | 'int' | 'enum'>, OptionType | 'min' | 'max' | 'int' | 'enum'>; | ||
declare function positional<TName extends string>(displayName: TName): Omit<OptionBuilderBase<BuilderConfig<'positional'>, string | undefined, OptionType | 'min' | 'max' | 'int' | 'alias'>, OptionType | 'min' | 'max' | 'int' | 'alias'>; | ||
declare function positional(): Omit<OptionBuilderBase<BuilderConfig<'positional'>, string | undefined, OptionType | 'min' | 'max' | 'int' | 'alias'>, OptionType | 'min' | 'max' | 'int' | 'alias'>; | ||
@@ -111,3 +135,4 @@ type HelpHandler = (calledFor: Command | Command[]) => any; | ||
type GenericCommandHandler = (options?: Record<string, OutputType> | undefined) => any; | ||
type RawCommand<TOpts extends Record<string, GenericBuilderInternals> | undefined = Record<string, GenericBuilderInternals> | undefined> = { | ||
type RawCommand<TOpts extends Record<string, GenericBuilderInternals> | undefined = Record<string, GenericBuilderInternals> | undefined> = TOpts extends Record<string, GenericBuilderInternalsLimited> | undefined ? RawCommandWithSubcommands<TOpts> : RawCommandWithPositionals<TOpts>; | ||
type RawCommandWithPositionals<TOpts extends Record<string, GenericBuilderInternals> | undefined = Record<string, GenericBuilderInternals> | undefined> = { | ||
name?: string; | ||
@@ -121,2 +146,22 @@ aliases?: [string, ...string[]]; | ||
}; | ||
type RawCommandWithSubcommands<TOpts extends Record<string, GenericBuilderInternalsLimited> | undefined = Record<string, GenericBuilderInternalsLimited> | undefined> = { | ||
name?: string; | ||
aliases?: [string, ...string[]]; | ||
description?: string; | ||
hidden?: boolean; | ||
options?: TOpts; | ||
help?: string | Function; | ||
handler?: CommandHandler<TOpts>; | ||
subcommands?: [Command, ...Command[]]; | ||
}; | ||
type AnyRawCommand<TOpts extends Record<string, GenericBuilderInternals> | undefined = Record<string, GenericBuilderInternals> | undefined> = { | ||
name?: string; | ||
aliases?: [string, ...string[]]; | ||
description?: string; | ||
hidden?: boolean; | ||
options?: TOpts; | ||
help?: string | Function; | ||
handler?: CommandHandler<TOpts>; | ||
subcommands?: [Command, ...Command[]]; | ||
}; | ||
type Command = { | ||
@@ -127,6 +172,16 @@ name: string; | ||
hidden?: boolean; | ||
options?: GenericProcessedOptions; | ||
options?: ProcessedOptions; | ||
help?: string | Function; | ||
handler: GenericCommandHandler; | ||
subcommands?: [Command, ...Command[]]; | ||
parent?: Command; | ||
}; | ||
type CommandCandidate = { | ||
data: string; | ||
originalIndex: number; | ||
}; | ||
type InnerCommandParseRes = { | ||
command: Command | undefined; | ||
args: string[]; | ||
}; | ||
declare const command: <TOpts extends Record<string, GenericBuilderInternals> | undefined>(command: RawCommand<TOpts>) => Command; | ||
@@ -143,2 +198,2 @@ /** | ||
export { type AssignConfigName, type BroCliConfig, BroCliError, type BuilderConfig, type Command, type CommandHandler, type GenericBuilderInternals, type GenericBuilderInternalsFields, type GenericCommandHandler, type GenericProcessedOptions, type HelpHandler, OptionBuilderBase, type OptionType, type OutputType, type ProcessedOptions, type RawCommand, type Simplify, type TypeOf, boolean, command, handler, number, positional, runCli, string }; | ||
export { type AnyRawCommand, type BroCliConfig, BroCliError, type BuilderConfig, type BuilderConfigLimited, type Command, type CommandCandidate, type CommandHandler, type GenericBuilderInternals, type GenericBuilderInternalsFields, type GenericBuilderInternalsFieldsLimited, type GenericBuilderInternalsLimited, type GenericCommandHandler, type HelpHandler, type InnerCommandParseRes, OptionBuilderBase, type OptionType, type OutputType, type ProcessedBuilderConfig, type ProcessedOptions, type RawCommand, type RawCommandWithPositionals, type RawCommandWithSubcommands, type Simplify, type TypeOf, boolean, command, handler, number, positional, runCli, string }; |
129
index.js
@@ -135,3 +135,3 @@ // src/brocli-error.ts | ||
function number(name) { | ||
return typeof name === "number" ? new OptionBuilderBase().number(name) : new OptionBuilderBase().number(); | ||
return typeof name === "string" ? new OptionBuilderBase().number(name) : new OptionBuilderBase().number(); | ||
} | ||
@@ -142,3 +142,3 @@ function boolean(name) { | ||
function positional(displayName) { | ||
return typeof displayName === "number" ? new OptionBuilderBase().positional(displayName) : new OptionBuilderBase().positional(); | ||
return typeof displayName === "string" ? new OptionBuilderBase().positional(displayName) : new OptionBuilderBase().positional(); | ||
} | ||
@@ -152,7 +152,16 @@ | ||
// src/command-core.ts | ||
var unknownCommand = () => { | ||
const msg = `Unable to recognize any of the commands. | ||
Use 'help' command to list all commands.`; | ||
var unknownCommand = (caller) => { | ||
const msg = `Unknown command: '${caller}'. | ||
Type '--help' to get help on the cli.`; | ||
return new Error(msg); | ||
}; | ||
var unknownSubcommand = (command2, caller) => { | ||
const name = getCommandNameRecursive(command2); | ||
const msg = `Unknown command: ${name} ${caller}. | ||
Type '${name} --help' to get the help on command.`; | ||
new Error( | ||
msg | ||
); | ||
return new Error(msg); | ||
}; | ||
var missingRequired = (command2, missingOpts) => { | ||
@@ -244,3 +253,6 @@ const msg = `Command '${command2.name}' is missing following required options: ${missingOpts.map((opt) => { | ||
const cfg = value._.config; | ||
if (cfg.type === "positional") continue; | ||
if (cfg.type === "positional") { | ||
entries.push([key, { config: cfg, $output: void 0 }]); | ||
continue; | ||
} | ||
const reservedNames = ["--help", "-h", "--version", "-v"]; | ||
@@ -280,6 +292,12 @@ const allNames = [cfg.name, ...cfg.aliases]; | ||
}; | ||
var command = (command2) => { | ||
var command = (command2) => commandCheckBypass(command2); | ||
var commandCheckBypass = (command2, ignoreReserved = true) => { | ||
const allNames = command2.aliases ? [command2.name, ...command2.aliases] : [command2.name]; | ||
const processedOptions = command2.options ? validateOptions(command2.options) : void 0; | ||
const cmd = command2; | ||
if (command2.subcommands && command2.options && Object.values(command2.options).find((opt) => opt._.config.type === "positional")) { | ||
throw new BroCliError( | ||
`Can't define command '${cmd.name}' - command can't have subcommands and positional args at the same time!` | ||
); | ||
} | ||
cmd.options = processedOptions; | ||
@@ -299,2 +317,7 @@ cmd.name = cmd.name ?? cmd.aliases?.shift(); | ||
allNames.forEach((n, i) => { | ||
if (!ignoreReserved && n === "help") { | ||
throw new BroCliError( | ||
`Can't define command '${cmd.name}' - 'help' is a reserved name. If you want to redefine help message - do so in runCli's config.` | ||
); | ||
} | ||
const idx = allNames.findIndex((an) => an === n); | ||
@@ -305,5 +328,29 @@ if (idx !== i) throw new BroCliError(`Can't define command '${cmd.name}' - duplicate alias '${n}'!`); | ||
}; | ||
var getCommandInner = (commands, candidates, args) => { | ||
const { data: arg, originalIndex: index } = candidates.shift(); | ||
const command2 = commands.find((c) => { | ||
const names = c.aliases ? [c.name, ...c.aliases] : [c.name]; | ||
const res = names.find((name) => name === arg); | ||
return res; | ||
}); | ||
if (!command2) { | ||
return { | ||
command: command2, | ||
args | ||
}; | ||
} | ||
const newArgs = removeByIndex(args, index); | ||
if (!candidates.length || !command2.subcommands) { | ||
return { | ||
command: command2, | ||
args: newArgs | ||
}; | ||
} | ||
const newCandidates = candidates.map((c) => ({ data: c.data, originalIndex: c.originalIndex - 1 })); | ||
const subcommand = getCommandInner(command2.subcommands, newCandidates, newArgs); | ||
if (!subcommand.command) throw unknownSubcommand(command2, candidates[0].data); | ||
return subcommand; | ||
}; | ||
var getCommand = (commands, args) => { | ||
let index = -1; | ||
let command2; | ||
const candidates = []; | ||
for (let i = 0; i < args.length; ++i) { | ||
@@ -315,13 +362,19 @@ const arg = args[i]; | ||
} | ||
command2 = commands.find((c) => { | ||
const names = c.aliases ? [c.name, ...c.aliases] : [c.name]; | ||
const res = names.find((name) => name === arg); | ||
if (res) index = i; | ||
return res; | ||
candidates.push({ | ||
data: arg, | ||
originalIndex: i | ||
}); | ||
if (command2) break; | ||
} | ||
if (!candidates.length) { | ||
return { | ||
command: void 0, | ||
args | ||
}; | ||
} | ||
const firstCandidate = candidates[0]; | ||
const { command: command2, args: argsRes } = getCommandInner(commands, candidates, args); | ||
if (!command2) throw unknownCommand(firstCandidate.data); | ||
return { | ||
command: command2, | ||
index | ||
args: argsRes | ||
}; | ||
@@ -339,4 +392,4 @@ }; | ||
const pos = positionals.shift(); | ||
if (pos[1].config.enumVals && !pos[1].config.enumVals.find((val) => val === dataPart)) { | ||
throw enumViolationPos(pos[1].config.name, arg, pos[1].config.enumVals); | ||
if (pos[1].enumVals && !pos[1].enumVals.find((val) => val === dataPart)) { | ||
throw enumViolationPos(pos[1].name, arg, pos[1].enumVals); | ||
} | ||
@@ -351,3 +404,3 @@ data = arg; | ||
} | ||
const option = options.find(([optKey, { config: opt }]) => { | ||
const option = options.find(([optKey, opt]) => { | ||
const names = [opt.name, ...opt.aliases]; | ||
@@ -371,2 +424,7 @@ if (opt.type === "boolean") { | ||
} | ||
if (!hasEq) { | ||
data = true; | ||
skipNext = false; | ||
return true; | ||
} | ||
throw invalidBooleanSyntax(match); | ||
@@ -403,5 +461,7 @@ } else { | ||
const options = command2.options; | ||
const optEntries = Object.entries(options ?? {}); | ||
const nonPositionalEntries = optEntries.filter(([key, opt]) => opt.config.type !== "positional"); | ||
const positionalEntries = optEntries.filter(([key, opt]) => opt.config.type === "positional"); | ||
const optEntries = Object.entries(options ?? {}).map( | ||
(opt) => [opt[0], opt[1].config] | ||
); | ||
const nonPositionalEntries = optEntries.filter(([key, opt]) => opt.type !== "positional"); | ||
const positionalEntries = optEntries.filter(([key, opt]) => opt.type === "positional"); | ||
const result = {}; | ||
@@ -423,3 +483,3 @@ const missingRequiredArr = []; | ||
} | ||
for (const [optKey, { config: option }] of optEntries) { | ||
for (const [optKey, option] of optEntries) { | ||
const data = result[optKey] ?? option.default; | ||
@@ -441,3 +501,3 @@ if (!omitKeysOfUndefinedOptions) { | ||
}; | ||
var helpCommand = (commands, helpHandler) => command({ | ||
var helpCommand = (commands, helpHandler) => commandCheckBypass({ | ||
name: "help", | ||
@@ -461,8 +521,10 @@ description: "List commands or command details", | ||
} | ||
}); | ||
var validateCommands = (commands) => { | ||
const cloned = clone(commands); | ||
}, true); | ||
var getCommandNameRecursive = (command2) => command2.parent ? `${getCommandNameRecursive(command2.parent)} ${command2.name}` : command2.name; | ||
var validateCommands = (commands, parent) => { | ||
const cloned = parent ? commands : clone(commands); | ||
const storedNames = {}; | ||
for (const cmd of cloned) { | ||
const storageVals = Object.values(storedNames); | ||
cmd.parent = parent; | ||
for (const storage of storageVals) { | ||
@@ -472,3 +534,3 @@ const nameOccupier = storage.find((e) => e === cmd.name); | ||
throw new Error( | ||
`Can't define command '${cmd.name}': name is already in use by command '${storage[0]}'!` | ||
`Can't define command '${getCommandNameRecursive(cmd)}': name is already in use by command '${parent ? `${getCommandNameRecursive(parent)} ` : ""}${storage[0]}'!` | ||
); | ||
@@ -482,3 +544,3 @@ } | ||
throw new Error( | ||
`Can't define command '${cmd.name}': alias '${alias}' is already in use by command '${storage[0]}'!` | ||
`Can't define command '${getCommandNameRecursive(cmd)}': alias '${alias}' is already in use by command '${parent ? `${getCommandNameRecursive(parent)} ` : ""}${storage[0]}'!` | ||
); | ||
@@ -489,5 +551,7 @@ } | ||
storedNames[cmd.name] = cmd.aliases ? [cmd.name, ...cmd.aliases] : [cmd.name]; | ||
if (cmd.subcommands) cmd.subcommands = validateCommands(cmd.subcommands, cmd); | ||
} | ||
return cloned; | ||
}; | ||
var removeByIndex = (arr, idx) => [...arr.slice(0, idx), ...arr.slice(idx + 1, arr.length)]; | ||
var rawCli = async (commands, config) => { | ||
@@ -523,6 +587,5 @@ let options; | ||
} | ||
const { command: command2, index } = getCommand(cmds, args); | ||
if (!command2) throw unknownCommand(); | ||
args = [...args.slice(0, index), ...args.slice(index + 1, args.length)]; | ||
options = parseOptions(command2, args, omitKeysOfUndefinedOptions); | ||
const { command: command2, args: newArgs } = getCommand(cmds, args); | ||
if (!command2) return helpHandler(processedCmds); | ||
options = parseOptions(command2, newArgs, omitKeysOfUndefinedOptions); | ||
cmd = command2; | ||
@@ -529,0 +592,0 @@ await cmd.handler(options); |
@@ -5,3 +5,3 @@ { | ||
"author": "Drizzle Team", | ||
"version": "0.3.0", | ||
"version": "0.4.0", | ||
"description": "Typed CLI command runner", | ||
@@ -8,0 +8,0 @@ "license": "Apache-2.0", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
192950
1412