diff --git a/go.mod b/go.mod index dc48050..5e84fd4 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.20 require ( github.com/DATA-DOG/go-sqlmock v1.5.0 - github.com/caarlos0/env/v6 v6.10.1 + github.com/caarlos0/env/v7 v7.1.0 github.com/go-logfmt/logfmt v0.6.0 github.com/jmoiron/sqlx v1.3.5 github.com/valyala/quicktemplate v1.7.0 diff --git a/go.sum b/go.sum index 117d561..9ae8d0a 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,8 @@ github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20O github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= github.com/andybalholm/brotli v1.0.3/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= -github.com/caarlos0/env/v6 v6.10.1 h1:t1mPSxNpei6M5yAeu1qtRdPAK29Nbcf/n3G7x+b3/II= -github.com/caarlos0/env/v6 v6.10.1/go.mod h1:hvp/ryKXKipEkcuYjs9mI4bBCg+UI0Yhgm5Zu0ddvwc= +github.com/caarlos0/env/v7 v7.1.0 h1:9lzTF5amyQeWHZzuZeKlCb5FWSUxpG1js43mhbY8ozg= +github.com/caarlos0/env/v7 v7.1.0/go.mod h1:LPPWniDUq4JaO6Q41vtlyikhMknqymCLBw0eX4dcH1E= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4= diff --git a/main.go b/main.go index 9234a34..244b11f 100644 --- a/main.go +++ b/main.go @@ -14,7 +14,7 @@ import ( "path/filepath" "time" - "github.com/caarlos0/env/v6" + "github.com/caarlos0/env/v7" "golang.org/x/text/feature/plural" "golang.org/x/text/language" "golang.org/x/text/message" diff --git a/vendor/github.com/caarlos0/env/v6/.gitignore b/vendor/github.com/caarlos0/env/v7/.gitignore similarity index 100% rename from vendor/github.com/caarlos0/env/v6/.gitignore rename to vendor/github.com/caarlos0/env/v7/.gitignore diff --git a/vendor/github.com/caarlos0/env/v6/.golangci.yml b/vendor/github.com/caarlos0/env/v7/.golangci.yml similarity index 100% rename from vendor/github.com/caarlos0/env/v6/.golangci.yml rename to vendor/github.com/caarlos0/env/v7/.golangci.yml diff --git a/vendor/github.com/caarlos0/env/v6/.goreleaser.yml b/vendor/github.com/caarlos0/env/v7/.goreleaser.yml similarity index 100% rename from vendor/github.com/caarlos0/env/v6/.goreleaser.yml rename to vendor/github.com/caarlos0/env/v7/.goreleaser.yml diff --git a/vendor/github.com/caarlos0/env/v6/LICENSE.md b/vendor/github.com/caarlos0/env/v7/LICENSE.md similarity index 100% rename from vendor/github.com/caarlos0/env/v6/LICENSE.md rename to vendor/github.com/caarlos0/env/v7/LICENSE.md diff --git a/vendor/github.com/caarlos0/env/v6/Makefile b/vendor/github.com/caarlos0/env/v7/Makefile similarity index 100% rename from vendor/github.com/caarlos0/env/v6/Makefile rename to vendor/github.com/caarlos0/env/v7/Makefile diff --git a/vendor/github.com/caarlos0/env/v6/README.md b/vendor/github.com/caarlos0/env/v7/README.md similarity index 77% rename from vendor/github.com/caarlos0/env/v6/README.md rename to vendor/github.com/caarlos0/env/v7/README.md index e56399b..9d982cb 100644 --- a/vendor/github.com/caarlos0/env/v6/README.md +++ b/vendor/github.com/caarlos0/env/v7/README.md @@ -1,8 +1,8 @@ # env -[![Build Status](https://img.shields.io/github/workflow/status/caarlos0/env/build?style=for-the-badge)](https://github.com/caarlos0/env/actions?workflow=build) +[![Build Status](https://img.shields.io/github/actions/workflow/status/caarlos0/env/build.yml?branch=main&style=for-the-badge)](https://github.com/caarlos0/env/actions?workflow=build) [![Coverage Status](https://img.shields.io/codecov/c/gh/caarlos0/env.svg?logo=codecov&style=for-the-badge)](https://codecov.io/gh/caarlos0/env) -[![](http://img.shields.io/badge/godoc-reference-5272B4.svg?style=for-the-badge)](https://pkg.go.dev/github.com/caarlos0/env/v6) +[![](http://img.shields.io/badge/godoc-reference-5272B4.svg?style=for-the-badge)](https://pkg.go.dev/github.com/caarlos0/env/v7) A simple and zero-dependencies library to parse environment variables into structs. @@ -11,7 +11,7 @@ A simple and zero-dependencies library to parse environment variables into struc Get the module with: ```sh -go get github.com/caarlos0/env/v6 +go get github.com/caarlos0/env/v7 ``` The usage looks like this: @@ -23,7 +23,7 @@ import ( "fmt" "time" - "github.com/caarlos0/env/v6" + "github.com/caarlos0/env/v7" ) type config struct { @@ -53,7 +53,14 @@ $ PRODUCTION=true HOSTS="host1:host2:host3" DURATION=1s go run main.go {Home:/your/home Port:3000 IsProduction:true Hosts:[host1 host2 host3] Duration:1s} ``` -⚠️⚠️⚠️ **Attention:** _unexported fields_ will be **ignored**. +## Caveats + +> **Warning** +> +> **This is important!** + +- _Unexported fields_ are **ignored** + ## Supported types and defaults @@ -80,11 +87,15 @@ Complete list: - `encoding.TextUnmarshaler` - `url.URL` -Pointers, slices and slices of pointers of those types are also supported. +Pointers, slices and slices of pointers, and maps of those types are also +supported. You can also use/define a [custom parser func](#custom-parser-funcs) for any other type you want. +You can also use custom keys and values in your maps, as long as you provide a +parser function for them. + If you set the `envDefault` tag for something, this value will be used in the case of absence of it in the environment. @@ -107,7 +118,7 @@ also accepts a `map[reflect.Type]env.ParserFunc`. If you add a custom parser for, say `Foo`, it will also be used to parse `*Foo` and `[]Foo` types. -Check the examples in the [go doc](http://pkg.go.dev/github.com/caarlos0/env/v6) +Check the examples in the [go doc](http://pkg.go.dev/github.com/caarlos0/env/v7) for more info. ### A note about `TextUnmarshaler` and `time.Time` @@ -148,7 +159,7 @@ type config struct { ## Not Empty fields -While `required` demands the environment variable to be check, it doesn't check its value. +While `required` demands the environment variable to be set, it doesn't check its value. If you want to make sure the environment is set and not empty, you need to use the `notEmpty` tag option instead (`env:"SOME_ENV,notEmpty"`). Example: @@ -185,7 +196,7 @@ package main import ( "fmt" "time" - "github.com/caarlos0/env/v6" + "github.com/caarlos0/env/v7" ) type config struct { @@ -217,6 +228,46 @@ $ SECRET=/tmp/secret \ ## Options +### Use field names as environment variables by default + +If you don't want to set the `env` tag on every field, you can use the +`UseFieldNameByDefault` option. + +It will use the field name as environment variable name. + +Here's an example: + + +```go +package main + +import ( + "fmt" + "log" + + "github.com/caarlos0/env/v7" +) + +type Config struct { + Username string // will use $USERNAME + Password string // will use $PASSWORD + UserFullName string // will use $USER_FULL_NAME +} + +func main() { + cfg := &Config{} + opts := &env.Options{UseFieldNameByDefault: true} + + // Load env vars. + if err := env.Parse(cfg, opts); err != nil { + log.Fatal(err) + } + + // Print the loaded data. + fmt.Printf("%+v\n", cfg) +} +``` + ### Environment By setting the `Options.Environment` map you can tell `Parse` to add those `keys` and `values` @@ -232,7 +283,7 @@ import ( "fmt" "log" - "github.com/caarlos0/env/v6" + "github.com/caarlos0/env/v7" ) type Config struct { @@ -251,7 +302,7 @@ func main() { } // Print the loaded data. - fmt.Printf("%+v\n", cfg.envData) + fmt.Printf("%+v\n", cfg) } ``` @@ -268,7 +319,7 @@ import ( "fmt" "log" - "github.com/caarlos0/env/v6" + "github.com/caarlos0/env/v7" ) type Config struct { @@ -285,7 +336,7 @@ func main() { } // Print the loaded data. - fmt.Printf("%+v\n", cfg.envData) + fmt.Printf("%+v\n", cfg) } ``` @@ -302,7 +353,7 @@ import ( "fmt" "log" - "github.com/caarlos0/env/v6" + "github.com/caarlos0/env/v7" ) type Config struct { @@ -318,7 +369,7 @@ type ComplexConfig struct { func main() { cfg := ComplexConfig{} - if err := Parse(&cfg, Options{ + if err := Parse(&cfg, Options{ Prefix: "T_", Environment: map[string]string{ "T_FOO_HOME": "/foo", @@ -336,7 +387,7 @@ func main() { } // Print the loaded data. - fmt.Printf("%+v\n", cfg.envData) + fmt.Printf("%+v\n", cfg) } ``` @@ -352,7 +403,7 @@ import ( "fmt" "log" - "github.com/caarlos0/env/v6" + "github.com/caarlos0/env/v7" ) type Config struct { @@ -374,7 +425,7 @@ func main() { } // Print the loaded data. - fmt.Printf("%+v\n", cfg.envData) + fmt.Printf("%+v\n", cfg) } ``` @@ -391,7 +442,7 @@ import ( "fmt" "log" - "github.com/caarlos0/env/v6" + "github.com/caarlos0/env/v7" ) type Config struct { @@ -409,7 +460,7 @@ func main() { } // Print the loaded data. - fmt.Printf("%+v\n", cfg.envData) + fmt.Printf("%+v\n", cfg) } ``` @@ -425,7 +476,7 @@ import ( "fmt" "log" - "github.com/caarlos0/env/v6" + "github.com/caarlos0/env/v7" ) type Config struct { @@ -447,6 +498,54 @@ func main() { } ``` +## Error handling + +You can handle the errors the library throws like so: + +```go +package main + +import ( + "fmt" + "log" + + "github.com/caarlos0/env/v7" +) + +type Config struct { + Username string `env:"USERNAME" envDefault:"admin"` + Password string `env:"PASSWORD"` +} + +func main() { + var cfg Config + err := env.Parse(&cfg) + if e, ok := err.(*env.AggregateError); ok { + for _, er := range e.Errors { + switch v := er.(type) { + case env.ParseError: + // handle it + case env.NotStructPtrError: + // handle it + case env.NoParserError: + // handle it + case env.NoSupportedTagOptionError: + // handle it + default: + fmt.Printf("Unknown error type %v", v) + } + } + } + + fmt.Printf("%+v", cfg) // {Username:admin Password:123456} +} +``` + +> **Info** +> +> If you want to check if an specific error is in the chain, you can also use +> `errors.Is()`. + ## Stargazers over time [![Stargazers over time](https://starchart.cc/caarlos0/env.svg)](https://starchart.cc/caarlos0/env) diff --git a/vendor/github.com/caarlos0/env/v6/env.go b/vendor/github.com/caarlos0/env/v7/env.go similarity index 79% rename from vendor/github.com/caarlos0/env/v6/env.go rename to vendor/github.com/caarlos0/env/v7/env.go index f0b09df..ce84c62 100644 --- a/vendor/github.com/caarlos0/env/v6/env.go +++ b/vendor/github.com/caarlos0/env/v7/env.go @@ -2,7 +2,6 @@ package env import ( "encoding" - "errors" "fmt" "net/url" "os" @@ -10,14 +9,11 @@ import ( "strconv" "strings" "time" + "unicode" ) // nolint: gochecknoglobals var ( - // ErrNotAStructPtr is returned if you pass something that is not a pointer to a - // Struct to Parse. - ErrNotAStructPtr = errors.New("env: expected a pointer to a Struct") - defaultBuiltInParsers = map[reflect.Kind]ParserFunc{ reflect.Bool: func(v string) (interface{}, error) { return strconv.ParseBool(v) @@ -79,14 +75,14 @@ func defaultTypeParsers() map[reflect.Type]ParserFunc { reflect.TypeOf(url.URL{}): func(v string) (interface{}, error) { u, err := url.Parse(v) if err != nil { - return nil, fmt.Errorf("unable to parse URL: %v", err) + return nil, newParseValueError("unable to parse URL", err) } return *u, nil }, reflect.TypeOf(time.Nanosecond): func(v string) (interface{}, error) { s, err := time.ParseDuration(v) if err != nil { - return nil, fmt.Errorf("unable to parse duration: %v", err) + return nil, newParseValueError("unable to parse duration", err) } return s, err }, @@ -107,15 +103,20 @@ type Options struct { // TagName specifies another tagname to use rather than the default env. TagName string - // RequiredIfNoDef automatically sets all env as required if they do not declare 'envDefault' + // RequiredIfNoDef automatically sets all env as required if they do not + // declare 'envDefault'. RequiredIfNoDef bool - // OnSet allows to run a function when a value is set + // OnSet allows to run a function when a value is set. OnSet OnSetFn - // Prefix define a prefix for each key + // Prefix define a prefix for each key. Prefix string + // UseFieldNameByDefault defines whether or not env should use the field + // name by default if the `env` key is missing. + UseFieldNameByDefault bool + // Sets to true if we have already configured once. configured bool } @@ -150,6 +151,7 @@ func configure(opts []Options) []Options { if item.Prefix != "" { opt.Prefix = item.Prefix } + opt.UseFieldNameByDefault = item.UseFieldNameByDefault opt.RequiredIfNoDef = item.RequiredIfNoDef } @@ -183,11 +185,11 @@ func ParseWithFuncs(v interface{}, funcMap map[reflect.Type]ParserFunc, opts ... ptrRef := reflect.ValueOf(v) if ptrRef.Kind() != reflect.Ptr { - return ErrNotAStructPtr + return newAggregateError(NotStructPtrError{}) } ref := ptrRef.Elem() if ref.Kind() != reflect.Struct { - return ErrNotAStructPtr + return newAggregateError(NotStructPtrError{}) } parsers := defaultTypeParsers() for k, v := range funcMap { @@ -200,22 +202,22 @@ func ParseWithFuncs(v interface{}, funcMap map[reflect.Type]ParserFunc, opts ... func doParse(ref reflect.Value, funcMap map[reflect.Type]ParserFunc, opts []Options) error { refType := ref.Type() - var agrErr aggregateError + var agrErr AggregateError for i := 0; i < refType.NumField(); i++ { refField := ref.Field(i) refTypeField := refType.Field(i) if err := doParseField(refField, refTypeField, funcMap, opts); err != nil { - if val, ok := err.(aggregateError); ok { - agrErr.errors = append(agrErr.errors, val.errors...) + if val, ok := err.(AggregateError); ok { + agrErr.Errors = append(agrErr.Errors, val.Errors...) } else { - agrErr.errors = append(agrErr.errors, err) + agrErr.Errors = append(agrErr.Errors, err) } } } - if len(agrErr.errors) == 0 { + if len(agrErr.Errors) == 0 { return nil } @@ -226,7 +228,7 @@ func doParseField(refField reflect.Value, refTypeField reflect.StructField, func if !refField.CanSet() { return nil } - if reflect.Ptr == refField.Kind() && refField.Elem().Kind() == reflect.Struct { + if reflect.Ptr == refField.Kind() && !refField.IsNil() { return ParseWithFuncs(refField.Interface(), funcMap, optsWithPrefix(refTypeField, opts)...) } if reflect.Struct == refField.Kind() && refField.CanAddr() && refField.Type().Name() == "" { @@ -248,6 +250,19 @@ func doParseField(refField reflect.Value, refTypeField reflect.StructField, func return nil } +const underscore rune = '_' + +func toEnvName(input string) string { + var output []rune + for i, c := range input { + if i > 0 && output[i-1] != underscore && c != underscore && unicode.ToUpper(c) == c { + output = append(output, underscore) + } + output = append(output, unicode.ToUpper(c)) + } + return string(output) +} + func get(field reflect.StructField, opts []Options) (val string, err error) { var exists bool var isDefault bool @@ -258,6 +273,9 @@ func get(field reflect.StructField, opts []Options) (val string, err error) { required := opts[0].RequiredIfNoDef prefix := opts[0].Prefix ownKey, tags := parseKeyForOption(field.Tag.Get(getTagName(opts))) + if ownKey == "" && opts[0].UseFieldNameByDefault { + ownKey = toEnvName(field.Name) + } key := prefix + ownKey for _, tag := range tags { switch tag { @@ -272,7 +290,7 @@ func get(field reflect.StructField, opts []Options) (val string, err error) { case "notEmpty": notEmpty = true default: - return "", fmt.Errorf("tag option %q not supported", tag) + return "", newNoSupportedTagOptionError(tag) } } expand := strings.EqualFold(field.Tag.Get("envExpand"), "true") @@ -288,18 +306,18 @@ func get(field reflect.StructField, opts []Options) (val string, err error) { } if required && !exists && len(ownKey) > 0 { - return "", fmt.Errorf(`required environment variable %q is not set`, key) + return "", newEnvVarIsNotSet(key) } if notEmpty && val == "" { - return "", fmt.Errorf("environment variable %q should not be empty", key) + return "", newEmptyEnvVarError(key) } if loadFile && val != "" { filename := val val, err = getFromFile(filename) if err != nil { - return "", fmt.Errorf(`could not load content of file "%s" from variable %s: %v`, filename, key, err) + return "", newLoadFileContentError(filename, key, err) } } @@ -325,6 +343,8 @@ func getOr(key, defaultValue string, defExists bool, envs map[string]string) (st switch { case (!exists || key == "") && defExists: return defaultValue, true, true + case exists && value == "" && defExists: + return defaultValue, true, true case !exists: return "", false, false } @@ -369,8 +389,11 @@ func set(field reflect.Value, sf reflect.StructField, value string, funcMap map[ return nil } - if field.Kind() == reflect.Slice { + switch field.Kind() { + case reflect.Slice: return handleSlice(field, value, sf, funcMap) + case reflect.Map: + return handleMap(field, value, sf, funcMap) } return newNoParserError(sf) @@ -417,6 +440,54 @@ func handleSlice(field reflect.Value, value string, sf reflect.StructField, func return nil } +func handleMap(field reflect.Value, value string, sf reflect.StructField, funcMap map[reflect.Type]ParserFunc) error { + keyType := sf.Type.Key() + keyParserFunc, ok := funcMap[keyType] + if !ok { + keyParserFunc, ok = defaultBuiltInParsers[keyType.Kind()] + if !ok { + return newNoParserError(sf) + } + } + + elemType := sf.Type.Elem() + elemParserFunc, ok := funcMap[elemType] + if !ok { + elemParserFunc, ok = defaultBuiltInParsers[elemType.Kind()] + if !ok { + return newNoParserError(sf) + } + } + + separator := sf.Tag.Get("envSeparator") + if separator == "" { + separator = "," + } + + result := reflect.MakeMap(sf.Type) + for _, part := range strings.Split(value, separator) { + pairs := strings.Split(part, ":") + if len(pairs) != 2 { + return newParseError(sf, fmt.Errorf(`%q should be in "key:value" format`, part)) + } + + key, err := keyParserFunc(pairs[0]) + if err != nil { + return newParseError(sf, err) + } + + elem, err := elemParserFunc(pairs[1]) + if err != nil { + return newParseError(sf, err) + } + + result.SetMapIndex(reflect.ValueOf(key).Convert(keyType), reflect.ValueOf(elem).Convert(elemType)) + } + + field.Set(result) + return nil +} + func asTextUnmarshaler(field reflect.Value) encoding.TextUnmarshaler { if reflect.Ptr == field.Kind() { if field.IsNil() { @@ -459,26 +530,6 @@ func parseTextUnmarshalers(field reflect.Value, data []string, sf reflect.Struct return nil } -func newParseError(sf reflect.StructField, err error) error { - return parseError{ - sf: sf, - err: err, - } -} - -type parseError struct { - sf reflect.StructField - err error -} - -func (e parseError) Error() string { - return fmt.Sprintf(`parse error on field "%s" of type "%s": %v`, e.sf.Name, e.sf.Type, e.err) -} - -func newNoParserError(sf reflect.StructField) error { - return fmt.Errorf(`no parser found for field "%s" of type "%s"`, sf.Name, sf.Type) -} - func optsWithPrefix(field reflect.StructField, opts []Options) []Options { subOpts := make([]Options, len(opts)) copy(subOpts, opts) @@ -487,18 +538,3 @@ func optsWithPrefix(field reflect.StructField, opts []Options) []Options { } return subOpts } - -type aggregateError struct { - errors []error -} - -func (e aggregateError) Error() string { - var sb strings.Builder - sb.WriteString("env:") - - for _, err := range e.errors { - sb.WriteString(fmt.Sprintf(" %v;", err.Error())) - } - - return strings.TrimRight(sb.String(), ";") -} diff --git a/vendor/github.com/caarlos0/env/v6/env_unix.go b/vendor/github.com/caarlos0/env/v7/env_unix.go similarity index 100% rename from vendor/github.com/caarlos0/env/v6/env_unix.go rename to vendor/github.com/caarlos0/env/v7/env_unix.go diff --git a/vendor/github.com/caarlos0/env/v6/env_windows.go b/vendor/github.com/caarlos0/env/v7/env_windows.go similarity index 100% rename from vendor/github.com/caarlos0/env/v6/env_windows.go rename to vendor/github.com/caarlos0/env/v7/env_windows.go diff --git a/vendor/github.com/caarlos0/env/v7/error.go b/vendor/github.com/caarlos0/env/v7/error.go new file mode 100644 index 0000000..cfc9766 --- /dev/null +++ b/vendor/github.com/caarlos0/env/v7/error.go @@ -0,0 +1,164 @@ +package env + +import ( + "fmt" + "reflect" + "strings" +) + +// An aggregated error wrapper to combine gathered errors. This allows either to display all errors or convert them individually +// List of the available errors +// ParseError +// NotStructPtrError +// NoParserError +// NoSupportedTagOptionError +// EnvVarIsNotSetError +// EmptyEnvVarError +// LoadFileContentError +// ParseValueError +type AggregateError struct { + Errors []error +} + +func newAggregateError(initErr error) error { + return AggregateError{ + []error{ + initErr, + }, + } +} + +func (e AggregateError) Error() string { + var sb strings.Builder + + sb.WriteString("env:") + + for _, err := range e.Errors { + sb.WriteString(fmt.Sprintf(" %v;", err.Error())) + } + + return strings.TrimRight(sb.String(), ";") +} + +// Is conforms with errors.Is. +func (e AggregateError) Is(err error) bool { + for _, ie := range e.Errors { + if reflect.TypeOf(ie) == reflect.TypeOf(err) { + return true + } + } + return false +} + +// The error occurs when it's impossible to convert the value for given type. +type ParseError struct { + Name string + Type reflect.Type + Err error +} + +func newParseError(sf reflect.StructField, err error) error { + return ParseError{sf.Name, sf.Type, err} +} + +func (e ParseError) Error() string { + return fmt.Sprintf(`parse error on field "%s" of type "%s": %v`, e.Name, e.Type, e.Err) +} + +// The error occurs when pass something that is not a pointer to a Struct to Parse +type NotStructPtrError struct{} + +func (e NotStructPtrError) Error() string { + return "expected a pointer to a Struct" +} + +// This error occurs when there is no parser provided for given type +// Supported types and defaults: https://github.com/caarlos0/env#supported-types-and-defaults +// How to create a custom parser: https://github.com/caarlos0/env#custom-parser-funcs +type NoParserError struct { + Name string + Type reflect.Type +} + +func newNoParserError(sf reflect.StructField) error { + return NoParserError{sf.Name, sf.Type} +} + +func (e NoParserError) Error() string { + return fmt.Sprintf(`no parser found for field "%s" of type "%s"`, e.Name, e.Type) +} + +// This error occurs when the given tag is not supported +// In-built supported tags: "", "file", "required", "unset", "notEmpty", "envDefault", "envExpand", "envSeparator" +// How to create a custom tag: https://github.com/caarlos0/env#changing-default-tag-name +type NoSupportedTagOptionError struct { + Tag string +} + +func newNoSupportedTagOptionError(tag string) error { + return NoSupportedTagOptionError{tag} +} + +func (e NoSupportedTagOptionError) Error() string { + return fmt.Sprintf("tag option %q not supported", e.Tag) +} + +// This error occurs when the required variable is not set +// Read about required fields: https://github.com/caarlos0/env#required-fields +type EnvVarIsNotSetError struct { + Key string +} + +func newEnvVarIsNotSet(key string) error { + return EnvVarIsNotSetError{key} +} + +func (e EnvVarIsNotSetError) Error() string { + return fmt.Sprintf(`required environment variable %q is not set`, e.Key) +} + +// This error occurs when the variable which must be not empty is existing but has an empty value +// Read about not empty fields: https://github.com/caarlos0/env#not-empty-fields +type EmptyEnvVarError struct { + Key string +} + +func newEmptyEnvVarError(key string) error { + return EmptyEnvVarError{key} +} + +func (e EmptyEnvVarError) Error() string { + return fmt.Sprintf("environment variable %q should not be empty", e.Key) +} + +// This error occurs when it's impossible to load the value from the file +// Read about From file feature: https://github.com/caarlos0/env#from-file +type LoadFileContentError struct { + Filename string + Key string + Err error +} + +func newLoadFileContentError(filename, key string, err error) error { + return LoadFileContentError{filename, key, err} +} + +func (e LoadFileContentError) Error() string { + return fmt.Sprintf(`could not load content of file "%s" from variable %s: %v`, e.Filename, e.Key, e.Err) +} + +// This error occurs when it's impossible to convert value using given parser +// Supported types and defaults: https://github.com/caarlos0/env#supported-types-and-defaults +// How to create a custom parser: https://github.com/caarlos0/env#custom-parser-funcs +type ParseValueError struct { + Msg string + Err error +} + +func newParseValueError(message string, err error) error { + return ParseValueError{message, err} +} + +func (e ParseValueError) Error() string { + return fmt.Sprintf("%s: %v", e.Msg, e.Err) +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 2f2259e..f3d480d 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1,9 +1,9 @@ # github.com/DATA-DOG/go-sqlmock v1.5.0 ## explicit github.com/DATA-DOG/go-sqlmock -# github.com/caarlos0/env/v6 v6.10.1 +# github.com/caarlos0/env/v7 v7.1.0 ## explicit; go 1.17 -github.com/caarlos0/env/v6 +github.com/caarlos0/env/v7 # github.com/dustin/go-humanize v1.0.1 ## explicit; go 1.16 github.com/dustin/go-humanize