protocheck

package module
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 4, 2025 License: MIT Imports: 8 Imported by: 0

README

protocheck

Go GoDoc

Lightweight solution to ProtocolBuffers message validation. protocheck-proto-gen is a protoc plugin that generates Go code.

features

  • expressions with Google/CEL
  • both message and field checks
  • nested messages
  • repeated, oneof and map fields
  • syntax validation of CEL expressions at generation time
  • supports proto3 and edition 2023

install

  go install github.com/emicklei/protocheck/cmd/protoc-gen-protocheck@latest
generate
  protoc --go_out=. --go_opt=paths=source_relative --protocheck_out=.

example

package hr;

import "check.proto";

message Person {
  
  // message cross-field checks
  option (check.message) = { 
    cel:"size(this.name + this.surname) > 0"  // cel is required
    fail:"name and surname cannot be empty"  // fail is optional
    id:"person_invariant" }; // id is optional
  
  // with per field state checks
  string name = 1 [(check.field) = { 
      cel:"size(this.name) > 1"                  
      fail:"name must be longer than 1" }];

  optional string middle_name = 2 [(check.field) = { 
      cel:"size(this.middle_name) > 0"           
      fail:"middle name (if set) cannot be empty" }];

  string surname = 3 [(check.field) = { 
      cel:"size(this.surname) > 1"               
      fail:"surname must be longer than 1" }];

  google.protobuf.Timestamp birth_date  = 4 [(check.field) = { 
      cel:"this.birth_date.getFullYear() > 2000" 
      id:"check_birth_date" }];

getFullYear is one of the supported CEL macros.

See CEL language definition for creating CEL expressions.

usage
p := &Person{
    Name:      "",
    BirthDate: &timestamppb.Timestamp{Seconds:1}
}
if err := p.Validate() ; err != nil {
  verr := protocheck.AsValidationError(err)
  for _ , each := range verr {
    log.Println(each)
  }
}
considerations

The protocheck package is inspired by bufbuild/protovalidate which also uses the powerful CEL expression language. However, it differs by:

  • this always refers to the message
  • minimal dependencies (cel and protobuf)
  • syntax is more compact

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// repeated check.Check field = 20030916;
	E_Field = &file_check_proto_extTypes[1]
)

Extension fields to descriptorpb.FieldOptions.

View Source
var (
	// repeated check.Check message = 20030916;
	E_Message = &file_check_proto_extTypes[0]
)

Extension fields to descriptorpb.MessageOptions.

View Source
var File_check_proto protoreflect.FileDescriptor

Functions

func MakeProgram

func MakeProgram(env *cel.Env, expression string) (cel.Program, error)

MakeProgram creates a cel Program for a given expression and environment.

Types

type Check

type Check struct {
	Id   string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`     // optional identifier for lookup purposes
	Fail string `protobuf:"bytes,2,opt,name=fail,proto3" json:"fail,omitempty"` // optional message to report when the check fails
	Cel  string `protobuf:"bytes,3,opt,name=cel,proto3" json:"cel,omitempty"`   // Google/CEL expression (https://github.com/google/cel-spec)
	// contains filtered or unexported fields
}

func (*Check) Descriptor deprecated

func (*Check) Descriptor() ([]byte, []int)

Deprecated: Use Check.ProtoReflect.Descriptor instead.

func (*Check) GetCel

func (x *Check) GetCel() string

func (*Check) GetFail

func (x *Check) GetFail() string

func (*Check) GetId

func (x *Check) GetId() string

func (*Check) ProtoMessage

func (*Check) ProtoMessage()

func (*Check) ProtoReflect

func (x *Check) ProtoReflect() protoreflect.Message

func (*Check) Reset

func (x *Check) Reset()

func (*Check) String

func (x *Check) String() string

type CheckError

type CheckError struct {
	Path string // path to the field that failed, if empty then the field is part of the root message
	Id   string // optional id of the check that failed
	Fail string // optional message to display
	Err  error  // set if the check failed due to an error
}

CheckError captures a failed check.

func (CheckError) WithParentField

func (c CheckError) WithParentField(parent string, key any) CheckError

WithParentField returns a new CheckError with the parent field prepended to the path.

func (CheckError) WithPath

func (c CheckError) WithPath(path string) CheckError

WithPath returns a new CheckError with the path set.

type Checker

type Checker struct {
	// contains filtered or unexported fields
}

Checker performs one check using a CEL program.

func NewChecker

func NewChecker(id string, fail string, cel string, fieldName string, isOptional bool, program cel.Program) Checker

NewChecker creates a Checker

func (Checker) WithEnabledFunc

func (c Checker) WithEnabledFunc(enabledFunc func(any) bool) Checker

func (Checker) WithIsSetFunc added in v0.2.0

func (c Checker) WithIsSetFunc(fun func(message any, fieldName string) bool) Checker

type MessageValidator

type MessageValidator struct {
	// contains filtered or unexported fields
}

MessageValidator holds a collection of checkers to validate a message.

func NewMessageValidator

func NewMessageValidator(messageCheckers, fieldCheckers []Checker) MessageValidator

NewMessageValidator creates a MessageValidator using two collections of checkers

func (MessageValidator) Validate

func (m MessageValidator) Validate(this any) (result ValidationError)

Validate runs all message and field checkers with the message. Always returns a ValidationError which can be empty (no failed checks)

type ValidationError

type ValidationError []CheckError

ValidationError is a collection of CheckError.

func AsValidationError added in v0.3.0

func AsValidationError(err error) ValidationError

AsValidationError converts an error or nil to a valid ValidationError (so could be empty).

func (ValidationError) Error

func (v ValidationError) Error() string

Error implements error

type Validator

type Validator interface {
	Validate() error
}

Validator is an interface that can be implemented by a message to validate itself.

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL