diff --git a/commandline/autocomplete_handler.go b/commandline/autocomplete_handler.go index 953971b..7327102 100644 --- a/commandline/autocomplete_handler.go +++ b/commandline/autocomplete_handler.go @@ -6,16 +6,14 @@ import ( "os" "path/filepath" "strings" - - "github.com/urfave/cli/v2" ) +const AutocompletePowershell = "powershell" +const AutocompleteBash = "bash" + const directoryPermissions = 0755 const filePermissions = 0644 -const Powershell = "powershell" -const Bash = "bash" - const completeHandlerEnabledCheck = "uipath_auto_complete" const powershellCompleteHandler = ` @@ -55,8 +53,8 @@ type autoCompleteHandler struct { } func (a autoCompleteHandler) EnableCompleter(shell string, filePath string) (string, error) { - if shell != Powershell && shell != Bash { - return "", fmt.Errorf("Invalid shell, supported values: %s, %s", Powershell, Bash) + if shell != AutocompletePowershell && shell != AutocompleteBash { + return "", fmt.Errorf("Invalid shell, supported values: %s, %s", AutocompletePowershell, AutocompleteBash) } profileFilePath, err := a.profileFilePath(shell, filePath) @@ -71,14 +69,14 @@ func (a autoCompleteHandler) profileFilePath(shell string, filePath string) (str if filePath != "" { return filePath, nil } - if shell == Powershell { + if shell == AutocompletePowershell { return PowershellProfilePath() } return BashrcPath() } func (a autoCompleteHandler) completeHandler(shell string) string { - if shell == Powershell { + if shell == AutocompletePowershell { return powershellCompleteHandler } return bashCompleteHandler @@ -136,17 +134,12 @@ func (a autoCompleteHandler) writeCompleterHandler(filePath string, completerHan return nil } -func (a autoCompleteHandler) Find(commandText string, commands []*cli.Command, exclude []string) []string { +func (a autoCompleteHandler) Find(commandText string, command *CommandDefinition, exclude []string) []string { words := strings.Split(commandText, " ") if len(words) < 2 { return []string{} } - command := &cli.Command{ - Name: "uipath", - Subcommands: commands, - } - for _, word := range words[1 : len(words)-1] { if strings.HasPrefix(word, "-") { break @@ -164,7 +157,7 @@ func (a autoCompleteHandler) Find(commandText string, commands []*cli.Command, e return a.searchCommands(lastWord, command.Subcommands, exclude) } -func (a autoCompleteHandler) findCommand(name string, commands []*cli.Command) *cli.Command { +func (a autoCompleteHandler) findCommand(name string, commands []*CommandDefinition) *CommandDefinition { for _, command := range commands { if command.Name == name { return command @@ -173,7 +166,7 @@ func (a autoCompleteHandler) findCommand(name string, commands []*cli.Command) * return nil } -func (a autoCompleteHandler) searchCommands(word string, commands []*cli.Command, exclude []string) []string { +func (a autoCompleteHandler) searchCommands(word string, commands []*CommandDefinition, exclude []string) []string { result := []string{} for _, command := range commands { if strings.HasPrefix(command.Name, word) { @@ -188,22 +181,16 @@ func (a autoCompleteHandler) searchCommands(word string, commands []*cli.Command return a.removeDuplicates(a.removeExcluded(result, exclude)) } -func (a autoCompleteHandler) searchFlags(word string, command *cli.Command, exclude []string) []string { +func (a autoCompleteHandler) searchFlags(word string, command *CommandDefinition, exclude []string) []string { result := []string{} for _, flag := range command.Flags { - flagNames := flag.Names() - for _, flagName := range flagNames { - if strings.HasPrefix(flagName, word) { - result = append(result, "--"+flagName) - } + if strings.HasPrefix(flag.Name, word) { + result = append(result, "--"+flag.Name) } } for _, flag := range command.Flags { - flagNames := flag.Names() - for _, flagName := range flagNames { - if strings.Contains(flagName, word) { - result = append(result, "--"+flagName) - } + if strings.Contains(flag.Name, word) { + result = append(result, "--"+flag.Name) } } return a.removeDuplicates(a.removeExcluded(result, exclude)) diff --git a/commandline/cli.go b/commandline/cli.go index 018d45b..01878cd 100644 --- a/commandline/cli.go +++ b/commandline/cli.go @@ -40,7 +40,11 @@ func (c Cli) run(args []string, input utils.Stream) error { PluginExecutor: c.pluginExecutor, DefinitionProvider: c.definitionProvider, } - flags := CommandBuilder.CreateDefaultFlags(false) + + flags := NewFlagBuilder(). + AddDefaultFlags(false). + Build() + commands, err := CommandBuilder.Create(args) if err != nil { return err @@ -51,8 +55,8 @@ func (c Cli) run(args []string, input utils.Stream) error { Usage: "Command-Line Interface for UiPath Services", UsageText: "uipath --parameter", Version: "1.0", - Flags: flags, - Commands: commands, + Flags: c.convertFlags(flags...), + Commands: c.convertCommands(commands...), Writer: c.stdOut, ErrWriter: c.stdErr, HideVersion: true, @@ -89,3 +93,128 @@ func NewCli( ) *Cli { return &Cli{stdIn, stdOut, stdErr, colors, definitionProvider, configProvider, executor, pluginExecutor} } + +func (c Cli) convertCommand(command *CommandDefinition) *cli.Command { + result := cli.Command{ + Name: command.Name, + Usage: command.Summary, + Description: command.Description, + Flags: c.convertFlags(command.Flags...), + Subcommands: c.convertCommands(command.Subcommands...), + CustomHelpTemplate: command.HelpTemplate, + Hidden: command.Hidden, + HideHelp: true, + } + if command.Action != nil { + result.Action = func(context *cli.Context) error { + return command.Action(&CommandExecContext{context}) + } + } + return &result +} + +func (c Cli) convertCommands(commands ...*CommandDefinition) []*cli.Command { + result := []*cli.Command{} + for _, command := range commands { + result = append(result, c.convertCommand(command)) + } + return result +} + +func (c Cli) convertStringSliceFlag(flag *FlagDefinition) *cli.StringSliceFlag { + envVars := []string{} + if flag.EnvVarName != "" { + envVars = append(envVars, flag.EnvVarName) + } + var value *cli.StringSlice + if flag.DefaultValue != nil { + value = cli.NewStringSlice(flag.DefaultValue.([]string)...) + } + return &cli.StringSliceFlag{ + Name: flag.Name, + Usage: flag.Summary, + EnvVars: envVars, + Required: flag.Required, + Hidden: flag.Hidden, + Value: value, + } +} + +func (c Cli) convertIntFlag(flag *FlagDefinition) *cli.IntFlag { + envVars := []string{} + if flag.EnvVarName != "" { + envVars = append(envVars, flag.EnvVarName) + } + var value int + if flag.DefaultValue != nil { + value = flag.DefaultValue.(int) + } + return &cli.IntFlag{ + Name: flag.Name, + Usage: flag.Summary, + EnvVars: envVars, + Required: flag.Required, + Hidden: flag.Hidden, + Value: value, + } +} + +func (c Cli) convertBoolFlag(flag *FlagDefinition) *cli.BoolFlag { + envVars := []string{} + if flag.EnvVarName != "" { + envVars = append(envVars, flag.EnvVarName) + } + var value bool + if flag.DefaultValue != nil { + value = flag.DefaultValue.(bool) + } + return &cli.BoolFlag{ + Name: flag.Name, + Usage: flag.Summary, + EnvVars: envVars, + Required: flag.Required, + Hidden: flag.Hidden, + Value: value, + } +} + +func (c Cli) convertStringFlag(flag *FlagDefinition) *cli.StringFlag { + envVars := []string{} + if flag.EnvVarName != "" { + envVars = append(envVars, flag.EnvVarName) + } + var value string + if flag.DefaultValue != nil { + value = flag.DefaultValue.(string) + } + return &cli.StringFlag{ + Name: flag.Name, + Usage: flag.Summary, + EnvVars: envVars, + Required: flag.Required, + Hidden: flag.Hidden, + Value: value, + } +} + +func (c Cli) convertFlag(flag *FlagDefinition) cli.Flag { + switch flag.Type { + case FlagTypeStringArray: + return c.convertStringSliceFlag(flag) + case FlagTypeInteger: + return c.convertIntFlag(flag) + case FlagTypeBoolean: + return c.convertBoolFlag(flag) + case FlagTypeString: + return c.convertStringFlag(flag) + } + panic(fmt.Sprintf("Unknown flag type: %s", flag.Type.String())) +} + +func (c Cli) convertFlags(flags ...*FlagDefinition) []cli.Flag { + result := []cli.Flag{} + for _, flag := range flags { + result = append(result, c.convertFlag(flag)) + } + return result +} diff --git a/commandline/command_builder.go b/commandline/command_builder.go index 9bbd149..8ab903b 100644 --- a/commandline/command_builder.go +++ b/commandline/command_builder.go @@ -17,64 +17,8 @@ import ( "github.com/UiPath/uipathcli/output" "github.com/UiPath/uipathcli/parser" "github.com/UiPath/uipathcli/utils" - "github.com/urfave/cli/v2" ) -const FromStdIn = "-" - -const insecureFlagName = "insecure" -const debugFlagName = "debug" -const profileFlagName = "profile" -const uriFlagName = "uri" -const identityUriFlagName = "identity-uri" -const organizationFlagName = "organization" -const tenantFlagName = "tenant" -const helpFlagName = "help" -const outputFormatFlagName = "output" -const queryFlagName = "query" -const waitFlagName = "wait" -const waitTimeoutFlagName = "wait-timeout" -const versionFlagName = "version" -const fileFlagName = "file" - -var predefinedFlags = []string{ - insecureFlagName, - debugFlagName, - profileFlagName, - uriFlagName, - identityUriFlagName, - organizationFlagName, - tenantFlagName, - helpFlagName, - outputFormatFlagName, - queryFlagName, - waitFlagName, - waitTimeoutFlagName, - versionFlagName, - fileFlagName, -} - -const outputFormatJson = "json" -const outputFormatText = "text" - -const subcommandHelpTemplate = `NAME: - {{template "helpNameTemplate" .}} - -USAGE: - {{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}}{{if .VisibleFlags}} [command options]{{end}}{{if .ArgsUsage}}{{.ArgsUsage}}{{else}} [arguments...]{{end}}{{end}}{{if .Description}} - -DESCRIPTION: - {{template "descriptionTemplate" .}}{{end}}{{if .VisibleCommands}} - -COMMANDS:{{template "visibleCommandTemplate" .}}{{end}}{{if .VisibleFlagCategories}} - -OPTIONS:{{template "visibleFlagCategoryTemplate" .}}{{else if .VisibleFlags}} - -OPTIONS:{{range $i, $e := .VisibleFlags}} - --{{$e.Name}} {{wrap $e.Usage 6}} -{{end}}{{end}} -` - // The CommandBuilder is creating all available operations and arguments for the CLI. type CommandBuilder struct { Input utils.Stream @@ -87,29 +31,29 @@ type CommandBuilder struct { DefinitionProvider DefinitionProvider } -func (b CommandBuilder) sort(commands []*cli.Command) { +func (b CommandBuilder) sort(commands []*CommandDefinition) { sort.Slice(commands, func(i, j int) bool { return commands[i].Name < commands[j].Name }) } -func (b CommandBuilder) fileInput(context *cli.Context, parameters []parser.Parameter) utils.Stream { - value := context.String(fileFlagName) +func (b CommandBuilder) fileInput(context *CommandExecContext, parameters []parser.Parameter) utils.Stream { + value := context.String(FlagNameFile) if value == "" { return nil } - if value == FromStdIn { + if value == FlagValueFromStdIn { return b.Input } for _, param := range parameters { - if strings.EqualFold(param.FieldName, fileFlagName) { + if strings.EqualFold(param.FieldName, FlagNameFile) { return nil } } return utils.NewFileStream(value) } -func (b CommandBuilder) createExecutionParameters(context *cli.Context, config *config.Config, operation parser.Operation) (executor.ExecutionParameters, error) { +func (b CommandBuilder) createExecutionParameters(context *CommandExecContext, config *config.Config, operation parser.Operation) (executor.ExecutionParameters, error) { typeConverter := newTypeConverter() parameters := []executor.ExecutionParameter{} @@ -163,23 +107,16 @@ func (b CommandBuilder) formatAllowedValues(values []interface{}) string { return result } -func (b CommandBuilder) createFlags(parameters []parser.Parameter) []cli.Flag { - flags := []cli.Flag{} +func (b CommandBuilder) createFlags(parameters []parser.Parameter) []*FlagDefinition { + flags := []*FlagDefinition{} for _, parameter := range parameters { formatter := newParameterFormatter(parameter) + flagType := FlagTypeString if parameter.IsArray() { - flag := cli.StringSliceFlag{ - Name: parameter.Name, - Usage: formatter.Description(), - } - flags = append(flags, &flag) - } else { - flag := cli.StringFlag{ - Name: parameter.Name, - Usage: formatter.Description(), - } - flags = append(flags, &flag) + flagType = FlagTypeStringArray } + flag := NewFlag(parameter.Name, formatter.Description(), flagType) + flags = append(flags, flag) } return flags } @@ -196,21 +133,21 @@ func (b CommandBuilder) sortParameters(parameters []parser.Parameter) { }) } -func (b CommandBuilder) outputFormat(config config.Config, context *cli.Context) (string, error) { - outputFormat := context.String(outputFormatFlagName) +func (b CommandBuilder) outputFormat(config config.Config, context *CommandExecContext) (string, error) { + outputFormat := context.String(FlagNameOutputFormat) if outputFormat == "" { outputFormat = config.Output } if outputFormat == "" { - outputFormat = outputFormatJson + outputFormat = FlagValueOutputFormatJson } - if outputFormat != outputFormatJson && outputFormat != outputFormatText { - return "", fmt.Errorf("Invalid output format '%s', allowed values: %s, %s", outputFormat, outputFormatJson, outputFormatText) + if outputFormat != FlagValueOutputFormatJson && outputFormat != FlagValueOutputFormatText { + return "", fmt.Errorf("Invalid output format '%s', allowed values: %s, %s", outputFormat, FlagValueOutputFormatJson, FlagValueOutputFormatText) } return outputFormat, nil } -func (b CommandBuilder) createBaseUri(operation parser.Operation, config config.Config, context *cli.Context) (url.URL, error) { +func (b CommandBuilder) createBaseUri(operation parser.Operation, config config.Config, context *CommandExecContext) (url.URL, error) { uriArgument, err := b.parseUriArgument(context) if err != nil { return operation.BaseUri, err @@ -222,12 +159,12 @@ func (b CommandBuilder) createBaseUri(operation parser.Operation, config config. return builder.Uri(), nil } -func (b CommandBuilder) createIdentityUri(context *cli.Context, config config.Config, baseUri url.URL) (*url.URL, error) { - uri := context.String(identityUriFlagName) +func (b CommandBuilder) createIdentityUri(context *CommandExecContext, config config.Config, baseUri url.URL) (*url.URL, error) { + uri := context.String(FlagNameIdentityUri) if uri != "" { identityUri, err := url.Parse(uri) if err != nil { - return nil, fmt.Errorf("Error parsing %s argument: %w", identityUriFlagName, err) + return nil, fmt.Errorf("Error parsing %s argument: %w", FlagNameIdentityUri, err) } return identityUri, nil } @@ -248,19 +185,19 @@ func (b CommandBuilder) createIdentityUri(context *cli.Context, config config.Co return identityUri, nil } -func (b CommandBuilder) parseUriArgument(context *cli.Context) (*url.URL, error) { - uriFlag := context.String(uriFlagName) +func (b CommandBuilder) parseUriArgument(context *CommandExecContext) (*url.URL, error) { + uriFlag := context.String(FlagNameUri) if uriFlag == "" { return nil, nil } uriArgument, err := url.Parse(uriFlag) if err != nil { - return nil, fmt.Errorf("Error parsing %s argument: %w", uriFlagName, err) + return nil, fmt.Errorf("Error parsing %s argument: %w", FlagNameUri, err) } return uriArgument, nil } -func (b CommandBuilder) getValue(parameter parser.Parameter, context *cli.Context, config config.Config) string { +func (b CommandBuilder) getValue(parameter parser.Parameter, context *CommandExecContext, config config.Config) string { value := context.String(parameter.Name) if value != "" { return value @@ -279,7 +216,7 @@ func (b CommandBuilder) getValue(parameter parser.Parameter, context *cli.Contex return "" } -func (b CommandBuilder) validateArguments(context *cli.Context, parameters []parser.Parameter, config config.Config) error { +func (b CommandBuilder) validateArguments(context *CommandExecContext, parameters []parser.Parameter, config config.Config) error { err := errors.New("Invalid arguments:") result := true for _, parameter := range parameters { @@ -321,7 +258,7 @@ func (b CommandBuilder) outputWriter(writer io.Writer, format string, query stri if query != "" { transformer = output.NewJmesPathTransformer(query) } - if format == outputFormatText { + if format == FlagValueOutputFormatText { return output.NewTextOutputWriter(writer, transformer) } return output.NewJsonOutputWriter(writer, transformer) @@ -334,23 +271,22 @@ func (b CommandBuilder) executeCommand(context executor.ExecutionContext, writer return b.Executor.Call(context, writer, logger) } -func (b CommandBuilder) createOperationCommand(operation parser.Operation) *cli.Command { +func (b CommandBuilder) createOperationCommand(operation parser.Operation) *CommandDefinition { parameters := operation.Parameters b.sortParameters(parameters) - flagBuilder := newFlagBuilder() - flagBuilder.AddFlags(b.createFlags(parameters)) - flagBuilder.AddFlags(b.CreateDefaultFlags(true)) - flagBuilder.AddFlag(b.HelpFlag()) - - return &cli.Command{ - Name: operation.Name, - Usage: operation.Summary, - Description: operation.Description, - Flags: flagBuilder.ToList(), - CustomHelpTemplate: subcommandHelpTemplate, - Action: func(context *cli.Context) error { - profileName := context.String(profileFlagName) + flags := NewFlagBuilder(). + AddFlags(b.createFlags(parameters)). + AddDefaultFlags(true). + AddHelpFlag(). + Build() + + return NewCommand(operation.Name, operation.Summary, operation.Description). + WithFlags(flags). + WithHelpTemplate(OperationCommandHelpTemplate). + WithHidden(operation.Hidden). + WithAction(func(context *CommandExecContext) error { + profileName := context.String(FlagNameProfile) config := b.ConfigProvider.Config(profileName) if config == nil { return fmt.Errorf("Could not find profile '%s'", profileName) @@ -359,9 +295,9 @@ func (b CommandBuilder) createOperationCommand(operation parser.Operation) *cli. if err != nil { return err } - query := context.String(queryFlagName) - wait := context.String(waitFlagName) - waitTimeout := context.Int(waitTimeoutFlagName) + query := context.String(FlagNameQuery) + wait := context.String(FlagNameWait) + waitTimeout := context.Int(FlagNameWaitTimeout) baseUri, err := b.createBaseUri(operation, *config, context) if err != nil { @@ -381,16 +317,16 @@ func (b CommandBuilder) createOperationCommand(operation parser.Operation) *cli. return err } - organization := context.String(organizationFlagName) + organization := context.String(FlagNameOrganization) if organization == "" { organization = config.Organization } - tenant := context.String(tenantFlagName) + tenant := context.String(FlagNameTenant) if tenant == "" { tenant = config.Tenant } - insecure := context.Bool(insecureFlagName) || config.Insecure - debug := context.Bool(debugFlagName) || config.Debug + insecure := context.Bool(FlagNameInsecure) || config.Insecure + debug := context.Bool(FlagNameDebug) || config.Debug identityUri, err := b.createIdentityUri(context, *config, baseUri) if err != nil { return err @@ -415,10 +351,7 @@ func (b CommandBuilder) createOperationCommand(operation parser.Operation) *cli. return b.executeWait(*executionContext, outputFormat, query, wait, waitTimeout) } return b.execute(*executionContext, outputFormat, query, nil) - }, - HideHelp: true, - Hidden: operation.Hidden, - } + }) } func (b CommandBuilder) executeWait(executionContext executor.ExecutionContext, outputFormat string, query string, wait string, waitTimeout int) error { @@ -495,20 +428,17 @@ func (b CommandBuilder) execute(executionContext executor.ExecutionContext, outp return err } -func (b CommandBuilder) createCategoryCommand(operation parser.Operation) *cli.Command { - return &cli.Command{ - Name: operation.Category.Name, - Usage: operation.Category.Summary, - Description: operation.Category.Description, - Flags: []cli.Flag{ - b.HelpFlag(), - b.VersionFlag(true), - }, - HideHelp: true, - } +func (b CommandBuilder) createCategoryCommand(operation parser.Operation) *CommandDefinition { + flags := NewFlagBuilder(). + AddHelpFlag(). + AddVersionFlag(true). + Build() + + return NewCommand(operation.Category.Name, operation.Category.Summary, operation.Category.Description). + WithFlags(flags) } -func (b CommandBuilder) createServiceCommandCategory(operation parser.Operation, categories map[string]*cli.Command) (bool, *cli.Command) { +func (b CommandBuilder) createServiceCommandCategory(operation parser.Operation, categories map[string]*CommandDefinition) (bool, *CommandDefinition) { isNewCategory := false operationCommand := b.createOperationCommand(operation) command, found := categories[operation.Category.Name] @@ -521,9 +451,9 @@ func (b CommandBuilder) createServiceCommandCategory(operation parser.Operation, return isNewCategory, command } -func (b CommandBuilder) createServiceCommand(definition parser.Definition) *cli.Command { - categories := map[string]*cli.Command{} - commands := []*cli.Command{} +func (b CommandBuilder) createServiceCommand(definition parser.Definition) *CommandDefinition { + categories := map[string]*CommandDefinition{} + commands := []*CommandDefinition{} for _, operation := range definition.Operations { if operation.Category == nil { command := b.createOperationCommand(operation) @@ -540,42 +470,31 @@ func (b CommandBuilder) createServiceCommand(definition parser.Definition) *cli. b.sort(command.Subcommands) } - return &cli.Command{ - Name: definition.Name, - Usage: definition.Summary, - Description: definition.Description, - Flags: []cli.Flag{ - b.HelpFlag(), - b.VersionFlag(true), - }, - Subcommands: commands, - HideHelp: true, - } + flags := NewFlagBuilder(). + AddHelpFlag(). + AddVersionFlag(true). + Build() + + return NewCommand(definition.Name, definition.Summary, definition.Description). + WithFlags(flags). + WithSubcommands(commands) } -func (b CommandBuilder) createAutoCompleteEnableCommand() *cli.Command { +func (b CommandBuilder) createAutoCompleteEnableCommand() *CommandDefinition { const shellFlagName = "shell" - const powershellFlagValue = "powershell" - const bashFlagValue = "bash" const fileFlagName = "file" - return &cli.Command{ - Name: "enable", - Usage: "Enable auto complete", - Description: "Enables auto complete in your shell", - Flags: []cli.Flag{ - &cli.StringFlag{ - Name: shellFlagName, - Usage: fmt.Sprintf("%s, %s", powershellFlagValue, bashFlagValue), - Required: true, - }, - &cli.StringFlag{ - Name: fileFlagName, - Hidden: true, - }, - b.HelpFlag(), - }, - Action: func(context *cli.Context) error { + flags := NewFlagBuilder(). + AddFlag(NewFlag(shellFlagName, fmt.Sprintf("%s, %s", AutocompletePowershell, AutocompleteBash), FlagTypeString). + WithRequired(true)). + AddFlag(NewFlag(fileFlagName, "The profile file path", FlagTypeString). + WithHidden(true)). + AddHelpFlag(). + Build() + + return NewCommand("enable", "Enable auto complete", "Enables auto complete in your shell"). + WithFlags(flags). + WithAction(func(context *CommandExecContext) error { shell := context.String(shellFlagName) filePath := context.String(fileFlagName) handler := newAutoCompleteHandler() @@ -585,28 +504,24 @@ func (b CommandBuilder) createAutoCompleteEnableCommand() *cli.Command { } fmt.Fprintln(b.StdOut, output) return nil - }, - HideHelp: true, - } -} - -func (b CommandBuilder) createAutoCompleteCompleteCommand(version string) *cli.Command { - return &cli.Command{ - Name: "complete", - Usage: "Autocomplete suggestions", - Description: "Returns the autocomplete suggestions", - Flags: []cli.Flag{ - &cli.StringFlag{ - Name: "command", - Usage: "The command to autocomplete", - Required: true, - }, - b.HelpFlag(), - }, - Action: func(context *cli.Context) error { + }) +} + +func (b CommandBuilder) createAutoCompleteCompleteCommand(version string) *CommandDefinition { + const commandFlagName = "command" + + flags := NewFlagBuilder(). + AddFlag(NewFlag(commandFlagName, "The command to autocomplete", FlagTypeString). + WithRequired(true)). + AddHelpFlag(). + Build() + + return NewCommand("complete", "Autocomplete suggestions", "Returns the autocomplete suggestions"). + WithFlags(flags). + WithAction(func(context *CommandExecContext) error { commandText := context.String("command") exclude := []string{} - for _, flagName := range predefinedFlags { + for _, flagName := range FlagNamesPredefined { exclude = append(exclude, "--"+flagName) } args := strings.Split(commandText, " ") @@ -615,103 +530,82 @@ func (b CommandBuilder) createAutoCompleteCompleteCommand(version string) *cli.C return err } commands := b.createServiceCommands(definitions) + command := NewCommand("uipath", "", ""). + WithSubcommands(commands) handler := newAutoCompleteHandler() - words := handler.Find(commandText, commands, exclude) + words := handler.Find(commandText, command, exclude) for _, word := range words { fmt.Fprintln(b.StdOut, word) } return nil - }, - HideHelp: true, - } -} - -func (b CommandBuilder) createAutoCompleteCommand(version string) *cli.Command { - return &cli.Command{ - Name: "autocomplete", - Usage: "Autocompletion", - Description: "Commands for autocompletion", - Flags: []cli.Flag{ - b.HelpFlag(), - }, - Subcommands: []*cli.Command{ - b.createAutoCompleteEnableCommand(), - b.createAutoCompleteCompleteCommand(version), - }, - HideHelp: true, - } -} - -func (b CommandBuilder) createConfigCommand() *cli.Command { - authFlagName := "auth" - flags := []cli.Flag{ - &cli.StringFlag{ - Name: authFlagName, - Usage: fmt.Sprintf("Authorization type: %s, %s, %s", CredentialsAuth, LoginAuth, PatAuth), - }, - &cli.StringFlag{ - Name: profileFlagName, - Usage: "Profile to configure", - EnvVars: []string{"UIPATH_PROFILE"}, - Value: config.DefaultProfile, - }, - b.HelpFlag(), - } - - return &cli.Command{ - Name: "config", - Usage: "Interactive Configuration", - Description: "Interactive command to configure the CLI", - Flags: flags, - Subcommands: []*cli.Command{ - b.createConfigSetCommand(), - }, - Action: func(context *cli.Context) error { - auth := context.String(authFlagName) - profileName := context.String(profileFlagName) + }) +} + +func (b CommandBuilder) createAutoCompleteCommand(version string) *CommandDefinition { + flags := NewFlagBuilder(). + AddHelpFlag(). + Build() + + subcommands := []*CommandDefinition{ + b.createAutoCompleteEnableCommand(), + b.createAutoCompleteCompleteCommand(version), + } + + return NewCommand("autocomplete", "Autocompletion", "Commands for autocompletion"). + WithFlags(flags). + WithSubcommands(subcommands) +} + +func (b CommandBuilder) createConfigCommand() *CommandDefinition { + const flagNameAuth = "auth" + + flags := NewFlagBuilder(). + AddFlag(NewFlag(flagNameAuth, fmt.Sprintf("Authorization type: %s, %s, %s", CredentialsAuth, LoginAuth, PatAuth), FlagTypeString)). + AddFlag(NewFlag(FlagNameProfile, "Profile to configure", FlagTypeString). + WithEnvVarName("UIPATH_PROFILE"). + WithDefaultValue(config.DefaultProfile)). + AddHelpFlag(). + Build() + + subcommands := []*CommandDefinition{ + b.createConfigSetCommand(), + } + + return NewCommand("config", "Interactive Configuration", "Interactive command to configure the CLI"). + WithFlags(flags). + WithSubcommands(subcommands). + WithAction(func(context *CommandExecContext) error { + auth := context.String(flagNameAuth) + profileName := context.String(FlagNameProfile) handler := newConfigCommandHandler(b.StdIn, b.StdOut, b.ConfigProvider) return handler.Configure(auth, profileName) - }, - HideHelp: true, - } -} - -func (b CommandBuilder) createConfigSetCommand() *cli.Command { - keyFlagName := "key" - valueFlagName := "value" - flags := []cli.Flag{ - &cli.StringFlag{ - Name: keyFlagName, - Usage: "The key", - Required: true, - }, - &cli.StringFlag{ - Name: valueFlagName, - Usage: "The value to set", - Required: true, - }, - &cli.StringFlag{ - Name: profileFlagName, - Usage: "Profile to configure", - EnvVars: []string{"UIPATH_PROFILE"}, - Value: config.DefaultProfile, - }, - b.HelpFlag(), - } - return &cli.Command{ - Name: "set", - Usage: "Set config parameters", - Description: "Set config parameters", - Flags: flags, - Action: func(context *cli.Context) error { - profileName := context.String(profileFlagName) - key := context.String(keyFlagName) - value := context.String(valueFlagName) + }) +} + +func (b CommandBuilder) createConfigSetCommand() *CommandDefinition { + const flagNameKey = "key" + const flagNameValue = "value" + + flags := NewFlagBuilder(). + AddFlag(NewFlag(flagNameKey, "The key", FlagTypeString). + WithRequired(true)). + AddFlag(NewFlag(flagNameValue, "The value to set", FlagTypeString). + WithRequired(true)). + AddFlag(NewFlag(FlagNameProfile, "Profile to configure", FlagTypeString). + WithEnvVarName("UIPATH_PROFILE"). + WithDefaultValue(config.DefaultProfile)). + AddHelpFlag(). + Build() + + return NewCommand("set", "Set config parameters", "Set config parameters"). + WithFlags(flags). + WithAction(func(context *CommandExecContext) error { + profileName := context.String(FlagNameProfile) + key := context.String(flagNameKey) + value := context.String(flagNameValue) handler := newConfigCommandHandler(b.StdIn, b.StdOut, b.ConfigProvider) return handler.Set(key, value, profileName) - }, - HideHelp: true, - } + }) } func (b CommandBuilder) loadDefinitions(args []string, version string) ([]parser.Definition, error) { @@ -753,47 +647,47 @@ func (b CommandBuilder) loadAutocompleteDefinitions(args []string, version strin return b.loadDefinitions(args, version) } -func (b CommandBuilder) createShowCommand(definitions []parser.Definition) *cli.Command { - return &cli.Command{ - Name: "commands", - Usage: "Inspect available CLI operations", - Description: "Command to inspect available uipath CLI operations", - Flags: []cli.Flag{ - b.HelpFlag(), - }, - Subcommands: []*cli.Command{ - { - Name: "show", - Usage: "Print CLI commands", - Description: "Print available uipath CLI commands", - Flags: []cli.Flag{ - b.HelpFlag(), - }, - Action: func(context *cli.Context) error { - flagBuilder := newFlagBuilder() - flagBuilder.AddFlags(b.CreateDefaultFlags(false)) - flagBuilder.AddFlag(b.HelpFlag()) - flags := flagBuilder.ToList() - - handler := newShowCommandHandler() - output, err := handler.Execute(definitions, flags) - if err != nil { - return err - } - fmt.Fprintln(b.StdOut, output) - return nil - }, - HideHelp: true, - Hidden: true, - }, - }, - HideHelp: true, - Hidden: true, - } -} - -func (b CommandBuilder) createServiceCommands(definitions []parser.Definition) []*cli.Command { - commands := []*cli.Command{} +func (b CommandBuilder) createShowCommand(definitions []parser.Definition) *CommandDefinition { + flags := NewFlagBuilder(). + AddHelpFlag(). + Build() + + return NewCommand("show", "Print CLI commands", "Print available uipath CLI commands"). + WithFlags(flags). + WithHidden(true). + WithAction(func(context *CommandExecContext) error { + defaultFlags := NewFlagBuilder(). + AddDefaultFlags(false). + AddHelpFlag(). + Build() + + handler := newShowCommandHandler() + output, err := handler.Execute(definitions, defaultFlags) + if err != nil { + return err + } + fmt.Fprintln(b.StdOut, output) + return nil + }) +} + +func (b CommandBuilder) createInspectCommand(definitions []parser.Definition) *CommandDefinition { + flags := NewFlagBuilder(). + AddHelpFlag(). + Build() + + subcommands := []*CommandDefinition{ + b.createShowCommand(definitions), + } + + return NewCommand("commands", "Inspect available CLI operations", "Command to inspect available uipath CLI operations"). + WithFlags(flags). + WithSubcommands(subcommands). + WithHidden(true) +} + +func (b CommandBuilder) createServiceCommands(definitions []parser.Definition) []*CommandDefinition { + commands := []*CommandDefinition{} for _, e := range definitions { command := b.createServiceCommand(e) commands = append(commands, command) @@ -820,9 +714,9 @@ func (b CommandBuilder) versionFromProfile(profile string) string { return config.Version } -func (b CommandBuilder) Create(args []string) ([]*cli.Command, error) { - version := b.parseArgument(args, versionFlagName) - profile := b.parseArgument(args, profileFlagName) +func (b CommandBuilder) Create(args []string) ([]*CommandDefinition, error) { + version := b.parseArgument(args, FlagNameVersion) + profile := b.parseArgument(args, FlagNameProfile) if version == "" && profile != "" { version = b.versionFromProfile(profile) } @@ -833,108 +727,7 @@ func (b CommandBuilder) Create(args []string) ([]*cli.Command, error) { servicesCommands := b.createServiceCommands(definitions) autocompleteCommand := b.createAutoCompleteCommand(version) configCommand := b.createConfigCommand() - showCommand := b.createShowCommand(definitions) - commands := append(servicesCommands, autocompleteCommand, configCommand, showCommand) + inspectCommand := b.createInspectCommand(definitions) + commands := append(servicesCommands, autocompleteCommand, configCommand, inspectCommand) return commands, nil } - -func (b CommandBuilder) CreateDefaultFlags(hidden bool) []cli.Flag { - return []cli.Flag{ - &cli.BoolFlag{ - Name: debugFlagName, - Usage: "Enable debug output", - EnvVars: []string{"UIPATH_DEBUG"}, - Value: false, - Hidden: hidden, - }, - &cli.StringFlag{ - Name: profileFlagName, - Usage: "Config profile to use", - EnvVars: []string{"UIPATH_PROFILE"}, - Value: config.DefaultProfile, - Hidden: hidden, - }, - &cli.StringFlag{ - Name: uriFlagName, - Usage: "Server Base-URI", - EnvVars: []string{"UIPATH_URI"}, - Hidden: hidden, - }, - &cli.StringFlag{ - Name: organizationFlagName, - Usage: "Organization name", - EnvVars: []string{"UIPATH_ORGANIZATION"}, - Hidden: hidden, - }, - &cli.StringFlag{ - Name: tenantFlagName, - Usage: "Tenant name", - EnvVars: []string{"UIPATH_TENANT"}, - Hidden: hidden, - }, - &cli.BoolFlag{ - Name: insecureFlagName, - Usage: "Disable HTTPS certificate check", - EnvVars: []string{"UIPATH_INSECURE"}, - Value: false, - Hidden: hidden, - }, - &cli.StringFlag{ - Name: outputFormatFlagName, - Usage: fmt.Sprintf("Set output format: %s (default), %s", outputFormatJson, outputFormatText), - EnvVars: []string{"UIPATH_OUTPUT"}, - Value: "", - Hidden: hidden, - }, - &cli.StringFlag{ - Name: queryFlagName, - Usage: "Perform JMESPath query on output", - Value: "", - Hidden: hidden, - }, - &cli.StringFlag{ - Name: waitFlagName, - Usage: "Waits for the provided condition (JMESPath expression)", - Value: "", - Hidden: hidden, - }, - &cli.IntFlag{ - Name: waitTimeoutFlagName, - Usage: "Time to wait in seconds for condition", - Value: 30, - Hidden: hidden, - }, - &cli.StringFlag{ - Name: fileFlagName, - Usage: "Provide input from file (use - for stdin)", - Value: "", - Hidden: hidden, - }, - &cli.StringFlag{ - Name: identityUriFlagName, - Usage: "Identity Server URI", - EnvVars: []string{"UIPATH_IDENTITY_URI"}, - Hidden: hidden, - }, - b.VersionFlag(hidden), - } -} - -func (b CommandBuilder) VersionFlag(hidden bool) cli.Flag { - return &cli.StringFlag{ - Name: versionFlagName, - Usage: "Specific service version", - EnvVars: []string{"UIPATH_VERSION"}, - Value: "", - Hidden: hidden, - } -} - -func (b CommandBuilder) HelpFlag() cli.Flag { - return &cli.BoolFlag{ - Name: helpFlagName, - Usage: "Show help", - Value: false, - Hidden: true, - } -} diff --git a/commandline/command_definition.go b/commandline/command_definition.go new file mode 100644 index 0000000..330e3a9 --- /dev/null +++ b/commandline/command_definition.go @@ -0,0 +1,62 @@ +package commandline + +import "github.com/urfave/cli/v2" + +// The CommandExecContext contains the flag values provided by the user. +type CommandExecContext struct { + *cli.Context +} + +// The CommandExecFunc is the function definition for executing a command action. +type CommandExecFunc func(*CommandExecContext) error + +// The CommandDefinition contains the metadata and builder methods for creating +// CLI commands. +type CommandDefinition struct { + Name string + Summary string + Description string + Flags []*FlagDefinition + Subcommands []*CommandDefinition + HelpTemplate string + Hidden bool + Action CommandExecFunc +} + +func (c *CommandDefinition) WithFlags(flags []*FlagDefinition) *CommandDefinition { + c.Flags = flags + return c +} + +func (c *CommandDefinition) WithSubcommands(subcommands []*CommandDefinition) *CommandDefinition { + c.Subcommands = subcommands + return c +} + +func (c *CommandDefinition) WithHidden(hidden bool) *CommandDefinition { + c.Hidden = hidden + return c +} + +func (c *CommandDefinition) WithHelpTemplate(helpTemplate string) *CommandDefinition { + c.HelpTemplate = helpTemplate + return c +} + +func (c *CommandDefinition) WithAction(action CommandExecFunc) *CommandDefinition { + c.Action = action + return c +} + +func NewCommand(name string, summary string, description string) *CommandDefinition { + return &CommandDefinition{ + name, + summary, + description, + nil, + nil, + "", + false, + nil, + } +} diff --git a/commandline/flag_builder.go b/commandline/flag_builder.go index bca3eb3..cd761a6 100644 --- a/commandline/flag_builder.go +++ b/commandline/flag_builder.go @@ -1,36 +1,156 @@ package commandline import ( - "github.com/urfave/cli/v2" + "fmt" + + "github.com/UiPath/uipathcli/config" ) -type flagBuilder struct { - flags map[string]cli.Flag +const FlagNameDebug = "debug" +const FlagNameProfile = "profile" +const FlagNameUri = "uri" +const FlagNameOrganization = "organization" +const FlagNameTenant = "tenant" +const FlagNameInsecure = "insecure" +const FlagNameOutputFormat = "output" +const FlagNameQuery = "query" +const FlagNameWait = "wait" +const FlagNameWaitTimeout = "wait-timeout" +const FlagNameFile = "file" +const FlagNameIdentityUri = "identity-uri" +const FlagNameVersion = "version" +const FlagNameHelp = "help" + +const FlagValueFromStdIn = "-" +const FlagValueOutputFormatJson = "json" +const FlagValueOutputFormatText = "text" + +var FlagNamesPredefined = []string{ + FlagNameDebug, + FlagNameProfile, + FlagNameUri, + FlagNameOrganization, + FlagNameTenant, + FlagNameInsecure, + FlagNameOutputFormat, + FlagNameQuery, + FlagNameWait, + FlagNameWaitTimeout, + FlagNameFile, + FlagNameIdentityUri, + FlagNameVersion, + FlagNameHelp, +} + +// The FlagBuilder can be used to prepare a list of flags for a CLI command. +// The builder takes care that flags with the same name are deduped. +type FlagBuilder struct { + flags map[string]*FlagDefinition order []string } -func (b *flagBuilder) AddFlag(flag cli.Flag) { - name := flag.Names()[0] +func (b *FlagBuilder) AddFlag(flag *FlagDefinition) *FlagBuilder { + name := flag.Name if _, found := b.flags[name]; !found { b.flags[name] = flag b.order = append(b.order, name) } + return b } -func (b *flagBuilder) AddFlags(flags []cli.Flag) { +func (b *FlagBuilder) AddFlags(flags []*FlagDefinition) *FlagBuilder { for _, flag := range flags { b.AddFlag(flag) } + return b +} + +func (b *FlagBuilder) AddDefaultFlags(hidden bool) *FlagBuilder { + b.AddFlags(b.defaultFlags(hidden)) + return b +} + +func (b *FlagBuilder) AddHelpFlag() *FlagBuilder { + b.AddFlag(b.helpFlag()) + return b } -func (b flagBuilder) ToList() []cli.Flag { - flags := []cli.Flag{} +func (b *FlagBuilder) AddVersionFlag(hidden bool) *FlagBuilder { + b.AddFlag(b.versionFlag(hidden)) + return b +} + +func (b FlagBuilder) Build() []*FlagDefinition { + flags := []*FlagDefinition{} for _, name := range b.order { flags = append(flags, b.flags[name]) } return flags } -func newFlagBuilder() *flagBuilder { - return &flagBuilder{map[string]cli.Flag{}, []string{}} +func (b FlagBuilder) defaultFlags(hidden bool) []*FlagDefinition { + return []*FlagDefinition{ + NewFlag(FlagNameDebug, "Enable debug output", FlagTypeBoolean). + WithEnvVarName("UIPATH_DEBUG"). + WithDefaultValue(false). + WithHidden(hidden), + NewFlag(FlagNameProfile, "Config profile to use", FlagTypeString). + WithEnvVarName("UIPATH_PROFILE"). + WithDefaultValue(config.DefaultProfile). + WithHidden(hidden), + NewFlag(FlagNameUri, "Server Base-URI", FlagTypeString). + WithEnvVarName("UIPATH_URI"). + WithDefaultValue(""). + WithHidden(hidden), + NewFlag(FlagNameOrganization, "Organization name", FlagTypeString). + WithEnvVarName("UIPATH_ORGANIZATION"). + WithDefaultValue(""). + WithHidden(hidden), + NewFlag(FlagNameTenant, "Tenant name", FlagTypeString). + WithEnvVarName("UIPATH_TENANT"). + WithDefaultValue(""). + WithHidden(hidden), + NewFlag(FlagNameInsecure, "Disable HTTPS certificate check", FlagTypeBoolean). + WithEnvVarName("UIPATH_INSECURE"). + WithDefaultValue(false). + WithHidden(hidden), + NewFlag(FlagNameOutputFormat, fmt.Sprintf("Set output format: %s (default), %s", FlagValueOutputFormatJson, FlagValueOutputFormatText), FlagTypeString). + WithEnvVarName("UIPATH_OUTPUT"). + WithDefaultValue(""). + WithHidden(hidden), + NewFlag(FlagNameQuery, "Perform JMESPath query on output", FlagTypeString). + WithDefaultValue(""). + WithHidden(hidden), + NewFlag(FlagNameWait, "Waits for the provided condition (JMESPath expression)", FlagTypeString). + WithDefaultValue(""). + WithHidden(hidden), + NewFlag(FlagNameWaitTimeout, "Time to wait in seconds for condition", FlagTypeInteger). + WithDefaultValue(30). + WithHidden(hidden), + NewFlag(FlagNameFile, "Provide input from file (use - for stdin)", FlagTypeString). + WithDefaultValue(""). + WithHidden(hidden), + NewFlag(FlagNameIdentityUri, "Identity Server URI", FlagTypeString). + WithEnvVarName("UIPATH_IDENTITY_URI"). + WithDefaultValue(""). + WithHidden(hidden), + b.versionFlag(hidden), + } +} + +func (b FlagBuilder) versionFlag(hidden bool) *FlagDefinition { + return NewFlag(FlagNameVersion, "Specific service version", FlagTypeString). + WithEnvVarName("UIPATH_VERSION"). + WithDefaultValue(""). + WithHidden(hidden) +} + +func (b FlagBuilder) helpFlag() *FlagDefinition { + return NewFlag(FlagNameHelp, "Show help", FlagTypeBoolean). + WithDefaultValue(false). + WithHidden(true) +} + +func NewFlagBuilder() *FlagBuilder { + return &FlagBuilder{map[string]*FlagDefinition{}, []string{}} } diff --git a/commandline/flag_definition.go b/commandline/flag_definition.go new file mode 100644 index 0000000..6bb7ae4 --- /dev/null +++ b/commandline/flag_definition.go @@ -0,0 +1,47 @@ +package commandline + +type FlagOptionFunc func(*FlagDefinition) + +// The FlagDefinition contains the metadata and builder methods for creating +// command line flags. +type FlagDefinition struct { + Name string + Summary string + Type FlagType + EnvVarName string + DefaultValue interface{} + Hidden bool + Required bool +} + +func (f *FlagDefinition) WithDefaultValue(value interface{}) *FlagDefinition { + f.DefaultValue = value + return f +} + +func (f *FlagDefinition) WithEnvVarName(envVarName string) *FlagDefinition { + f.EnvVarName = envVarName + return f +} + +func (f *FlagDefinition) WithHidden(hidden bool) *FlagDefinition { + f.Hidden = hidden + return f +} + +func (f *FlagDefinition) WithRequired(required bool) *FlagDefinition { + f.Required = required + return f +} + +func NewFlag(name string, summary string, flagType FlagType) *FlagDefinition { + return &FlagDefinition{ + name, + summary, + flagType, + "", + nil, + false, + false, + } +} diff --git a/commandline/flag_type.go b/commandline/flag_type.go new file mode 100644 index 0000000..63e3ed3 --- /dev/null +++ b/commandline/flag_type.go @@ -0,0 +1,27 @@ +package commandline + +import "fmt" + +// The FlagType is an enum of the supported flag definition types. +type FlagType int + +const ( + FlagTypeString FlagType = iota + 1 + FlagTypeInteger + FlagTypeBoolean + FlagTypeStringArray +) + +func (t FlagType) String() string { + switch t { + case FlagTypeString: + return "string" + case FlagTypeInteger: + return "integer" + case FlagTypeBoolean: + return "boolean" + case FlagTypeStringArray: + return "stringArray" + } + panic(fmt.Sprintf("Unknown flag type: %d", int(t))) +} diff --git a/commandline/help_templates.go b/commandline/help_templates.go new file mode 100644 index 0000000..566b6bc --- /dev/null +++ b/commandline/help_templates.go @@ -0,0 +1,19 @@ +package commandline + +const OperationCommandHelpTemplate = `NAME: + {{template "helpNameTemplate" .}} + +USAGE: + {{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}}{{if .VisibleFlags}} [command options]{{end}}{{if .ArgsUsage}}{{.ArgsUsage}}{{else}} [arguments...]{{end}}{{end}}{{if .Description}} + +DESCRIPTION: + {{template "descriptionTemplate" .}}{{end}}{{if .VisibleCommands}} + +COMMANDS:{{template "visibleCommandTemplate" .}}{{end}}{{if .VisibleFlagCategories}} + +OPTIONS:{{template "visibleFlagCategoryTemplate" .}}{{else if .VisibleFlags}} + +OPTIONS:{{range $i, $e := .VisibleFlags}} + --{{$e.Name}} {{wrap $e.Usage 6}} +{{end}}{{end}} +` diff --git a/commandline/show_command_handler.go b/commandline/show_command_handler.go index ec26b86..ce7e3ca 100644 --- a/commandline/show_command_handler.go +++ b/commandline/show_command_handler.go @@ -5,7 +5,6 @@ import ( "sort" "github.com/UiPath/uipathcli/parser" - "github.com/urfave/cli/v2" ) // showCommandHandler prints all available uipathcli commands @@ -29,7 +28,7 @@ type commandJson struct { Subcommands []commandJson `json:"subcommands"` } -func (h showCommandHandler) Execute(definitions []parser.Definition, globalFlags []cli.Flag) (string, error) { +func (h showCommandHandler) Execute(definitions []parser.Definition, globalFlags []*FlagDefinition) (string, error) { result := commandJson{ Name: "uipath", Description: "Command line interface to simplify, script and automate API calls for UiPath services", @@ -104,7 +103,7 @@ func (h showCommandHandler) convertOperationToCommand(operation parser.Operation } } -func (h showCommandHandler) convertFlagsToCommandParameters(flags []cli.Flag) []parameterJson { +func (h showCommandHandler) convertFlagsToCommandParameters(flags []*FlagDefinition) []parameterJson { result := []parameterJson{} for _, f := range flags { result = append(result, h.convertFlagToCommandParameter(f)) @@ -120,37 +119,14 @@ func (h showCommandHandler) convertParametersToCommandParameters(parameters []pa return result } -func (h showCommandHandler) convertFlagToCommandParameter(flag cli.Flag) parameterJson { - intFlag, ok := flag.(*cli.IntFlag) - if ok { - return parameterJson{ - Name: intFlag.Name, - Description: intFlag.Usage, - Type: "integer", - Required: false, - AllowedValues: []interface{}{}, - DefaultValue: intFlag.Value, - } - } - boolFlag, ok := flag.(*cli.BoolFlag) - if ok { - return parameterJson{ - Name: boolFlag.Name, - Description: boolFlag.Usage, - Type: "boolean", - Required: false, - AllowedValues: []interface{}{}, - DefaultValue: boolFlag.Value, - } - } - stringFlag := flag.(*cli.StringFlag) +func (h showCommandHandler) convertFlagToCommandParameter(flag *FlagDefinition) parameterJson { return parameterJson{ - Name: stringFlag.Name, - Description: stringFlag.Usage, - Type: "string", + Name: flag.Name, + Description: flag.Summary, + Type: flag.Type.String(), Required: false, AllowedValues: []interface{}{}, - DefaultValue: stringFlag.Value, + DefaultValue: flag.DefaultValue, } }