embed

package
v0.1.3 Latest Latest
Warning

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

Go to latest
Published: Jun 21, 2023 License: MIT Imports: 1 Imported by: 0

Documentation

Index

Constants

View Source
const FojiDotYaml = `` /* 3177-byte string literal not displayed */
View Source
const FojiSlashDbListDotConsoleDotTpl = `` /* 1605-byte string literal not displayed */
View Source
const FojiSlashEmbedDotGoDotTpl = `// Code generated by foji {{ version }}, template: {{ templateFile }}; DO NOT EDIT.

package {{ .PackageName }}

import "os"

func List() []string {
	return []string{
{{- range .FileGroups }}
	{{- range .Files }}
		"{{ .Name }}",
	{{- end }}
{{- end}}
		}
}

func Get(filename string) ([]byte, error) {
	switch filename {
{{- range .FileGroups }}
{{- range .Files }}
	case "{{ .Name }}":
		return {{ case (goToken .Name) }}Bytes, nil
{{- end }}
{{- end}}
	}

	return nil, os.ErrNotExist
}

func GetString(filename string) (string, error) {
	switch filename {
{{- range .FileGroups }}
{{- range .Files }}
	case "{{ .Name }}":
		return {{ case (goToken .Name) }}, nil
{{- end }}
{{- end}}
	}

	return "", os.ErrNotExist
}
{{- range .FileGroups }}
{{- range .Files }}

// {{.Name}}
var {{ case (goToken .Name) }}Bytes = []byte({{ case (goToken .Name) }})
const {{ case (goToken .Name) }} = ` + "`" + `{{ backQuote (toString .Content) }}` + "`" + `
{{- end -}}
{{end -}}`
View Source
const FojiSlashEnumDotGoDotTpl = `` /* 3759-byte string literal not displayed */
View Source
const FojiSlashFieldsDotGoDotTpl = `` /* 11105-byte string literal not displayed */
View Source
const FojiSlashOpenapiSlashAuthDotGoDotTpl = `` /* 3781-byte string literal not displayed */
View Source
const FojiSlashOpenapiSlashDocsDotGoDotTpl = `` /* 589-byte string literal not displayed */
View Source
const FojiSlashOpenapiSlashHandlerDotGoDotTpl = `` /* 11915-byte string literal not displayed */
View Source
const FojiSlashOpenapiSlashMainDotGoDotTpl = `package main

import (
	"context"
	"errors"
	"fmt"
	"net/http"
	"os"
	"os/signal"
	"sync"
	"time"

	"github.com/bir/iken/config"
	"github.com/bir/iken/errs"
	"github.com/bir/iken/httplog"
	"github.com/go-chi/chi/v5"
	"github.com/lavaai/kit/auth"
	"github.com/rs/zerolog"
	"github.com/rs/zerolog/log"
	chiTrace "gopkg.in/DataDog/dd-trace-go.v1/contrib/go-chi/chi.v5"

	"{{ .Params.Package }}"
)

type Config struct {
	Debug               bool          ` + "`" + `env:"DEBUG"` + "`" + `
	Port                int           ` + "`" + `env:"PORT, 3500"` + "`" + `
	HttpWriteTimeout    time.Duration ` + "`" + `env:"HTTP_WRITE_TIMEOUT, 30s"` + "`" + `
	HttpReadTimeout     time.Duration ` + "`" + `env:"HTTP_READ_TIMEOUT, 30s"` + "`" + `
	HttpIdleTimeout     time.Duration ` + "`" + `env:"HTTP_IDLE_TIMEOUT, 50s"` + "`" + `
	HttpShutdownTimeout time.Duration ` + "`" + `env:"HTTP_SHUTDOWN_TIMEOUT, 5s"` + "`" + `
}

func main() {
	var cfg Config
	err := config.Load(&cfg)
	if err != nil {
		log.Fatal().Err(err).Msg("loading config")
	}

	l := setupLogging(true)

	router := chi.NewRouter().With(
		httplog.RecoverLogger(l),
		chiTrace.Middleware(),
		httplog.RequestLogger(httplog.LogAll),
	)

	svc :=  {{ $.PackageName }}.New()
	{{ $.PackageName }}.RegisterHTTP(svc, router
{{- if .HasAuthentication -}}
	{{- range $security, $value := .File.API.Components.SecuritySchemes -}}
	, {{ $.PackageName }}.{{ pascal $security }}Auth({{ pascal $security }}Auth)
	{{- end -}}
    {{- if .HasAuthorization -}}
	, Authorize
    {{- end -}}
{{- end -}}
)

	httpServer := http.Server{
		Addr:         fmt.Sprintf(":%d", cfg.Port),
		WriteTimeout: cfg.HttpWriteTimeout,
		ReadTimeout:  cfg.HttpReadTimeout,
		IdleTimeout:  cfg.HttpIdleTimeout,
		Handler:      router,
	}

	httpServerExit := make(chan int, 1)

	go func() {
		defer func() { httpServerExit <- 1 }()

		l.Info().Msgf("Serving on: http://%s", httpServer.Addr)
		if err := httpServer.ListenAndServe(); err != nil {
			if !errors.Is(err, http.ErrServerClosed) {
				log.Error().Stack().Err(err).Msg("HTTP Server error")
			}
		}
		log.Info().Msg("HTTP Server stopped")
	}()

	sigInt := make(chan os.Signal, 1)

	signal.Notify(sigInt, os.Interrupt) // We'll start graceful shutdowns when quit via SIGINT (Ctrl+C)

	var wg sync.WaitGroup // Block until we receive any signal.

	select {
	case <-sigInt:
		shutdownServer(&httpServer, cfg.HttpShutdownTimeout, &wg)
		log.Info().Msg("SIGINT received, shutting down.")
	case <-httpServerExit:
		log.Info().Msg("HTTP Server exited")
	}

	wg.Wait()

}

func setupLogging(consoleLog bool) zerolog.Logger {
	zerolog.DurationFieldInteger = true
	zerolog.DurationFieldUnit = time.Millisecond
	zerolog.ErrorStackMarshaler = errs.MarshalStack
	zerolog.TimeFieldFormat = zerolog.TimeFormatUnix

	if consoleLog {
		log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
	}

	zerolog.DefaultContextLogger = &log.Logger

	return log.Logger
}

func shutdownServer(server *http.Server, duration time.Duration, wg *sync.WaitGroup) {
	wg.Add(1)

	go func() {
		defer wg.Done()

		ctx, cancel := context.WithTimeout(context.Background(), duration)
		defer cancel()

		err := server.Shutdown(ctx)
		if err != nil {
			log.Error().Stack().Err(err).Msg("Error shutting down server.")
		}
	}()
}

{{- if .HasAuthentication -}}
	{{- range $security, $value := .File.API.Components.SecuritySchemes }}

func {{ pascal $security }}Auth(ctx context.Context, key string) (*{{ $.CheckPackage $.Params.Auth "" }}, error){
	return nil, {{ $.PackageName }}.ErrNotImplemented
}
	{{- end -}}
    {{- if .HasAuthentication }}

func Authorize(ctx context.Context, user *auth.LavaUser, scopes []string) error {
	return form.ErrNotImplemented
}

{{- end -}}
{{- end -}}`
View Source
const FojiSlashOpenapiSlashModelDotGoDotTpl = `{{- define "propertyDeclaration"}}
    {{- $key := .RuntimeParams.key }}
    {{- $schema := .RuntimeParams.schema }}
    {{- $typeName := .RuntimeParams.typeName }}
    {{- goDoc $schema.Value.Description }}
    {{ pascal $key }} {{ $.GetType .PackageName (print $typeName " " $key) $schema }} ` + "`" + `json:"{{$key}},omitempty"` + "`" + `
{{- end -}}

{{- define "enum"}}
{{- $schema := .RuntimeParams.schema }}
{{- $description := .RuntimeParams.description }}
{{- $name := .RuntimeParams.name }}
{{- $enumType := $.CheckPackage ($.EnumName $name) $.PackageName -}}
{{- if and (empty $schema.Ref) (not (empty $schema.Value.Enum)) }}

// {{$enumType}}
{{- goDoc $description }}
type {{ $enumType }} int8

const (
    Unknown{{ $enumType }} {{ $enumType }} = iota
    {{- range $i, $value := $schema.Value.Enum }}
    {{ $enumType }}{{ pascal (goToken (printf "%v" $value)) }}
    {{- end }}
)

func New{{ $enumType }}(name string) {{ $enumType }} {
    switch name {
    {{- range $schema.Value.Enum  }}
    case "{{ . }}":
        return {{ $enumType }}{{ pascal (goToken (printf "%v" .)) }}
    {{- end }}
    }

    return {{ $enumType }}(0)
}

var  {{ $enumType }}String = map[{{ $enumType }}]string{
    {{- range $schema.Value.Enum }}
        {{ $enumType }}{{ pascal (goToken (printf "%v" .)) }}: "{{ (printf "%v" .) }}",
    {{- end }}
}

func (e {{ $enumType }}) String() string {
    return {{ $enumType }}String[e]
}

func (e *{{ $enumType }}) UnmarshalJSON(input []byte) (err error) {
	var i int8

	err = json.Unmarshal(input, &i)
	if err == nil {
		*e = {{ $enumType }}(i)
		return nil
	}

	var s string

	err = json.Unmarshal(input, &s)
	if err != nil {
		return err
	}

	*e = New{{ $enumType }}(s)

	return nil
}

func (e *{{ $enumType }}) MarshalJSON() ([]byte, error) {
    return json.Marshal(e.String())
}
{{- end -}}
{{- end -}}

{{- define "typeDeclaration"}}
{{ $schema := .RuntimeParams.schema }}
{{- $key := .RuntimeParams.key }}
{{- $label := .RuntimeParams.label }}

{{- if not ($.HasExtension $schema "x-go-type" )}}
{{- $typeName := $.GetType $.PackageName $key $schema }}
// {{ $typeName}}
{{- goDoc $schema.Value.Description }}
//
// OpenAPI {{$label}}: {{ $key }}

    {{- if in $schema.Value.Type "object" "" }}
type {{ pascal $key }} struct {
    {{- range $key, $schema := $.SchemaProperties $schema  false}}
        {{- template "propertyDeclaration" ($.WithParams "key" $key "schema" $schema "typeName" $typeName)}}
    {{- end }}
    {{- range $schema.Value.AllOf }}
        {{- if notEmpty .Ref }}

    // OpenAPI Ref: {{ .Ref }}
    {{ $.GetType $.PackageName "" . }}
        {{- end }}
    {{- end }}
}
    {{- else }}
type {{ pascal $key }} {{ $.GetType $.PackageName (pascal (print $typeName " Item" )) $schema }}
    {{- end }}

{{- /* Nested Types */}}
    {{- range $key, $schema := $.SchemaProperties $schema false }}
        {{- if not (empty $schema.Value.Properties )}}
            {{- if empty $schema.Ref -}}
                {{- template "typeDeclaration" ($.WithParams "key" (pascal (print $typeName " " $key)) "schema" $schema "label" (print  $typeName " inline " $key))}}
            {{- end -}}
        {{- else if eq $schema.Value.Type "array"}}
            {{- if empty $schema.Value.Items.Ref -}}
                {{- if not (empty ($.SchemaProperties $schema.Value.Items false ))}}
                    {{- template "typeDeclaration" ($.WithParams "key" (pascal (print $typeName " " $key)) "schema" $schema.Value.Items "label" (print  $typeName " inline item " $key))}}
                {{- end }}
            {{- end }}
        {{- end }}
    {{- end }}
        {{- /* Nested Arrays */}}
    {{- if eq $schema.Value.Type "array"}}
        {{- if empty $schema.Value.Items.Ref -}}
            {{- if not (empty ($.SchemaProperties $schema.Value.Items false ))}}
                {{- template "typeDeclaration" ($.WithParams "key" (pascal (print $typeName " Item" )) "schema" $schema.Value.Items "label" (print  $typeName " inline item " $key))}}
            {{- end }}
        {{- end }}
    {{- end }}

{{- /*    Regex Validation Patterns */ -}}
    {{- range $key, $schema := $.SchemaProperties $schema false}}
        {{- if notEmpty $schema.Value.Pattern }}
var {{ camel $typeName }}{{ pascal $key }}Pattern = regexp.MustCompile(` + "`" + `{{ $schema.Value.Pattern }}` + "`" + `)
        {{- end}}
    {{- end }}

{{- /*    Enums */}}
    {{- range $key, $schema := $.SchemaEnums $schema }}
        {{- template "enum" ($.WithParams "name" (print $typeName " " $key) "schema" $schema "description" (print $label " : " $key ))}}
    {{- end -}}

{{- $hasValidation := $.HasValidation $schema -}}
{{- if or $hasValidation  $schema.Value.Required }}

func (p *{{ pascal $key }}) UnmarshalJSON(b []byte) error {
    {{- if $schema.Value.Required }}
    var requiredCheck map[string]interface{}

    if err := json.Unmarshal(b, &requiredCheck); err != nil {
        return validation.Error{err.Error(), fmt.Errorf("{{ pascal $key }}.UnmarshalJSON Required: ` + "`" + `%v` + "`" + `: %w", string(b), err)}
    }

    var validationErrors validation.Errors
    {{ range $field := $schema.Value.Required }}
    if _, ok := requiredCheck["{{ $field }}"]; !ok {
        validationErrors.Add("{{ $field }}", "missing required field")
    }
    {{ end }}

    if validationErrors != nil {
        return validationErrors.GetErr()
    }
    {{ end }}
    type  {{ pascal $key }}JSON {{ pascal $key }}
    var parseObject {{ pascal $key }}JSON

    if err := json.Unmarshal(b, &parseObject); err != nil {
        return validation.Error{err.Error(), fmt.Errorf("{{ pascal $key }}.UnmarshalJSON: ` + "`" + `%v` + "`" + `: %w", string(b), err)}
    }

    v := {{ pascal $key }}(parseObject)

{{ if $hasValidation}}
    if err := v.Validate(); err != nil {
        return err
    }
{{ end }}

    p = &v

    return nil
}

    {{ if $hasValidation}}
func (p {{ pascal $key }}) MarshalJSON() ([]byte, error) {
    if err := p.Validate(); err != nil {
        return nil, err
    }

    b, err := json.Marshal(p)
    if err != nil {
        return nil, fmt.Errorf("{{ pascal $key }}.Marshal: ` + "`" + `%+v` + "`" + `: %w", p, err)
    }

    return b, nil
}
    {{ end }}
{{end}}

    {{- if $.HasValidation $schema }}
func (p {{ pascal $key }}) Validate() error {
    var err validation.Errors
        {{- range $key, $schema := $.SchemaProperties $schema true }}
            {{- if in $schema.Value.Type "number" "integer" }}
                {{- $fieldType := $.GetType $.PackageName $key $schema }}
                {{- if isNotNil $schema.Value.Min }}

    if p.{{ pascal $key }} <{{ if $schema.Value.ExclusiveMin }}={{end}} {{ $schema.Value.Min }} {
        _ = err.Add("{{$key}}", "must be >{{ if not $schema.Value.ExclusiveMin }}={{end}} {{ $schema.Value.Min }}")
    }
                {{- end }}
                {{- if isNotNil $schema.Value.Max }}

    if p.{{ pascal $key }} >{{ if $schema.Value.ExclusiveMax }}={{end}} {{ $schema.Value.Max }} {
        _ = err.Add("{{$key}}", "must be <{{ if not $schema.Value.ExclusiveMax }}={{end}} {{ $schema.Value.Max }}")
    }
                {{- end }}
                {{- if isNotNil $schema.Value.MultipleOf }}
                    {{- if eq $schema.Value.Type "integer" }}

    if p.{{ pascal $key }} % {{ $schema.Value.MultipleOf }} != 0 {
        _ = err.Add("{{$key}}", "must be multiple of {{ $schema.Value.MultipleOf }}")
    }
                    {{- else }}
    if math.Mod({{ if not (eq $fieldType "float64") }}float64({{ end }}p.{{ pascal $key }}{{ if not (eq $fieldType "float64") }}){{end}}, {{ $schema.Value.MultipleOf }}) != 0 {
        _ = err.Add("{{$key}}", "must be multiple of {{ $schema.Value.MultipleOf }}")
    }
                    {{- end }}
                {{- end }}
            {{- else if eq $schema.Value.Type "string" }}
                {{- $fieldType := $.GetType $.PackageName $key $schema }}
                {{- if gt $schema.Value.MinLength 0 }}

    if len(p.{{ pascal $key }}) < {{ $schema.Value.MinLength }} {
        _ = err.Add("{{$key}}", "length must be >= {{ $schema.Value.MinLength }}")
    }
                {{- end }}
                {{- if isNotNil $schema.Value.MaxLength }}

    if len(p.{{ pascal $key }}) > {{ $schema.Value.MaxLength }} {
        _ = err.Add("{{$key}}", "length must be <= {{ $schema.Value.MaxLength }}")
    }
                {{- end }}
                {{- if notEmpty $schema.Value.Pattern }}

    if !{{ camel $typeName }}{{ pascal $key }}Pattern.MatchString( p.{{ pascal $key }})  {
        _ = err.Add("{{$key}}", ` + "`" + `must match "{{ $schema.Value.Pattern }}"` + "`" + `)
    }
                {{- end }}
            {{- else if eq $schema.Value.Type "array" }}
                {{- if gt $schema.Value.MinItems 0 }}

    if len(p.{{ pascal $key }}) < {{ $schema.Value.MinItems }} {
        _ = err.Add("{{$key}}", "length must be >= {{ $schema.Value.MinItems }}")
    }
                {{- end }}
                {{- if isNotNil $schema.Value.MaxItems }}

    if len(p.{{ pascal $key }}) > {{ $schema.Value.MaxItems }} {
        _ = err.Add("{{$key}}", "length must be <= {{ $schema.Value.MaxItems }}")
    }
                {{- end }}
            {{- else if notEmpty $schema.Ref }}
                {{- if $.HasValidation $schema }}

    if subErr := p.{{ pascal $key }}.Validate(); subErr != nil {
        _ = err.Add("{{ $key }}", subErr)
    }
                {{- end -}}
            {{- end }}
        {{- end }}

    return err.GetErr()
}
    {{- end -}}
{{- end -}}
{{- end -}}

// Code generated by foji {{ version }}, template: {{ templateFile }}; DO NOT EDIT.

package {{ .PackageName }}

import (
    "regexp"

{{- .CheckAllTypes .PackageName -}}
{{ range .GoImports }}
    "{{ . }}"
{{- end }}

    "github.com/bir/iken/validation"
)

// Component Schemas

{{ range $key, $schema := .ComponentSchemas }}
    {{- template "typeDeclaration" ($.WithParams "key" $key "schema" $schema "label" "Component Schema")}}
{{- end }}

// Component Parameters

{{ range $key, $param := .ComponentParameters }}
        {{- template "paramDeclaration" ($.WithParams "param" $param "name" "" "label" "Component Parameter: ")}}
{{- end }}

{{- define "paramDeclaration"}}
    {{- $param := .RuntimeParams.param }}
    {{- $name := .RuntimeParams.name }}
    {{- $label := .RuntimeParams.label }}
    {{- if empty $param.Ref -}}
        {{- template "enum" ($.WithParams "name" (print $name " " $param.Value.Name) "schema" $param.Value.Schema "description" (print $param.Value.Description "\n" $label $param.Value.Name ))}}
        {{- if eq $param.Value.Schema.Value.Type "array"}}
            {{- template "enum" ($.WithParams "name" (print $name " " $param.Value.Name) "schema" $param.Value.Schema.Value.Items "description" (print $label $param.Value.Name " Item"))}}
        {{- end }}
    {{- end -}}
{{- end }}

// Path Operations

{{/* Inline Request/Reponse Types */ -}}
{{ range $name, $path := .API.Paths }}
    {{- range $verb, $op := $path.Operations }}
        {{- /* Inline Request */ -}}
        {{- $bodySchema := $.GetRequestBodyLocal $op}}
        {{- if $.SchemaIsComplex $bodySchema -}}
            {{- template "typeDeclaration" ($.WithParams "key" (print $op.OperationID "Request") "schema" $bodySchema "label" (print $op.OperationID " Body") )}}
        {{- end }}

        {{- /* Inline Response */ -}}
        {{- $opResponse := $.GetOpHappyResponse $.PackageName $op }}
        {{- if isNotNil $opResponse.MediaType }}
            {{- if  $.SchemaIsComplex $opResponse.MediaType.Schema -}}
                {{- template "typeDeclaration" ($.WithParams "key" (print $op.OperationID " Response") "schema" $opResponse.MediaType.Schema "label" (print $op.OperationID " Response") )}}
            {{- end }}
        {{- end }}

        {{- /* Inline Params */ -}}
        {{- range $param := $.OpParams $path $op }}
            {{- template "paramDeclaration" ($.WithParams "param" $param "name" $op.OperationID "label" (print "Op: " $op.OperationID " Param: "))}}
        {{- end }}
    {{- end }}
{{- end }}
`
View Source
const FojiSlashOpenapiSlashServiceDotGoDotTpl = `` /* 2048-byte string literal not displayed */
View Source
const FojiSlashOpenapiSlashStubDotYamlDotTpl = `` /* 4893-byte string literal not displayed */
View Source
const FojiSlashPgxSlashDbDotGoDotTpl = `` /* 668-byte string literal not displayed */
View Source
const FojiSlashPgxSlashModelDotGoDotTpl = `// Code generated by foji {{ version }}, template: {{ templateFile }}; DO NOT EDIT.
{{- $table := .Table.Name}}
{{- $goName := case .Table.Name -}}
{{- $colNames := .Table.Columns.ByOrdinal.Names }}
{{- $pkNames := cases .Table.PrimaryKeys.ByOrdinal.Names }}

package {{ $.PackageName }}

import (
	"fmt"

{{- range .Imports }}
	"{{ . }}"
{{- end }}
)

// {{$goName}} represents a record from '{{.Schema.Name}}.{{$table}}'.
type {{$goName}} struct {
{{- range .Table.Columns.ByOrdinal }}
	{{ case .Name }} {{ $.GetType . $.PackageName }}  ` + "`" + `json:"{{ .Name }},omitempty"` + "`" + `
{{- end }}
}

func (r {{$goName}}) String() string {
	return fmt.Sprintf( "{{$goName}}{
		{{- csv ($pkNames.Sprintf "%s:%%v" ) }}}",
		{{- csv ($pkNames.Sprintf "r.%s" ) }})
}

// Field values for every column in {{.Table.Name}}.  These are used for custom where clause queries
var (
{{- range .Table.Columns.ByOrdinal }}
	{{$goName}}{{case .Name}} {{ title (replaceEach ( $.GetType . $.PackageName) "" "." "*" "{" "}" ) }}Field = "{{ .Name }}"
{{- end}}
)

`
View Source
const FojiSlashPgxSlashTableDotGoDotTpl = `// Code generated by foji {{ version }}, template: {{ templateFile }}; DO NOT EDIT.
{{- $pkgName := "pg" }}
{{- $table := .Table.Name}}
{{- $schema := .Table.Schema.Name}}
{{- $goName := case $table }}
{{- $hasSoftDeletes := .Table.Columns.Names.Contains "deleted_at"}}
{{- $mutableCols := (.Table.Columns.Filter .Table.PrimaryKeys.Paths).ByOrdinal.Names }}
{{- $mutableFields := (cases $mutableCols).Sprintf "row.%s"}}
{{- $scanFields := (cases .Table.Columns.ByOrdinal.Names).Sprintf "&row.%s"}}
{{- $selectFields := csv .Table.Columns.ByOrdinal.Names}}
{{- $PKs := cases .Table.PrimaryKeys.ByOrdinal.Names }}
{{- $PKFields := csv ($PKs.Sprintf "row.%s")}}
{{- $PKScanFields := csv ($PKs.Sprintf "&row.%s")}}

package {{ $pkgName }}

import (
	"context"
	"fmt"

	"github.com/jackc/pgx/v5"

	"{{.Params.Package}}"
{{- range .Imports }}
	"{{ . }}"
{{- end }}
)

const querySelect{{$goName}} = ` + "`" + `SELECT
	{{ $selectFields }}
FROM {{$schema}}.{{$table}} ` + "`" + `

func scan{{$goName}}(rr pgx.Rows) ([]*{{$.PackageName}}.{{$goName}}, error) {
	var result []*{{$.PackageName}}.{{$goName}}
	for rr.Next() {
		row := {{$.PackageName}}.{{$goName}}{}
		err := rr.Scan({{ csv $scanFields }})
		if err != nil {
			return nil, fmt.Errorf("scan{{$goName}}:%w", err)
		}
		result = append(result, &row)
	}
	return result, nil
}

func scanOne{{$goName}}(rr pgx.Row) (*{{$.PackageName}}.{{$goName}}, error) {
	row := {{$.PackageName}}.{{$goName}}{}
	err := rr.Scan({{ csv $scanFields }})
	if err != nil {
		return nil, fmt.Errorf("{{$goName}}:%w", err)
	}
	return &row, nil
}

// All retrieves all rows from '{{$table}}' as a slice of {{$goName}}.
func (r Repo) All{{$goName}}(ctx context.Context) ([]*{{$.PackageName}}.{{$goName}}, error) {
	query :=  querySelect{{$goName }}
{{- if $hasSoftDeletes -}}
	+ ` + "`" + `WHERE deleted_at is NULL ` + "`" + `
{{- end}}
	q, err := r.db.Query(ctx,query)
	if err != nil {
		return nil, fmt.Errorf("{{$goName}}:%w", err)
	}
	return scan{{$goName}}(q)
}

// Count gets size of '{{$table}}'.
func (r Repo) Count{{$goName}}(ctx context.Context, where {{$.PackageName}}.WhereClause) (int, error) {
	idx := 1
	query := ` + "`" + `SELECT
		count(*) as count
		FROM {{$schema}}.{{$table}}
		WHERE ` + "`" + ` + where.String(&idx)
		
	count := 0
	return count, r.db.QueryRow(ctx, query, where.Values()...).Scan(&count)
}

// Select retrieves rows from '{{$table}}' as a slice of {{$goName}}.
func (r Repo) Select{{$goName}}(ctx context.Context, where {{$.PackageName}}.WhereClause) ([]*{{$.PackageName}}.{{$goName}}, error) {
	idx := 1
	query := querySelect{{$goName}} + " WHERE " + where.String(&idx)
{{- if $hasSoftDeletes -}}
	+ ` + "`" + ` AND deleted_at is NULL ` + "`" + `
{{- end}}

	q, err := r.db.Query(ctx, query, where.Values()...)
	if err != nil {
		return nil, fmt.Errorf("{{$goName}}:%w", err)
	}
	return scan{{$goName}}(q)
}

// SelectOrder retrieves rows from '{{$table}}' as a slice of {{$goName}} in a particular order.
func (r Repo) SelectOrder{{$goName}}(ctx context.Context, where {{$.PackageName}}.WhereClause, orderBy {{$.PackageName}}.OrderByClause) ([]*{{$.PackageName}}.{{$goName}}, error) {
	idx := 1
	query := querySelect{{$goName}} + " WHERE " + where.String(&idx)
{{- if $hasSoftDeletes -}}
	+ ` + "`" + ` AND deleted_at is NULL ` + "`" + `
{{- end}} + " " + orderBy.String()

	q, err := r.db.Query(ctx, query, where.Values()...)
	if err != nil {
		return nil, fmt.Errorf("{{$goName}}:%w", err)
	}
	return scan{{$goName}}(q)
}

// First retrieve one row from '{{$table}}' when sorted by orderBy.
func (r Repo) First{{$goName}}(ctx context.Context, where {{$.PackageName}}.WhereClause, orderBy {{$.PackageName}}.OrderByClause) (*{{$.PackageName}}.{{$goName}}, error) {
	idx := 1
	query := querySelect{{$goName}} + " WHERE " + where.String(&idx)
{{- if $hasSoftDeletes -}}
	+ ` + "`" + ` AND deleted_at is NULL ` + "`" + `
{{- end}} + " " + orderBy.String() + " LIMIT 1"

	q := r.db.QueryRow(ctx, query, where.Values()...)
	return scanOne{{$goName}}(q)
}

{{- /* Takes the number of values to produce and produces a list of postgres
placeholders of the form $1, $2, etc */}}
{{- define "values" -}}
	{{$nums := numbers 1 . -}}
	{{$indices := $nums.Sprintf "$%s" -}}
	{{csv $indices -}}
{{end}}

// Insert inserts the row into the database.
func (r Repo) Insert{{$goName}}(ctx context.Context, row *{{$.PackageName}}.{{$goName}}) error {
const query = ` + "`" + `INSERT INTO {{$schema}}.{{$table}}
{{- if gt (len $mutableCols) 0}}
	({{ csv $mutableCols }})
	VALUES
	({{template "values" (len $mutableCols) }})
{{- else}}
	DEFAULT VALUES
{{- end}}
	RETURNING
		{{csv .Table.PrimaryKeys.Names.Sort }}` + "`" + `
	q := r.db.QueryRow(ctx, query,{{- csv $mutableFields }})
	return q.Scan({{$PKScanFields}})
}
{{if gt (len $mutableCols) 0}}
// Update the Row in the database.
func (r Repo) Update{{$goName}}(ctx context.Context, row *{{$.PackageName}}.{{$goName}}) error {
	query := ` + "`" + `UPDATE {{$schema}}.{{$table}}
	SET
		({{csv $mutableCols }}) =
		({{ template "values" (len $mutableCols) }})
	WHERE
	{{$last := sum (len .Table.PrimaryKeys) (len $mutableCols)}}
	{{- $first := inc (len $mutableCols)}}
	{{- range $x, $name := .Table.PrimaryKeys.Names.Sort -}}
		{{$name}} = ${{sum $first $x}}{{if lt (sum $x $first) $last}} AND {{end}}
	{{- end}}` + "`" + `

	_, err := r.db.Exec(ctx, query, {{csv $mutableFields }}, {{$PKFields}})
	return fmt.Errorf("{{$goName}}:%w", err)
	}
{{end}}
// Set sets a single column on an existing row in the database.
func (r Repo) Set{{$goName}}(ctx context.Context, set {{$.PackageName}}.Where, where {{$.PackageName}}.WhereClause) (int64, error) {
	idx := 2
	query := ` + "`" + `UPDATE {{$schema}}.{{$table}} SET ` + "`" + ` +
		set.Field + " = $1 " +
		` + "`" + `WHERE ` + "`" + ` +
		where.String(&idx)

	res, err := r.db.Exec(ctx, query, append([]interface{}{ set.Value }, where.Values()...)...)
	if err != nil {
		return 0, fmt.Errorf("{{$goName}}:%w", err)
	}
	return res.RowsAffected(), nil
}
{{- if .Table.HasPrimaryKey }}
{{- if $hasSoftDeletes}}
// Delete{{$goName}} soft deletes the row from the database. Returns the number of items soft deleted.
{{else}}
// Delete{{$goName}} deletes the Row from the database. Returns the number of items deleted.
{{end}}
func (r Repo) Delete{{$goName}}( ctx context.Context, {{ $.Parameterize .Table.PrimaryKeys "%s %s" $pkgName }}) (int64, error) {
	{{- if $hasSoftDeletes}}
	const query = ` + "`" + `UPDATE {{$schema}}.{{$table}}
		SET deleted_at = now()
		WHERE
		{{ range $x, $name := .Table.PrimaryKeys.Names.Sort -}}
			{{$name}} = ${{inc $x}}{{if lt $x (sum (len $.Table.PrimaryKeys) -1)}} AND {{end}}
		{{- end}} AND deleted_at is NULL
		` + "`" + `
	{{- else }}
	const query = ` + "`" + `DELETE FROM {{$schema}}.{{$table}} WHERE
		{{ range $x, $name := .Table.PrimaryKeys.Names.Sort -}}
			{{$name}} = ${{inc $x}}{{if lt $x (sum (len $.Table.PrimaryKeys) -1)}} AND {{end}}
		{{- end}}` + "`" + `{{- end}}
	res, err := r.db.Exec(ctx, query,
	{{- csv .Table.PrimaryKeys.Names.Sort.Camel  -}}
	)
	if err != nil {
		return 0, fmt.Errorf("{{$goName}}:%w", err)
	}
	return res.RowsAffected(), nil
}
{{- if $hasSoftDeletes}}
// DeletePermanent{{$goName}} deletes the Row from the database. This bypasses the soft delete mechanism.
// Returns the number of items deleted.
func (r Repo) DeletePermanent{{$goName}}( ctx context.Context, {{ $.Parameterize .Table.PrimaryKeys "%s %s" $pkgName }}) (int64, error) {
	const query = ` + "`" + `DELETE FROM {{$schema}}.{{$table}} WHERE
		{{ range $x, $name := .Table.PrimaryKeys.Names.Sort -}}
			{{$name}} = ${{inc $x}}{{if lt $x (sum (len $.Table.PrimaryKeys) -1)}} AND {{end}}
		{{- end}}` + "`" + `
	res, err := r.db.Exec(ctx, query,
	{{- csv .Table.PrimaryKeys.Names.Sort.Camel  -}}
	)
	if err != nil {
		return 0, fmt.Errorf("{{$goName}}:%w", err)
	}
	return res.RowsAffected(), nil
}
{{end}}
{{end}}
// DeleteWhere{{$goName}} deletes Rows from the database and returns the number of rows deleted.
func (r Repo) DeleteWhere{{$goName}}(ctx context.Context, where {{$.PackageName}}.WhereClause) (int64, error) {
	idx := 1
{{ if $hasSoftDeletes}}
	query := ` + "`" + `UPDATE {{$schema}}.{{$table}}
		SET deleted_at = now()
		WHERE ` + "`" + ` + where.String(&idx) + ` + "`" + ` AND deleted_at is NULL` + "`" + `
{{ else }}
	query := ` + "`" + `DELETE FROM {{$schema}}.{{$table}}
		WHERE ` + "`" + ` + where.String(&idx)
{{ end }}
	res, err := r.db.Exec(ctx, query, where.Values()...)
	if err != nil {
		return 0, fmt.Errorf("{{$goName}}:%w", err)
	}
	return res.RowsAffected(), nil
}
{{ if $hasSoftDeletes}}
// UndeleteWhere{{$goName}} undeletes the Row from the database.
func (r Repo) Undelete{{$goName}}(ctx context.Context, {{ $.Parameterize .Table.PrimaryKeys "%s %s" $pkgName }}) (int64, error) {
	query := ` + "`" + `UPDATE {{$schema}}.{{$table}}
	SET deleted_at = NULL
	WHERE
{{- range $x, $name := .Table.PrimaryKeys.Names.Sort }}
	{{$name}} = ${{inc $x}}{{if lt $x (sum (len $.Table.PrimaryKeys) -1)}} AND {{end}}
{{- end}} AND deleted_at is not NULL` + "`" + `

	res, err := r.db.Exec(ctx, query, {{ csv .Table.PrimaryKeys.Names.Sort.Camel  -}})
	if err != nil {
		return 0, fmt.Errorf("{{$goName}}:%w", err)
	}
	return res.RowsAffected(), nil
}

// DeleteWherePermanent{{$goName}} deletes the Row from the database. This bypasses the soft delete mechanism.
// Returns the number of items deleted.
func (r Repo) DeleteWherePermanent{{$goName}}(ctx context.Context, where {{$.PackageName}}.WhereClause) (int64, error) {
	idx := 1
	query := ` + "`" + `DELETE FROM {{$schema}}.{{$table}}
		WHERE ` + "`" + ` + where.String(&idx)

	res, err := r.db.Exec(ctx, query,  where.Values()...)
	if err != nil {
		return 0, fmt.Errorf("{{$goName}}:%w", err)
	}
	return res.RowsAffected(), nil
}

// UndeleteWhere{{$goName}} undeletes the Row from the database.
func (r Repo) UndeleteWhere{{$goName}}(ctx context.Context, where {{$.PackageName}}.WhereClause) (int64, error) {
	idx := 1
	query := ` + "`" + `UPDATE {{$schema}}.{{$table}}
		SET deleted_at = null
		WHERE ` + "`" + ` + where.String(&idx) + ` + "`" + ` AND deleted_at is NOT NULL` + "`" + `

	res, err := r.db.Exec(ctx, query, where.Values()...)
	if err != nil {
		return 0, fmt.Errorf("{{$goName}}:%w", err)
	}
	return res.RowsAffected(), nil
}

{{ end -}}

{{ range .Table.Indexes -}}
	{{- $FuncName := print $goName "By" ((cases .Columns.Names).Join "") -}}
	{{- if $.Table.PrimaryKeys.Names.ContainsAll .Columns.Names -}}
		{{- $FuncName = print "Get" $goName -}}
	{{- end -}}
// {{$FuncName}} retrieves a row from '{{$.Table.Schema.Name}}.{{$.Table.Name}}'.
//
// Generated from index '{{.Name}}'.
func (r Repo) {{ $FuncName }}(ctx context.Context, {{ $.Parameterize .Columns "%s %s" $pkgName }}) ({{ if not .IsUnique }}[]{{ end }}*{{$.PackageName}}.{{$goName}}, error) {
	query := querySelect{{$goName}} + ` + "`" + ` WHERE {{csv .Columns.Names.Sort }} = {{template "values" (len .Columns)}}
{{- if $hasSoftDeletes }} AND deleted_at is NULL{{ end}}` + "`" + `

{{- if .IsUnique }}
	q := r.db.QueryRow(ctx, query, {{ csv (.Columns.Names.Sort.Camel) }})
{{- else }}
	q, err := r.db.Query(ctx, query, {{ csv (.Columns.Names.Sort.Camel) }})
	if err != nil {
		return nil, fmt.Errorf("{{$goName}}.{{ $FuncName }}:%w", err)
	}
{{- end }}

{{- if .IsUnique }}
	return scanOne{{$goName}}(q)
{{- else }}
	return scan{{$goName}}(q)
{{- end }}
}

{{ end }}`
View Source
const FojiSlashSqlRepoDotGoDotTpl = `// Code generated by foji {{ version }}, template: {{ templateFile }}; DO NOT EDIT.

package pg

import (
	"context"
	"fmt"

{{- range .Imports }}
	"{{ . }}"
{{- end }}
)

{{- range .Queries }}
{{ $resultType := $.GetType .Result.TypeParam $.PackageName }}

{{- if .Result.GenerateType }}
// {{.Result.Type}} represents a result from '{{.Name}}'.
type {{.Result.Type}} struct {
{{- range .Result.Params.ByOrdinal }}
	{{ pascal .Name }} {{ $.GetType . $.PackageName }}  ` + "`" + `json:"{{ .Name }},omitempty"` + "`" + ` // postgres type: {{ .Type }} {{- if .Nullable }} NULLABLE {{ end }}
{{- end }}
}
{{- end }}

// {{.Name}} returns {{ $resultType }}
{{- if notEmpty .Comment }}
// {{.Comment}}
{{- end }}
func (r Repo) {{ .Name }}(ctx context.Context{{if gt (len .Params) 0}}, {{end}}{{ $.Parameterize .Params.ByOrdinal "%s %s" $.PackageName }}) ({{ if .IsType "query" }}[]{{ end }}*{{$resultType}}, error) {
	const query = ` + "`" + `{{ backQuote .SQL }}` + "`" + `

{{- if .IsType "query" }}
	q, err := r.db.Query(ctx, query{{if gt (len .Params) 0}}, {{ csv (.Params.ByQuery.Names.Camel)}}{{end}})
	if err != nil {
		return nil, fmt.Errorf("{{.Name}}.Query:%w", err)
	}

	var out []*{{ $resultType }}

	for q.Next() {
		row := {{ $resultType }}{}
		err := q.Scan({{ csv (.Result.Params.ByQuery.Names.Pascal.Sprintf "&row.%s")}})
		if err != nil {
			return nil, fmt.Errorf("{{.Name}}.Scan:%w", err)
		}

		out = append(out, &row)
	}

	return out, nil
{{- else }}
	q := r.db.QueryRow(ctx, query{{if gt (len .Params) 0}},{{end}} {{ csv (.Params.ByQuery.Names.Camel) }})
	{{/*        return scanOne{{$goName}}(q)*/}}
{{- end }}
}
{{- end }}
`
View Source
const InitDotYaml = `` /* 269-byte string literal not displayed */

Variables

View Source
var FojiDotYamlBytes = []byte(FojiDotYaml)

foji.yaml

View Source
var FojiSlashDbListDotConsoleDotTplBytes = []byte(FojiSlashDbListDotConsoleDotTpl)

foji/dbList.console.tpl

View Source
var FojiSlashEmbedDotGoDotTplBytes = []byte(FojiSlashEmbedDotGoDotTpl)

foji/embed.go.tpl

View Source
var FojiSlashEnumDotGoDotTplBytes = []byte(FojiSlashEnumDotGoDotTpl)

foji/enum.go.tpl

View Source
var FojiSlashFieldsDotGoDotTplBytes = []byte(FojiSlashFieldsDotGoDotTpl)

foji/fields.go.tpl

View Source
var FojiSlashOpenapiSlashAuthDotGoDotTplBytes = []byte(FojiSlashOpenapiSlashAuthDotGoDotTpl)

foji/openapi/auth.go.tpl

View Source
var FojiSlashOpenapiSlashDocsDotGoDotTplBytes = []byte(FojiSlashOpenapiSlashDocsDotGoDotTpl)

foji/openapi/docs.go.tpl

View Source
var FojiSlashOpenapiSlashHandlerDotGoDotTplBytes = []byte(FojiSlashOpenapiSlashHandlerDotGoDotTpl)

foji/openapi/handler.go.tpl

View Source
var FojiSlashOpenapiSlashMainDotGoDotTplBytes = []byte(FojiSlashOpenapiSlashMainDotGoDotTpl)

foji/openapi/main.go.tpl

View Source
var FojiSlashOpenapiSlashModelDotGoDotTplBytes = []byte(FojiSlashOpenapiSlashModelDotGoDotTpl)

foji/openapi/model.go.tpl

View Source
var FojiSlashOpenapiSlashServiceDotGoDotTplBytes = []byte(FojiSlashOpenapiSlashServiceDotGoDotTpl)

foji/openapi/service.go.tpl

View Source
var FojiSlashOpenapiSlashStubDotYamlDotTplBytes = []byte(FojiSlashOpenapiSlashStubDotYamlDotTpl)

foji/openapi/stub.yaml.tpl

View Source
var FojiSlashPgxSlashDbDotGoDotTplBytes = []byte(FojiSlashPgxSlashDbDotGoDotTpl)

foji/pgx/db.go.tpl

View Source
var FojiSlashPgxSlashModelDotGoDotTplBytes = []byte(FojiSlashPgxSlashModelDotGoDotTpl)

foji/pgx/model.go.tpl

View Source
var FojiSlashPgxSlashTableDotGoDotTplBytes = []byte(FojiSlashPgxSlashTableDotGoDotTpl)

foji/pgx/table.go.tpl

View Source
var FojiSlashSqlRepoDotGoDotTplBytes = []byte(FojiSlashSqlRepoDotGoDotTpl)

foji/sqlRepo.go.tpl

View Source
var InitDotYamlBytes = []byte(InitDotYaml)

init.yaml

Functions

func Get

func Get(filename string) ([]byte, error)

func GetString

func GetString(filename string) (string, error)

func List

func List() []string

Types

This section is empty.

Jump to

Keyboard shortcuts

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