generator

package
v0.71.0 Latest Latest
Warning

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

Go to latest
Published: Sep 21, 2023 License: MIT Imports: 11 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var DtoTemplate, _ = template.New("dtoTemplate").Parse(`
{{define "DTO_STRUCT"}}
type {{.DtoDecl}} struct {
	{{- range .Fields}}
		{{- if .ShouldBeInDto}}
		{{.Name}} {{.DtoKind}} {{if .Required}}// required{{end}}
		{{- end}}
	{{- end}}
}

{{- range .Fields}}
	{{if .IsStruct}}
	{{template "DTO_STRUCT" .}}
	{{end}}
{{- end}}
{{end}}

//go:generate go run ../../dto-builder-generator/main.go

var (
	{{- range .Operations}}
	_ optionsProvider[{{.OptsField.KindNoPtr}}] = new({{.OptsField.DtoDecl}})
	{{- end}}
)

{{- range .Operations}}
	{{template "DTO_STRUCT" .OptsField}}
{{- end}}
`)
View Source
var ImplementationTemplate, _ = template.New("implementationTemplate").Parse(`
{{define "MAPPING" -}}
	&{{.KindNoPtr}}{
		{{- range .Fields}}
			{{- if .ShouldBeInDto}}
			{{if .IsStruct}}{{else}}{{.Name}}: r{{.Path}},{{end}}
			{{- end}}
		{{- end}}
	}
	{{range .Fields}}
		{{if .ShouldBeInDto}}
			{{if .IsStruct}}
				if r{{.Path}} != nil {
					opts{{.Path}} = {{template "MAPPING" .}}
				}
			{{end}}
		{{end}}
	{{end}}
{{end}}
import "context"

{{$impl := .NameLowerCased}}
var _ {{.Name}} = (*{{$impl}})(nil)

type {{$impl}} struct {
	client *Client
}
{{range .Operations}}
func (v *{{$impl}}) {{.Name}}(ctx context.Context, request *{{.OptsField.DtoDecl}}) error {
	opts := request.toOpts()
	return validateAndExec(v.client, ctx, opts)
}
{{end}}

{{range .Operations}}
func (r *{{.OptsField.DtoDecl}}) toOpts() *{{.OptsField.KindNoPtr}} {
	opts := {{template "MAPPING" .OptsField}}
	return opts
}
{{end}}
`)
View Source
var IntegrationTestsTemplate, _ = template.New("integrationTestsTemplate").Parse(`
import "testing"

func TestInt_{{.Name}}(t *testing.T) {
	// TODO: fill me
}
`)
View Source
var InterfaceTemplate, _ = template.New("interfaceTemplate").Parse(`
import "context"

type {{.Name}} interface {
	{{- range .Operations}}
		{{.Name}}(ctx context.Context, request *{{.OptsField.DtoDecl}}) error
	{{- end}}
}
`)
View Source
var OptionsTemplate, _ = template.New("optionsTemplate").Parse(`
// {{.OptsField.KindNoPtr}} is based on {{.Doc}}.
type {{.OptsField.KindNoPtr}} struct {
	{{- range .OptsField.Fields}}
			{{.Name}} {{.Kind}} {{.TagsPrintable}}
	{{- end}}
}
`)
View Source
var PackageTemplate, _ = template.New("packageTemplate").Parse(`
package {{.}}
`)
View Source
var StructTemplate, _ = template.New("structTemplate").Parse(`
type {{.KindNoPtr}} struct {
	{{- range .Fields}}
			{{.Name}} {{.Kind}} {{.TagsPrintable}}
	{{- end}}
}
`)

TODO: merge with template above? (requires moving Doc to field)

View Source
var TestFuncTemplate, _ = template.New("testFuncTemplate").Parse(`
{{define "VALIDATION_TEST"}}
	{{$field := .}}
	{{- range .Validations}}
	{{.TodoComment $field}}
	{{- end}}
{{end}}

{{define "VALIDATIONS"}}
	{{template "VALIDATION_TEST" .}}
	{{- range .Fields}}
		{{if .HasAnyValidationInSubtree}}
			{{template "VALIDATIONS" .}}
		{{end}}
	{{- end}}
{{end}}

import "testing"

{{- range .Operations}}
func Test{{.ObjectInterface.Name}}_{{.Name}}(t *testing.T) {
	id := random{{.ObjectInterface.IdentifierKind}}(t)

	defaultOpts := func() *{{.OptsField.KindNoPtr}} {
		return &{{.OptsField.KindNoPtr}}{
			name: id,
		}
	}
	// TODO: remove me
	_ = defaultOpts()

	// TODO: fill me
	{{template "VALIDATIONS" .OptsField}}
}
{{end}}
`)
View Source
var ValidationsImplTemplate, _ = template.New("validationsImplTemplate").Parse(`
{{define "VALIDATIONS"}}
	{{$field := .}}
	{{- range .Validations}}
	if {{.Condition $field}} {
		errs = append(errs, {{.Error}})
	}
	{{- end}}
	{{- range .Fields}}
		{{if .HasAnyValidationInSubtree}}
			if valueSet(opts{{.Path}}) {
				{{template "VALIDATIONS" .}}
			}
		{{end}}
	{{- end}}
{{end}}

import "errors"

var (
{{- range .Operations}}
	_ validatable = new({{.OptsField.KindNoPtr}})
{{- end}}
)
{{range .Operations}}
func (opts *{{.OptsField.KindNoPtr}}) validate() error {
	if opts == nil {
		return errors.Join(errNilOptions)
	}
	var errs []error
	{{template "VALIDATIONS" .OptsField}}
	return errors.Join(errs...)
}
{{end}}
`)

Functions

func GenerateDtos

func GenerateDtos(writer io.Writer, def *Interface)

func GenerateImplementation

func GenerateImplementation(writer io.Writer, def *Interface)

func GenerateIntegrationTests

func GenerateIntegrationTests(writer io.Writer, def *Interface)

func GenerateInterface

func GenerateInterface(writer io.Writer, def *Interface)

func GenerateUnitTests

func GenerateUnitTests(writer io.Writer, def *Interface)

func GenerateValidations

func GenerateValidations(writer io.Writer, def *Interface)

func WriteCodeToFile

func WriteCodeToFile(buffer *bytes.Buffer, fileName string)

Types

type Field

type Field struct {
	// Parent allows to traverse fields hierarchy more easily, nil for root
	Parent *Field
	// Fields defines children, use for struct fields
	Fields []*Field
	// Validations defines validations on given field level (e.g. oneOf for children)
	Validations []*Validation

	// Name is how field is called in parent struct
	Name string
	// Kind is fields type (e.g. string, *bool)
	Kind string
	// Tags should contain ddl and sql tags used for SQL generation
	Tags map[string][]string
	// Required is used to mark fields which are essential (it's used e.g. for DTO builders generation)
	Required bool
}

Field defines properties of a single field or struct (by defining Fields)

func NewField

func NewField(
	name string,
	kind string,
	tags map[string][]string,
) *Field

func (*Field) DtoDecl

func (field *Field) DtoDecl() string

DtoDecl returns how struct should be declared in generated DTO (e.g. definition is without a pointer)

func (*Field) DtoKind

func (field *Field) DtoKind() string

DtoKind returns what should be fields kind in generated DTO, because it may differ from Kind

func (*Field) HasAnyValidationInSubtree

func (field *Field) HasAnyValidationInSubtree() bool

HasAnyValidationInSubtree checks if any validations are present from current field level downwards

func (*Field) IsRoot

func (field *Field) IsRoot() bool

IsRoot checks if field is at the top of field hierarchy, basically it is true for Option structs

func (*Field) IsStruct

func (field *Field) IsStruct() bool

IsStruct checks if field is a struct

func (*Field) KindNoPtr

func (field *Field) KindNoPtr() string

KindNoPtr return field's Kind but without pointer

func (*Field) Path

func (field *Field) Path() string

Path returns the way through the tree to the top, with dot separator (e.g. .SomeField.SomeChild)

func (*Field) ShouldBeInDto

func (field *Field) ShouldBeInDto() bool

ShouldBeInDto checks if field is not some static SQL field which should not be interacted with by SDK user TODO: this is a very naive implementation, consider fixing it with DSL builder connection

func (*Field) TagsPrintable

func (field *Field) TagsPrintable() string

TagsPrintable defines how tags are printed in options structs, it ensures the same order of tags for every field

func (*Field) WithFields

func (field *Field) WithFields(fields []*Field) *Field

func (*Field) WithParent

func (field *Field) WithParent(parent *Field) *Field

func (*Field) WithRequired

func (field *Field) WithRequired(required bool) *Field

func (*Field) WithValidations

func (field *Field) WithValidations(validations []*Validation) *Field

type Interface

type Interface struct {
	// Name is the interface's name, e.g. "DatabaseRoles"
	Name string
	// NameSingular is the prefix/suffix which can be used to create other structs and methods, e.g. "DatabaseRole"
	NameSingular string
	// Operations contains all operations for given interface
	Operations []*Operation
	// IdentifierKind keeps identifier of the underlying object (e.g. DatabaseObjectIdentifier)
	IdentifierKind string
}

Interface groups operations for particular object or objects family (e.g. DATABASE ROLE)

func NewInterface

func NewInterface(
	name string,
	nameSingular string,
	identifierKind string,
) *Interface

func (*Interface) NameLowerCased

func (i *Interface) NameLowerCased() string

NameLowerCased returns interface name starting with a lower case letter

func (*Interface) WithOperations

func (i *Interface) WithOperations(operations []*Operation) *Interface

type Operation

type Operation struct {
	// Name is the operation's name, e.g. "Create"
	Name string
	// ObjectInterface points to the containing interface
	ObjectInterface *Interface
	// Doc is the URL for the doc used to create given operation, e.g. https://docs.snowflake.com/en/sql-reference/sql/create-database-role
	Doc string
	// OptsField defines opts used to create SQL for given operation
	OptsField *Field
}

Operation defines a single operation for given object or objects family (e.g. CREATE DATABASE ROLE)

func NewOperation

func NewOperation(
	name string,
	doc string,
) *Operation

func (*Operation) WithObjectInterface

func (s *Operation) WithObjectInterface(objectInterface *Interface) *Operation

func (*Operation) WithOptsField

func (s *Operation) WithOptsField(optsField *Field) *Operation

type Validation

type Validation struct {
	Type       ValidationType
	FieldNames []string
}

func NewValidation

func NewValidation(
	vType ValidationType,
	fieldNames []string,
) *Validation

func (*Validation) Condition

func (v *Validation) Condition(field *Field) string

func (*Validation) Error

func (v *Validation) Error() string

func (*Validation) TodoComment

func (v *Validation) TodoComment(field *Field) string

type ValidationType

type ValidationType int64

ValidationType contains all handled validation types. Below validations are marked to be contained here or not: - opts not nil - not present here, handled on template level - valid identifier - present here, for now put on level containing given field - conflicting fields - present here, put on level containing given fields - exactly one value set - present here, put on level containing given fields - at least one value set - present here, put on level containing given fields - nested validation conditionally - not present here, handled by putting validations on lower level fields

const (
	ValidIdentifier ValidationType = iota
	ConflictingFields
	ExactlyOneValueSet
	AtLeastOneValueSet
)

Jump to

Keyboard shortcuts

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