diff --git a/Makefile b/Makefile index 82994e4..f5f103e 100644 --- a/Makefile +++ b/Makefile @@ -11,9 +11,9 @@ test: go test ./... test_generate: - go run main.go weld openAPI -c tests/csvresponse/foji.yaml - go run main.go weld openAPI -c tests/example/foji.yaml - go run main.go weld openAPI -c tests/auth/foji.yaml + go run main.go weld openAPI openAPIClient -c tests/csvresponse/foji.yaml + go run main.go weld openAPI openAPIClient -c tests/example/foji.yaml + go run main.go weld openAPI openAPIClient -c tests/auth/foji.yaml cd tests; go run tests_main.go test_gen: test_generate fmt @@ -38,4 +38,4 @@ tools: go install golang.org/x/tools/cmd/goimports@latest go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@latest -.PHONY: sqlRepo testSchemaList testStub testDumpConfig lint test test_gen test_generate cover tidy update updateAll install tools \ No newline at end of file +.PHONY: sqlRepo testSchemaList testStub testDumpConfig lint test test_gen test_generate cover tidy update updateAll install tools diff --git a/cfg/config.go b/cfg/config.go index 1a5092e..1a06964 100644 --- a/cfg/config.go +++ b/cfg/config.go @@ -145,6 +145,19 @@ func (pp ParamMap) HasString(name string) (string, bool) { return s, ok } +// GetBool returns a bool param identified by `name`, otherwise false. +// Accepts either a bool or the string "true". +func (pp ParamMap) GetBool(name string) bool { + switch v := pp[name].(type) { + case bool: + return v + case string: + return v == "true" + } + + return false +} + // GetWithDefault returns a string param identified by `name`, otherwise returns the default. func (pp ParamMap) GetWithDefault(name, def string) string { p, ok := pp[name] diff --git a/foji.yaml b/foji.yaml index c49859a..f3ff1f1 100644 --- a/foji.yaml +++ b/foji.yaml @@ -32,3 +32,7 @@ processes: params: Package: github.com/gofoji/foji/test Auth: github.com/gofoji/foji/test.User + openAPIClient: + params: + Package: github.com/gofoji/foji/test + Auth: github.com/gofoji/foji/test.User diff --git a/foji/foji.yaml b/foji/foji.yaml index a6293b4..97fc936 100644 --- a/foji/foji.yaml +++ b/foji/foji.yaml @@ -98,3 +98,11 @@ processes: 'service_gen.go': foji/openapi/service.go.tpl 'handlers_gen.go': foji/openapi/handler.go.tpl '!cmd/serve/main.go': foji/openapi/main.go.tpl + openAPIClient: + format: go + resources: [ api ] + params: + IgnoreGoType: true + OpenAPIFile: + 'models_gen.go': foji/openapi/model.go.tpl + 'client_gen.go': foji/openapi/client.go.tpl diff --git a/foji/openapi/client.go.tpl b/foji/openapi/client.go.tpl new file mode 100644 index 0000000..12b18e0 --- /dev/null +++ b/foji/openapi/client.go.tpl @@ -0,0 +1,442 @@ +{{- define "toStr" -}} + {{- $e := .RuntimeParams.expr -}} + {{- $t := .RuntimeParams.goType -}} + {{- if .RuntimeParams.isEnum -}}{{ $e }}.String() + {{- else if eq $t "string" -}}{{ $e }} + {{- else if eq $t "time.Time" -}}{{ $e }}.Format(time.RFC3339) + {{- else if eq $t "uuid.UUID" -}}{{ $e }}.String() + {{- else if eq $t "bool" -}}strconv.FormatBool({{ $e }}) + {{- else if eq $t "int" -}}strconv.Itoa({{ $e }}) + {{- else if eq $t "int32" -}}strconv.FormatInt(int64({{ $e }}), 10) + {{- else if eq $t "int16" -}}strconv.FormatInt(int64({{ $e }}), 10) + {{- else if eq $t "int64" -}}strconv.FormatInt({{ $e }}, 10) + {{- else if eq $t "float32" -}}strconv.FormatFloat(float64({{ $e }}), 'f', -1, 32) + {{- else if eq $t "float64" -}}strconv.FormatFloat({{ $e }}, 'f', -1, 64) + {{- else -}}fmt.Sprintf("%v", {{ $e }}) + {{- end -}} +{{- end -}} + +{{- define "clientAuth" -}} + {{- $scheme := .RuntimeParams.scheme -}} + {{- $mode := .RuntimeParams.mode -}} + {{- $s := index $.API.Components.SecuritySchemes $scheme -}} + {{- $v := $s.Value -}} + {{- $c := camel $scheme -}} + {{- $kind := "header" -}} + {{- if $.SecurityHasExtension $s "x-raw-client-auth" -}}{{ $kind = "raw" }} + {{- else if eq $v.Type "http" -}} + {{- if eq $v.Scheme "basic" -}}{{ $kind = "basic" }}{{- else -}}{{ $kind = "bearer" }}{{- end -}} + {{- else if or (eq $v.Type "oauth2") (eq $v.Type "openIdConnect") -}}{{ $kind = "wrap" }} + {{- else if eq $v.In "query" -}}{{ $kind = "query" }} + {{- else if eq $v.In "cookie" -}}{{ $kind = "cookie" }} + {{- else -}}{{ $kind = "header" }}{{- end -}} + + {{- $prefix := $.Params.GetWithDefault "TypePrefix" "" -}} + {{- if eq $mode "param" -}} + {{- if eq $kind "raw" -}}{{ $c }}Auth {{ $prefix }}ClientAuthenticator + {{- else if eq $kind "basic" -}}{{ $c }}Auth {{ $prefix }}ClientBasicAuthenticator + {{- else if eq $kind "cookie" -}}{{ $c }}Auth {{ $prefix }}ClientCookieAuthenticator + {{- else if eq $kind "wrap" -}}{{ $c }}Auth {{ $prefix }}ClientWrappingAuthenticator + {{- else -}}{{ $c }}Auth {{ $prefix }}ClientTokenAuthenticator + {{- end -}} + {{- else if eq $mode "construct" }} + {{- if eq $kind "raw" }} + {{ $c }}Auth: {{ $c }}Auth, + {{- else if eq $kind "header" }} + {{ $c }}Auth: httputil.HeaderClientAuth("{{ $v.Name }}", {{ $c }}Auth), + {{- else if eq $kind "query" }} + {{ $c }}Auth: httputil.QueryClientAuth("{{ $v.Name }}", {{ $c }}Auth), + {{- else if eq $kind "bearer" }} + {{ $c }}Auth: httputil.BearerClientAuth("Authorization", {{ $c }}Auth), + {{- else if eq $kind "basic" }} + {{ $c }}Auth: httputil.BasicClientAuth({{ $c }}Auth), + {{- else if eq $kind "cookie" }} + {{ $c }}Auth: httputil.CookieClientAuth({{ $c }}Auth), + {{- else if eq $kind "wrap" }} + {{ $c }}Auth: httputil.WrapClientAuth({{ $c }}Auth), + {{- end -}} + {{- else if eq $mode "apply" }} + httpClient, err = c.{{ $c }}Auth(req, httpClient, user) + if err != nil { + return {{ $.RuntimeParams.errRet }}err + } + {{- end -}} +{{- end -}} + +{{- define "clientMethodSignature"}} + {{- $path := .RuntimeParams.path -}} + {{- $op := .RuntimeParams.op -}} + {{- $package := .RuntimeParams.package -}} + {{- $body := .GetRequestBody $op -}} + {{- if $.OpSecuritySchemes $op }} user *{{ $.CheckPackage $.Params.Auth $package -}},{{ end }} + {{- range $param := $.OpParams $path $op -}} + {{- $name := print $op.OperationID " " $param.Value.Name -}} + {{- if notEmpty $param.Ref }}{{ $name = trimPrefix "#/components/parameters/" $param.Ref }}{{ end -}} + {{ goToken (camel $param.Value.Name) -}} + {{- if $.ParamIsOptionalType $param }} *{{ end }} {{ $.GetType $package $name $param.Value.Schema }}, + {{- end -}} + {{- if isNotNil $body}} + {{- $type := $.GetType $package (print $op.OperationID " Request") $body.Schema }} body {{ $type -}} + {{- end -}} + ) ( + {{- $response := $.GetOpHappyResponseType $package $op}} + {{- if notEmpty $response}}{{ $.CheckPackage $response $package}}, {{ end }}error) +{{- end -}} + +{{- $package := $.PackageName }} +{{- $prefix := $.Params.GetWithDefault "TypePrefix" "" }} + +// Code generated by foji, template: {{ templateFile }}; DO NOT EDIT. + +package {{ $package }} + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "io" + "mime/multipart" + "net/http" + "strconv" + "strings" + + "github.com/bir/iken/httputil" +{{- .CheckAllTypes $package ($.Params.GetWithDefault "Auth" "") -}} +{{- range .GoImports }} + "{{ . }}" +{{- end }} +) + +{{ if .HasAuthentication -}} +{{ .ErrorIf (empty $.Params.Auth) "params.Auth" -}} + +type ( + {{ $prefix }}ClientAuthenticator = httputil.ClientAuthenticateFunc[*{{ $.CheckPackage $.Params.Auth $package }}] + {{ $prefix }}ClientTokenAuthenticator = httputil.ClientTokenAuthenticatorFunc[*{{ $.CheckPackage $.Params.Auth $package }}] + {{ $prefix }}ClientBasicAuthenticator = httputil.ClientBasicAuthenticatorFunc[*{{ $.CheckPackage $.Params.Auth $package }}] + {{ $prefix }}ClientCookieAuthenticator = httputil.ClientCookieAuthenticatorFunc[*{{ $.CheckPackage $.Params.Auth $package }}] + {{ $prefix }}ClientWrappingAuthenticator = httputil.ClientWrappingAuthenticatorFunc[*{{ $.CheckPackage $.Params.Auth $package }}] + +{{- if .HasComplexAuth }} + {{ $prefix }}ClientSecurityGroup = httputil.ClientSecurityGroup[*{{ $.CheckPackage $.Params.Auth $package }}] + {{ $prefix }}ClientSecurityGroups = httputil.ClientSecurityGroups[*{{ $.CheckPackage $.Params.Auth $package }}] +{{- end }} +) + +{{ end -}} + +type {{ $prefix }}Methods interface { +{{- range $name, $path := .API.Paths.Map }} + {{- range $verb, $op := $path.Operations }} + {{ pascal $op.OperationID }}(ctx context.Context, + {{- template "clientMethodSignature" ($.WithParams "op" $op "package" $package "path" $path) }} + {{- end }} +{{- end }} +} + +type {{ $prefix }}Client struct { + baseURL string + httpClient *http.Client +{{- range $security, $value := .API.Components.SecuritySchemes }} + {{ camel $security }}Auth {{ $prefix }}ClientAuthenticator +{{- end }} +{{- range $name, $path := .API.Paths.Map }} + {{- range $verb, $op := $path.Operations }} + {{- if not ($.IsSimpleAuth $op) }} + {{ camel $op.OperationID}}Security {{ $prefix }}ClientSecurityGroups + {{- end}} + {{- end}} +{{- end}} +} + +func New{{ $prefix }}Client(baseURL string, httpClient *http.Client +{{- range $security, $value := .API.Components.SecuritySchemes }}, {{ template "clientAuth" ($.WithParams "scheme" $security "mode" "param") }}{{- end }}) *{{ $prefix }}Client { + c := &{{ $prefix }}Client{ + baseURL: baseURL, + httpClient: httpClient, +{{- range $security, $value := .API.Components.SecuritySchemes }}{{ template "clientAuth" ($.WithParams "scheme" $security "mode" "construct") }}{{- end }} + } +{{- range $name, $path := .API.Paths.Map }} + {{- range $verb, $op := $path.Operations }} + {{- if not ($.IsSimpleAuth $op) }} + + c.{{ camel $op.OperationID}}Security = {{ $prefix }}ClientSecurityGroups{ + {{- range $securityGroup := $.OpSecurity $op }} + {{ $prefix }}ClientSecurityGroup{ + {{- range $security, $scopes := $securityGroup -}} + c.{{ camel $security }}Auth, + {{- end -}} + }, + {{- end }} + } + {{- end}} + {{- end}} +{{- end}} + + return c +} + +{{- range $name, $path := .API.Paths.Map }} + {{- range $verb, $op := $path.Operations }} + {{- $body := $.GetRequestBody $op }} + {{- $opResponse := $.GetOpHappyResponse $package $op }} + {{- $respType := $opResponse.GoType }} + {{- $errRet := "" }} + {{- if notEmpty $respType }}{{ if eq $respType "string" }}{{ $errRet = "\"\", " }}{{ else }}{{ $errRet = "nil, " }}{{ end }}{{ end }} + +{{ goDoc (pascal $op.OperationID) }} +{{- goDoc $op.Summary }} +{{- goDoc $op.Description }} +func (c *{{ $prefix }}Client) {{ pascal $op.OperationID }}(ctx context.Context, + {{- template "clientMethodSignature" ($.WithParams "op" $op "package" $package "path" $path) }} { + u := c.baseURL + "{{ $name }}" + {{- $hasQuery := false }} + {{- range $param := $.OpParams $path $op }}{{ if eq $param.Value.In "query" }}{{ $hasQuery = true }}{{ end }}{{ end }} + {{- if $hasQuery }} + queryParams := url.Values{} + {{- end }} + {{- range $param := $.OpParams $path $op }} + {{- $pName := $param.Value.Name }} + {{- $var := goToken (camel $pName) }} + {{- $tName := print $op.OperationID " " $pName }} + {{- if notEmpty $param.Ref }}{{ $tName = trimPrefix "#/components/parameters/" $param.Ref }}{{ end }} + {{- $goType := $.GetType $package $tName $param.Value.Schema }} + {{- $isArray := $param.Value.Schema.Value.Type.Is "array" }} + {{- $isEnum := $.ParamIsEnum $param }} + {{- if $isArray }} + {{- $elemType := $.StripArray $goType }} + {{- $isArrayEnum := $.ParamIsEnumArray $param }} + {{- if eq $param.Value.In "query" }} + for _, v := range {{ $var }} { + queryParams.Add("{{ $pName }}", {{ template "toStr" ($.WithParams "expr" "v" "goType" $elemType "isEnum" $isArrayEnum) }}) + } + {{- end }} + {{- else if $.ParamIsOptionalType $param }} + {{- $deref := print "(*" $var ")" }} + if {{ $var }} != nil { + {{- if eq $param.Value.In "query" }} + queryParams.Set("{{ $pName }}", {{ template "toStr" ($.WithParams "expr" $deref "goType" $goType "isEnum" $isEnum) }}) + {{- end }} + } + {{- else }} + {{- if eq $param.Value.In "path" }} + u = strings.Replace(u, "{{ printf "{%s}" $pName }}", url.PathEscape({{ template "toStr" ($.WithParams "expr" $var "goType" $goType "isEnum" $isEnum) }}), 1) + {{- else if eq $param.Value.In "query" }} + queryParams.Set("{{ $pName }}", {{ template "toStr" ($.WithParams "expr" $var "goType" $goType "isEnum" $isEnum) }}) + {{- end }} + {{- end }} + {{- end }} + {{- if $hasQuery }} + + if len(queryParams) > 0 { + u += "?" + queryParams.Encode() + } + {{- end }} + + {{- if isNotNil $body }} + {{- if $body.IsJson }} + + buf, err := json.Marshal(body) + if err != nil { + return {{ $errRet }}fmt.Errorf("marshal request body: %w", err) + } + + reqBody := bytes.NewReader(buf) + contentType := "application/json" + {{- else if $body.IsText }} + + reqBody := strings.NewReader(body) + contentType := "text/plain" + {{- else if $body.IsForm }} + + form := url.Values{} + {{- range $field, $schemaProp := $.SchemaProperties $body.Schema }} + {{- $fGoType := $.GetType $package (print $op.OperationID " " $field) $schemaProp }} + {{- $fVar := print "body." (pascal $field) }} + {{- $fIsPtr := and (not ($.IsRequiredProperty $field $body.Schema)) $schemaProp.Value.Nullable }} + {{- if $schemaProp.Value.Type.Is "array" }} + for _, v := range {{ $fVar }} { + form.Add("{{ $field }}", {{ template "toStr" ($.WithParams "expr" "v" "goType" ($.StripArray $fGoType) "isEnum" ($.SchemaIsEnumArray $schemaProp)) }}) + } + {{- else if $fIsPtr }} + if {{ $fVar }} != nil { + form.Set("{{ $field }}", {{ template "toStr" ($.WithParams "expr" (print "(*" $fVar ")") "goType" $fGoType "isEnum" ($.SchemaIsEnum $schemaProp)) }}) + } + {{- else }} + form.Set("{{ $field }}", {{ template "toStr" ($.WithParams "expr" $fVar "goType" $fGoType "isEnum" ($.SchemaIsEnum $schemaProp)) }}) + {{- end }} + {{- end }} + + reqBody := strings.NewReader(form.Encode()) + contentType := "application/x-www-form-urlencoded" + {{- else if $body.IsMultipartForm }} + + var bodyBuf bytes.Buffer + + mw := multipart.NewWriter(&bodyBuf) + {{- range $field, $schemaProp := $.SchemaProperties $body.Schema }} + {{- $fGoType := $.GetType $package (print $op.OperationID " " $field) $schemaProp }} + {{- $fVar := print "body." (pascal $field) }} + {{- $fRequired := $.IsRequiredProperty $field $body.Schema }} + {{- $fIsPtr := and (not $fRequired) $schemaProp.Value.Nullable }} + {{- if eq $fGoType "forms.File" }} + {{ if not $fRequired }}if {{ $fVar }}.File != nil { {{ end -}} + { + part, err := mw.CreateFormFile("{{ $field }}", {{ $fVar }}.Filename) + if err != nil { + return {{ $errRet }}fmt.Errorf("multipart file {{ $field }}: %w", err) + } + + if _, err := io.Copy(part, {{ $fVar }}.File); err != nil { + return {{ $errRet }}fmt.Errorf("multipart file {{ $field }}: %w", err) + } + } + {{- if not $fRequired }} }{{ end }} + {{- else if $schemaProp.Value.Type.Is "array" }} + for _, v := range {{ $fVar }} { + if err := mw.WriteField("{{ $field }}", {{ template "toStr" ($.WithParams "expr" "v" "goType" ($.StripArray $fGoType) "isEnum" ($.SchemaIsEnumArray $schemaProp)) }}); err != nil { + return {{ $errRet }}fmt.Errorf("multipart field {{ $field }}: %w", err) + } + } + {{- else if $fIsPtr }} + if {{ $fVar }} != nil { + if err := mw.WriteField("{{ $field }}", {{ template "toStr" ($.WithParams "expr" (print "(*" $fVar ")") "goType" $fGoType "isEnum" ($.SchemaIsEnum $schemaProp)) }}); err != nil { + return {{ $errRet }}fmt.Errorf("multipart field {{ $field }}: %w", err) + } + } + {{- else }} + if err := mw.WriteField("{{ $field }}", {{ template "toStr" ($.WithParams "expr" $fVar "goType" $fGoType "isEnum" ($.SchemaIsEnum $schemaProp)) }}); err != nil { + return {{ $errRet }}fmt.Errorf("multipart field {{ $field }}: %w", err) + } + {{- end }} + {{- end }} + + if err := mw.Close(); err != nil { + return {{ $errRet }}fmt.Errorf("multipart close: %w", err) + } + + reqBody := &bodyBuf + contentType := mw.FormDataContentType() + {{- end }} + {{- end }} + + req, err := http.NewRequestWithContext(ctx, "{{ $verb }}", u, {{ if isNotNil $body }}reqBody{{ else }}http.NoBody{{ end }}) + if err != nil { + return {{ $errRet }}err + } + {{- if isNotNil $body }} + + req.Header.Set("Content-Type", contentType) + {{- end }} + {{- range $param := $.OpParams $path $op }} + {{- $pName := $param.Value.Name }} + {{- $var := goToken (camel $pName) }} + {{- $tName := print $op.OperationID " " $pName }} + {{- if notEmpty $param.Ref }}{{ $tName = trimPrefix "#/components/parameters/" $param.Ref }}{{ end }} + {{- $goType := $.GetType $package $tName $param.Value.Schema }} + {{- $isEnum := $.ParamIsEnum $param }} + {{- if eq $param.Value.In "header" }} + {{- if $.ParamIsOptionalType $param }} + + if {{ $var }} != nil { + req.Header.Set("{{ $pName }}", {{ template "toStr" ($.WithParams "expr" (print "(*" $var ")") "goType" $goType "isEnum" $isEnum) }}) + } + {{- else }} + + req.Header.Set("{{ $pName }}", {{ template "toStr" ($.WithParams "expr" $var "goType" $goType "isEnum" $isEnum) }}) + {{- end }} + {{- else if eq $param.Value.In "cookie" }} + {{- if $.ParamIsOptionalType $param }} + + if {{ $var }} != nil { + req.AddCookie(&http.Cookie{Name: "{{ $pName }}", Value: {{ template "toStr" ($.WithParams "expr" (print "(*" $var ")") "goType" $goType "isEnum" $isEnum) }}}) + } + {{- else }} + + req.AddCookie(&http.Cookie{Name: "{{ $pName }}", Value: {{ template "toStr" ($.WithParams "expr" $var "goType" $goType "isEnum" $isEnum) }}}) + {{- end }} + {{- end }} + {{- end }} + + httpClient := c.httpClient + {{- if $.IsSimpleAuth $op }} + {{- range $scheme := $.OpSecuritySchemes $op }}{{ template "clientAuth" ($.WithParams "scheme" $scheme "mode" "apply" "errRet" $errRet) }}{{- end }} + {{- else }} + httpClient, err = c.{{ camel $op.OperationID}}Security.Auth(req, httpClient, user) + if err != nil { + return {{ $errRet }}err + } + {{- end }} + + resp, err := httpClient.Do(req) + if err != nil { + return {{ $errRet }}err + } + {{- if ne $respType "io.Reader" }} + defer resp.Body.Close() + {{- end }} + + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + {{- if eq $respType "io.Reader" }} + defer resp.Body.Close() + {{- end }} + errBody, _ := io.ReadAll(resp.Body) + + return {{ $errRet }}httputil.UnexpectedResponseError{Resp: resp, URL: u, Body: errBody} + } + + {{- if eq $respType "" }} + + return nil + {{- else if $opResponse.MimeType.IsJson }} + {{- if hasPrefix "*" $respType }} + + var out {{ trimPrefix "*" $respType }} + if err := httputil.GetJSONBody(resp.Body, &out); err != nil { + return {{ $errRet }}err + } + + return &out, nil + {{- else }} + + var out {{ $respType }} + if err := httputil.GetJSONBody(resp.Body, &out); err != nil { + return {{ $errRet }}err + } + + return out, nil + {{- end }} + {{- else if eq $respType "io.Reader" }} + + return resp.Body, nil + {{- else if eq $respType "[]byte" }} + + out, err := io.ReadAll(resp.Body) + if err != nil { + return {{ $errRet }}fmt.Errorf("read response: %w", err) + } + + return out, nil + {{- else if hasPrefix "*" $respType }} + + out, err := io.ReadAll(resp.Body) + if err != nil { + return {{ $errRet }}fmt.Errorf("read response: %w", err) + } + + v := {{ trimPrefix "*" $respType }}(out) + + return &v, nil + {{- else }} + + out, err := io.ReadAll(resp.Body) + if err != nil { + return {{ $errRet }}fmt.Errorf("read response: %w", err) + } + + return {{ $respType }}(out), nil + {{- end }} +} + {{- end }} +{{- end }} diff --git a/foji/openapi/model.go.tpl b/foji/openapi/model.go.tpl index 96aa48a..8bf14a4 100644 --- a/foji/openapi/model.go.tpl +++ b/foji/openapi/model.go.tpl @@ -193,8 +193,10 @@ func (e *{{ $enumType }}) Scan(src any) error { {{- $key := .RuntimeParams.key }} {{- $label := .RuntimeParams.label }} -{{- if not ($.HasExtension $schema "x-go-type" )}} +{{- if or ($.Params.GetBool "IgnoreGoType") (not ($.HasExtension $schema "x-go-type" ))}} {{- $typeName := $.GetType $.PackageName $key $schema }} +{{- $rawName := pascal $key }} +{{- $declName := $.PrefixType $rawName }} // {{ $typeName}} {{- goDoc $schema.Value.Description }} // @@ -204,14 +206,14 @@ func (e *{{ $enumType }}) Scan(src any) error { {{- $label := .RuntimeParams.label }} {{- template "enum" ($.WithParams "name" $key "schema" $schema "description" (print $label " : " $key ))}} {{- else if and ($schema.Value.Type.Permits "object") (gt (len ($.SchemaProperties $schema)) 0) }} -type {{ pascal $key }} struct { +type {{ $declName }} struct { {{- range $field, $schemaProp := $.SchemaProperties $schema}} {{- $isRequired := $.IsRequiredProperty $field $schema -}} - {{- template "propertyDeclaration" ($.WithParams "key" $field "schema" $schemaProp "typeName" $typeName "isRequired" $isRequired)}} + {{- template "propertyDeclaration" ($.WithParams "key" $field "schema" $schemaProp "typeName" $rawName "isRequired" $isRequired)}} {{- end }} } {{- else }} -type {{ pascal $key }} {{ $.GetType $.PackageName (pascal (print $typeName " Item" )) $schema }} +type {{ $declName }} {{ $.GetType $.PackageName (pascal (print $rawName " Item" )) $schema }} {{- end }} {{- $hasValidation := $.HasValidation $schema -}} @@ -221,14 +223,14 @@ type {{ pascal $key }} {{ $.GetType $.PackageName (pascal (print $typeName " Ite {{- range $key, $schemaProp := $.SchemaProperties $schema }} {{- if not (empty $schemaProp.Value.Properties )}} {{- if empty $schemaProp.Ref -}} - {{- template "typeDeclaration" ($.WithParams "mediaType" "application/json" "key" (pascal (print $typeName " " $key)) "schema" $schemaProp "label" (print $typeName " inline " $key))}} + {{- template "typeDeclaration" ($.WithParams "mediaType" "application/json" "key" (pascal (print $rawName " " $key)) "schema" $schemaProp "label" (print $typeName " inline " $key))}} {{- end -}} {{- else if $schemaProp.Value.Type.Is "array"}} {{- if empty $schemaProp.Value.Items.Ref -}} {{- $isEnumItem := $.IsDefaultEnum $key $schemaProp.Value.Items }} {{- $hasProperties := not (empty ($.SchemaProperties $schemaProp.Value.Items )) }} {{- if or $isEnumItem $hasProperties}} - {{- template "typeDeclaration" ($.WithParams "mediaType" "application/json" "key" (pascal (print $typeName " " $key)) "schema" $schemaProp.Value.Items "label" (print $typeName " inline item " $key))}} + {{- template "typeDeclaration" ($.WithParams "mediaType" "application/json" "key" (pascal (print $rawName " " $key)) "schema" $schemaProp.Value.Items "label" (print $typeName " inline item " $key))}} {{- end }} {{- end }} {{- end }} @@ -239,7 +241,7 @@ type {{ pascal $key }} {{ $.GetType $.PackageName (pascal (print $typeName " Ite {{- $isEnumItem := $.IsDefaultEnum $key $schema.Value.Items }} {{- $hasProperties := not (empty ($.SchemaProperties $schema.Value.Items )) }} {{- if or $isEnumItem $hasProperties}} - {{- template "typeDeclaration" ($.WithParams "mediaType" "application/json" "key" (pascal (print $typeName " Item" )) "schema" $schema.Value.Items "label" (print $typeName " inline item " $key))}} + {{- template "typeDeclaration" ($.WithParams "mediaType" "application/json" "key" (pascal (print $rawName " Item" )) "schema" $schema.Value.Items "label" (print $typeName " inline item " $key))}} {{- end }} {{- end }} {{- end }} @@ -247,35 +249,35 @@ type {{ pascal $key }} {{ $.GetType $.PackageName (pascal (print $typeName " Ite {{- /* Regex Validation Patterns */ -}} {{- range $key, $schemaProp := $.SchemaProperties $schema }} {{- if and (notEmpty $schemaProp.Value.Pattern) (empty $schemaProp.Ref) }} -var {{ camel $typeName }}{{ pascal $key }}Pattern = regexp.MustCompile(`{{ $schemaProp.Value.Pattern }}`) +var {{ camel $declName }}{{ pascal $key }}Pattern = regexp.MustCompile(`{{ $schemaProp.Value.Pattern }}`) {{- end}} {{- end }} {{- if and $hasValidation (notEmpty $schema.Value.Pattern) (empty $schema.Ref) }} -var {{ camel $key }}Pattern = regexp.MustCompile(`{{ $schema.Value.Pattern }}`) +var {{ camel $declName }}Pattern = regexp.MustCompile(`{{ $schema.Value.Pattern }}`) {{ end }} {{- /* Enums */}} {{- range $key, $schemaEnum := $.SchemaEnums $schema }} - {{- template "enum" ($.WithParams "name" (print $typeName " " $key) "schema" $schemaEnum "description" (print $label " : " $key ))}} + {{- template "enum" ($.WithParams "name" (print $rawName " " $key) "schema" $schemaEnum "description" (print $label " : " $key ))}} {{- end -}} {{if eq $mediaType "application/json" }} {{- if or $hasValidation $hasRequired (.SchemaPropertiesHaveDefaults $schema)}} -func (p *{{ pascal $key }}) UnmarshalJSON(b []byte) error { +func (p *{{ $declName }}) UnmarshalJSON(b []byte) error { var err error {{- if or $hasRequired (.SchemaPropertiesHaveDefaults $schema) }} var requiredCheck map[string]any err = json.Unmarshal(b, &requiredCheck) if err != nil { - return validation.Error{err.Error(), fmt.Errorf("{{ pascal $key }}.UnmarshalJSON Required: `%v`: %w", string(b), err)} + return validation.Error{err.Error(), fmt.Errorf("{{ $declName }}.UnmarshalJSON Required: `%v`: %w", string(b), err)} } var validationErrors validation.Errors {{ range $field, $schemaProp := ($.RequiredProperties $schema) }} if _, ok := requiredCheck["{{ $field }}"]; !ok { - validationErrors.Add("{{ $field }}", ErrMissingRequiredField) + validationErrors.Add("{{ $field }}", Err{{ $.Params.GetWithDefault "TypePrefix" "" }}MissingRequiredField) } {{ end }} @@ -284,15 +286,15 @@ func (p *{{ pascal $key }}) UnmarshalJSON(b []byte) error { } {{ end }} - type {{ pascal $key }}JSON {{ pascal $key }} - var parseObject {{ pascal $key }}JSON + type {{ $declName }}JSON {{ $declName }} + var parseObject {{ $declName }}JSON err = json.Unmarshal(b, &parseObject) if err != nil { - return validation.Error{err.Error(), fmt.Errorf("{{ pascal $key }}.UnmarshalJSON: `%v`: %w", string(b), err)} + return validation.Error{err.Error(), fmt.Errorf("{{ $declName }}.UnmarshalJSON: `%v`: %w", string(b), err)} } - v := {{ pascal $key }}(parseObject) + v := {{ $declName }}(parseObject) {{ range $field, $schemaProp := $.SchemaProperties $schema}} {{ $typeName := (print $key " " $field) -}} @@ -338,16 +340,16 @@ func (p *{{ pascal $key }}) UnmarshalJSON(b []byte) error { } {{ if $hasValidation}} -func (p {{ pascal $key }}) MarshalJSON() ([]byte, error) { +func (p {{ $declName }}) MarshalJSON() ([]byte, error) { err := p.Validate() if err != nil { return nil, err } - type unvalidated {{ pascal $key }} // Skips the validation check + type unvalidated {{ $declName }} // Skips the validation check b, err := json.Marshal(unvalidated(p)) if err != nil { - return nil, fmt.Errorf("{{ pascal $key }}.Marshal: `%+v`: %w", p, err) + return nil, fmt.Errorf("{{ $declName }}.Marshal: `%+v`: %w", p, err) } return b, nil @@ -359,11 +361,11 @@ func (p {{ pascal $key }}) MarshalJSON() ([]byte, error) { {{if or (eq $mediaType "multipart/form-data") (eq $mediaType "application/x-www-form-urlencoded")}} -func ParseForm{{ pascal $key }}(r *http.Request) ({{ pascal $key }}, error) { +func ParseForm{{ $declName }}(r *http.Request) ({{ $declName }}, error) { var ( parseErrors validation.Errors err error - v {{ pascal $key }} + v {{ $declName }} ) {{ range $field, $schemaProp := $.SchemaProperties $schema }} @@ -433,13 +435,13 @@ func ParseForm{{ pascal $key }}(r *http.Request) ({{ pascal $key }}, error) { {{ end }} if parseErrors != nil { - return {{ pascal $key }}{}, parseErrors.GetErr() + return {{ $declName }}{}, parseErrors.GetErr() } {{ if $hasValidation}} err = v.Validate() if err != nil { - return {{ pascal $key }}{}, err + return {{ $declName }}{}, err } {{ end }} @@ -451,7 +453,7 @@ func ParseForm{{ pascal $key }}(r *http.Request) ({{ pascal $key }}, error) { {{- if $hasValidation }} {{ $properties := $.SchemaProperties $schema }} {{- if not (empty $properties )}} -func (p {{ pascal $key }}) Validate() error { +func (p {{ $declName }}) Validate() error { var err validation.Errors {{ range $fieldName, $schemaProp := $properties }} {{- if $.HasValidation $schemaProp }} @@ -466,21 +468,21 @@ func (p {{ pascal $key }}) Validate() error { {{- $isRequired := $.IsRequiredProperty $fieldName $schema -}} {{- $isPointer := and (not $isRequired) ($schemaProp.Value.Nullable) }} -func (p {{ pascal $key }}) Validate{{ pascal $fieldName }}(err *validation.Errors) { +func (p {{ $declName }}) Validate{{ pascal $fieldName }}(err *validation.Errors) { {{- if $isPointer }} if p.{{ pascal $fieldName }} == nil { return } {{ end -}} - {{- template "validateField" ($.WithParams "fieldName" $fieldName "schema" $schemaProp "typeName" $key "isPointer" $isPointer ) -}} + {{- template "validateField" ($.WithParams "fieldName" $fieldName "schema" $schemaProp "typeName" $declName "isPointer" $isPointer ) -}} } {{- end }} {{- end }} {{ else -}} -func (p {{ pascal $key }}) Validate() error { +func (p {{ $declName }}) Validate() error { var err validation.Errors - {{- template "validateField" ($.WithParams "fieldName" "" "schema" $schema "typeName" $key "isPointer" false )}} + {{- template "validateField" ($.WithParams "fieldName" "" "schema" $schema "typeName" $declName "isPointer" false )}} return err.GetErr() } @@ -506,7 +508,7 @@ import ( "github.com/bir/iken/validation" ) -var ErrMissingRequiredField = errors.New("missing required field") +var Err{{ $.Params.GetWithDefault "TypePrefix" "" }}MissingRequiredField = errors.New("missing required field") // Component Schemas diff --git a/output/openapi.go b/output/openapi.go index 74be954..171f14c 100644 --- a/output/openapi.go +++ b/output/openapi.go @@ -95,7 +95,19 @@ func (o *OpenAPIFileContext) GetTypeName(pkg string, s *openapi3.SchemaRef) stri return o.CheckPackage(t, pkg) } - return o.CheckPackage(ref, pkg) + return o.CheckPackage(o.PrefixType(ref), pkg) +} + +// PrefixType applies the TypePrefix param (if any) to a type name, which may be package-qualified. +func (o *OpenAPIFileContext) PrefixType(name string) string { + prefix := o.Params.GetWithDefault("TypePrefix", "") + if prefix == "" { + return name + } + + pos := strings.LastIndex(name, ".") + 1 + + return name[:pos] + prefix + name[pos:] } func (o *OpenAPIFileContext) TypeOnly(name string) string { @@ -153,7 +165,7 @@ func (o *OpenAPIFileContext) GetType(currentPackage, name string, s *openapi3.Sc return "" } - if override, ok := s.Value.Extensions["x-go-type"]; ok { + if override, ok := s.Value.Extensions["x-go-type"]; ok && !o.Params.GetBool("IgnoreGoType") { return o.getXGoType(currentPackage, override) } @@ -193,7 +205,7 @@ func (o *OpenAPIFileContext) GetType(currentPackage, name string, s *openapi3.Sc return "any" } - name = o.PackageName() + "." + kace.Pascal(name) + name = o.PrefixType(o.PackageName() + "." + kace.Pascal(name)) return o.CheckPackage(name, currentPackage) } @@ -211,7 +223,7 @@ func (o *OpenAPIFileContext) GetType(currentPackage, name string, s *openapi3.Sc func (o *OpenAPIFileContext) EnumName(name string) string { // TODO: Support override via template - return o.PackageName() + "." + kace.Pascal(name) + return o.PrefixType(o.PackageName() + "." + kace.Pascal(name)) } func (o *OpenAPIFileContext) EnumNew(name string) string { @@ -656,6 +668,52 @@ func (o *OpenAPIFileContext) OpSecurity(op *openapi3.Operation) openapi3.Securit return o.API.Security } +// OpSecuritySchemes returns the distinct security scheme names referenced by the operation +// across all of its security requirement groups, sorted for deterministic output. +func (o *OpenAPIFileContext) OpSecuritySchemes(op *openapi3.Operation) []string { + seen := map[string]bool{} + + for _, group := range o.OpSecurity(op) { + for key := range group { + seen[key] = true + } + } + + out := make([]string, 0, len(seen)) + for k := range seen { + out = append(out, k) + } + + slices.Sort(out) + + return out +} + +// OpSecurityGroups returns the operation's security requirement groups as sorted scheme-name +// slices (AND within a group, OR across groups), with duplicate groups removed so the generated +// validation does not repeat identical conditions. An empty slice element represents an empty +// requirement (anonymous access permitted). +func (o *OpenAPIFileContext) OpSecurityGroups(op *openapi3.Operation) [][]string { + var out [][]string + + seen := map[string]bool{} + + for _, group := range o.OpSecurity(op) { + schemes := mapKeysSorted(group) + + key := strings.Join(schemes, "\x00") + if seen[key] { + continue + } + + seen[key] = true + + out = append(out, schemes) + } + + return out +} + func hasAuthorization(security openapi3.SecurityRequirements) bool { for _, ss := range security { for _, scopes := range ss { diff --git a/tests/auth/foji.yaml b/tests/auth/foji.yaml index 65c9eea..e2c0c7c 100644 --- a/tests/auth/foji.yaml +++ b/tests/auth/foji.yaml @@ -11,3 +11,10 @@ processes: 'tests/auth/http_handler_gen.go': foji/openapi/handler.go.tpl 'tests/auth/model_gen.go': foji/openapi/model.go.tpl 'tests/auth/service_gen.go': foji/openapi/service.go.tpl + openAPIClient: + params: + Package: foji/tests/auth + Auth: tests/example.ExampleAuth + OpenAPIFile: + 'tests/auth/model_gen.go': foji/openapi/model.go.tpl + 'tests/auth/http_client_gen.go': foji/openapi/client.go.tpl diff --git a/tests/auth/http_client_gen.go b/tests/auth/http_client_gen.go new file mode 100644 index 0000000..995358f --- /dev/null +++ b/tests/auth/http_client_gen.go @@ -0,0 +1,447 @@ +// Code generated by foji, template: foji/openapi/client.go.tpl; DO NOT EDIT. + +package auth + +import ( + "context" + "io" + "net/http" + "net/url" + + "github.com/bir/iken/httputil" + "tests/example" +) + +type ( + ClientAuthenticator = httputil.ClientAuthenticateFunc[*example.ExampleAuth] + ClientTokenAuthenticator = httputil.ClientTokenAuthenticatorFunc[*example.ExampleAuth] + ClientBasicAuthenticator = httputil.ClientBasicAuthenticatorFunc[*example.ExampleAuth] + ClientCookieAuthenticator = httputil.ClientCookieAuthenticatorFunc[*example.ExampleAuth] + ClientWrappingAuthenticator = httputil.ClientWrappingAuthenticatorFunc[*example.ExampleAuth] + ClientSecurityGroup = httputil.ClientSecurityGroup[*example.ExampleAuth] + ClientSecurityGroups = httputil.ClientSecurityGroups[*example.ExampleAuth] +) + +type Methods interface { + ListAdminUsers(ctx context.Context, user *example.ExampleAuth) ([]User, error) + QueryDataWithApiKey(ctx context.Context, user *example.ExampleAuth, query *string) error + ListDocuments(ctx context.Context, user *example.ExampleAuth) error + CreateDocument(ctx context.Context, user *example.ExampleAuth) error + Overview(ctx context.Context, user *example.ExampleAuth) error + GetDetailedProfile(ctx context.Context, user *example.ExampleAuth) error + GetProtectedResource(ctx context.Context, user *example.ExampleAuth) error + GetPublicStatus(ctx context.Context) (*GetPublicStatusResponse, error) + GetCurrentUser(ctx context.Context, user *example.ExampleAuth) (*User, error) + GetUserProfile(ctx context.Context, user *example.ExampleAuth) (*User, error) +} + +type Client struct { + baseURL string + httpClient *http.Client + apiKeyCookieAuth ClientAuthenticator + apiKeyHeaderAuth ClientAuthenticator + apiKeyQueryAuth ClientAuthenticator + basicAuthAuth ClientAuthenticator + bearerAuthAuth ClientAuthenticator + oauth2ClientCredentialsExampleAuth ClientAuthenticator + oauth2ExampleAuth ClientAuthenticator + openIdconnectAuth ClientAuthenticator + rawAuth ClientAuthenticator + listAdminUsersSecurity ClientSecurityGroups + queryDataWithApiKeySecurity ClientSecurityGroups + createDocumentSecurity ClientSecurityGroups + getProtectedResourceSecurity ClientSecurityGroups + getCurrentUserSecurity ClientSecurityGroups +} + +func NewClient(baseURL string, httpClient *http.Client, apiKeyCookieAuth ClientCookieAuthenticator, apiKeyHeaderAuth ClientTokenAuthenticator, apiKeyQueryAuth ClientTokenAuthenticator, basicAuthAuth ClientBasicAuthenticator, bearerAuthAuth ClientTokenAuthenticator, oauth2ClientCredentialsExampleAuth ClientWrappingAuthenticator, oauth2ExampleAuth ClientWrappingAuthenticator, openIdconnectAuth ClientWrappingAuthenticator, rawAuth ClientAuthenticator) *Client { + c := &Client{ + baseURL: baseURL, + httpClient: httpClient, + apiKeyCookieAuth: httputil.CookieClientAuth(apiKeyCookieAuth), + apiKeyHeaderAuth: httputil.HeaderClientAuth("X-API-Key", apiKeyHeaderAuth), + apiKeyQueryAuth: httputil.QueryClientAuth("query_key_name", apiKeyQueryAuth), + basicAuthAuth: httputil.BasicClientAuth(basicAuthAuth), + bearerAuthAuth: httputil.BearerClientAuth("Authorization", bearerAuthAuth), + oauth2ClientCredentialsExampleAuth: httputil.WrapClientAuth(oauth2ClientCredentialsExampleAuth), + oauth2ExampleAuth: httputil.WrapClientAuth(oauth2ExampleAuth), + openIdconnectAuth: httputil.WrapClientAuth(openIdconnectAuth), + rawAuth: rawAuth, + } + + c.listAdminUsersSecurity = ClientSecurityGroups{ + ClientSecurityGroup{c.apiKeyHeaderAuth, c.bearerAuthAuth}, + } + + c.queryDataWithApiKeySecurity = ClientSecurityGroups{ + ClientSecurityGroup{c.apiKeyHeaderAuth}, + ClientSecurityGroup{c.apiKeyQueryAuth}, + ClientSecurityGroup{c.apiKeyCookieAuth}, + ClientSecurityGroup{c.rawAuth}, + } + + c.createDocumentSecurity = ClientSecurityGroups{ + ClientSecurityGroup{c.apiKeyHeaderAuth, c.bearerAuthAuth}, + } + + c.getProtectedResourceSecurity = ClientSecurityGroups{ + ClientSecurityGroup{c.apiKeyHeaderAuth, c.basicAuthAuth}, + ClientSecurityGroup{c.apiKeyCookieAuth, c.bearerAuthAuth}, + } + + c.getCurrentUserSecurity = ClientSecurityGroups{ + ClientSecurityGroup{c.apiKeyHeaderAuth}, + ClientSecurityGroup{c.bearerAuthAuth}, + ClientSecurityGroup{c.oauth2ExampleAuth}, + } + + return c +} + +// ListAdminUsers +// List all users (admin only) +// Requires both API key AND bearer token with admin scope +func (c *Client) ListAdminUsers(ctx context.Context, user *example.ExampleAuth) ([]User, error) { + u := c.baseURL + "/admin/users" + + req, err := http.NewRequestWithContext(ctx, "GET", u, http.NoBody) + if err != nil { + return nil, err + } + + httpClient := c.httpClient + httpClient, err = c.listAdminUsersSecurity.Auth(req, httpClient, user) + if err != nil { + return nil, err + } + + resp, err := httpClient.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + errBody, _ := io.ReadAll(resp.Body) + + return nil, httputil.UnexpectedResponseError{Resp: resp, URL: u, Body: errBody} + } + + var out []User + if err := httputil.GetJSONBody(resp.Body, &out); err != nil { + return nil, err + } + + return out, nil +} + +// QueryDataWithApiKey +// Query data with API key +// Accepts API key in header, query parameter, or cookie +func (c *Client) QueryDataWithApiKey(ctx context.Context, user *example.ExampleAuth, query *string) error { + u := c.baseURL + "/data/query" + queryParams := url.Values{} + if query != nil { + queryParams.Set("query", (*query)) + } + + if len(queryParams) > 0 { + u += "?" + queryParams.Encode() + } + + req, err := http.NewRequestWithContext(ctx, "GET", u, http.NoBody) + if err != nil { + return err + } + + httpClient := c.httpClient + httpClient, err = c.queryDataWithApiKeySecurity.Auth(req, httpClient, user) + if err != nil { + return err + } + + resp, err := httpClient.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + errBody, _ := io.ReadAll(resp.Body) + + return httputil.UnexpectedResponseError{Resp: resp, URL: u, Body: errBody} + } + + return nil +} + +// ListDocuments +// List documents +// Requires basic authentication +func (c *Client) ListDocuments(ctx context.Context, user *example.ExampleAuth) error { + u := c.baseURL + "/documents" + + req, err := http.NewRequestWithContext(ctx, "GET", u, http.NoBody) + if err != nil { + return err + } + + httpClient := c.httpClient + httpClient, err = c.basicAuthAuth(req, httpClient, user) + if err != nil { + return err + } + + resp, err := httpClient.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + errBody, _ := io.ReadAll(resp.Body) + + return httputil.UnexpectedResponseError{Resp: resp, URL: u, Body: errBody} + } + + return nil +} + +// CreateDocument +// Create document +// Requires API key with bearer token +func (c *Client) CreateDocument(ctx context.Context, user *example.ExampleAuth) error { + u := c.baseURL + "/documents" + + req, err := http.NewRequestWithContext(ctx, "POST", u, http.NoBody) + if err != nil { + return err + } + + httpClient := c.httpClient + httpClient, err = c.createDocumentSecurity.Auth(req, httpClient, user) + if err != nil { + return err + } + + resp, err := httpClient.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + errBody, _ := io.ReadAll(resp.Body) + + return httputil.UnexpectedResponseError{Resp: resp, URL: u, Body: errBody} + } + + return nil +} + +// Overview +// System overview +// Requires OAuth client credentials +func (c *Client) Overview(ctx context.Context, user *example.ExampleAuth) error { + u := c.baseURL + "/overview" + + req, err := http.NewRequestWithContext(ctx, "GET", u, http.NoBody) + if err != nil { + return err + } + + httpClient := c.httpClient + httpClient, err = c.oauth2ClientCredentialsExampleAuth(req, httpClient, user) + if err != nil { + return err + } + + resp, err := httpClient.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + errBody, _ := io.ReadAll(resp.Body) + + return httputil.UnexpectedResponseError{Resp: resp, URL: u, Body: errBody} + } + + return nil +} + +// GetDetailedProfile +// Get detailed profile +// Requires OpenID Connect authentication +func (c *Client) GetDetailedProfile(ctx context.Context, user *example.ExampleAuth) error { + u := c.baseURL + "/profile/detailed" + + req, err := http.NewRequestWithContext(ctx, "GET", u, http.NoBody) + if err != nil { + return err + } + + httpClient := c.httpClient + httpClient, err = c.openIdconnectAuth(req, httpClient, user) + if err != nil { + return err + } + + resp, err := httpClient.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + errBody, _ := io.ReadAll(resp.Body) + + return httputil.UnexpectedResponseError{Resp: resp, URL: u, Body: errBody} + } + + return nil +} + +// GetProtectedResource +// Access protected resource +// Multiple authentication options: +// 1. OAuth2 with read scope, OR +// 2. API key (header) + Basic auth, OR +// 3. Bearer token + API +// key (cookie) +func (c *Client) GetProtectedResource(ctx context.Context, user *example.ExampleAuth) error { + u := c.baseURL + "/protected-resource" + + req, err := http.NewRequestWithContext(ctx, "GET", u, http.NoBody) + if err != nil { + return err + } + + httpClient := c.httpClient + httpClient, err = c.getProtectedResourceSecurity.Auth(req, httpClient, user) + if err != nil { + return err + } + + resp, err := httpClient.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + errBody, _ := io.ReadAll(resp.Body) + + return httputil.UnexpectedResponseError{Resp: resp, URL: u, Body: errBody} + } + + return nil +} + +// GetPublicStatus +// Get API status +// Public endpoint that requires no authentication +func (c *Client) GetPublicStatus(ctx context.Context) (*GetPublicStatusResponse, error) { + u := c.baseURL + "/public/status" + + req, err := http.NewRequestWithContext(ctx, "GET", u, http.NoBody) + if err != nil { + return nil, err + } + + httpClient := c.httpClient + + resp, err := httpClient.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + errBody, _ := io.ReadAll(resp.Body) + + return nil, httputil.UnexpectedResponseError{Resp: resp, URL: u, Body: errBody} + } + + var out GetPublicStatusResponse + if err := httputil.GetJSONBody(resp.Body, &out); err != nil { + return nil, err + } + + return &out, nil +} + +// GetCurrentUser +// Get current user +// Requires either API key in header OR bearer token +func (c *Client) GetCurrentUser(ctx context.Context, user *example.ExampleAuth) (*User, error) { + u := c.baseURL + "/users/me" + + req, err := http.NewRequestWithContext(ctx, "GET", u, http.NoBody) + if err != nil { + return nil, err + } + + httpClient := c.httpClient + httpClient, err = c.getCurrentUserSecurity.Auth(req, httpClient, user) + if err != nil { + return nil, err + } + + resp, err := httpClient.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + errBody, _ := io.ReadAll(resp.Body) + + return nil, httputil.UnexpectedResponseError{Resp: resp, URL: u, Body: errBody} + } + + var out User + if err := httputil.GetJSONBody(resp.Body, &out); err != nil { + return nil, err + } + + return &out, nil +} + +// GetUserProfile +// Get user profile +// Requires bearer token authentication +func (c *Client) GetUserProfile(ctx context.Context, user *example.ExampleAuth) (*User, error) { + u := c.baseURL + "/users/profile" + + req, err := http.NewRequestWithContext(ctx, "GET", u, http.NoBody) + if err != nil { + return nil, err + } + + httpClient := c.httpClient + httpClient, err = c.bearerAuthAuth(req, httpClient, user) + if err != nil { + return nil, err + } + + resp, err := httpClient.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + errBody, _ := io.ReadAll(resp.Body) + + return nil, httputil.UnexpectedResponseError{Resp: resp, URL: u, Body: errBody} + } + + var out User + if err := httputil.GetJSONBody(resp.Body, &out); err != nil { + return nil, err + } + + return &out, nil +} diff --git a/tests/auth/http_handler_gen.go b/tests/auth/http_handler_gen.go index 4b8d4c4..e11a476 100644 --- a/tests/auth/http_handler_gen.go +++ b/tests/auth/http_handler_gen.go @@ -28,6 +28,7 @@ type Operations interface { QueryDataWithApiKey(ctx context.Context, user *example.ExampleAuth, query *string) error ListDocuments(ctx context.Context, user *example.ExampleAuth) error CreateDocument(ctx context.Context, user *example.ExampleAuth) error + Overview(ctx context.Context, user *example.ExampleAuth) error GetDetailedProfile(ctx context.Context, user *example.ExampleAuth) error GetProtectedResource(ctx context.Context, user *example.ExampleAuth) error GetPublicStatus(ctx context.Context) (*GetPublicStatusResponse, error) @@ -36,39 +37,41 @@ type Operations interface { } type OpenAPIHandlers struct { - ops Operations - apiKeyCookieAuth RequestAuthenticator - apiKeyHeaderAuth RequestAuthenticator - apiKeyQueryAuth RequestAuthenticator - basicAuthAuth RequestAuthenticator - bearerAuthAuth RequestAuthenticator - oauth2ExampleAuth RequestAuthenticator - openIdconnectAuth RequestAuthenticator - rawAuth RequestAuthenticator - authorize AuthorizeFunc - listAdminUsersSecurity SecurityGroups - queryDataWithApiKeySecurity SecurityGroups - createDocumentSecurity SecurityGroups - getProtectedResourceSecurity SecurityGroups - getCurrentUserSecurity SecurityGroups + ops Operations + apiKeyCookieAuth RequestAuthenticator + apiKeyHeaderAuth RequestAuthenticator + apiKeyQueryAuth RequestAuthenticator + basicAuthAuth RequestAuthenticator + bearerAuthAuth RequestAuthenticator + oauth2ClientCredentialsExampleAuth RequestAuthenticator + oauth2ExampleAuth RequestAuthenticator + openIdconnectAuth RequestAuthenticator + rawAuth RequestAuthenticator + authorize AuthorizeFunc + listAdminUsersSecurity SecurityGroups + queryDataWithApiKeySecurity SecurityGroups + createDocumentSecurity SecurityGroups + getProtectedResourceSecurity SecurityGroups + getCurrentUserSecurity SecurityGroups } type Mux interface { Handle(pattern string, handler http.Handler) } -func RegisterHTTP(ops Operations, r Mux, apiKeyCookieAuth TokenAuthenticator, apiKeyHeaderAuth TokenAuthenticator, apiKeyQueryAuth TokenAuthenticator, basicAuthAuth BasicAuthenticator, bearerAuthAuth TokenAuthenticator, oauth2ExampleAuth RequestAuthenticator, openIdconnectAuth RequestAuthenticator, rawAuth RequestAuthenticator, authorize AuthorizeFunc) *OpenAPIHandlers { +func RegisterHTTP(ops Operations, r Mux, apiKeyCookieAuth TokenAuthenticator, apiKeyHeaderAuth TokenAuthenticator, apiKeyQueryAuth TokenAuthenticator, basicAuthAuth BasicAuthenticator, bearerAuthAuth TokenAuthenticator, oauth2ClientCredentialsExampleAuth RequestAuthenticator, oauth2ExampleAuth RequestAuthenticator, openIdconnectAuth RequestAuthenticator, rawAuth RequestAuthenticator, authorize AuthorizeFunc) *OpenAPIHandlers { s := OpenAPIHandlers{ - ops: ops, - apiKeyCookieAuth: httputil.CookieAuth("cookie_name", apiKeyCookieAuth), - apiKeyHeaderAuth: httputil.HeaderAuth("X-API-Key", apiKeyHeaderAuth), - apiKeyQueryAuth: httputil.QueryAuth("query_key_name", apiKeyQueryAuth), - basicAuthAuth: httputil.BasicAuth(basicAuthAuth), - bearerAuthAuth: httputil.BearerAuth("Authorization", bearerAuthAuth), - oauth2ExampleAuth: oauth2ExampleAuth, - openIdconnectAuth: openIdconnectAuth, - rawAuth: rawAuth, - authorize: authorize, + ops: ops, + apiKeyCookieAuth: httputil.CookieAuth("cookie_name", apiKeyCookieAuth), + apiKeyHeaderAuth: httputil.HeaderAuth("X-API-Key", apiKeyHeaderAuth), + apiKeyQueryAuth: httputil.QueryAuth("query_key_name", apiKeyQueryAuth), + basicAuthAuth: httputil.BasicAuth(basicAuthAuth), + bearerAuthAuth: httputil.BearerAuth("Authorization", bearerAuthAuth), + oauth2ClientCredentialsExampleAuth: oauth2ClientCredentialsExampleAuth, + oauth2ExampleAuth: oauth2ExampleAuth, + openIdconnectAuth: openIdconnectAuth, + rawAuth: rawAuth, + authorize: authorize, } s.listAdminUsersSecurity = SecurityGroups{ @@ -101,6 +104,7 @@ func RegisterHTTP(ops Operations, r Mux, apiKeyCookieAuth TokenAuthenticator, ap r.Handle("GET /data/query", http.HandlerFunc(s.QueryDataWithApiKey)) r.Handle("GET /documents", http.HandlerFunc(s.ListDocuments)) r.Handle("POST /documents", http.HandlerFunc(s.CreateDocument)) + r.Handle("GET /overview", http.HandlerFunc(s.Overview)) r.Handle("GET /profile/detailed", http.HandlerFunc(s.GetDetailedProfile)) r.Handle("GET /protected-resource", http.HandlerFunc(s.GetProtectedResource)) r.Handle("GET /public/status", http.HandlerFunc(s.GetPublicStatus)) @@ -233,6 +237,32 @@ func (h OpenAPIHandlers) CreateDocument(w http.ResponseWriter, r *http.Request) w.WriteHeader(201) } +// Overview +// System overview +// Requires OAuth client credentials +func (h OpenAPIHandlers) Overview(w http.ResponseWriter, r *http.Request) { + var err error + + logctx.SetOperation(r.Context(), "overview") + logctx.AddStrToContext(r.Context(), "op", "overview") + + user, err := h.oauth2ClientCredentialsExampleAuth(r) + if err != nil { + httputil.ErrorHandler(w, r, err) + + return + } + + err = h.ops.Overview(r.Context(), user) + if err != nil { + httputil.ErrorHandler(w, r, err) + + return + } + + w.WriteHeader(200) +} + // GetDetailedProfile // Get detailed profile // Requires OpenID Connect authentication diff --git a/tests/auth/openapi.yaml b/tests/auth/openapi.yaml index 79222fa..3766e97 100644 --- a/tests/auth/openapi.yaml +++ b/tests/auth/openapi.yaml @@ -61,6 +61,7 @@ components: # Custom auth that processes the request directly using `x-raw-auth`. Raw: x-raw-auth: true + x-raw-client-auth: true type: apiKey name: Authorization in: header @@ -80,6 +81,15 @@ components: write:pets: modify pets in your account read:pets: read your pets + Oauth2ClientCredentialsExample: + type: oauth2 + flows: + clientCredentials: + tokenUrl: https://example.com/api/oauth/token + scopes: + write:pets: modify pets in your account + read:pets: read your pets + schemas: User: type: object @@ -245,6 +255,18 @@ paths: '200': description: Detailed user profile + # OAuth Client Credentials + /overview: + get: + operationId: overview + summary: System overview + description: Requires OAuth client credentials + security: + - Oauth2ClientCredentialsExample: [] + responses: + '200': + description: System overview data + # API key variations /data/query: get: diff --git a/tests/auth/service_gen.go b/tests/auth/service_gen.go index f71ffa7..8930459 100644 --- a/tests/auth/service_gen.go +++ b/tests/auth/service_gen.go @@ -45,6 +45,13 @@ func (s *GenService) CreateDocument(ctx context.Context, user *example.ExampleAu return errors.ErrUnsupported } +// Overview +// System overview +// Requires OAuth client credentials +func (s *GenService) Overview(ctx context.Context, user *example.ExampleAuth) error { + return errors.ErrUnsupported +} + // GetDetailedProfile // Get detailed profile // Requires OpenID Connect authentication diff --git a/tests/csvresponse/foji.yaml b/tests/csvresponse/foji.yaml index 6d12117..589ea48 100644 --- a/tests/csvresponse/foji.yaml +++ b/tests/csvresponse/foji.yaml @@ -10,3 +10,10 @@ processes: OpenAPIFile: 'tests/csvresponse/http_handler_gen.go': foji/openapi/handler.go.tpl 'tests/csvresponse/model_gen.go': foji/openapi/model.go.tpl + openAPIClient: + params: + Package: foji/tests/csvresponse + Auth: ExampleAuth + OpenAPIFile: + 'tests/csvresponse/model_gen.go': foji/openapi/model.go.tpl + 'tests/csvresponse/http_client_gen.go': foji/openapi/client.go.tpl diff --git a/tests/csvresponse/http_client_gen.go b/tests/csvresponse/http_client_gen.go new file mode 100644 index 0000000..a90ff98 --- /dev/null +++ b/tests/csvresponse/http_client_gen.go @@ -0,0 +1,130 @@ +// Code generated by foji, template: foji/openapi/client.go.tpl; DO NOT EDIT. + +package csvresponse + +import ( + "context" + "fmt" + "io" + "net/http" + + "github.com/bir/iken/httputil" +) + +type ( + ClientAuthenticator = httputil.ClientAuthenticateFunc[*ExampleAuth] + ClientTokenAuthenticator = httputil.ClientTokenAuthenticatorFunc[*ExampleAuth] + ClientBasicAuthenticator = httputil.ClientBasicAuthenticatorFunc[*ExampleAuth] + ClientCookieAuthenticator = httputil.ClientCookieAuthenticatorFunc[*ExampleAuth] + ClientWrappingAuthenticator = httputil.ClientWrappingAuthenticatorFunc[*ExampleAuth] +) + +type Methods interface { + GetByteCsv(ctx context.Context) ([]byte, error) + GetReaderCsv(ctx context.Context) (io.Reader, error) + GetStringCsv(ctx context.Context) (string, error) +} + +type Client struct { + baseURL string + httpClient *http.Client + headerAuthAuth ClientAuthenticator +} + +func NewClient(baseURL string, httpClient *http.Client, headerAuthAuth ClientTokenAuthenticator) *Client { + c := &Client{ + baseURL: baseURL, + httpClient: httpClient, + headerAuthAuth: httputil.HeaderClientAuth("Authorization", headerAuthAuth), + } + + return c +} + +// GetByteCsv +func (c *Client) GetByteCsv(ctx context.Context) ([]byte, error) { + u := c.baseURL + "/bytesCSV" + + req, err := http.NewRequestWithContext(ctx, "GET", u, http.NoBody) + if err != nil { + return nil, err + } + + httpClient := c.httpClient + + resp, err := httpClient.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + errBody, _ := io.ReadAll(resp.Body) + + return nil, httputil.UnexpectedResponseError{Resp: resp, URL: u, Body: errBody} + } + + out, err := io.ReadAll(resp.Body) + if err != nil { + return nil, fmt.Errorf("read response: %w", err) + } + + return out, nil +} + +// GetReaderCsv +func (c *Client) GetReaderCsv(ctx context.Context) (io.Reader, error) { + u := c.baseURL + "/readerCSV" + + req, err := http.NewRequestWithContext(ctx, "GET", u, http.NoBody) + if err != nil { + return nil, err + } + + httpClient := c.httpClient + + resp, err := httpClient.Do(req) + if err != nil { + return nil, err + } + + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + defer resp.Body.Close() + errBody, _ := io.ReadAll(resp.Body) + + return nil, httputil.UnexpectedResponseError{Resp: resp, URL: u, Body: errBody} + } + + return resp.Body, nil +} + +// GetStringCsv +func (c *Client) GetStringCsv(ctx context.Context) (string, error) { + u := c.baseURL + "/stringCSV" + + req, err := http.NewRequestWithContext(ctx, "GET", u, http.NoBody) + if err != nil { + return "", err + } + + httpClient := c.httpClient + + resp, err := httpClient.Do(req) + if err != nil { + return "", err + } + defer resp.Body.Close() + + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + errBody, _ := io.ReadAll(resp.Body) + + return "", httputil.UnexpectedResponseError{Resp: resp, URL: u, Body: errBody} + } + + out, err := io.ReadAll(resp.Body) + if err != nil { + return "", fmt.Errorf("read response: %w", err) + } + + return string(out), nil +} diff --git a/tests/example/client_model_gen.go b/tests/example/client_model_gen.go new file mode 100644 index 0000000..f1cf2b6 --- /dev/null +++ b/tests/example/client_model_gen.go @@ -0,0 +1,3484 @@ +// Code generated by foji, template: foji/openapi/model.go.tpl; DO NOT EDIT. + +package example + +import ( + "database/sql/driver" + "encoding/json" + "errors" + "fmt" + "math" + "net/http" + "regexp" + "time" + + "github.com/bir/iken/forms" + "github.com/bir/iken/validation" + "github.com/google/uuid" +) + +var ErrExampleMissingRequiredField = errors.New("missing required field") + +// Component Schemas + +// ExampleBar +// +// OpenAPI Component Schema: Bar +type ExampleBar struct { + Bars string `json:"bars,omitempty,omitzero"` +} + +var exampleBarBarsPattern = regexp.MustCompile(`(b1|b2)`) + +func (p *ExampleBar) UnmarshalJSON(b []byte) error { + var err error + + type ExampleBarJSON ExampleBar + var parseObject ExampleBarJSON + + err = json.Unmarshal(b, &parseObject) + if err != nil { + return validation.Error{err.Error(), fmt.Errorf("ExampleBar.UnmarshalJSON: `%v`: %w", string(b), err)} + } + + v := ExampleBar(parseObject) + + err = v.Validate() + if err != nil { + return err + } + + *p = v + + return nil +} + +func (p ExampleBar) MarshalJSON() ([]byte, error) { + err := p.Validate() + if err != nil { + return nil, err + } + + type unvalidated ExampleBar // Skips the validation check + b, err := json.Marshal(unvalidated(p)) + if err != nil { + return nil, fmt.Errorf("ExampleBar.Marshal: `%+v`: %w", p, err) + } + + return b, nil +} + +func (p ExampleBar) Validate() error { + var err validation.Errors + + p.ValidateBars(&err) + + return err.GetErr() +} + +func (p ExampleBar) ValidateBars(err *validation.Errors) { + if len(p.Bars) < 2 { + _ = err.Add("bars", "length must be >= 2") + } + + if p.Bars != "" && !exampleBarBarsPattern.MatchString(string(p.Bars)) { + _ = err.Add("bars", `must match "(b1|b2)"`) + } +} + +// ExampleBuzz +// +// OpenAPI Component Schema: Buzz +type ExampleBuzz struct { + Buzzes string `json:"buzzes,omitempty,omitzero"` +} + +// ExampleDefaultWithoutRequired +// +// OpenAPI Component Schema: DefaultWithoutRequired +type ExampleDefaultWithoutRequired struct { + F1 string `json:"f1,omitempty,omitzero"` +} + +func (p *ExampleDefaultWithoutRequired) UnmarshalJSON(b []byte) error { + var err error + var requiredCheck map[string]any + + err = json.Unmarshal(b, &requiredCheck) + if err != nil { + return validation.Error{err.Error(), fmt.Errorf("ExampleDefaultWithoutRequired.UnmarshalJSON Required: `%v`: %w", string(b), err)} + } + + var validationErrors validation.Errors + + if validationErrors != nil { + return validationErrors.GetErr() + } + + type ExampleDefaultWithoutRequiredJSON ExampleDefaultWithoutRequired + var parseObject ExampleDefaultWithoutRequiredJSON + + err = json.Unmarshal(b, &parseObject) + if err != nil { + return validation.Error{err.Error(), fmt.Errorf("ExampleDefaultWithoutRequired.UnmarshalJSON: `%v`: %w", string(b), err)} + } + + v := ExampleDefaultWithoutRequired(parseObject) + + if _, ok := requiredCheck["f1"]; !ok { + v.F1 = "surprise!" + } + + *p = v + + return nil +} + +// ExampleExample +// +// OpenAPI Component Schema: Example +type ExampleExample struct { + ID uuid.UUID `json:"id"` + IdMaybe *uuid.UUID `json:"idMaybe,omitempty,omitzero"` + Name string `json:"name,omitempty,omitzero"` + PlayerAlways ExamplePlayerAlways `json:"playerAlways,omitempty,omitzero"` + PlayerID uuid.UUID `json:"playerId,omitempty,omitzero"` + PlayerMaybe *ExamplePlayerMaybe `json:"playerMaybe,omitempty,omitzero"` +} + +func (p *ExampleExample) UnmarshalJSON(b []byte) error { + var err error + var requiredCheck map[string]any + + err = json.Unmarshal(b, &requiredCheck) + if err != nil { + return validation.Error{err.Error(), fmt.Errorf("ExampleExample.UnmarshalJSON Required: `%v`: %w", string(b), err)} + } + + var validationErrors validation.Errors + + if _, ok := requiredCheck["id"]; !ok { + validationErrors.Add("id", ErrExampleMissingRequiredField) + } + + if validationErrors != nil { + return validationErrors.GetErr() + } + + type ExampleExampleJSON ExampleExample + var parseObject ExampleExampleJSON + + err = json.Unmarshal(b, &parseObject) + if err != nil { + return validation.Error{err.Error(), fmt.Errorf("ExampleExample.UnmarshalJSON: `%v`: %w", string(b), err)} + } + + v := ExampleExample(parseObject) + + *p = v + + return nil +} + +// ExampleExamples +// +// OpenAPI Component Schema: Examples +type ExampleExamples struct { + List []ExampleExample `json:"list"` +} + +func (p *ExampleExamples) UnmarshalJSON(b []byte) error { + var err error + var requiredCheck map[string]any + + err = json.Unmarshal(b, &requiredCheck) + if err != nil { + return validation.Error{err.Error(), fmt.Errorf("ExampleExamples.UnmarshalJSON Required: `%v`: %w", string(b), err)} + } + + var validationErrors validation.Errors + + if _, ok := requiredCheck["list"]; !ok { + validationErrors.Add("list", ErrExampleMissingRequiredField) + } + + if validationErrors != nil { + return validationErrors.GetErr() + } + + type ExampleExamplesJSON ExampleExamples + var parseObject ExampleExamplesJSON + + err = json.Unmarshal(b, &parseObject) + if err != nil { + return validation.Error{err.Error(), fmt.Errorf("ExampleExamples.UnmarshalJSON: `%v`: %w", string(b), err)} + } + + v := ExampleExamples(parseObject) + + *p = v + + return nil +} + +// ExampleFoo +// +// OpenAPI Component Schema: Foo +type ExampleFoo struct { + Foos ExampleFooString `json:"foos,omitempty,omitzero"` +} + +func (p *ExampleFoo) UnmarshalJSON(b []byte) error { + var err error + + type ExampleFooJSON ExampleFoo + var parseObject ExampleFooJSON + + err = json.Unmarshal(b, &parseObject) + if err != nil { + return validation.Error{err.Error(), fmt.Errorf("ExampleFoo.UnmarshalJSON: `%v`: %w", string(b), err)} + } + + v := ExampleFoo(parseObject) + + err = v.Validate() + if err != nil { + return err + } + + *p = v + + return nil +} + +func (p ExampleFoo) MarshalJSON() ([]byte, error) { + err := p.Validate() + if err != nil { + return nil, err + } + + type unvalidated ExampleFoo // Skips the validation check + b, err := json.Marshal(unvalidated(p)) + if err != nil { + return nil, fmt.Errorf("ExampleFoo.Marshal: `%+v`: %w", p, err) + } + + return b, nil +} + +func (p ExampleFoo) Validate() error { + var err validation.Errors + + p.ValidateFoos(&err) + + return err.GetErr() +} + +func (p ExampleFoo) ValidateFoos(err *validation.Errors) { + if subErr := p.Foos.Validate(); subErr != nil { + _ = err.Add("foos", subErr) + } +} + +// ExampleFooBar +// +// OpenAPI Component Schema: FooBar +type ExampleFooBar struct { + A string `json:"a"` + B ExampleSeason `json:"b,omitempty,omitzero"` + Bars string `json:"bars,omitempty,omitzero"` + C ExampleIntValue `json:"c,omitempty"` + Foos ExampleFooString `json:"foos,omitempty,omitzero"` +} + +var exampleFooBarBarsPattern = regexp.MustCompile(`(b1|b2)`) + +func (p *ExampleFooBar) UnmarshalJSON(b []byte) error { + var err error + var requiredCheck map[string]any + + err = json.Unmarshal(b, &requiredCheck) + if err != nil { + return validation.Error{err.Error(), fmt.Errorf("ExampleFooBar.UnmarshalJSON Required: `%v`: %w", string(b), err)} + } + + var validationErrors validation.Errors + + if _, ok := requiredCheck["a"]; !ok { + validationErrors.Add("a", ErrExampleMissingRequiredField) + } + + if validationErrors != nil { + return validationErrors.GetErr() + } + + type ExampleFooBarJSON ExampleFooBar + var parseObject ExampleFooBarJSON + + err = json.Unmarshal(b, &parseObject) + if err != nil { + return validation.Error{err.Error(), fmt.Errorf("ExampleFooBar.UnmarshalJSON: `%v`: %w", string(b), err)} + } + + v := ExampleFooBar(parseObject) + + err = v.Validate() + if err != nil { + return err + } + + *p = v + + return nil +} + +func (p ExampleFooBar) MarshalJSON() ([]byte, error) { + err := p.Validate() + if err != nil { + return nil, err + } + + type unvalidated ExampleFooBar // Skips the validation check + b, err := json.Marshal(unvalidated(p)) + if err != nil { + return nil, fmt.Errorf("ExampleFooBar.Marshal: `%+v`: %w", p, err) + } + + return b, nil +} + +func (p ExampleFooBar) Validate() error { + var err validation.Errors + + p.ValidateA(&err) + p.ValidateBars(&err) + p.ValidateC(&err) + p.ValidateFoos(&err) + + return err.GetErr() +} + +func (p ExampleFooBar) ValidateA(err *validation.Errors) { + if len(p.A) < 2 { + _ = err.Add("a", "length must be >= 2") + } +} + +func (p ExampleFooBar) ValidateBars(err *validation.Errors) { + if len(p.Bars) < 2 { + _ = err.Add("bars", "length must be >= 2") + } + + if p.Bars != "" && !exampleFooBarBarsPattern.MatchString(string(p.Bars)) { + _ = err.Add("bars", `must match "(b1|b2)"`) + } +} + +func (p ExampleFooBar) ValidateC(err *validation.Errors) { + if subErr := p.C.Validate(); subErr != nil { + _ = err.Add("c", subErr) + } +} + +func (p ExampleFooBar) ValidateFoos(err *validation.Errors) { + if subErr := p.Foos.Validate(); subErr != nil { + _ = err.Add("foos", subErr) + } +} + +// ExampleFooBarBuzz +// +// OpenAPI Component Schema: FooBarBuzz +type ExampleFooBarBuzz struct { + A string `json:"a,omitempty,omitzero"` + B ExampleSeason `json:"b,omitempty,omitzero"` + Bars string `json:"bars,omitempty,omitzero"` + Buzzes string `json:"buzzes,omitempty,omitzero"` + C ExampleIntValue `json:"c,omitempty"` + Foos ExampleFooString `json:"foos,omitempty,omitzero"` + X bool `json:"x,omitempty"` +} + +var exampleFooBarBuzzBarsPattern = regexp.MustCompile(`(b1|b2)`) + +func (p *ExampleFooBarBuzz) UnmarshalJSON(b []byte) error { + var err error + + type ExampleFooBarBuzzJSON ExampleFooBarBuzz + var parseObject ExampleFooBarBuzzJSON + + err = json.Unmarshal(b, &parseObject) + if err != nil { + return validation.Error{err.Error(), fmt.Errorf("ExampleFooBarBuzz.UnmarshalJSON: `%v`: %w", string(b), err)} + } + + v := ExampleFooBarBuzz(parseObject) + + err = v.Validate() + if err != nil { + return err + } + + *p = v + + return nil +} + +func (p ExampleFooBarBuzz) MarshalJSON() ([]byte, error) { + err := p.Validate() + if err != nil { + return nil, err + } + + type unvalidated ExampleFooBarBuzz // Skips the validation check + b, err := json.Marshal(unvalidated(p)) + if err != nil { + return nil, fmt.Errorf("ExampleFooBarBuzz.Marshal: `%+v`: %w", p, err) + } + + return b, nil +} + +func (p ExampleFooBarBuzz) Validate() error { + var err validation.Errors + + p.ValidateA(&err) + p.ValidateBars(&err) + p.ValidateC(&err) + p.ValidateFoos(&err) + + return err.GetErr() +} + +func (p ExampleFooBarBuzz) ValidateA(err *validation.Errors) { + if len(p.A) < 2 { + _ = err.Add("a", "length must be >= 2") + } +} + +func (p ExampleFooBarBuzz) ValidateBars(err *validation.Errors) { + if len(p.Bars) < 2 { + _ = err.Add("bars", "length must be >= 2") + } + + if p.Bars != "" && !exampleFooBarBuzzBarsPattern.MatchString(string(p.Bars)) { + _ = err.Add("bars", `must match "(b1|b2)"`) + } +} + +func (p ExampleFooBarBuzz) ValidateC(err *validation.Errors) { + if subErr := p.C.Validate(); subErr != nil { + _ = err.Add("c", subErr) + } +} + +func (p ExampleFooBarBuzz) ValidateFoos(err *validation.Errors) { + if subErr := p.Foos.Validate(); subErr != nil { + _ = err.Add("foos", subErr) + } +} + +// string +// +// OpenAPI Component Schema: FooString +type ExampleFooString string + +var exampleFooStringPattern = regexp.MustCompile(`(f1|f2)`) + +func (p *ExampleFooString) UnmarshalJSON(b []byte) error { + var err error + + type ExampleFooStringJSON ExampleFooString + var parseObject ExampleFooStringJSON + + err = json.Unmarshal(b, &parseObject) + if err != nil { + return validation.Error{err.Error(), fmt.Errorf("ExampleFooString.UnmarshalJSON: `%v`: %w", string(b), err)} + } + + v := ExampleFooString(parseObject) + + err = v.Validate() + if err != nil { + return err + } + + *p = v + + return nil +} + +func (p ExampleFooString) MarshalJSON() ([]byte, error) { + err := p.Validate() + if err != nil { + return nil, err + } + + type unvalidated ExampleFooString // Skips the validation check + b, err := json.Marshal(unvalidated(p)) + if err != nil { + return nil, fmt.Errorf("ExampleFooString.Marshal: `%+v`: %w", p, err) + } + + return b, nil +} + +func (p ExampleFooString) Validate() error { + var err validation.Errors + + if p != "" && !exampleFooStringPattern.MatchString(string(p)) { + _ = err.Add("", `must match "(f1|f2)"`) + } + + return err.GetErr() +} + +// int32 +// +// OpenAPI Component Schema: IntValue +type ExampleIntValue int32 + +func (p *ExampleIntValue) UnmarshalJSON(b []byte) error { + var err error + + type ExampleIntValueJSON ExampleIntValue + var parseObject ExampleIntValueJSON + + err = json.Unmarshal(b, &parseObject) + if err != nil { + return validation.Error{err.Error(), fmt.Errorf("ExampleIntValue.UnmarshalJSON: `%v`: %w", string(b), err)} + } + + v := ExampleIntValue(parseObject) + + err = v.Validate() + if err != nil { + return err + } + + *p = v + + return nil +} + +func (p ExampleIntValue) MarshalJSON() ([]byte, error) { + err := p.Validate() + if err != nil { + return nil, err + } + + type unvalidated ExampleIntValue // Skips the validation check + b, err := json.Marshal(unvalidated(p)) + if err != nil { + return nil, fmt.Errorf("ExampleIntValue.Marshal: `%+v`: %w", p, err) + } + + return b, nil +} + +func (p ExampleIntValue) Validate() error { + var err validation.Errors + + if p < 2 { + _ = err.Add("", "must be >= 2") + } + + if p > 10 { + _ = err.Add("", "must be <= 10") + } + + if p%2 != 0 { + _ = err.Add("", "must be multiple of 2") + } + + return err.GetErr() +} + +// any +// Named object +// +// OpenAPI Component Schema: NamedObject +type ExampleNamedObject any + +// ExampleNotRequiredWithValidation +// +// OpenAPI Component Schema: NotRequiredWithValidation +type ExampleNotRequiredWithValidation struct { + F1 []string `json:"f1,omitempty"` +} + +func (p *ExampleNotRequiredWithValidation) UnmarshalJSON(b []byte) error { + var err error + + type ExampleNotRequiredWithValidationJSON ExampleNotRequiredWithValidation + var parseObject ExampleNotRequiredWithValidationJSON + + err = json.Unmarshal(b, &parseObject) + if err != nil { + return validation.Error{err.Error(), fmt.Errorf("ExampleNotRequiredWithValidation.UnmarshalJSON: `%v`: %w", string(b), err)} + } + + v := ExampleNotRequiredWithValidation(parseObject) + + err = v.Validate() + if err != nil { + return err + } + + *p = v + + return nil +} + +func (p ExampleNotRequiredWithValidation) MarshalJSON() ([]byte, error) { + err := p.Validate() + if err != nil { + return nil, err + } + + type unvalidated ExampleNotRequiredWithValidation // Skips the validation check + b, err := json.Marshal(unvalidated(p)) + if err != nil { + return nil, fmt.Errorf("ExampleNotRequiredWithValidation.Marshal: `%+v`: %w", p, err) + } + + return b, nil +} + +func (p ExampleNotRequiredWithValidation) Validate() error { + var err validation.Errors + + p.ValidateF1(&err) + + return err.GetErr() +} + +func (p ExampleNotRequiredWithValidation) ValidateF1(err *validation.Errors) { + if len(p.F1) < 2 { + _ = err.Add("f1", "length must be >= 2") + } +} + +// ExamplePatterns +// +// OpenAPI Component Schema: Patterns +type ExamplePatterns struct { + ID uuid.UUID `json:"id"` + IdMaybe uuid.UUID `json:"idMaybe,omitempty,omitzero"` + State *string `json:"state,omitempty,omitzero"` + State2 string `json:"state2,omitempty,omitzero"` + State3 *string `json:"state3,omitempty,omitzero"` + StateAlways string `json:"stateAlways"` + SubInt ExampleIntValue `json:"subInt,omitempty"` + SubObject ExampleSubPattern `json:"subObject"` + SubObjectMaybe *ExampleSubPattern `json:"subObjectMaybe,omitempty,omitzero"` + SubState ExampleState `json:"subState"` + SubStateMaybe *ExampleState `json:"subStateMaybe,omitempty,omitzero"` + SubValue ExamplePatternsSubValue `json:"subValue,omitempty,omitzero"` + TimeStamp time.Time `json:"timeStamp"` + TimeStampMaybe time.Time `json:"timeStampMaybe,omitempty,omitzero"` + Value int32 `json:"value,omitempty"` + ValueF float32 `json:"valueF,omitempty"` + ValueFmaybe *float32 `json:"valueFMaybe,omitempty"` + ValueMaybe *int32 `json:"valueMaybe,omitempty"` + Values []string `json:"values,omitempty"` + ValuesMaybe *[]string `json:"valuesMaybe,omitempty"` +} + +// ExamplePatternsSubValue +// +// OpenAPI ExamplePatterns inline subValue: PatternsSubValue +type ExamplePatternsSubValue struct { + Num int32 `json:"num,omitempty"` +} + +func (p *ExamplePatternsSubValue) UnmarshalJSON(b []byte) error { + var err error + + type ExamplePatternsSubValueJSON ExamplePatternsSubValue + var parseObject ExamplePatternsSubValueJSON + + err = json.Unmarshal(b, &parseObject) + if err != nil { + return validation.Error{err.Error(), fmt.Errorf("ExamplePatternsSubValue.UnmarshalJSON: `%v`: %w", string(b), err)} + } + + v := ExamplePatternsSubValue(parseObject) + + err = v.Validate() + if err != nil { + return err + } + + *p = v + + return nil +} + +func (p ExamplePatternsSubValue) MarshalJSON() ([]byte, error) { + err := p.Validate() + if err != nil { + return nil, err + } + + type unvalidated ExamplePatternsSubValue // Skips the validation check + b, err := json.Marshal(unvalidated(p)) + if err != nil { + return nil, fmt.Errorf("ExamplePatternsSubValue.Marshal: `%+v`: %w", p, err) + } + + return b, nil +} + +func (p ExamplePatternsSubValue) Validate() error { + var err validation.Errors + + p.ValidateNum(&err) + + return err.GetErr() +} + +func (p ExamplePatternsSubValue) ValidateNum(err *validation.Errors) { + if p.Num < 2 { + _ = err.Add("num", "must be >= 2") + } +} + +var ( + examplePatternsStatePattern = regexp.MustCompile(`(enabled|disabled)`) + examplePatternsState2Pattern = regexp.MustCompile(`(enabled|disabled)`) + examplePatternsStateAlwaysPattern = regexp.MustCompile(`(enabled|disabled)`) +) + +func (p *ExamplePatterns) UnmarshalJSON(b []byte) error { + var err error + var requiredCheck map[string]any + + err = json.Unmarshal(b, &requiredCheck) + if err != nil { + return validation.Error{err.Error(), fmt.Errorf("ExamplePatterns.UnmarshalJSON Required: `%v`: %w", string(b), err)} + } + + var validationErrors validation.Errors + + if _, ok := requiredCheck["id"]; !ok { + validationErrors.Add("id", ErrExampleMissingRequiredField) + } + + if _, ok := requiredCheck["stateAlways"]; !ok { + validationErrors.Add("stateAlways", ErrExampleMissingRequiredField) + } + + if _, ok := requiredCheck["subObject"]; !ok { + validationErrors.Add("subObject", ErrExampleMissingRequiredField) + } + + if _, ok := requiredCheck["subState"]; !ok { + validationErrors.Add("subState", ErrExampleMissingRequiredField) + } + + if _, ok := requiredCheck["timeStamp"]; !ok { + validationErrors.Add("timeStamp", ErrExampleMissingRequiredField) + } + + if validationErrors != nil { + return validationErrors.GetErr() + } + + type ExamplePatternsJSON ExamplePatterns + var parseObject ExamplePatternsJSON + + err = json.Unmarshal(b, &parseObject) + if err != nil { + return validation.Error{err.Error(), fmt.Errorf("ExamplePatterns.UnmarshalJSON: `%v`: %w", string(b), err)} + } + + v := ExamplePatterns(parseObject) + + if _, ok := requiredCheck["state3"]; !ok { + var defaultVal string = "completed" + v.State3 = &defaultVal + } + + err = v.Validate() + if err != nil { + return err + } + + *p = v + + return nil +} + +func (p ExamplePatterns) MarshalJSON() ([]byte, error) { + err := p.Validate() + if err != nil { + return nil, err + } + + type unvalidated ExamplePatterns // Skips the validation check + b, err := json.Marshal(unvalidated(p)) + if err != nil { + return nil, fmt.Errorf("ExamplePatterns.Marshal: `%+v`: %w", p, err) + } + + return b, nil +} + +func (p ExamplePatterns) Validate() error { + var err validation.Errors + + p.ValidateState(&err) + p.ValidateState2(&err) + p.ValidateStateAlways(&err) + p.ValidateSubInt(&err) + p.ValidateSubObject(&err) + p.ValidateSubObjectMaybe(&err) + p.ValidateSubState(&err) + p.ValidateSubStateMaybe(&err) + p.ValidateSubValue(&err) + p.ValidateValue(&err) + p.ValidateValueF(&err) + p.ValidateValueFmaybe(&err) + p.ValidateValueMaybe(&err) + p.ValidateValues(&err) + p.ValidateValuesMaybe(&err) + + return err.GetErr() +} + +func (p ExamplePatterns) ValidateState(err *validation.Errors) { + if p.State == nil { + return + } + + if len(*p.State) < 2 { + _ = err.Add("state", "length must be >= 2") + } + + if len(*p.State) > 10 { + _ = err.Add("state", "length must be <= 10") + } + + if *p.State != "" && !examplePatternsStatePattern.MatchString(string(*p.State)) { + _ = err.Add("state", `must match "(enabled|disabled)"`) + } +} + +func (p ExamplePatterns) ValidateState2(err *validation.Errors) { + if p.State2 != "" && !examplePatternsState2Pattern.MatchString(string(p.State2)) { + _ = err.Add("state2", `must match "(enabled|disabled)"`) + } +} + +func (p ExamplePatterns) ValidateStateAlways(err *validation.Errors) { + if p.StateAlways != "" && !examplePatternsStateAlwaysPattern.MatchString(string(p.StateAlways)) { + _ = err.Add("stateAlways", `must match "(enabled|disabled)"`) + } +} + +func (p ExamplePatterns) ValidateSubInt(err *validation.Errors) { + if subErr := p.SubInt.Validate(); subErr != nil { + _ = err.Add("subInt", subErr) + } +} + +func (p ExamplePatterns) ValidateSubObject(err *validation.Errors) { + if subErr := p.SubObject.Validate(); subErr != nil { + _ = err.Add("subObject", subErr) + } +} + +func (p ExamplePatterns) ValidateSubObjectMaybe(err *validation.Errors) { + if p.SubObjectMaybe == nil { + return + } + + if p.SubObjectMaybe != nil { + if subErr := p.SubObjectMaybe.Validate(); subErr != nil { + _ = err.Add("subObjectMaybe", subErr) + } + } +} + +func (p ExamplePatterns) ValidateSubState(err *validation.Errors) { + if subErr := p.SubState.Validate(); subErr != nil { + _ = err.Add("subState", subErr) + } +} + +func (p ExamplePatterns) ValidateSubStateMaybe(err *validation.Errors) { + if p.SubStateMaybe == nil { + return + } + + if p.SubStateMaybe != nil { + if subErr := p.SubStateMaybe.Validate(); subErr != nil { + _ = err.Add("subStateMaybe", subErr) + } + } +} + +func (p ExamplePatterns) ValidateSubValue(err *validation.Errors) { + if subErr := p.SubValue.Validate(); subErr != nil { + _ = err.Add("subValue", subErr) + } +} + +func (p ExamplePatterns) ValidateValue(err *validation.Errors) { + if p.Value < 2 { + _ = err.Add("value", "must be >= 2") + } + + if p.Value > 10 { + _ = err.Add("value", "must be <= 10") + } + + if p.Value%2 != 0 { + _ = err.Add("value", "must be multiple of 2") + } +} + +func (p ExamplePatterns) ValidateValueF(err *validation.Errors) { + if p.ValueF < 2 { + _ = err.Add("valueF", "must be >= 2") + } + + if p.ValueF > 10 { + _ = err.Add("valueF", "must be <= 10") + } + + if math.Mod(float64(p.ValueF), 2) != 0 { + _ = err.Add("valueF", "must be multiple of 2") + } +} + +func (p ExamplePatterns) ValidateValueFmaybe(err *validation.Errors) { + if p.ValueFmaybe == nil { + return + } + + if *p.ValueFmaybe < 2 { + _ = err.Add("valueFMaybe", "must be >= 2") + } + + if *p.ValueFmaybe > 10 { + _ = err.Add("valueFMaybe", "must be <= 10") + } + + if math.Mod(float64(*p.ValueFmaybe), 2) != 0 { + _ = err.Add("valueFMaybe", "must be multiple of 2") + } +} + +func (p ExamplePatterns) ValidateValueMaybe(err *validation.Errors) { + if p.ValueMaybe == nil { + return + } + + if *p.ValueMaybe < 2 { + _ = err.Add("valueMaybe", "must be >= 2") + } + + if *p.ValueMaybe > 10 { + _ = err.Add("valueMaybe", "must be <= 10") + } + + if *p.ValueMaybe%2 != 0 { + _ = err.Add("valueMaybe", "must be multiple of 2") + } +} + +func (p ExamplePatterns) ValidateValues(err *validation.Errors) { + if len(p.Values) < 2 { + _ = err.Add("values", "length must be >= 2") + } + + if len(p.Values) > 10 { + _ = err.Add("values", "length must be <= 10") + } +} + +func (p ExamplePatterns) ValidateValuesMaybe(err *validation.Errors) { + if p.ValuesMaybe == nil { + return + } + + if len(*p.ValuesMaybe) < 2 { + _ = err.Add("valuesMaybe", "length must be >= 2") + } + + if len(*p.ValuesMaybe) > 10 { + _ = err.Add("valuesMaybe", "length must be <= 10") + } +} + +// ExamplePlayerAlways +// +// OpenAPI Component Schema: PlayerAlways +type ExamplePlayerAlways struct { + ID uuid.UUID `json:"id"` +} + +func (p *ExamplePlayerAlways) UnmarshalJSON(b []byte) error { + var err error + var requiredCheck map[string]any + + err = json.Unmarshal(b, &requiredCheck) + if err != nil { + return validation.Error{err.Error(), fmt.Errorf("ExamplePlayerAlways.UnmarshalJSON Required: `%v`: %w", string(b), err)} + } + + var validationErrors validation.Errors + + if _, ok := requiredCheck["id"]; !ok { + validationErrors.Add("id", ErrExampleMissingRequiredField) + } + + if validationErrors != nil { + return validationErrors.GetErr() + } + + type ExamplePlayerAlwaysJSON ExamplePlayerAlways + var parseObject ExamplePlayerAlwaysJSON + + err = json.Unmarshal(b, &parseObject) + if err != nil { + return validation.Error{err.Error(), fmt.Errorf("ExamplePlayerAlways.UnmarshalJSON: `%v`: %w", string(b), err)} + } + + v := ExamplePlayerAlways(parseObject) + + *p = v + + return nil +} + +// uuid.UUID +// +// OpenAPI Component Schema: PlayerId +type ExamplePlayerID uuid.UUID + +// ExamplePlayerMaybe +// +// OpenAPI Component Schema: PlayerMaybe +type ExamplePlayerMaybe struct { + ID uuid.UUID `json:"id"` +} + +func (p *ExamplePlayerMaybe) UnmarshalJSON(b []byte) error { + var err error + var requiredCheck map[string]any + + err = json.Unmarshal(b, &requiredCheck) + if err != nil { + return validation.Error{err.Error(), fmt.Errorf("ExamplePlayerMaybe.UnmarshalJSON Required: `%v`: %w", string(b), err)} + } + + var validationErrors validation.Errors + + if _, ok := requiredCheck["id"]; !ok { + validationErrors.Add("id", ErrExampleMissingRequiredField) + } + + if validationErrors != nil { + return validationErrors.GetErr() + } + + type ExamplePlayerMaybeJSON ExamplePlayerMaybe + var parseObject ExamplePlayerMaybeJSON + + err = json.Unmarshal(b, &parseObject) + if err != nil { + return validation.Error{err.Error(), fmt.Errorf("ExamplePlayerMaybe.UnmarshalJSON: `%v`: %w", string(b), err)} + } + + v := ExamplePlayerMaybe(parseObject) + + *p = v + + return nil +} + +// ExampleSeason +// +// OpenAPI Component Schema: Season + +// ExampleSeason +// Component Schema : Season +type ExampleSeason int8 + +const ( + UnknownExampleSeason ExampleSeason = iota + ExampleSeasonSpring + ExampleSeasonSummer + ExampleSeasonFall + ExampleSeasonWinter +) + +func NewExampleSeason(name string) ExampleSeason { + switch name { + case "spring": + return ExampleSeasonSpring + case "summer": + return ExampleSeasonSummer + case "fall": + return ExampleSeasonFall + case "winter": + return ExampleSeasonWinter + } + + return ExampleSeason(0) +} + +var ExampleSeasonString = map[ExampleSeason]string{ + ExampleSeasonSpring: "spring", + ExampleSeasonSummer: "summer", + ExampleSeasonFall: "fall", + ExampleSeasonWinter: "winter", +} + +func (e ExampleSeason) String() string { + return ExampleSeasonString[e] +} + +func (e *ExampleSeason) UnmarshalJSON(input []byte) (err error) { + var i int8 + + err = json.Unmarshal(input, &i) + if err == nil { + *e = ExampleSeason(i) + return nil + } + + var s string + + err = json.Unmarshal(input, &s) + if err != nil { + return err + } + + *e = NewExampleSeason(s) + + return nil +} + +func (e ExampleSeason) MarshalJSON() ([]byte, error) { + return json.Marshal(e.String()) +} + +func (e ExampleSeason) Value() (driver.Value, error) { + return json.Marshal(e.String()) +} + +func (e *ExampleSeason) Scan(src any) error { + s, ok := src.(string) + if !ok { + return fmt.Errorf("ExampleSeason.scan: scanned a %T, not []byte", src) //nolint + } + + *e = NewExampleSeason(s) + + return nil +} + +// ExampleSeasonNullable +// +// OpenAPI Component Schema: SeasonNullable + +// ExampleSeasonNullable +// Component Schema : SeasonNullable +type ExampleSeasonNullable int8 + +const ( + UnknownExampleSeasonNullable ExampleSeasonNullable = iota + ExampleSeasonNullableSpring + ExampleSeasonNullableSummer + ExampleSeasonNullableFall + ExampleSeasonNullableWinter +) + +func NewExampleSeasonNullable(name string) ExampleSeasonNullable { + switch name { + case "spring": + return ExampleSeasonNullableSpring + case "summer": + return ExampleSeasonNullableSummer + case "fall": + return ExampleSeasonNullableFall + case "winter": + return ExampleSeasonNullableWinter + } + + return ExampleSeasonNullable(0) +} + +var ExampleSeasonNullableString = map[ExampleSeasonNullable]string{ + ExampleSeasonNullableSpring: "spring", + ExampleSeasonNullableSummer: "summer", + ExampleSeasonNullableFall: "fall", + ExampleSeasonNullableWinter: "winter", +} + +func (e ExampleSeasonNullable) String() string { + return ExampleSeasonNullableString[e] +} + +func (e *ExampleSeasonNullable) UnmarshalJSON(input []byte) (err error) { + var i int8 + + err = json.Unmarshal(input, &i) + if err == nil { + *e = ExampleSeasonNullable(i) + return nil + } + + var s string + + err = json.Unmarshal(input, &s) + if err != nil { + return err + } + + *e = NewExampleSeasonNullable(s) + + return nil +} + +func (e ExampleSeasonNullable) MarshalJSON() ([]byte, error) { + return json.Marshal(e.String()) +} + +func (e ExampleSeasonNullable) Value() (driver.Value, error) { + return json.Marshal(e.String()) +} + +func (e *ExampleSeasonNullable) Scan(src any) error { + s, ok := src.(string) + if !ok { + return fmt.Errorf("ExampleSeasonNullable.scan: scanned a %T, not []byte", src) //nolint + } + + *e = NewExampleSeasonNullable(s) + + return nil +} + +// string +// +// OpenAPI Component Schema: State +type ExampleState string + +var exampleStatePattern = regexp.MustCompile(`(enabled|disabled)`) + +func (p *ExampleState) UnmarshalJSON(b []byte) error { + var err error + + type ExampleStateJSON ExampleState + var parseObject ExampleStateJSON + + err = json.Unmarshal(b, &parseObject) + if err != nil { + return validation.Error{err.Error(), fmt.Errorf("ExampleState.UnmarshalJSON: `%v`: %w", string(b), err)} + } + + v := ExampleState(parseObject) + + err = v.Validate() + if err != nil { + return err + } + + *p = v + + return nil +} + +func (p ExampleState) MarshalJSON() ([]byte, error) { + err := p.Validate() + if err != nil { + return nil, err + } + + type unvalidated ExampleState // Skips the validation check + b, err := json.Marshal(unvalidated(p)) + if err != nil { + return nil, fmt.Errorf("ExampleState.Marshal: `%+v`: %w", p, err) + } + + return b, nil +} + +func (p ExampleState) Validate() error { + var err validation.Errors + + if len(p) < 2 { + _ = err.Add("", "length must be >= 2") + } + + if len(p) > 10 { + _ = err.Add("", "length must be <= 10") + } + + if p != "" && !exampleStatePattern.MatchString(string(p)) { + _ = err.Add("", `must match "(enabled|disabled)"`) + } + + return err.GetErr() +} + +// ExampleSubPattern +// +// OpenAPI Component Schema: SubPattern +type ExampleSubPattern struct { + Num int32 `json:"num,omitempty"` +} + +func (p *ExampleSubPattern) UnmarshalJSON(b []byte) error { + var err error + + type ExampleSubPatternJSON ExampleSubPattern + var parseObject ExampleSubPatternJSON + + err = json.Unmarshal(b, &parseObject) + if err != nil { + return validation.Error{err.Error(), fmt.Errorf("ExampleSubPattern.UnmarshalJSON: `%v`: %w", string(b), err)} + } + + v := ExampleSubPattern(parseObject) + + err = v.Validate() + if err != nil { + return err + } + + *p = v + + return nil +} + +func (p ExampleSubPattern) MarshalJSON() ([]byte, error) { + err := p.Validate() + if err != nil { + return nil, err + } + + type unvalidated ExampleSubPattern // Skips the validation check + b, err := json.Marshal(unvalidated(p)) + if err != nil { + return nil, fmt.Errorf("ExampleSubPattern.Marshal: `%+v`: %w", p, err) + } + + return b, nil +} + +func (p ExampleSubPattern) Validate() error { + var err validation.Errors + + p.ValidateNum(&err) + + return err.GetErr() +} + +func (p ExampleSubPattern) ValidateNum(err *validation.Errors) { + if p.Num < 2 { + _ = err.Add("num", "must be >= 2") + } +} + +// []ExampleXarrayEnum +// +// OpenAPI Component Schema: XArrayEnum +type ExampleXarrayEnum []ExampleXarrayEnumItem + +// ExampleXarrayEnumItem +// +// OpenAPI []ExampleXarrayEnum inline item XArrayEnum: XarrayEnumItem + +// ExampleXarrayEnumItem +// []ExampleXarrayEnum inline item XArrayEnum : XarrayEnumItem +type ExampleXarrayEnumItem int8 + +const ( + UnknownExampleXarrayEnumItem ExampleXarrayEnumItem = iota + ExampleXarrayEnumItemOptionA + ExampleXarrayEnumItemOptionB + ExampleXarrayEnumItemOptionC +) + +func NewExampleXarrayEnumItem(name string) ExampleXarrayEnumItem { + switch name { + case "option_a": + return ExampleXarrayEnumItemOptionA + case "option_b": + return ExampleXarrayEnumItemOptionB + case "option_c": + return ExampleXarrayEnumItemOptionC + } + + return ExampleXarrayEnumItem(0) +} + +var ExampleXarrayEnumItemString = map[ExampleXarrayEnumItem]string{ + ExampleXarrayEnumItemOptionA: "option_a", + ExampleXarrayEnumItemOptionB: "option_b", + ExampleXarrayEnumItemOptionC: "option_c", +} + +func (e ExampleXarrayEnumItem) String() string { + return ExampleXarrayEnumItemString[e] +} + +func (e *ExampleXarrayEnumItem) UnmarshalJSON(input []byte) (err error) { + var i int8 + + err = json.Unmarshal(input, &i) + if err == nil { + *e = ExampleXarrayEnumItem(i) + return nil + } + + var s string + + err = json.Unmarshal(input, &s) + if err != nil { + return err + } + + *e = NewExampleXarrayEnumItem(s) + + return nil +} + +func (e ExampleXarrayEnumItem) MarshalJSON() ([]byte, error) { + return json.Marshal(e.String()) +} + +func (e ExampleXarrayEnumItem) Value() (driver.Value, error) { + return json.Marshal(e.String()) +} + +func (e *ExampleXarrayEnumItem) Scan(src any) error { + s, ok := src.(string) + if !ok { + return fmt.Errorf("ExampleXarrayEnumItem.scan: scanned a %T, not []byte", src) //nolint + } + + *e = NewExampleXarrayEnumItem(s) + + return nil +} + +// []ExampleXarrayObjectArrayEnum +// +// OpenAPI Component Schema: XArrayObjectArrayEnum +type ExampleXarrayObjectArrayEnum []ExampleXarrayObjectArrayEnumItem + +// ExampleXarrayObjectArrayEnumItem +// +// OpenAPI []ExampleXarrayObjectArrayEnum inline item XArrayObjectArrayEnum: XarrayObjectArrayEnumItem +type ExampleXarrayObjectArrayEnumItem struct { + List []ExampleXarrayObjectArrayEnumItemList `json:"list,omitempty"` +} + +// ExampleXarrayObjectArrayEnumItemList +// +// OpenAPI ExampleXarrayObjectArrayEnumItem inline item list: XarrayObjectArrayEnumItemList + +// ExampleXarrayObjectArrayEnumItemList +// ExampleXarrayObjectArrayEnumItem inline item list : XarrayObjectArrayEnumItemList +type ExampleXarrayObjectArrayEnumItemList int8 + +const ( + UnknownExampleXarrayObjectArrayEnumItemList ExampleXarrayObjectArrayEnumItemList = iota + ExampleXarrayObjectArrayEnumItemListOptionA + ExampleXarrayObjectArrayEnumItemListOptionB + ExampleXarrayObjectArrayEnumItemListOptionC +) + +func NewExampleXarrayObjectArrayEnumItemList(name string) ExampleXarrayObjectArrayEnumItemList { + switch name { + case "option_a": + return ExampleXarrayObjectArrayEnumItemListOptionA + case "option_b": + return ExampleXarrayObjectArrayEnumItemListOptionB + case "option_c": + return ExampleXarrayObjectArrayEnumItemListOptionC + } + + return ExampleXarrayObjectArrayEnumItemList(0) +} + +var ExampleXarrayObjectArrayEnumItemListString = map[ExampleXarrayObjectArrayEnumItemList]string{ + ExampleXarrayObjectArrayEnumItemListOptionA: "option_a", + ExampleXarrayObjectArrayEnumItemListOptionB: "option_b", + ExampleXarrayObjectArrayEnumItemListOptionC: "option_c", +} + +func (e ExampleXarrayObjectArrayEnumItemList) String() string { + return ExampleXarrayObjectArrayEnumItemListString[e] +} + +func (e *ExampleXarrayObjectArrayEnumItemList) UnmarshalJSON(input []byte) (err error) { + var i int8 + + err = json.Unmarshal(input, &i) + if err == nil { + *e = ExampleXarrayObjectArrayEnumItemList(i) + return nil + } + + var s string + + err = json.Unmarshal(input, &s) + if err != nil { + return err + } + + *e = NewExampleXarrayObjectArrayEnumItemList(s) + + return nil +} + +func (e ExampleXarrayObjectArrayEnumItemList) MarshalJSON() ([]byte, error) { + return json.Marshal(e.String()) +} + +func (e ExampleXarrayObjectArrayEnumItemList) Value() (driver.Value, error) { + return json.Marshal(e.String()) +} + +func (e *ExampleXarrayObjectArrayEnumItemList) Scan(src any) error { + s, ok := src.(string) + if !ok { + return fmt.Errorf("ExampleXarrayObjectArrayEnumItemList.scan: scanned a %T, not []byte", src) //nolint + } + + *e = NewExampleXarrayObjectArrayEnumItemList(s) + + return nil +} + +// []ExampleXarrayObjectEnum +// +// OpenAPI Component Schema: XArrayObjectEnum +type ExampleXarrayObjectEnum []ExampleXarrayObjectEnumItem + +// ExampleXarrayObjectEnumItem +// +// OpenAPI []ExampleXarrayObjectEnum inline item XArrayObjectEnum: XarrayObjectEnumItem +type ExampleXarrayObjectEnumItem struct { + Options ExampleXarrayObjectEnumItemOptions `json:"options,omitempty,omitzero"` +} + +// ExampleXarrayObjectEnumItemOptions +// []ExampleXarrayObjectEnum inline item XArrayObjectEnum : options +type ExampleXarrayObjectEnumItemOptions int8 + +const ( + UnknownExampleXarrayObjectEnumItemOptions ExampleXarrayObjectEnumItemOptions = iota + ExampleXarrayObjectEnumItemOptionsOptionA + ExampleXarrayObjectEnumItemOptionsOptionB + ExampleXarrayObjectEnumItemOptionsOptionC +) + +func NewExampleXarrayObjectEnumItemOptions(name string) ExampleXarrayObjectEnumItemOptions { + switch name { + case "option_a": + return ExampleXarrayObjectEnumItemOptionsOptionA + case "option_b": + return ExampleXarrayObjectEnumItemOptionsOptionB + case "option_c": + return ExampleXarrayObjectEnumItemOptionsOptionC + } + + return ExampleXarrayObjectEnumItemOptions(0) +} + +var ExampleXarrayObjectEnumItemOptionsString = map[ExampleXarrayObjectEnumItemOptions]string{ + ExampleXarrayObjectEnumItemOptionsOptionA: "option_a", + ExampleXarrayObjectEnumItemOptionsOptionB: "option_b", + ExampleXarrayObjectEnumItemOptionsOptionC: "option_c", +} + +func (e ExampleXarrayObjectEnumItemOptions) String() string { + return ExampleXarrayObjectEnumItemOptionsString[e] +} + +func (e *ExampleXarrayObjectEnumItemOptions) UnmarshalJSON(input []byte) (err error) { + var i int8 + + err = json.Unmarshal(input, &i) + if err == nil { + *e = ExampleXarrayObjectEnumItemOptions(i) + return nil + } + + var s string + + err = json.Unmarshal(input, &s) + if err != nil { + return err + } + + *e = NewExampleXarrayObjectEnumItemOptions(s) + + return nil +} + +func (e ExampleXarrayObjectEnumItemOptions) MarshalJSON() ([]byte, error) { + return json.Marshal(e.String()) +} + +func (e ExampleXarrayObjectEnumItemOptions) Value() (driver.Value, error) { + return json.Marshal(e.String()) +} + +func (e *ExampleXarrayObjectEnumItemOptions) Scan(src any) error { + s, ok := src.(string) + if !ok { + return fmt.Errorf("ExampleXarrayObjectEnumItemOptions.scan: scanned a %T, not []byte", src) //nolint + } + + *e = NewExampleXarrayObjectEnumItemOptions(s) + + return nil +} + +// ExampleXobjectArrayEnum +// +// OpenAPI Component Schema: XObjectArrayEnum +type ExampleXobjectArrayEnum struct { + Items []ExampleXobjectArrayEnumItems `json:"items,omitempty"` +} + +// ExampleXobjectArrayEnumItems +// +// OpenAPI ExampleXobjectArrayEnum inline item items: XobjectArrayEnumItems + +// ExampleXobjectArrayEnumItems +// ExampleXobjectArrayEnum inline item items : XobjectArrayEnumItems +type ExampleXobjectArrayEnumItems int8 + +const ( + UnknownExampleXobjectArrayEnumItems ExampleXobjectArrayEnumItems = iota + ExampleXobjectArrayEnumItemsOptionA + ExampleXobjectArrayEnumItemsOptionB + ExampleXobjectArrayEnumItemsOptionC +) + +func NewExampleXobjectArrayEnumItems(name string) ExampleXobjectArrayEnumItems { + switch name { + case "option_a": + return ExampleXobjectArrayEnumItemsOptionA + case "option_b": + return ExampleXobjectArrayEnumItemsOptionB + case "option_c": + return ExampleXobjectArrayEnumItemsOptionC + } + + return ExampleXobjectArrayEnumItems(0) +} + +var ExampleXobjectArrayEnumItemsString = map[ExampleXobjectArrayEnumItems]string{ + ExampleXobjectArrayEnumItemsOptionA: "option_a", + ExampleXobjectArrayEnumItemsOptionB: "option_b", + ExampleXobjectArrayEnumItemsOptionC: "option_c", +} + +func (e ExampleXobjectArrayEnumItems) String() string { + return ExampleXobjectArrayEnumItemsString[e] +} + +func (e *ExampleXobjectArrayEnumItems) UnmarshalJSON(input []byte) (err error) { + var i int8 + + err = json.Unmarshal(input, &i) + if err == nil { + *e = ExampleXobjectArrayEnumItems(i) + return nil + } + + var s string + + err = json.Unmarshal(input, &s) + if err != nil { + return err + } + + *e = NewExampleXobjectArrayEnumItems(s) + + return nil +} + +func (e ExampleXobjectArrayEnumItems) MarshalJSON() ([]byte, error) { + return json.Marshal(e.String()) +} + +func (e ExampleXobjectArrayEnumItems) Value() (driver.Value, error) { + return json.Marshal(e.String()) +} + +func (e *ExampleXobjectArrayEnumItems) Scan(src any) error { + s, ok := src.(string) + if !ok { + return fmt.Errorf("ExampleXobjectArrayEnumItems.scan: scanned a %T, not []byte", src) //nolint + } + + *e = NewExampleXobjectArrayEnumItems(s) + + return nil +} + +// ExampleXobjectArrayObjectEnum +// +// OpenAPI Component Schema: XObjectArrayObjectEnum +type ExampleXobjectArrayObjectEnum struct { + List []ExampleXobjectArrayObjectEnumList `json:"list,omitempty"` +} + +// ExampleXobjectArrayObjectEnumList +// +// OpenAPI ExampleXobjectArrayObjectEnum inline item list: XobjectArrayObjectEnumList +type ExampleXobjectArrayObjectEnumList struct { + Options ExampleXobjectArrayObjectEnumListOptions `json:"options,omitempty,omitzero"` +} + +// ExampleXobjectArrayObjectEnumListOptions +// ExampleXobjectArrayObjectEnum inline item list : options +type ExampleXobjectArrayObjectEnumListOptions int8 + +const ( + UnknownExampleXobjectArrayObjectEnumListOptions ExampleXobjectArrayObjectEnumListOptions = iota + ExampleXobjectArrayObjectEnumListOptionsOptionA + ExampleXobjectArrayObjectEnumListOptionsOptionB + ExampleXobjectArrayObjectEnumListOptionsOptionC +) + +func NewExampleXobjectArrayObjectEnumListOptions(name string) ExampleXobjectArrayObjectEnumListOptions { + switch name { + case "option_a": + return ExampleXobjectArrayObjectEnumListOptionsOptionA + case "option_b": + return ExampleXobjectArrayObjectEnumListOptionsOptionB + case "option_c": + return ExampleXobjectArrayObjectEnumListOptionsOptionC + } + + return ExampleXobjectArrayObjectEnumListOptions(0) +} + +var ExampleXobjectArrayObjectEnumListOptionsString = map[ExampleXobjectArrayObjectEnumListOptions]string{ + ExampleXobjectArrayObjectEnumListOptionsOptionA: "option_a", + ExampleXobjectArrayObjectEnumListOptionsOptionB: "option_b", + ExampleXobjectArrayObjectEnumListOptionsOptionC: "option_c", +} + +func (e ExampleXobjectArrayObjectEnumListOptions) String() string { + return ExampleXobjectArrayObjectEnumListOptionsString[e] +} + +func (e *ExampleXobjectArrayObjectEnumListOptions) UnmarshalJSON(input []byte) (err error) { + var i int8 + + err = json.Unmarshal(input, &i) + if err == nil { + *e = ExampleXobjectArrayObjectEnumListOptions(i) + return nil + } + + var s string + + err = json.Unmarshal(input, &s) + if err != nil { + return err + } + + *e = NewExampleXobjectArrayObjectEnumListOptions(s) + + return nil +} + +func (e ExampleXobjectArrayObjectEnumListOptions) MarshalJSON() ([]byte, error) { + return json.Marshal(e.String()) +} + +func (e ExampleXobjectArrayObjectEnumListOptions) Value() (driver.Value, error) { + return json.Marshal(e.String()) +} + +func (e *ExampleXobjectArrayObjectEnumListOptions) Scan(src any) error { + s, ok := src.(string) + if !ok { + return fmt.Errorf("ExampleXobjectArrayObjectEnumListOptions.scan: scanned a %T, not []byte", src) //nolint + } + + *e = NewExampleXobjectArrayObjectEnumListOptions(s) + + return nil +} + +// ExampleXobjectEnum +// +// OpenAPI Component Schema: XObjectEnum +type ExampleXobjectEnum struct { + Options ExampleXobjectEnumOptions `json:"options,omitempty,omitzero"` +} + +// ExampleXobjectEnumOptions +// Component Schema : options +type ExampleXobjectEnumOptions int8 + +const ( + UnknownExampleXobjectEnumOptions ExampleXobjectEnumOptions = iota + ExampleXobjectEnumOptionsOptionA + ExampleXobjectEnumOptionsOptionB + ExampleXobjectEnumOptionsOptionC +) + +func NewExampleXobjectEnumOptions(name string) ExampleXobjectEnumOptions { + switch name { + case "option_a": + return ExampleXobjectEnumOptionsOptionA + case "option_b": + return ExampleXobjectEnumOptionsOptionB + case "option_c": + return ExampleXobjectEnumOptionsOptionC + } + + return ExampleXobjectEnumOptions(0) +} + +var ExampleXobjectEnumOptionsString = map[ExampleXobjectEnumOptions]string{ + ExampleXobjectEnumOptionsOptionA: "option_a", + ExampleXobjectEnumOptionsOptionB: "option_b", + ExampleXobjectEnumOptionsOptionC: "option_c", +} + +func (e ExampleXobjectEnumOptions) String() string { + return ExampleXobjectEnumOptionsString[e] +} + +func (e *ExampleXobjectEnumOptions) UnmarshalJSON(input []byte) (err error) { + var i int8 + + err = json.Unmarshal(input, &i) + if err == nil { + *e = ExampleXobjectEnumOptions(i) + return nil + } + + var s string + + err = json.Unmarshal(input, &s) + if err != nil { + return err + } + + *e = NewExampleXobjectEnumOptions(s) + + return nil +} + +func (e ExampleXobjectEnumOptions) MarshalJSON() ([]byte, error) { + return json.Marshal(e.String()) +} + +func (e ExampleXobjectEnumOptions) Value() (driver.Value, error) { + return json.Marshal(e.String()) +} + +func (e *ExampleXobjectEnumOptions) Scan(src any) error { + s, ok := src.(string) + if !ok { + return fmt.Errorf("ExampleXobjectEnumOptions.scan: scanned a %T, not []byte", src) //nolint + } + + *e = NewExampleXobjectEnumOptions(s) + + return nil +} + +// ExampleErrorV1 +// Standard error format +// +// OpenAPI Component Schema: errorV1 +type ExampleErrorV1 struct { + Code string `json:"code,omitempty,omitzero"` + Message string `json:"message,omitempty,omitzero"` +} + +// ExampleExampleKebabCaseField +// +// OpenAPI Component Schema: example-kebab-case-field +type ExampleExampleKebabCaseField struct { + Seniority string `json:"seniority,omitempty,omitzero"` + Tier string `json:"tier,omitempty,omitzero"` +} + +var ( + exampleExampleKebabCaseFieldSeniorityPattern = regexp.MustCompile(`(^[1-9]\d*$)`) + exampleExampleKebabCaseFieldTierPattern = regexp.MustCompile(`(alpha|beta|gama)`) +) + +func (p *ExampleExampleKebabCaseField) UnmarshalJSON(b []byte) error { + var err error + + type ExampleExampleKebabCaseFieldJSON ExampleExampleKebabCaseField + var parseObject ExampleExampleKebabCaseFieldJSON + + err = json.Unmarshal(b, &parseObject) + if err != nil { + return validation.Error{err.Error(), fmt.Errorf("ExampleExampleKebabCaseField.UnmarshalJSON: `%v`: %w", string(b), err)} + } + + v := ExampleExampleKebabCaseField(parseObject) + + err = v.Validate() + if err != nil { + return err + } + + *p = v + + return nil +} + +func (p ExampleExampleKebabCaseField) MarshalJSON() ([]byte, error) { + err := p.Validate() + if err != nil { + return nil, err + } + + type unvalidated ExampleExampleKebabCaseField // Skips the validation check + b, err := json.Marshal(unvalidated(p)) + if err != nil { + return nil, fmt.Errorf("ExampleExampleKebabCaseField.Marshal: `%+v`: %w", p, err) + } + + return b, nil +} + +func (p ExampleExampleKebabCaseField) Validate() error { + var err validation.Errors + + p.ValidateSeniority(&err) + p.ValidateTier(&err) + + return err.GetErr() +} + +func (p ExampleExampleKebabCaseField) ValidateSeniority(err *validation.Errors) { + if p.Seniority != "" && !exampleExampleKebabCaseFieldSeniorityPattern.MatchString(string(p.Seniority)) { + _ = err.Add("seniority", `must match "(^[1-9]\d*$)"`) + } +} + +func (p ExampleExampleKebabCaseField) ValidateTier(err *validation.Errors) { + if p.Tier != "" && !exampleExampleKebabCaseFieldTierPattern.MatchString(string(p.Tier)) { + _ = err.Add("tier", `must match "(alpha|beta|gama)"`) + } +} + +// Component Parameters + +// ExampleColorQuery +// Component Parameter: color +type ExampleColorQuery int8 + +const ( + UnknownExampleColorQuery ExampleColorQuery = iota + ExampleColorQueryRed + ExampleColorQueryGreen + ExampleColorQueryBlue +) + +func NewExampleColorQuery(name string) ExampleColorQuery { + switch name { + case "red": + return ExampleColorQueryRed + case "green": + return ExampleColorQueryGreen + case "blue": + return ExampleColorQueryBlue + } + + return ExampleColorQuery(0) +} + +var ExampleColorQueryString = map[ExampleColorQuery]string{ + ExampleColorQueryRed: "red", + ExampleColorQueryGreen: "green", + ExampleColorQueryBlue: "blue", +} + +func (e ExampleColorQuery) String() string { + return ExampleColorQueryString[e] +} + +func (e *ExampleColorQuery) UnmarshalJSON(input []byte) (err error) { + var i int8 + + err = json.Unmarshal(input, &i) + if err == nil { + *e = ExampleColorQuery(i) + return nil + } + + var s string + + err = json.Unmarshal(input, &s) + if err != nil { + return err + } + + *e = NewExampleColorQuery(s) + + return nil +} + +func (e ExampleColorQuery) MarshalJSON() ([]byte, error) { + return json.Marshal(e.String()) +} + +func (e ExampleColorQuery) Value() (driver.Value, error) { + return json.Marshal(e.String()) +} + +func (e *ExampleColorQuery) Scan(src any) error { + s, ok := src.(string) + if !ok { + return fmt.Errorf("ExampleColorQuery.scan: scanned a %T, not []byte", src) //nolint + } + + *e = NewExampleColorQuery(s) + + return nil +} + +// ExampleColorQueryDefault +// Component Parameter: colorDefault +type ExampleColorQueryDefault int8 + +const ( + UnknownExampleColorQueryDefault ExampleColorQueryDefault = iota + ExampleColorQueryDefaultRed + ExampleColorQueryDefaultGreen + ExampleColorQueryDefaultBlue +) + +func NewExampleColorQueryDefault(name string) ExampleColorQueryDefault { + switch name { + case "red": + return ExampleColorQueryDefaultRed + case "green": + return ExampleColorQueryDefaultGreen + case "blue": + return ExampleColorQueryDefaultBlue + } + + return ExampleColorQueryDefault(0) +} + +var ExampleColorQueryDefaultString = map[ExampleColorQueryDefault]string{ + ExampleColorQueryDefaultRed: "red", + ExampleColorQueryDefaultGreen: "green", + ExampleColorQueryDefaultBlue: "blue", +} + +func (e ExampleColorQueryDefault) String() string { + return ExampleColorQueryDefaultString[e] +} + +func (e *ExampleColorQueryDefault) UnmarshalJSON(input []byte) (err error) { + var i int8 + + err = json.Unmarshal(input, &i) + if err == nil { + *e = ExampleColorQueryDefault(i) + return nil + } + + var s string + + err = json.Unmarshal(input, &s) + if err != nil { + return err + } + + *e = NewExampleColorQueryDefault(s) + + return nil +} + +func (e ExampleColorQueryDefault) MarshalJSON() ([]byte, error) { + return json.Marshal(e.String()) +} + +func (e ExampleColorQueryDefault) Value() (driver.Value, error) { + return json.Marshal(e.String()) +} + +func (e *ExampleColorQueryDefault) Scan(src any) error { + s, ok := src.(string) + if !ok { + return fmt.Errorf("ExampleColorQueryDefault.scan: scanned a %T, not []byte", src) //nolint + } + + *e = NewExampleColorQueryDefault(s) + + return nil +} + +// Path Operations + +// ExampleAddFormRequest +// +// OpenAPI AddForm Body: AddForm Request +type ExampleAddFormRequest struct { + F01 bool `json:"f01,omitempty"` + F01Null *bool `json:"f01Null,omitempty"` + F01B bool `json:"f01b,omitempty"` + F01BNull *bool `json:"f01bNull,omitempty"` + F02 int32 `json:"f02,omitempty"` + F02Null *int32 `json:"f02Null,omitempty"` + F03 int32 `json:"f03,omitempty"` + F03Null *int32 `json:"f03Null,omitempty"` + F04 int64 `json:"f04,omitempty"` + F04Null *int64 `json:"f04Null,omitempty"` + F05 time.Time `json:"f05,omitempty,omitzero"` + F05Null *time.Time `json:"f05Null,omitempty,omitzero"` + F06 uuid.UUID `json:"f06,omitempty,omitzero"` + F06Null *uuid.UUID `json:"f06Null,omitempty,omitzero"` + F07 string `json:"f07"` + F07Null *string `json:"f07Null,omitempty,omitzero"` + F08 ExampleAddFormRequestF08 `json:"f08,omitempty,omitzero"` + F08Null *ExampleAddFormRequestF08Null `json:"f08Null,omitempty,omitzero"` + F09 ExampleSeason `json:"f09,omitempty,omitzero"` + F09Null *ExampleSeasonNullable `json:"f09Null,omitempty,omitzero"` + F10 []string `json:"f10,omitempty"` + F11 []int32 `json:"f11,omitempty"` + F12 []ExampleSeason `json:"f12,omitempty"` + F13 string `json:"f13,omitempty,omitzero"` + F13Null *string `json:"f13Null,omitempty,omitzero"` +} + +// ExampleAddFormRequestF08 +// AddForm Body : f08 +type ExampleAddFormRequestF08 int8 + +const ( + UnknownExampleAddFormRequestF08 ExampleAddFormRequestF08 = iota + ExampleAddFormRequestF08ValueA + ExampleAddFormRequestF08ValueB + ExampleAddFormRequestF08ValueC +) + +func NewExampleAddFormRequestF08(name string) ExampleAddFormRequestF08 { + switch name { + case "valueA": + return ExampleAddFormRequestF08ValueA + case "valueB": + return ExampleAddFormRequestF08ValueB + case "valueC": + return ExampleAddFormRequestF08ValueC + } + + return ExampleAddFormRequestF08(0) +} + +var ExampleAddFormRequestF08String = map[ExampleAddFormRequestF08]string{ + ExampleAddFormRequestF08ValueA: "valueA", + ExampleAddFormRequestF08ValueB: "valueB", + ExampleAddFormRequestF08ValueC: "valueC", +} + +func (e ExampleAddFormRequestF08) String() string { + return ExampleAddFormRequestF08String[e] +} + +func (e *ExampleAddFormRequestF08) UnmarshalJSON(input []byte) (err error) { + var i int8 + + err = json.Unmarshal(input, &i) + if err == nil { + *e = ExampleAddFormRequestF08(i) + return nil + } + + var s string + + err = json.Unmarshal(input, &s) + if err != nil { + return err + } + + *e = NewExampleAddFormRequestF08(s) + + return nil +} + +func (e ExampleAddFormRequestF08) MarshalJSON() ([]byte, error) { + return json.Marshal(e.String()) +} + +func (e ExampleAddFormRequestF08) Value() (driver.Value, error) { + return json.Marshal(e.String()) +} + +func (e *ExampleAddFormRequestF08) Scan(src any) error { + s, ok := src.(string) + if !ok { + return fmt.Errorf("ExampleAddFormRequestF08.scan: scanned a %T, not []byte", src) //nolint + } + + *e = NewExampleAddFormRequestF08(s) + + return nil +} + +// ExampleAddFormRequestF08Null +// AddForm Body : f08Null +type ExampleAddFormRequestF08Null int8 + +const ( + UnknownExampleAddFormRequestF08Null ExampleAddFormRequestF08Null = iota + ExampleAddFormRequestF08NullValueA + ExampleAddFormRequestF08NullValueB + ExampleAddFormRequestF08NullValueC +) + +func NewExampleAddFormRequestF08Null(name string) ExampleAddFormRequestF08Null { + switch name { + case "valueA": + return ExampleAddFormRequestF08NullValueA + case "valueB": + return ExampleAddFormRequestF08NullValueB + case "valueC": + return ExampleAddFormRequestF08NullValueC + } + + return ExampleAddFormRequestF08Null(0) +} + +var ExampleAddFormRequestF08NullString = map[ExampleAddFormRequestF08Null]string{ + ExampleAddFormRequestF08NullValueA: "valueA", + ExampleAddFormRequestF08NullValueB: "valueB", + ExampleAddFormRequestF08NullValueC: "valueC", +} + +func (e ExampleAddFormRequestF08Null) String() string { + return ExampleAddFormRequestF08NullString[e] +} + +func (e *ExampleAddFormRequestF08Null) UnmarshalJSON(input []byte) (err error) { + var i int8 + + err = json.Unmarshal(input, &i) + if err == nil { + *e = ExampleAddFormRequestF08Null(i) + return nil + } + + var s string + + err = json.Unmarshal(input, &s) + if err != nil { + return err + } + + *e = NewExampleAddFormRequestF08Null(s) + + return nil +} + +func (e ExampleAddFormRequestF08Null) MarshalJSON() ([]byte, error) { + return json.Marshal(e.String()) +} + +func (e ExampleAddFormRequestF08Null) Value() (driver.Value, error) { + return json.Marshal(e.String()) +} + +func (e *ExampleAddFormRequestF08Null) Scan(src any) error { + s, ok := src.(string) + if !ok { + return fmt.Errorf("ExampleAddFormRequestF08Null.scan: scanned a %T, not []byte", src) //nolint + } + + *e = NewExampleAddFormRequestF08Null(s) + + return nil +} + +func ParseFormExampleAddFormRequest(r *http.Request) (ExampleAddFormRequest, error) { + var ( + parseErrors validation.Errors + err error + v ExampleAddFormRequest + ) + + paramF01, ok, err := forms.GetBool(r.FormValue, "f01", false) + if err != nil { + parseErrors.Add("f01", err) + } else if ok { + v.F01 = paramF01 + } + + paramF01Null, ok, err := forms.GetBool(r.FormValue, "f01Null", false) + if err != nil { + parseErrors.Add("f01Null", err) + } else if ok { + v.F01Null = ¶mF01Null + } + + paramF01B, ok, err := forms.GetBool(r.FormValue, "f01b", false) + if err != nil { + parseErrors.Add("f01b", err) + } else if !ok { + paramF01B = true + } + + v.F01B = paramF01B + + paramF01BNull, ok, err := forms.GetBool(r.FormValue, "f01bNull", false) + if err != nil { + parseErrors.Add("f01bNull", err) + } else if !ok { + paramF01BNull = true + } + + v.F01BNull = ¶mF01BNull + + paramF02, ok, err := forms.GetInt32(r.FormValue, "f02", false) + if err != nil { + parseErrors.Add("f02", err) + } else if ok { + v.F02 = paramF02 + } + + paramF02Null, ok, err := forms.GetInt32(r.FormValue, "f02Null", false) + if err != nil { + parseErrors.Add("f02Null", err) + } else if ok { + v.F02Null = ¶mF02Null + } + + paramF03, ok, err := forms.GetInt32(r.FormValue, "f03", false) + if err != nil { + parseErrors.Add("f03", err) + } else if ok { + v.F03 = paramF03 + } + + paramF03Null, ok, err := forms.GetInt32(r.FormValue, "f03Null", false) + if err != nil { + parseErrors.Add("f03Null", err) + } else if ok { + v.F03Null = ¶mF03Null + } + + paramF04, ok, err := forms.GetInt64(r.FormValue, "f04", false) + if err != nil { + parseErrors.Add("f04", err) + } else if !ok { + paramF04 = 1 + } + + v.F04 = paramF04 + + paramF04Null, ok, err := forms.GetInt64(r.FormValue, "f04Null", false) + if err != nil { + parseErrors.Add("f04Null", err) + } else if !ok { + paramF04Null = 2 + } + + v.F04Null = ¶mF04Null + + paramF05, ok, err := forms.GetTime(r.FormValue, "f05", false) + if err != nil { + parseErrors.Add("f05", err) + } else if ok { + v.F05 = paramF05 + } + + paramF05Null, ok, err := forms.GetTime(r.FormValue, "f05Null", false) + if err != nil { + parseErrors.Add("f05Null", err) + } else if ok { + v.F05Null = ¶mF05Null + } + + paramF06, ok, err := forms.GetUUID(r.FormValue, "f06", false) + if err != nil { + parseErrors.Add("f06", err) + } else if ok { + v.F06 = paramF06 + } + + paramF06Null, ok, err := forms.GetUUID(r.FormValue, "f06Null", false) + if err != nil { + parseErrors.Add("f06Null", err) + } else if ok { + v.F06Null = ¶mF06Null + } + + paramF07, ok, err := forms.GetString(r.FormValue, "f07", true) + if err != nil { + parseErrors.Add("f07", err) + } else if ok { + v.F07 = paramF07 + } + + paramF07Null, ok, err := forms.GetString(r.FormValue, "f07Null", false) + if err != nil { + parseErrors.Add("f07Null", err) + } else if ok { + v.F07Null = ¶mF07Null + } + + paramF08, ok, err := forms.GetEnum(r.FormValue, "f08", false, NewExampleAddFormRequestF08) + if err != nil { + parseErrors.Add("f08", err) + } else if !ok { + paramF08 = ExampleAddFormRequestF08ValueA + } + + v.F08 = paramF08 + + paramF08Null, ok, err := forms.GetEnum(r.FormValue, "f08Null", false, NewExampleAddFormRequestF08Null) + if err != nil { + parseErrors.Add("f08Null", err) + } else if !ok { + paramF08Null = ExampleAddFormRequestF08NullValueB + } + + v.F08Null = ¶mF08Null + + paramF09, ok, err := forms.GetEnum(r.FormValue, "f09", false, NewExampleSeason) + if err != nil { + parseErrors.Add("f09", err) + } else if ok { + v.F09 = paramF09 + } + + paramF09Null, ok, err := forms.GetEnum(r.FormValue, "f09Null", false, NewExampleSeasonNullable) + if err != nil { + parseErrors.Add("f09Null", err) + } else if ok { + v.F09Null = ¶mF09Null + } + + v.F10, _, err = forms.GetStringArray(r.FormValue, "f10", false) + if err != nil { + parseErrors.Add("f10", err) + } + + v.F11, _, err = forms.GetInt32Array(r.FormValue, "f11", false) + if err != nil { + parseErrors.Add("f11", err) + } + + v.F12, _, err = forms.GetEnumArray(r.FormValue, "f12", false, NewExampleSeason) + if err != nil { + parseErrors.Add("f12", err) + } + + paramF13, ok, err := forms.GetString(r.FormValue, "f13", false) + if err != nil { + parseErrors.Add("f13", err) + } else if !ok { + paramF13 = "someValue" + } + + v.F13 = paramF13 + + paramF13Null, ok, err := forms.GetString(r.FormValue, "f13Null", false) + if err != nil { + parseErrors.Add("f13Null", err) + } else if !ok { + paramF13Null = "someValue2" + } + + v.F13Null = ¶mF13Null + + if parseErrors != nil { + return ExampleAddFormRequest{}, parseErrors.GetErr() + } + + err = v.Validate() + if err != nil { + return ExampleAddFormRequest{}, err + } + + return v, nil +} + +func (p ExampleAddFormRequest) Validate() error { + var err validation.Errors + + p.ValidateF10(&err) + + return err.GetErr() +} + +func (p ExampleAddFormRequest) ValidateF10(err *validation.Errors) { + if len(p.F10) < 1 { + _ = err.Add("f10", "length must be >= 1") + } +} + +// ExampleAddMultipartFormRequest +// +// OpenAPI AddMultipartForm Body: AddMultipartForm Request +type ExampleAddMultipartFormRequest struct { + F1 bool `json:"f1,omitempty"` + F2 int32 `json:"f2,omitempty"` + F3 int32 `json:"f3,omitempty"` + F4 int64 `json:"f4,omitempty"` + F5 time.Time `json:"f5,omitempty,omitzero"` + F6 uuid.UUID `json:"f6,omitempty,omitzero"` + F7 string `json:"f7,omitempty,omitzero"` + File1 forms.File `json:"file1"` + File2 forms.File `json:"file2,omitempty,omitzero"` +} + +func ParseFormExampleAddMultipartFormRequest(r *http.Request) (ExampleAddMultipartFormRequest, error) { + var ( + parseErrors validation.Errors + err error + v ExampleAddMultipartFormRequest + ) + + paramF1, ok, err := forms.GetBool(r.FormValue, "f1", false) + if err != nil { + parseErrors.Add("f1", err) + } else if ok { + v.F1 = paramF1 + } + + paramF2, ok, err := forms.GetInt32(r.FormValue, "f2", false) + if err != nil { + parseErrors.Add("f2", err) + } else if ok { + v.F2 = paramF2 + } + + paramF3, ok, err := forms.GetInt32(r.FormValue, "f3", false) + if err != nil { + parseErrors.Add("f3", err) + } else if ok { + v.F3 = paramF3 + } + + paramF4, ok, err := forms.GetInt64(r.FormValue, "f4", false) + if err != nil { + parseErrors.Add("f4", err) + } else if ok { + v.F4 = paramF4 + } + + paramF5, ok, err := forms.GetTime(r.FormValue, "f5", false) + if err != nil { + parseErrors.Add("f5", err) + } else if ok { + v.F5 = paramF5 + } + + paramF6, ok, err := forms.GetUUID(r.FormValue, "f6", false) + if err != nil { + parseErrors.Add("f6", err) + } else if ok { + v.F6 = paramF6 + } + + paramF7, ok, err := forms.GetString(r.FormValue, "f7", false) + if err != nil { + parseErrors.Add("f7", err) + } else if ok { + v.F7 = paramF7 + } + + paramFile1, ok, err := forms.GetFile(r, "file1", true) + if err != nil { + parseErrors.Add("file1", err) + } else if ok { + v.File1 = paramFile1 + } + + paramFile2, ok, err := forms.GetFile(r, "file2", false) + if err != nil { + parseErrors.Add("file2", err) + } else if ok { + v.File2 = paramFile2 + } + + if parseErrors != nil { + return ExampleAddMultipartFormRequest{}, parseErrors.GetErr() + } + + return v, nil +} + +// ExampleAddInlinedAllOfRequest +// +// OpenAPI AddInlinedAllOf Body: AddInlinedAllOf Request +type ExampleAddInlinedAllOfRequest struct { + Foos ExampleFooString `json:"foos,omitempty,omitzero"` + Special bool `json:"special,omitempty"` +} + +func (p *ExampleAddInlinedAllOfRequest) UnmarshalJSON(b []byte) error { + var err error + + type ExampleAddInlinedAllOfRequestJSON ExampleAddInlinedAllOfRequest + var parseObject ExampleAddInlinedAllOfRequestJSON + + err = json.Unmarshal(b, &parseObject) + if err != nil { + return validation.Error{err.Error(), fmt.Errorf("ExampleAddInlinedAllOfRequest.UnmarshalJSON: `%v`: %w", string(b), err)} + } + + v := ExampleAddInlinedAllOfRequest(parseObject) + + err = v.Validate() + if err != nil { + return err + } + + *p = v + + return nil +} + +func (p ExampleAddInlinedAllOfRequest) MarshalJSON() ([]byte, error) { + err := p.Validate() + if err != nil { + return nil, err + } + + type unvalidated ExampleAddInlinedAllOfRequest // Skips the validation check + b, err := json.Marshal(unvalidated(p)) + if err != nil { + return nil, fmt.Errorf("ExampleAddInlinedAllOfRequest.Marshal: `%+v`: %w", p, err) + } + + return b, nil +} + +func (p ExampleAddInlinedAllOfRequest) Validate() error { + var err validation.Errors + + p.ValidateFoos(&err) + + return err.GetErr() +} + +func (p ExampleAddInlinedAllOfRequest) ValidateFoos(err *validation.Errors) { + if subErr := p.Foos.Validate(); subErr != nil { + _ = err.Add("foos", subErr) + } +} + +// ExampleAddInlinedBodyRequest +// +// OpenAPI AddInlinedBody Body: AddInlinedBody Request +type ExampleAddInlinedBodyRequest struct { + F01 bool `json:"f01,omitempty"` + F01Null *bool `json:"f01Null,omitempty"` + F01B bool `json:"f01b,omitempty"` + F01BNull *bool `json:"f01bNull,omitempty"` + F02 int32 `json:"f02,omitempty"` + F02Null *int32 `json:"f02Null,omitempty"` + F03 int32 `json:"f03,omitempty"` + F03Null *int32 `json:"f03Null,omitempty"` + F04 int64 `json:"f04,omitempty"` + F04Null *int64 `json:"f04Null,omitempty"` + F05 time.Time `json:"f05,omitempty,omitzero"` + F05Null *time.Time `json:"f05Null,omitempty,omitzero"` + F06 uuid.UUID `json:"f06,omitempty,omitzero"` + F06Null *uuid.UUID `json:"f06Null,omitempty,omitzero"` + F07 string `json:"f07"` + F07Null *string `json:"f07Null,omitempty,omitzero"` + F08 ExampleAddInlinedBodyRequestF08 `json:"f08,omitempty,omitzero"` + F08Null *ExampleAddInlinedBodyRequestF08Null `json:"f08Null,omitempty,omitzero"` + F09 ExampleSeason `json:"f09,omitempty,omitzero"` + F09Null *ExampleSeasonNullable `json:"f09Null,omitempty,omitzero"` + F10 []string `json:"f10"` + F11 []int32 `json:"f11,omitempty"` + F12 []ExampleSeason `json:"f12,omitempty"` + F13 string `json:"f13,omitempty,omitzero"` + F13Null *string `json:"f13Null,omitempty,omitzero"` +} + +// ExampleAddInlinedBodyRequestF08 +// AddInlinedBody Body : f08 +type ExampleAddInlinedBodyRequestF08 int8 + +const ( + UnknownExampleAddInlinedBodyRequestF08 ExampleAddInlinedBodyRequestF08 = iota + ExampleAddInlinedBodyRequestF08ValueA + ExampleAddInlinedBodyRequestF08ValueB + ExampleAddInlinedBodyRequestF08ValueC +) + +func NewExampleAddInlinedBodyRequestF08(name string) ExampleAddInlinedBodyRequestF08 { + switch name { + case "valueA": + return ExampleAddInlinedBodyRequestF08ValueA + case "valueB": + return ExampleAddInlinedBodyRequestF08ValueB + case "valueC": + return ExampleAddInlinedBodyRequestF08ValueC + } + + return ExampleAddInlinedBodyRequestF08(0) +} + +var ExampleAddInlinedBodyRequestF08String = map[ExampleAddInlinedBodyRequestF08]string{ + ExampleAddInlinedBodyRequestF08ValueA: "valueA", + ExampleAddInlinedBodyRequestF08ValueB: "valueB", + ExampleAddInlinedBodyRequestF08ValueC: "valueC", +} + +func (e ExampleAddInlinedBodyRequestF08) String() string { + return ExampleAddInlinedBodyRequestF08String[e] +} + +func (e *ExampleAddInlinedBodyRequestF08) UnmarshalJSON(input []byte) (err error) { + var i int8 + + err = json.Unmarshal(input, &i) + if err == nil { + *e = ExampleAddInlinedBodyRequestF08(i) + return nil + } + + var s string + + err = json.Unmarshal(input, &s) + if err != nil { + return err + } + + *e = NewExampleAddInlinedBodyRequestF08(s) + + return nil +} + +func (e ExampleAddInlinedBodyRequestF08) MarshalJSON() ([]byte, error) { + return json.Marshal(e.String()) +} + +func (e ExampleAddInlinedBodyRequestF08) Value() (driver.Value, error) { + return json.Marshal(e.String()) +} + +func (e *ExampleAddInlinedBodyRequestF08) Scan(src any) error { + s, ok := src.(string) + if !ok { + return fmt.Errorf("ExampleAddInlinedBodyRequestF08.scan: scanned a %T, not []byte", src) //nolint + } + + *e = NewExampleAddInlinedBodyRequestF08(s) + + return nil +} + +// ExampleAddInlinedBodyRequestF08Null +// AddInlinedBody Body : f08Null +type ExampleAddInlinedBodyRequestF08Null int8 + +const ( + UnknownExampleAddInlinedBodyRequestF08Null ExampleAddInlinedBodyRequestF08Null = iota + ExampleAddInlinedBodyRequestF08NullValueA + ExampleAddInlinedBodyRequestF08NullValueB + ExampleAddInlinedBodyRequestF08NullValueC +) + +func NewExampleAddInlinedBodyRequestF08Null(name string) ExampleAddInlinedBodyRequestF08Null { + switch name { + case "valueA": + return ExampleAddInlinedBodyRequestF08NullValueA + case "valueB": + return ExampleAddInlinedBodyRequestF08NullValueB + case "valueC": + return ExampleAddInlinedBodyRequestF08NullValueC + } + + return ExampleAddInlinedBodyRequestF08Null(0) +} + +var ExampleAddInlinedBodyRequestF08NullString = map[ExampleAddInlinedBodyRequestF08Null]string{ + ExampleAddInlinedBodyRequestF08NullValueA: "valueA", + ExampleAddInlinedBodyRequestF08NullValueB: "valueB", + ExampleAddInlinedBodyRequestF08NullValueC: "valueC", +} + +func (e ExampleAddInlinedBodyRequestF08Null) String() string { + return ExampleAddInlinedBodyRequestF08NullString[e] +} + +func (e *ExampleAddInlinedBodyRequestF08Null) UnmarshalJSON(input []byte) (err error) { + var i int8 + + err = json.Unmarshal(input, &i) + if err == nil { + *e = ExampleAddInlinedBodyRequestF08Null(i) + return nil + } + + var s string + + err = json.Unmarshal(input, &s) + if err != nil { + return err + } + + *e = NewExampleAddInlinedBodyRequestF08Null(s) + + return nil +} + +func (e ExampleAddInlinedBodyRequestF08Null) MarshalJSON() ([]byte, error) { + return json.Marshal(e.String()) +} + +func (e ExampleAddInlinedBodyRequestF08Null) Value() (driver.Value, error) { + return json.Marshal(e.String()) +} + +func (e *ExampleAddInlinedBodyRequestF08Null) Scan(src any) error { + s, ok := src.(string) + if !ok { + return fmt.Errorf("ExampleAddInlinedBodyRequestF08Null.scan: scanned a %T, not []byte", src) //nolint + } + + *e = NewExampleAddInlinedBodyRequestF08Null(s) + + return nil +} + +func (p *ExampleAddInlinedBodyRequest) UnmarshalJSON(b []byte) error { + var err error + var requiredCheck map[string]any + + err = json.Unmarshal(b, &requiredCheck) + if err != nil { + return validation.Error{err.Error(), fmt.Errorf("ExampleAddInlinedBodyRequest.UnmarshalJSON Required: `%v`: %w", string(b), err)} + } + + var validationErrors validation.Errors + + if _, ok := requiredCheck["f07"]; !ok { + validationErrors.Add("f07", ErrExampleMissingRequiredField) + } + + if _, ok := requiredCheck["f10"]; !ok { + validationErrors.Add("f10", ErrExampleMissingRequiredField) + } + + if validationErrors != nil { + return validationErrors.GetErr() + } + + type ExampleAddInlinedBodyRequestJSON ExampleAddInlinedBodyRequest + var parseObject ExampleAddInlinedBodyRequestJSON + + err = json.Unmarshal(b, &parseObject) + if err != nil { + return validation.Error{err.Error(), fmt.Errorf("ExampleAddInlinedBodyRequest.UnmarshalJSON: `%v`: %w", string(b), err)} + } + + v := ExampleAddInlinedBodyRequest(parseObject) + + if _, ok := requiredCheck["f01b"]; !ok { + v.F01B = true + } + + if _, ok := requiredCheck["f01bNull"]; !ok { + var defaultVal bool = true + v.F01BNull = &defaultVal + } + + if _, ok := requiredCheck["f04"]; !ok { + v.F04 = 1 + } + + if _, ok := requiredCheck["f04Null"]; !ok { + var defaultVal int64 = 2 + v.F04Null = &defaultVal + } + + if _, ok := requiredCheck["f08"]; !ok { + v.F08 = ExampleAddInlinedBodyRequestF08ValueA + } + + if _, ok := requiredCheck["f08Null"]; !ok { + defaultVal := ExampleAddInlinedBodyRequestF08NullValueB + v.F08Null = &defaultVal + } + + if _, ok := requiredCheck["f13"]; !ok { + v.F13 = "someValue" + } + + if _, ok := requiredCheck["f13Null"]; !ok { + var defaultVal string = "someValue2" + v.F13Null = &defaultVal + } + + err = v.Validate() + if err != nil { + return err + } + + *p = v + + return nil +} + +func (p ExampleAddInlinedBodyRequest) MarshalJSON() ([]byte, error) { + err := p.Validate() + if err != nil { + return nil, err + } + + type unvalidated ExampleAddInlinedBodyRequest // Skips the validation check + b, err := json.Marshal(unvalidated(p)) + if err != nil { + return nil, fmt.Errorf("ExampleAddInlinedBodyRequest.Marshal: `%+v`: %w", p, err) + } + + return b, nil +} + +func (p ExampleAddInlinedBodyRequest) Validate() error { + var err validation.Errors + + p.ValidateF10(&err) + + return err.GetErr() +} + +func (p ExampleAddInlinedBodyRequest) ValidateF10(err *validation.Errors) { + if len(p.F10) < 1 { + _ = err.Add("f10", "length must be >= 1") + } +} + +// ExampleGetExampleParamsEnumTest +// Enum Description +// Op: getExampleParams Param: enumTest +type ExampleGetExampleParamsEnumTest int8 + +const ( + UnknownExampleGetExampleParamsEnumTest ExampleGetExampleParamsEnumTest = iota + ExampleGetExampleParamsEnumTestValueA + ExampleGetExampleParamsEnumTestValueB +) + +func NewExampleGetExampleParamsEnumTest(name string) ExampleGetExampleParamsEnumTest { + switch name { + case "valueA": + return ExampleGetExampleParamsEnumTestValueA + case "valueB": + return ExampleGetExampleParamsEnumTestValueB + } + + return ExampleGetExampleParamsEnumTest(0) +} + +var ExampleGetExampleParamsEnumTestString = map[ExampleGetExampleParamsEnumTest]string{ + ExampleGetExampleParamsEnumTestValueA: "valueA", + ExampleGetExampleParamsEnumTestValueB: "valueB", +} + +func (e ExampleGetExampleParamsEnumTest) String() string { + return ExampleGetExampleParamsEnumTestString[e] +} + +func (e *ExampleGetExampleParamsEnumTest) UnmarshalJSON(input []byte) (err error) { + var i int8 + + err = json.Unmarshal(input, &i) + if err == nil { + *e = ExampleGetExampleParamsEnumTest(i) + return nil + } + + var s string + + err = json.Unmarshal(input, &s) + if err != nil { + return err + } + + *e = NewExampleGetExampleParamsEnumTest(s) + + return nil +} + +func (e ExampleGetExampleParamsEnumTest) MarshalJSON() ([]byte, error) { + return json.Marshal(e.String()) +} + +func (e ExampleGetExampleParamsEnumTest) Value() (driver.Value, error) { + return json.Marshal(e.String()) +} + +func (e *ExampleGetExampleParamsEnumTest) Scan(src any) error { + s, ok := src.(string) + if !ok { + return fmt.Errorf("ExampleGetExampleParamsEnumTest.scan: scanned a %T, not []byte", src) //nolint + } + + *e = NewExampleGetExampleParamsEnumTest(s) + + return nil +} + +// ExampleGetRawRequestVehicle +// Op: getRawRequest Param: vehicle +type ExampleGetRawRequestVehicle int8 + +const ( + UnknownExampleGetRawRequestVehicle ExampleGetRawRequestVehicle = iota + ExampleGetRawRequestVehicleCar + ExampleGetRawRequestVehicleTruck + ExampleGetRawRequestVehicleBike +) + +func NewExampleGetRawRequestVehicle(name string) ExampleGetRawRequestVehicle { + switch name { + case "car": + return ExampleGetRawRequestVehicleCar + case "truck": + return ExampleGetRawRequestVehicleTruck + case "bike": + return ExampleGetRawRequestVehicleBike + } + + return ExampleGetRawRequestVehicle(0) +} + +var ExampleGetRawRequestVehicleString = map[ExampleGetRawRequestVehicle]string{ + ExampleGetRawRequestVehicleCar: "car", + ExampleGetRawRequestVehicleTruck: "truck", + ExampleGetRawRequestVehicleBike: "bike", +} + +func (e ExampleGetRawRequestVehicle) String() string { + return ExampleGetRawRequestVehicleString[e] +} + +func (e *ExampleGetRawRequestVehicle) UnmarshalJSON(input []byte) (err error) { + var i int8 + + err = json.Unmarshal(input, &i) + if err == nil { + *e = ExampleGetRawRequestVehicle(i) + return nil + } + + var s string + + err = json.Unmarshal(input, &s) + if err != nil { + return err + } + + *e = NewExampleGetRawRequestVehicle(s) + + return nil +} + +func (e ExampleGetRawRequestVehicle) MarshalJSON() ([]byte, error) { + return json.Marshal(e.String()) +} + +func (e ExampleGetRawRequestVehicle) Value() (driver.Value, error) { + return json.Marshal(e.String()) +} + +func (e *ExampleGetRawRequestVehicle) Scan(src any) error { + s, ok := src.(string) + if !ok { + return fmt.Errorf("ExampleGetRawRequestVehicle.scan: scanned a %T, not []byte", src) //nolint + } + + *e = NewExampleGetRawRequestVehicle(s) + + return nil +} + +// ExampleGetRawRequestResponseVehicle +// Op: getRawRequestResponse Param: vehicle +type ExampleGetRawRequestResponseVehicle int8 + +const ( + UnknownExampleGetRawRequestResponseVehicle ExampleGetRawRequestResponseVehicle = iota + ExampleGetRawRequestResponseVehicleCar + ExampleGetRawRequestResponseVehicleTruck + ExampleGetRawRequestResponseVehicleBike +) + +func NewExampleGetRawRequestResponseVehicle(name string) ExampleGetRawRequestResponseVehicle { + switch name { + case "car": + return ExampleGetRawRequestResponseVehicleCar + case "truck": + return ExampleGetRawRequestResponseVehicleTruck + case "bike": + return ExampleGetRawRequestResponseVehicleBike + } + + return ExampleGetRawRequestResponseVehicle(0) +} + +var ExampleGetRawRequestResponseVehicleString = map[ExampleGetRawRequestResponseVehicle]string{ + ExampleGetRawRequestResponseVehicleCar: "car", + ExampleGetRawRequestResponseVehicleTruck: "truck", + ExampleGetRawRequestResponseVehicleBike: "bike", +} + +func (e ExampleGetRawRequestResponseVehicle) String() string { + return ExampleGetRawRequestResponseVehicleString[e] +} + +func (e *ExampleGetRawRequestResponseVehicle) UnmarshalJSON(input []byte) (err error) { + var i int8 + + err = json.Unmarshal(input, &i) + if err == nil { + *e = ExampleGetRawRequestResponseVehicle(i) + return nil + } + + var s string + + err = json.Unmarshal(input, &s) + if err != nil { + return err + } + + *e = NewExampleGetRawRequestResponseVehicle(s) + + return nil +} + +func (e ExampleGetRawRequestResponseVehicle) MarshalJSON() ([]byte, error) { + return json.Marshal(e.String()) +} + +func (e ExampleGetRawRequestResponseVehicle) Value() (driver.Value, error) { + return json.Marshal(e.String()) +} + +func (e *ExampleGetRawRequestResponseVehicle) Scan(src any) error { + s, ok := src.(string) + if !ok { + return fmt.Errorf("ExampleGetRawRequestResponseVehicle.scan: scanned a %T, not []byte", src) //nolint + } + + *e = NewExampleGetRawRequestResponseVehicle(s) + + return nil +} + +// ExampleGetRawRequestResponseAndHeadersVehicle +// Op: getRawRequestResponseAndHeaders Param: vehicle +type ExampleGetRawRequestResponseAndHeadersVehicle int8 + +const ( + UnknownExampleGetRawRequestResponseAndHeadersVehicle ExampleGetRawRequestResponseAndHeadersVehicle = iota + ExampleGetRawRequestResponseAndHeadersVehicleCar + ExampleGetRawRequestResponseAndHeadersVehicleTruck + ExampleGetRawRequestResponseAndHeadersVehicleBike +) + +func NewExampleGetRawRequestResponseAndHeadersVehicle(name string) ExampleGetRawRequestResponseAndHeadersVehicle { + switch name { + case "car": + return ExampleGetRawRequestResponseAndHeadersVehicleCar + case "truck": + return ExampleGetRawRequestResponseAndHeadersVehicleTruck + case "bike": + return ExampleGetRawRequestResponseAndHeadersVehicleBike + } + + return ExampleGetRawRequestResponseAndHeadersVehicle(0) +} + +var ExampleGetRawRequestResponseAndHeadersVehicleString = map[ExampleGetRawRequestResponseAndHeadersVehicle]string{ + ExampleGetRawRequestResponseAndHeadersVehicleCar: "car", + ExampleGetRawRequestResponseAndHeadersVehicleTruck: "truck", + ExampleGetRawRequestResponseAndHeadersVehicleBike: "bike", +} + +func (e ExampleGetRawRequestResponseAndHeadersVehicle) String() string { + return ExampleGetRawRequestResponseAndHeadersVehicleString[e] +} + +func (e *ExampleGetRawRequestResponseAndHeadersVehicle) UnmarshalJSON(input []byte) (err error) { + var i int8 + + err = json.Unmarshal(input, &i) + if err == nil { + *e = ExampleGetRawRequestResponseAndHeadersVehicle(i) + return nil + } + + var s string + + err = json.Unmarshal(input, &s) + if err != nil { + return err + } + + *e = NewExampleGetRawRequestResponseAndHeadersVehicle(s) + + return nil +} + +func (e ExampleGetRawRequestResponseAndHeadersVehicle) MarshalJSON() ([]byte, error) { + return json.Marshal(e.String()) +} + +func (e ExampleGetRawRequestResponseAndHeadersVehicle) Value() (driver.Value, error) { + return json.Marshal(e.String()) +} + +func (e *ExampleGetRawRequestResponseAndHeadersVehicle) Scan(src any) error { + s, ok := src.(string) + if !ok { + return fmt.Errorf("ExampleGetRawRequestResponseAndHeadersVehicle.scan: scanned a %T, not []byte", src) //nolint + } + + *e = NewExampleGetRawRequestResponseAndHeadersVehicle(s) + + return nil +} + +// ExampleGetRawResponseVehicle +// Op: getRawResponse Param: vehicle +type ExampleGetRawResponseVehicle int8 + +const ( + UnknownExampleGetRawResponseVehicle ExampleGetRawResponseVehicle = iota + ExampleGetRawResponseVehicleCar + ExampleGetRawResponseVehicleTruck + ExampleGetRawResponseVehicleBike +) + +func NewExampleGetRawResponseVehicle(name string) ExampleGetRawResponseVehicle { + switch name { + case "car": + return ExampleGetRawResponseVehicleCar + case "truck": + return ExampleGetRawResponseVehicleTruck + case "bike": + return ExampleGetRawResponseVehicleBike + } + + return ExampleGetRawResponseVehicle(0) +} + +var ExampleGetRawResponseVehicleString = map[ExampleGetRawResponseVehicle]string{ + ExampleGetRawResponseVehicleCar: "car", + ExampleGetRawResponseVehicleTruck: "truck", + ExampleGetRawResponseVehicleBike: "bike", +} + +func (e ExampleGetRawResponseVehicle) String() string { + return ExampleGetRawResponseVehicleString[e] +} + +func (e *ExampleGetRawResponseVehicle) UnmarshalJSON(input []byte) (err error) { + var i int8 + + err = json.Unmarshal(input, &i) + if err == nil { + *e = ExampleGetRawResponseVehicle(i) + return nil + } + + var s string + + err = json.Unmarshal(input, &s) + if err != nil { + return err + } + + *e = NewExampleGetRawResponseVehicle(s) + + return nil +} + +func (e ExampleGetRawResponseVehicle) MarshalJSON() ([]byte, error) { + return json.Marshal(e.String()) +} + +func (e ExampleGetRawResponseVehicle) Value() (driver.Value, error) { + return json.Marshal(e.String()) +} + +func (e *ExampleGetRawResponseVehicle) Scan(src any) error { + s, ok := src.(string) + if !ok { + return fmt.Errorf("ExampleGetRawResponseVehicle.scan: scanned a %T, not []byte", src) //nolint + } + + *e = NewExampleGetRawResponseVehicle(s) + + return nil +} + +// ExampleGetTestVehicle +// Op: getTest Param: vehicle +type ExampleGetTestVehicle int8 + +const ( + UnknownExampleGetTestVehicle ExampleGetTestVehicle = iota + ExampleGetTestVehicleCar + ExampleGetTestVehicleTruck + ExampleGetTestVehicleBike +) + +func NewExampleGetTestVehicle(name string) ExampleGetTestVehicle { + switch name { + case "car": + return ExampleGetTestVehicleCar + case "truck": + return ExampleGetTestVehicleTruck + case "bike": + return ExampleGetTestVehicleBike + } + + return ExampleGetTestVehicle(0) +} + +var ExampleGetTestVehicleString = map[ExampleGetTestVehicle]string{ + ExampleGetTestVehicleCar: "car", + ExampleGetTestVehicleTruck: "truck", + ExampleGetTestVehicleBike: "bike", +} + +func (e ExampleGetTestVehicle) String() string { + return ExampleGetTestVehicleString[e] +} + +func (e *ExampleGetTestVehicle) UnmarshalJSON(input []byte) (err error) { + var i int8 + + err = json.Unmarshal(input, &i) + if err == nil { + *e = ExampleGetTestVehicle(i) + return nil + } + + var s string + + err = json.Unmarshal(input, &s) + if err != nil { + return err + } + + *e = NewExampleGetTestVehicle(s) + + return nil +} + +func (e ExampleGetTestVehicle) MarshalJSON() ([]byte, error) { + return json.Marshal(e.String()) +} + +func (e ExampleGetTestVehicle) Value() (driver.Value, error) { + return json.Marshal(e.String()) +} + +func (e *ExampleGetTestVehicle) Scan(src any) error { + s, ok := src.(string) + if !ok { + return fmt.Errorf("ExampleGetTestVehicle.scan: scanned a %T, not []byte", src) //nolint + } + + *e = NewExampleGetTestVehicle(s) + + return nil +} + +// ExampleGetTestVehicleDefault +// Op: getTest Param: vehicleDefault +type ExampleGetTestVehicleDefault int8 + +const ( + UnknownExampleGetTestVehicleDefault ExampleGetTestVehicleDefault = iota + ExampleGetTestVehicleDefaultCar + ExampleGetTestVehicleDefaultTruck + ExampleGetTestVehicleDefaultBike +) + +func NewExampleGetTestVehicleDefault(name string) ExampleGetTestVehicleDefault { + switch name { + case "car": + return ExampleGetTestVehicleDefaultCar + case "truck": + return ExampleGetTestVehicleDefaultTruck + case "bike": + return ExampleGetTestVehicleDefaultBike + } + + return ExampleGetTestVehicleDefault(0) +} + +var ExampleGetTestVehicleDefaultString = map[ExampleGetTestVehicleDefault]string{ + ExampleGetTestVehicleDefaultCar: "car", + ExampleGetTestVehicleDefaultTruck: "truck", + ExampleGetTestVehicleDefaultBike: "bike", +} + +func (e ExampleGetTestVehicleDefault) String() string { + return ExampleGetTestVehicleDefaultString[e] +} + +func (e *ExampleGetTestVehicleDefault) UnmarshalJSON(input []byte) (err error) { + var i int8 + + err = json.Unmarshal(input, &i) + if err == nil { + *e = ExampleGetTestVehicleDefault(i) + return nil + } + + var s string + + err = json.Unmarshal(input, &s) + if err != nil { + return err + } + + *e = NewExampleGetTestVehicleDefault(s) + + return nil +} + +func (e ExampleGetTestVehicleDefault) MarshalJSON() ([]byte, error) { + return json.Marshal(e.String()) +} + +func (e ExampleGetTestVehicleDefault) Value() (driver.Value, error) { + return json.Marshal(e.String()) +} + +func (e *ExampleGetTestVehicleDefault) Scan(src any) error { + s, ok := src.(string) + if !ok { + return fmt.Errorf("ExampleGetTestVehicleDefault.scan: scanned a %T, not []byte", src) //nolint + } + + *e = NewExampleGetTestVehicleDefault(s) + + return nil +} diff --git a/tests/example/foji.yaml b/tests/example/foji.yaml index 128a01a..59c0079 100644 --- a/tests/example/foji.yaml +++ b/tests/example/foji.yaml @@ -10,3 +10,11 @@ processes: OpenAPIFile: tests/example/http_handler_gen.go: foji/openapi/handler.go.tpl tests/example/model_gen.go: foji/openapi/model.go.tpl + openAPIClient: + params: + Package: foji/tests/example + Auth: ExampleAuth + TypePrefix: Example + OpenAPIFile: + tests/example/client_model_gen.go: foji/openapi/model.go.tpl + tests/example/http_client_gen.go: foji/openapi/client.go.tpl diff --git a/tests/example/http_client_gen.go b/tests/example/http_client_gen.go new file mode 100644 index 0000000..6b1a0a1 --- /dev/null +++ b/tests/example/http_client_gen.go @@ -0,0 +1,1055 @@ +// Code generated by foji, template: foji/openapi/client.go.tpl; DO NOT EDIT. + +package example + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "io" + "mime/multipart" + "net/http" + "net/url" + "strconv" + "strings" + "time" + + "github.com/bir/iken/httputil" + "github.com/google/uuid" +) + +type ( + ExampleClientAuthenticator = httputil.ClientAuthenticateFunc[*ExampleAuth] + ExampleClientTokenAuthenticator = httputil.ClientTokenAuthenticatorFunc[*ExampleAuth] + ExampleClientBasicAuthenticator = httputil.ClientBasicAuthenticatorFunc[*ExampleAuth] + ExampleClientCookieAuthenticator = httputil.ClientCookieAuthenticatorFunc[*ExampleAuth] + ExampleClientWrappingAuthenticator = httputil.ClientWrappingAuthenticatorFunc[*ExampleAuth] + ExampleClientSecurityGroup = httputil.ClientSecurityGroup[*ExampleAuth] + ExampleClientSecurityGroups = httputil.ClientSecurityGroups[*ExampleAuth] +) + +type ExampleMethods interface { + GetExamples(ctx context.Context) (*ExampleExamples, error) + GetAuthComplex(ctx context.Context, user *ExampleAuth) error + GetAuthSimple(ctx context.Context, user *ExampleAuth) error + GetAuthSimpleMaybe(ctx context.Context, user *ExampleAuth) error + GetAuthSimple2(ctx context.Context, user *ExampleAuth) error + GetAuthSimple2Maybe(ctx context.Context, user *ExampleAuth) error + GetAuthComplexMaybe(ctx context.Context, user *ExampleAuth) error + GetComplexSecurity(ctx context.Context, user *ExampleAuth) ([]TestInt, error) + AddForm(ctx context.Context, body ExampleAddFormRequest) (*ExampleFooBar, error) + AddMultipartForm(ctx context.Context, body ExampleAddMultipartFormRequest) (*ExampleFooBar, error) + HeaderResponse(ctx context.Context) error + AddInlinedAllOf(ctx context.Context, body ExampleAddInlinedAllOfRequest) (*ExampleFooBar, error) + AddInlinedBody(ctx context.Context, body ExampleAddInlinedBodyRequest) (*ExampleFooBar, error) + GetExampleParams(ctx context.Context, k1 string, k2 uuid.UUID, k3 time.Time, k4 int32, k5 int64, enumTest ExampleGetExampleParamsEnumTest) (*ExampleExample, error) + NoResponse(ctx context.Context, body ExampleFoo) error + GetExampleOptional(ctx context.Context, k1 *string, k2 *uuid.UUID, k3 *time.Time, k4 *int32, k5 *int64, k5Default int64) (*ExampleExample, error) + GetExampleQuery(ctx context.Context, k1 string, k2 uuid.UUID, k3 time.Time, k4 int32, k5 int64, k6 []string, k7 []uuid.UUID) (*ExampleExample, error) + GetRawBody(ctx context.Context, body ExampleFoo) (*ExampleExample, error) + GetRawRequest(ctx context.Context, vehicle ExampleGetRawRequestVehicle) (*ExampleExample, error) + GetRawRequestResponse(ctx context.Context, vehicle ExampleGetRawRequestResponseVehicle) (*ExampleExample, error) + GetRawRequestResponseAndHeaders(ctx context.Context, vehicle ExampleGetRawRequestResponseAndHeadersVehicle) (*ExampleExample, error) + GetRawResponse(ctx context.Context, vehicle ExampleGetRawResponseVehicle) (*ExampleExample, error) + GetTest(ctx context.Context, vehicle ExampleGetTestVehicle, vehicleDefault ExampleGetTestVehicleDefault, playerID uuid.UUID, color ExampleColorQuery, colorDefault ExampleColorQueryDefault, season ExampleSeason) (*ExampleExample, error) +} + +type ExampleClient struct { + baseURL string + httpClient *http.Client + bearerAuth ExampleClientAuthenticator + customHeaderAuthAuth ExampleClientAuthenticator + headerAuthAuth ExampleClientAuthenticator + jwtAuth ExampleClientAuthenticator + rawAuth ExampleClientAuthenticator + getAuthComplexSecurity ExampleClientSecurityGroups + getAuthSimpleMaybeSecurity ExampleClientSecurityGroups + getAuthSimple2MaybeSecurity ExampleClientSecurityGroups + getAuthComplexMaybeSecurity ExampleClientSecurityGroups + getComplexSecuritySecurity ExampleClientSecurityGroups +} + +func NewExampleClient(baseURL string, httpClient *http.Client, bearerAuth ExampleClientTokenAuthenticator, customHeaderAuthAuth ExampleClientTokenAuthenticator, headerAuthAuth ExampleClientTokenAuthenticator, jwtAuth ExampleClientTokenAuthenticator, rawAuth ExampleClientTokenAuthenticator) *ExampleClient { + c := &ExampleClient{ + baseURL: baseURL, + httpClient: httpClient, + bearerAuth: httputil.BearerClientAuth("Authorization", bearerAuth), + customHeaderAuthAuth: httputil.HeaderClientAuth("X-CUSTOM-HEADER", customHeaderAuthAuth), + headerAuthAuth: httputil.HeaderClientAuth("Authorization", headerAuthAuth), + jwtAuth: httputil.QueryClientAuth("jwt", jwtAuth), + rawAuth: httputil.HeaderClientAuth("Authorization", rawAuth), + } + + c.getAuthComplexSecurity = ExampleClientSecurityGroups{ + ExampleClientSecurityGroup{c.headerAuthAuth}, + ExampleClientSecurityGroup{c.headerAuthAuth}, + ExampleClientSecurityGroup{c.jwtAuth}, + } + + c.getAuthSimpleMaybeSecurity = ExampleClientSecurityGroups{ + ExampleClientSecurityGroup{c.headerAuthAuth}, + ExampleClientSecurityGroup{}, + } + + c.getAuthSimple2MaybeSecurity = ExampleClientSecurityGroups{ + ExampleClientSecurityGroup{c.headerAuthAuth}, + ExampleClientSecurityGroup{c.headerAuthAuth}, + ExampleClientSecurityGroup{}, + } + + c.getAuthComplexMaybeSecurity = ExampleClientSecurityGroups{ + ExampleClientSecurityGroup{c.headerAuthAuth}, + ExampleClientSecurityGroup{c.jwtAuth}, + ExampleClientSecurityGroup{}, + } + + c.getComplexSecuritySecurity = ExampleClientSecurityGroups{ + ExampleClientSecurityGroup{c.rawAuth}, + ExampleClientSecurityGroup{c.bearerAuth}, + ExampleClientSecurityGroup{c.customHeaderAuthAuth}, + } + + return c +} + +// GetExamples +func (c *ExampleClient) GetExamples(ctx context.Context) (*ExampleExamples, error) { + u := c.baseURL + "/examples" + + req, err := http.NewRequestWithContext(ctx, "GET", u, http.NoBody) + if err != nil { + return nil, err + } + + httpClient := c.httpClient + + resp, err := httpClient.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + errBody, _ := io.ReadAll(resp.Body) + + return nil, httputil.UnexpectedResponseError{Resp: resp, URL: u, Body: errBody} + } + + var out ExampleExamples + if err := httputil.GetJSONBody(resp.Body, &out); err != nil { + return nil, err + } + + return &out, nil +} + +// GetAuthComplex +func (c *ExampleClient) GetAuthComplex(ctx context.Context, user *ExampleAuth) error { + u := c.baseURL + "/examples/auth/complex" + + req, err := http.NewRequestWithContext(ctx, "GET", u, http.NoBody) + if err != nil { + return err + } + + httpClient := c.httpClient + httpClient, err = c.getAuthComplexSecurity.Auth(req, httpClient, user) + if err != nil { + return err + } + + resp, err := httpClient.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + errBody, _ := io.ReadAll(resp.Body) + + return httputil.UnexpectedResponseError{Resp: resp, URL: u, Body: errBody} + } + + return nil +} + +// GetAuthSimple +func (c *ExampleClient) GetAuthSimple(ctx context.Context, user *ExampleAuth) error { + u := c.baseURL + "/examples/auth/simple" + + req, err := http.NewRequestWithContext(ctx, "GET", u, http.NoBody) + if err != nil { + return err + } + + httpClient := c.httpClient + httpClient, err = c.headerAuthAuth(req, httpClient, user) + if err != nil { + return err + } + + resp, err := httpClient.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + errBody, _ := io.ReadAll(resp.Body) + + return httputil.UnexpectedResponseError{Resp: resp, URL: u, Body: errBody} + } + + return nil +} + +// GetAuthSimpleMaybe +func (c *ExampleClient) GetAuthSimpleMaybe(ctx context.Context, user *ExampleAuth) error { + u := c.baseURL + "/examples/auth/simple/maybe" + + req, err := http.NewRequestWithContext(ctx, "GET", u, http.NoBody) + if err != nil { + return err + } + + httpClient := c.httpClient + httpClient, err = c.getAuthSimpleMaybeSecurity.Auth(req, httpClient, user) + if err != nil { + return err + } + + resp, err := httpClient.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + errBody, _ := io.ReadAll(resp.Body) + + return httputil.UnexpectedResponseError{Resp: resp, URL: u, Body: errBody} + } + + return nil +} + +// GetAuthSimple2 +func (c *ExampleClient) GetAuthSimple2(ctx context.Context, user *ExampleAuth) error { + u := c.baseURL + "/examples/auth/simple2" + + req, err := http.NewRequestWithContext(ctx, "GET", u, http.NoBody) + if err != nil { + return err + } + + httpClient := c.httpClient + httpClient, err = c.headerAuthAuth(req, httpClient, user) + if err != nil { + return err + } + + resp, err := httpClient.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + errBody, _ := io.ReadAll(resp.Body) + + return httputil.UnexpectedResponseError{Resp: resp, URL: u, Body: errBody} + } + + return nil +} + +// GetAuthSimple2Maybe +func (c *ExampleClient) GetAuthSimple2Maybe(ctx context.Context, user *ExampleAuth) error { + u := c.baseURL + "/examples/auth/simple2/maybe" + + req, err := http.NewRequestWithContext(ctx, "GET", u, http.NoBody) + if err != nil { + return err + } + + httpClient := c.httpClient + httpClient, err = c.getAuthSimple2MaybeSecurity.Auth(req, httpClient, user) + if err != nil { + return err + } + + resp, err := httpClient.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + errBody, _ := io.ReadAll(resp.Body) + + return httputil.UnexpectedResponseError{Resp: resp, URL: u, Body: errBody} + } + + return nil +} + +// GetAuthComplexMaybe +func (c *ExampleClient) GetAuthComplexMaybe(ctx context.Context, user *ExampleAuth) error { + u := c.baseURL + "/examples/complexAuthMaybe" + + req, err := http.NewRequestWithContext(ctx, "GET", u, http.NoBody) + if err != nil { + return err + } + + httpClient := c.httpClient + httpClient, err = c.getAuthComplexMaybeSecurity.Auth(req, httpClient, user) + if err != nil { + return err + } + + resp, err := httpClient.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + errBody, _ := io.ReadAll(resp.Body) + + return httputil.UnexpectedResponseError{Resp: resp, URL: u, Body: errBody} + } + + return nil +} + +// GetComplexSecurity +func (c *ExampleClient) GetComplexSecurity(ctx context.Context, user *ExampleAuth) ([]TestInt, error) { + u := c.baseURL + "/examples/complexSecurity" + + req, err := http.NewRequestWithContext(ctx, "GET", u, http.NoBody) + if err != nil { + return nil, err + } + + httpClient := c.httpClient + httpClient, err = c.getComplexSecuritySecurity.Auth(req, httpClient, user) + if err != nil { + return nil, err + } + + resp, err := httpClient.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + errBody, _ := io.ReadAll(resp.Body) + + return nil, httputil.UnexpectedResponseError{Resp: resp, URL: u, Body: errBody} + } + + var out []TestInt + if err := httputil.GetJSONBody(resp.Body, &out); err != nil { + return nil, err + } + + return out, nil +} + +// AddForm +func (c *ExampleClient) AddForm(ctx context.Context, body ExampleAddFormRequest) (*ExampleFooBar, error) { + u := c.baseURL + "/examples/form" + + form := url.Values{} + form.Set("f01", strconv.FormatBool(body.F01)) + if body.F01Null != nil { + form.Set("f01Null", strconv.FormatBool((*body.F01Null))) + } + form.Set("f01b", strconv.FormatBool(body.F01B)) + if body.F01BNull != nil { + form.Set("f01bNull", strconv.FormatBool((*body.F01BNull))) + } + form.Set("f02", strconv.FormatInt(int64(body.F02), 10)) + if body.F02Null != nil { + form.Set("f02Null", strconv.FormatInt(int64((*body.F02Null)), 10)) + } + form.Set("f03", strconv.FormatInt(int64(body.F03), 10)) + if body.F03Null != nil { + form.Set("f03Null", strconv.FormatInt(int64((*body.F03Null)), 10)) + } + form.Set("f04", strconv.FormatInt(body.F04, 10)) + if body.F04Null != nil { + form.Set("f04Null", strconv.FormatInt((*body.F04Null), 10)) + } + form.Set("f05", body.F05.Format(time.RFC3339)) + if body.F05Null != nil { + form.Set("f05Null", (*body.F05Null).Format(time.RFC3339)) + } + form.Set("f06", body.F06.String()) + if body.F06Null != nil { + form.Set("f06Null", (*body.F06Null).String()) + } + form.Set("f07", body.F07) + if body.F07Null != nil { + form.Set("f07Null", (*body.F07Null)) + } + form.Set("f08", body.F08.String()) + if body.F08Null != nil { + form.Set("f08Null", (*body.F08Null).String()) + } + form.Set("f09", body.F09.String()) + if body.F09Null != nil { + form.Set("f09Null", (*body.F09Null).String()) + } + for _, v := range body.F10 { + form.Add("f10", v) + } + for _, v := range body.F11 { + form.Add("f11", strconv.FormatInt(int64(v), 10)) + } + for _, v := range body.F12 { + form.Add("f12", v.String()) + } + form.Set("f13", body.F13) + if body.F13Null != nil { + form.Set("f13Null", (*body.F13Null)) + } + + reqBody := strings.NewReader(form.Encode()) + contentType := "application/x-www-form-urlencoded" + + req, err := http.NewRequestWithContext(ctx, "POST", u, reqBody) + if err != nil { + return nil, err + } + + req.Header.Set("Content-Type", contentType) + + httpClient := c.httpClient + + resp, err := httpClient.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + errBody, _ := io.ReadAll(resp.Body) + + return nil, httputil.UnexpectedResponseError{Resp: resp, URL: u, Body: errBody} + } + + var out ExampleFooBar + if err := httputil.GetJSONBody(resp.Body, &out); err != nil { + return nil, err + } + + return &out, nil +} + +// AddMultipartForm +func (c *ExampleClient) AddMultipartForm(ctx context.Context, body ExampleAddMultipartFormRequest) (*ExampleFooBar, error) { + u := c.baseURL + "/examples/form:multipart" + + var bodyBuf bytes.Buffer + + mw := multipart.NewWriter(&bodyBuf) + if err := mw.WriteField("f1", strconv.FormatBool(body.F1)); err != nil { + return nil, fmt.Errorf("multipart field f1: %w", err) + } + if err := mw.WriteField("f2", strconv.FormatInt(int64(body.F2), 10)); err != nil { + return nil, fmt.Errorf("multipart field f2: %w", err) + } + if err := mw.WriteField("f3", strconv.FormatInt(int64(body.F3), 10)); err != nil { + return nil, fmt.Errorf("multipart field f3: %w", err) + } + if err := mw.WriteField("f4", strconv.FormatInt(body.F4, 10)); err != nil { + return nil, fmt.Errorf("multipart field f4: %w", err) + } + if err := mw.WriteField("f5", body.F5.Format(time.RFC3339)); err != nil { + return nil, fmt.Errorf("multipart field f5: %w", err) + } + if err := mw.WriteField("f6", body.F6.String()); err != nil { + return nil, fmt.Errorf("multipart field f6: %w", err) + } + if err := mw.WriteField("f7", body.F7); err != nil { + return nil, fmt.Errorf("multipart field f7: %w", err) + } + { + part, err := mw.CreateFormFile("file1", body.File1.Filename) + if err != nil { + return nil, fmt.Errorf("multipart file file1: %w", err) + } + + if _, err := io.Copy(part, body.File1.File); err != nil { + return nil, fmt.Errorf("multipart file file1: %w", err) + } + } + if body.File2.File != nil { + { + part, err := mw.CreateFormFile("file2", body.File2.Filename) + if err != nil { + return nil, fmt.Errorf("multipart file file2: %w", err) + } + + if _, err := io.Copy(part, body.File2.File); err != nil { + return nil, fmt.Errorf("multipart file file2: %w", err) + } + } + } + + if err := mw.Close(); err != nil { + return nil, fmt.Errorf("multipart close: %w", err) + } + + reqBody := &bodyBuf + contentType := mw.FormDataContentType() + + req, err := http.NewRequestWithContext(ctx, "POST", u, reqBody) + if err != nil { + return nil, err + } + + req.Header.Set("Content-Type", contentType) + + httpClient := c.httpClient + + resp, err := httpClient.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + errBody, _ := io.ReadAll(resp.Body) + + return nil, httputil.UnexpectedResponseError{Resp: resp, URL: u, Body: errBody} + } + + var out ExampleFooBar + if err := httputil.GetJSONBody(resp.Body, &out); err != nil { + return nil, err + } + + return &out, nil +} + +// HeaderResponse +// Check header responses +func (c *ExampleClient) HeaderResponse(ctx context.Context) error { + u := c.baseURL + "/examples/header" + + req, err := http.NewRequestWithContext(ctx, "GET", u, http.NoBody) + if err != nil { + return err + } + + httpClient := c.httpClient + + resp, err := httpClient.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + errBody, _ := io.ReadAll(resp.Body) + + return httputil.UnexpectedResponseError{Resp: resp, URL: u, Body: errBody} + } + + return nil +} + +// AddInlinedAllOf +func (c *ExampleClient) AddInlinedAllOf(ctx context.Context, body ExampleAddInlinedAllOfRequest) (*ExampleFooBar, error) { + u := c.baseURL + "/examples/inlinedAllOf" + + buf, err := json.Marshal(body) + if err != nil { + return nil, fmt.Errorf("marshal request body: %w", err) + } + + reqBody := bytes.NewReader(buf) + contentType := "application/json" + + req, err := http.NewRequestWithContext(ctx, "POST", u, reqBody) + if err != nil { + return nil, err + } + + req.Header.Set("Content-Type", contentType) + + httpClient := c.httpClient + + resp, err := httpClient.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + errBody, _ := io.ReadAll(resp.Body) + + return nil, httputil.UnexpectedResponseError{Resp: resp, URL: u, Body: errBody} + } + + var out ExampleFooBar + if err := httputil.GetJSONBody(resp.Body, &out); err != nil { + return nil, err + } + + return &out, nil +} + +// AddInlinedBody +func (c *ExampleClient) AddInlinedBody(ctx context.Context, body ExampleAddInlinedBodyRequest) (*ExampleFooBar, error) { + u := c.baseURL + "/examples/inlinedBody" + + buf, err := json.Marshal(body) + if err != nil { + return nil, fmt.Errorf("marshal request body: %w", err) + } + + reqBody := bytes.NewReader(buf) + contentType := "application/json" + + req, err := http.NewRequestWithContext(ctx, "POST", u, reqBody) + if err != nil { + return nil, err + } + + req.Header.Set("Content-Type", contentType) + + httpClient := c.httpClient + + resp, err := httpClient.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + errBody, _ := io.ReadAll(resp.Body) + + return nil, httputil.UnexpectedResponseError{Resp: resp, URL: u, Body: errBody} + } + + var out ExampleFooBar + if err := httputil.GetJSONBody(resp.Body, &out); err != nil { + return nil, err + } + + return &out, nil +} + +// GetExampleParams +func (c *ExampleClient) GetExampleParams(ctx context.Context, k1 string, k2 uuid.UUID, k3 time.Time, k4 int32, k5 int64, enumTest ExampleGetExampleParamsEnumTest) (*ExampleExample, error) { + u := c.baseURL + "/examples/key1/{k1}/key2/{k2}/key3/{k3}/key4/{key4}/key5/{key5}" + queryParams := url.Values{} + u = strings.Replace(u, "{k1}", url.PathEscape(k1), 1) + u = strings.Replace(u, "{k2}", url.PathEscape(k2.String()), 1) + u = strings.Replace(u, "{k3}", url.PathEscape(k3.Format(time.RFC3339)), 1) + u = strings.Replace(u, "{k4}", url.PathEscape(strconv.FormatInt(int64(k4), 10)), 1) + u = strings.Replace(u, "{k5}", url.PathEscape(strconv.FormatInt(k5, 10)), 1) + queryParams.Set("enumTest", enumTest.String()) + + if len(queryParams) > 0 { + u += "?" + queryParams.Encode() + } + + req, err := http.NewRequestWithContext(ctx, "GET", u, http.NoBody) + if err != nil { + return nil, err + } + + httpClient := c.httpClient + + resp, err := httpClient.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + errBody, _ := io.ReadAll(resp.Body) + + return nil, httputil.UnexpectedResponseError{Resp: resp, URL: u, Body: errBody} + } + + var out ExampleExample + if err := httputil.GetJSONBody(resp.Body, &out); err != nil { + return nil, err + } + + return &out, nil +} + +// NoResponse +func (c *ExampleClient) NoResponse(ctx context.Context, body ExampleFoo) error { + u := c.baseURL + "/examples/noResponse" + + buf, err := json.Marshal(body) + if err != nil { + return fmt.Errorf("marshal request body: %w", err) + } + + reqBody := bytes.NewReader(buf) + contentType := "application/json" + + req, err := http.NewRequestWithContext(ctx, "POST", u, reqBody) + if err != nil { + return err + } + + req.Header.Set("Content-Type", contentType) + + httpClient := c.httpClient + + resp, err := httpClient.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + errBody, _ := io.ReadAll(resp.Body) + + return httputil.UnexpectedResponseError{Resp: resp, URL: u, Body: errBody} + } + + return nil +} + +// GetExampleOptional +func (c *ExampleClient) GetExampleOptional(ctx context.Context, k1 *string, k2 *uuid.UUID, k3 *time.Time, k4 *int32, k5 *int64, k5Default int64) (*ExampleExample, error) { + u := c.baseURL + "/examples/optional" + queryParams := url.Values{} + if k1 != nil { + queryParams.Set("k1", (*k1)) + } + if k2 != nil { + queryParams.Set("k2", (*k2).String()) + } + if k3 != nil { + queryParams.Set("k3", (*k3).Format(time.RFC3339)) + } + if k4 != nil { + queryParams.Set("k4", strconv.FormatInt(int64((*k4)), 10)) + } + if k5 != nil { + queryParams.Set("k5", strconv.FormatInt((*k5), 10)) + } + queryParams.Set("k5Default", strconv.FormatInt(k5Default, 10)) + + if len(queryParams) > 0 { + u += "?" + queryParams.Encode() + } + + req, err := http.NewRequestWithContext(ctx, "GET", u, http.NoBody) + if err != nil { + return nil, err + } + + httpClient := c.httpClient + + resp, err := httpClient.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + errBody, _ := io.ReadAll(resp.Body) + + return nil, httputil.UnexpectedResponseError{Resp: resp, URL: u, Body: errBody} + } + + var out ExampleExample + if err := httputil.GetJSONBody(resp.Body, &out); err != nil { + return nil, err + } + + return &out, nil +} + +// GetExampleQuery +func (c *ExampleClient) GetExampleQuery(ctx context.Context, k1 string, k2 uuid.UUID, k3 time.Time, k4 int32, k5 int64, k6 []string, k7 []uuid.UUID) (*ExampleExample, error) { + u := c.baseURL + "/examples/query" + queryParams := url.Values{} + queryParams.Set("k1", k1) + queryParams.Set("k2", k2.String()) + queryParams.Set("k3", k3.Format(time.RFC3339)) + queryParams.Set("k4", strconv.FormatInt(int64(k4), 10)) + queryParams.Set("k5", strconv.FormatInt(k5, 10)) + for _, v := range k6 { + queryParams.Add("k6", v) + } + for _, v := range k7 { + queryParams.Add("k7", v.String()) + } + + if len(queryParams) > 0 { + u += "?" + queryParams.Encode() + } + + req, err := http.NewRequestWithContext(ctx, "GET", u, http.NoBody) + if err != nil { + return nil, err + } + + httpClient := c.httpClient + + resp, err := httpClient.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + errBody, _ := io.ReadAll(resp.Body) + + return nil, httputil.UnexpectedResponseError{Resp: resp, URL: u, Body: errBody} + } + + var out ExampleExample + if err := httputil.GetJSONBody(resp.Body, &out); err != nil { + return nil, err + } + + return &out, nil +} + +// GetRawBody +func (c *ExampleClient) GetRawBody(ctx context.Context, body ExampleFoo) (*ExampleExample, error) { + u := c.baseURL + "/examples/rawBody" + + buf, err := json.Marshal(body) + if err != nil { + return nil, fmt.Errorf("marshal request body: %w", err) + } + + reqBody := bytes.NewReader(buf) + contentType := "application/json" + + req, err := http.NewRequestWithContext(ctx, "GET", u, reqBody) + if err != nil { + return nil, err + } + + req.Header.Set("Content-Type", contentType) + + httpClient := c.httpClient + + resp, err := httpClient.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + errBody, _ := io.ReadAll(resp.Body) + + return nil, httputil.UnexpectedResponseError{Resp: resp, URL: u, Body: errBody} + } + + var out ExampleExample + if err := httputil.GetJSONBody(resp.Body, &out); err != nil { + return nil, err + } + + return &out, nil +} + +// GetRawRequest +func (c *ExampleClient) GetRawRequest(ctx context.Context, vehicle ExampleGetRawRequestVehicle) (*ExampleExample, error) { + u := c.baseURL + "/examples/rawRequest" + queryParams := url.Values{} + queryParams.Set("vehicle", vehicle.String()) + + if len(queryParams) > 0 { + u += "?" + queryParams.Encode() + } + + req, err := http.NewRequestWithContext(ctx, "GET", u, http.NoBody) + if err != nil { + return nil, err + } + + httpClient := c.httpClient + + resp, err := httpClient.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + errBody, _ := io.ReadAll(resp.Body) + + return nil, httputil.UnexpectedResponseError{Resp: resp, URL: u, Body: errBody} + } + + var out ExampleExample + if err := httputil.GetJSONBody(resp.Body, &out); err != nil { + return nil, err + } + + return &out, nil +} + +// GetRawRequestResponse +func (c *ExampleClient) GetRawRequestResponse(ctx context.Context, vehicle ExampleGetRawRequestResponseVehicle) (*ExampleExample, error) { + u := c.baseURL + "/examples/rawRequestResponse" + queryParams := url.Values{} + queryParams.Set("vehicle", vehicle.String()) + + if len(queryParams) > 0 { + u += "?" + queryParams.Encode() + } + + req, err := http.NewRequestWithContext(ctx, "GET", u, http.NoBody) + if err != nil { + return nil, err + } + + httpClient := c.httpClient + + resp, err := httpClient.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + errBody, _ := io.ReadAll(resp.Body) + + return nil, httputil.UnexpectedResponseError{Resp: resp, URL: u, Body: errBody} + } + + var out ExampleExample + if err := httputil.GetJSONBody(resp.Body, &out); err != nil { + return nil, err + } + + return &out, nil +} + +// GetRawRequestResponseAndHeaders +func (c *ExampleClient) GetRawRequestResponseAndHeaders(ctx context.Context, vehicle ExampleGetRawRequestResponseAndHeadersVehicle) (*ExampleExample, error) { + u := c.baseURL + "/examples/rawRequestResponseAndHeaders" + queryParams := url.Values{} + queryParams.Set("vehicle", vehicle.String()) + + if len(queryParams) > 0 { + u += "?" + queryParams.Encode() + } + + req, err := http.NewRequestWithContext(ctx, "GET", u, http.NoBody) + if err != nil { + return nil, err + } + + httpClient := c.httpClient + + resp, err := httpClient.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + errBody, _ := io.ReadAll(resp.Body) + + return nil, httputil.UnexpectedResponseError{Resp: resp, URL: u, Body: errBody} + } + + var out ExampleExample + if err := httputil.GetJSONBody(resp.Body, &out); err != nil { + return nil, err + } + + return &out, nil +} + +// GetRawResponse +func (c *ExampleClient) GetRawResponse(ctx context.Context, vehicle ExampleGetRawResponseVehicle) (*ExampleExample, error) { + u := c.baseURL + "/examples/rawResponse" + queryParams := url.Values{} + queryParams.Set("vehicle", vehicle.String()) + + if len(queryParams) > 0 { + u += "?" + queryParams.Encode() + } + + req, err := http.NewRequestWithContext(ctx, "GET", u, http.NoBody) + if err != nil { + return nil, err + } + + httpClient := c.httpClient + + resp, err := httpClient.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + errBody, _ := io.ReadAll(resp.Body) + + return nil, httputil.UnexpectedResponseError{Resp: resp, URL: u, Body: errBody} + } + + var out ExampleExample + if err := httputil.GetJSONBody(resp.Body, &out); err != nil { + return nil, err + } + + return &out, nil +} + +// GetTest +func (c *ExampleClient) GetTest(ctx context.Context, vehicle ExampleGetTestVehicle, vehicleDefault ExampleGetTestVehicleDefault, playerID uuid.UUID, color ExampleColorQuery, colorDefault ExampleColorQueryDefault, season ExampleSeason) (*ExampleExample, error) { + u := c.baseURL + "/examples/test" + queryParams := url.Values{} + queryParams.Set("vehicle", vehicle.String()) + queryParams.Set("vehicleDefault", vehicleDefault.String()) + queryParams.Set("playerId", playerID.String()) + queryParams.Set("color", color.String()) + queryParams.Set("colorDefault", colorDefault.String()) + u = strings.Replace(u, "{season}", url.PathEscape(season.String()), 1) + + if len(queryParams) > 0 { + u += "?" + queryParams.Encode() + } + + req, err := http.NewRequestWithContext(ctx, "GET", u, http.NoBody) + if err != nil { + return nil, err + } + + httpClient := c.httpClient + + resp, err := httpClient.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + errBody, _ := io.ReadAll(resp.Body) + + return nil, httputil.UnexpectedResponseError{Resp: resp, URL: u, Body: errBody} + } + + var out ExampleExample + if err := httputil.GetJSONBody(resp.Body, &out); err != nil { + return nil, err + } + + return &out, nil +} diff --git a/tests/example/model_gen.go b/tests/example/model_gen.go index 3d15654..007b54c 100644 --- a/tests/example/model_gen.go +++ b/tests/example/model_gen.go @@ -17,7 +17,7 @@ import ( "github.com/google/uuid" ) -var ErrMissingRequiredField = errors.New("missing required field") +var ErrExampleMissingRequiredField = errors.New("missing required field") // Component Schemas @@ -158,7 +158,7 @@ func (p *Example) UnmarshalJSON(b []byte) error { var validationErrors validation.Errors if _, ok := requiredCheck["id"]; !ok { - validationErrors.Add("id", ErrMissingRequiredField) + validationErrors.Add("id", ErrExampleMissingRequiredField) } if validationErrors != nil { @@ -199,7 +199,7 @@ func (p *Examples) UnmarshalJSON(b []byte) error { var validationErrors validation.Errors if _, ok := requiredCheck["list"]; !ok { - validationErrors.Add("list", ErrMissingRequiredField) + validationErrors.Add("list", ErrExampleMissingRequiredField) } if validationErrors != nil { @@ -305,7 +305,7 @@ func (p *FooBar) UnmarshalJSON(b []byte) error { var validationErrors validation.Errors if _, ok := requiredCheck["a"]; !ok { - validationErrors.Add("a", ErrMissingRequiredField) + validationErrors.Add("a", ErrExampleMissingRequiredField) } if validationErrors != nil { @@ -762,23 +762,23 @@ func (p *Patterns) UnmarshalJSON(b []byte) error { var validationErrors validation.Errors if _, ok := requiredCheck["id"]; !ok { - validationErrors.Add("id", ErrMissingRequiredField) + validationErrors.Add("id", ErrExampleMissingRequiredField) } if _, ok := requiredCheck["stateAlways"]; !ok { - validationErrors.Add("stateAlways", ErrMissingRequiredField) + validationErrors.Add("stateAlways", ErrExampleMissingRequiredField) } if _, ok := requiredCheck["subObject"]; !ok { - validationErrors.Add("subObject", ErrMissingRequiredField) + validationErrors.Add("subObject", ErrExampleMissingRequiredField) } if _, ok := requiredCheck["subState"]; !ok { - validationErrors.Add("subState", ErrMissingRequiredField) + validationErrors.Add("subState", ErrExampleMissingRequiredField) } if _, ok := requiredCheck["timeStamp"]; !ok { - validationErrors.Add("timeStamp", ErrMissingRequiredField) + validationErrors.Add("timeStamp", ErrExampleMissingRequiredField) } if validationErrors != nil { @@ -1032,7 +1032,7 @@ func (p *PlayerAlways) UnmarshalJSON(b []byte) error { var validationErrors validation.Errors if _, ok := requiredCheck["id"]; !ok { - validationErrors.Add("id", ErrMissingRequiredField) + validationErrors.Add("id", ErrExampleMissingRequiredField) } if validationErrors != nil { @@ -1078,7 +1078,7 @@ func (p *PlayerMaybe) UnmarshalJSON(b []byte) error { var validationErrors validation.Errors if _, ok := requiredCheck["id"]; !ok { - validationErrors.Add("id", ErrMissingRequiredField) + validationErrors.Add("id", ErrExampleMissingRequiredField) } if validationErrors != nil { @@ -2872,11 +2872,11 @@ func (p *AddInlinedBodyRequest) UnmarshalJSON(b []byte) error { var validationErrors validation.Errors if _, ok := requiredCheck["f07"]; !ok { - validationErrors.Add("f07", ErrMissingRequiredField) + validationErrors.Add("f07", ErrExampleMissingRequiredField) } if _, ok := requiredCheck["f10"]; !ok { - validationErrors.Add("f10", ErrMissingRequiredField) + validationErrors.Add("f10", ErrExampleMissingRequiredField) } if validationErrors != nil { diff --git a/tests/go.mod b/tests/go.mod index 2093f3d..8cb22ea 100644 --- a/tests/go.mod +++ b/tests/go.mod @@ -3,7 +3,7 @@ module tests go 1.26.0 require ( - github.com/bir/iken v0.8.12 + github.com/bir/iken v0.8.13 github.com/google/uuid v1.6.0 github.com/stretchr/testify v1.11.1 ) diff --git a/tests/go.sum b/tests/go.sum index 8ca2ccb..8653908 100644 --- a/tests/go.sum +++ b/tests/go.sum @@ -1,5 +1,7 @@ github.com/bir/iken v0.8.12 h1:ROLRu5f8KIYSuKcSLzOrpbpaNLQHzzOUnYBihijvMzk= github.com/bir/iken v0.8.12/go.mod h1:F3gTwkXjHAJ0thzPYo2iOk+Ot35TOv4vmGq9JdEIlG0= +github.com/bir/iken v0.8.13 h1:KQ5IqszCnbk5ENTGxj9m8G1v1I1kqc94gJdY0mhotrM= +github.com/bir/iken v0.8.13/go.mod h1:F3gTwkXjHAJ0thzPYo2iOk+Ot35TOv4vmGq9JdEIlG0= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -25,8 +27,6 @@ github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= -golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k= golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= diff --git a/tests/tests_main.go b/tests/tests_main.go index dfcdcfd..55619ab 100644 --- a/tests/tests_main.go +++ b/tests/tests_main.go @@ -26,6 +26,32 @@ func authorize(ctx context.Context, user *example.ExampleAuth, scopes []string) return nil } +func csvClientToken(ctx context.Context, user *csvresponse.ExampleAuth) (string, error) { + return "", nil +} + +func clientToken(ctx context.Context, user *example.ExampleAuth) (string, error) { + return "", nil +} + +func clientBasic(ctx context.Context, user *example.ExampleAuth) (string, string, error) { + return "", "", nil +} + +func clientCookie(ctx context.Context, user *example.ExampleAuth) (*http.Cookie, error) { + return nil, nil +} + +func clientWrap(ctx context.Context, inner *http.Client, user *example.ExampleAuth) (*http.Client, error) { + return inner, nil +} + +func clientRaw(r *http.Request, inner *http.Client, user *example.ExampleAuth) (*http.Client, error) { + return inner, nil +} + +func isA[T any](_ T) {} + func main() { // Requires the generated Operations to match the Service layer var _ csvresponse.Operations = &csvresponse.Service{} @@ -34,7 +60,12 @@ func main() { example.RegisterHTTP(ops, http.NewServeMux(), tokenAuth, tokenAuth, tokenAuth, tokenAuth, rawAuth, authorize) var authOps auth.Operations = &auth.Service{} - auth.RegisterHTTP(authOps, http.NewServeMux(), tokenAuth, tokenAuth, tokenAuth, basicAuth, tokenAuth, rawAuth, rawAuth, rawAuth, authorize) + auth.RegisterHTTP(authOps, http.NewServeMux(), tokenAuth, tokenAuth, tokenAuth, basicAuth, tokenAuth, rawAuth, rawAuth, rawAuth, rawAuth, authorize) + + // Requires the generated clients to construct with authenticators matching each security scheme, and meet the interface. + isA[csvresponse.Methods](csvresponse.NewClient("http://localhost", http.DefaultClient, csvClientToken)) + isA[example.ExampleMethods](example.NewExampleClient("http://localhost", http.DefaultClient, clientToken, clientToken, clientToken, clientToken, clientToken)) + isA[auth.Methods](auth.NewClient("http://localhost", http.DefaultClient, clientCookie, clientToken, clientToken, clientBasic, clientToken, clientWrap, clientWrap, clientWrap, clientRaw)) os.Exit(0) }