Skip to content

About

Simple validation using code generation. No reflection welcome.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

29 Commits

Folders and files

Repository files navigation

gatekeeper

Simple validation using code generation. No reflection welcome.

Gatekeeper generates code that validates http request form values.

Validated values are assigned to corresponding struct fields without the use of reflection.

To generate a .gatekeeper.go file, run gatekeeper on a .yaml configuration file. You may need to run go mod tidy after generation in order to resolve dependencies such as libphonenumber if they are not already included in your project.

see example/gatekeeper.yaml for an example configuration file

features

  • Validation for

    • Ints
      • min and max
    • Strings
      • min length and max length
    • Emails
    • Options (must be one of { "January", "February", etc }
    • time.Time
      • specify time format (DateOnly, DateTime, etc)
    • UUIDS
    • Regex Matching
    • Phone Numbers
      • provided as *libphonenumber.PhoneNumber validated against a region
  • Handler Decorator Functionality is provided to convert a handler that takes in the request, responseWriter, a pointer to the validated struct, and a *gkerror.ValidationErrGroup to an http.HandlerFunc by decorating it to create and validate the struct, then pass it to your function. All you need to do is create a function like:

        func UserHandler(w http.ResponseWriter, r *http.Request, User *User, errs *gkerror.ValidationErrGroup) {
            // do something with the struct and errors        
            if errs.Any() {
                // an error occurred
                firstNameErrs := errs.ByField("FirstName") 
                // do something with errors on the FirstName field
            }
        }

    then you can pass it to the generated function decorator to get an http.HandlerFunc:

        handler := NewUserHandler(UserHandler) // this returns an http.HandlerFunc that can be assigned to a route
  • Interfaces The generated struct is attached getter methods for each of its fields in the form of Get() , like so:

    func (x *User) GetFirstName() string {
        return x.FirstName
    }
    
    func (x *User) GetLastName() string {
        return x.LastName
    }
    
    func (x *User) GetEmail() string {
        return x.Email
    }
    
    func (x *User) GetId() uuid.UUID {
        return x.Id
    }
    
    func (x *User) GetCreatedAt() time.Time {
        return x.CreatedAt
    }
    
    func (x *User) GetPhoneNumber() *libphonenumber.PhoneNumber {
        return x.PhoneNumber
    }
    
    func (x *User) GetAge() int {
        return x.Age
    }
    
    func (x *User) GetBirthMonth() string {
        return x.BirthMonth
    }

    This allows for interfaces to be emitter to other packages using the emit_interface_to property of the object configuration.

    For example we can specify that we'd like the interface to be emitted to package other located at ./other:

    package other
    
    import (
        "time"
    
        "github.com/google/uuid"
        "github.com/ttacon/libphonenumber"
    )
    
    type IUser interface {
        GetFirstName() string
        GetLastName() string
        GetEmail() string
        GetId() uuid.UUID
        GetCreatedAt() time.Time
        GetPhoneNumber() *libphonenumber.PhoneNumber
        GetAge() int
        GetBirthMonth() string
    }

roadmap

features to implement going forward

  • File types
  • Additional primitives and other custom types (booleans, slices, int64, uuid.UUID, etc)
  • Middleware provider
  • Custom object-level validators
  • Fine-grained error handling
  • File watching & caching
  • Generate tests for sample data
  • Additional string features:
    • hasPrefix
    • hasSuffix
    • includes
    • doesn't include
    • alphaNumeric
  • Additional Int features:
    • isPositive
    • isNegative
    • isMultipleOf
  • optional fields with default values
  • URLs
  • IP addresses
  • Mac Addresses
  • Emojis
  • Additional UUID versions uuidv4, uuidv6, etc
  • JWTs
  • Parsing from request body as JSON
  • Panic on Error option w/ recover handler
  • Validation escape on first failure
  • Support for externally defined types
  • Comparison against other fields (i.e. .NumberOne must be greater than .NumberTwo)
  • Colors (rgba, hex)
  • Valid JSON string
    • marshal into provided type
  • Social Security Numbers
  • Emit interface to another directory/package

internals

  • Run generation of all objects in parallel using a workgroup
  • Better validation/error messages for configuration files

About

Simple validation using code generation. No reflection welcome.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages