Skip to content

Validations

maxlandon edited this page Jan 2, 2023 · 3 revisions

The flags library also enables users to validate flags and positional arguments.

Using the validation option

Before showing tags and implementation, here is how a user would want to provide validation for the commands at scan-time:

package main

import (
	"github.com/reeflective/flags"
	"github.com/reeflective/flags/example/commands"
	genflags "github.com/reeflective/flags/gen/flags"
	"github.com/reeflective/flags/validator"
)

func main() {
    // Generate a default validator.
    validatorFunc := validator.New()
        
    rootData := commands.Root{}
        
    // Generate the command tree with the validator as option.
    rootCmd := genflags.Generate(&rootData, flags.Validator(validatorFunc))
        
    rootCmd.Execute()
}

Validation tags

The easiest way to provide builtin validation to flags and positional fields is to declare a tag validate which value is a compliant go-validator notation.

The following demonstrates simple validation tags:

type Command struct {
	Args struct {
		IP     string   `validate:"ipv4"`
		Emails []string `required:"1-2" validate:"email"`
	} `positional-args:"yes"`
        
    // Flags
	Path         string            `short:"p" long:"path" validate:"file"`
	OptionalPath string            `short:"d" long:"opt-dir" optional-value:"/home/user" validate:"dir"`
	Files        []string          `short:"f" long:"files" complete:"Files" validate:"file"`
}

The validations will be run at execution time, and if the completions package is used, once an argument has been entered in the command line. This allows to have early feedback on the validity of the command input.

Validation interfaces

Types can also implement the following interface to provide validation:

type ValueValidator interface {
	// IsValidValue returns an error if the provided string value is not valid for the flag.
	IsValidValue(value string) error
}

Additional custom validators

The go-playground.Validator type allows users to register custom validation functions, which can then be referenced in the validation tags of flags/args fields. If you wish to use a custom validator, the following demonstrates how to do it:

package main

import (
	"github.com/reeflective/flags"
	flagsValidate "github.com/reeflective/flags/validator"
	"github.com/go-playground/validator/v10"
)

func main() {
    // Create a validator with go-playground library
    validate := validator.New()
        
    // ... Add custom validations to the validate object...
        
    // Pass this validator to the flags instantiator
    flagsValidator := flagsValidate.NewWith(validate) 
        
    // Generate the command tree with the validator as option. 
    rootCmd := genflags.Generate(&rootData, flags.Validator(validatorFunc))
}