-
Notifications
You must be signed in to change notification settings - Fork 21
/
Copy pathfactory.go
83 lines (69 loc) · 2.08 KB
/
factory.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
package config
import (
"errors"
"fmt"
"os"
"strings"
"github.com/spf13/viper"
)
// ConfigFactory is the interface for [Config] factories.
type ConfigFactory interface {
Create(options ...ConfigOption) (*Config, error)
}
// DefaultConfigFactory is the default [ConfigFactory] implementation.
type DefaultConfigFactory struct{}
// NewDefaultConfigFactory returns a [DefaultConfigFactory], implementing [ConfigFactory].
func NewDefaultConfigFactory() ConfigFactory {
return &DefaultConfigFactory{}
}
// Create returns a new [Config], and accepts a list of [ConfigOption].
// For example:
//
// var cfg, _ = config.NewDefaultConfigFactory().Create()
//
// is equivalent to:
//
// var cfg, _ = config.NewDefaultConfigFactory().Create(
// config.WithFileName("config"), // config files base name
// config.WithFilePaths(".", "./configs"), // config files lookup paths
// )
func (f *DefaultConfigFactory) Create(options ...ConfigOption) (*Config, error) {
appliedOptions := DefaultConfigOptions()
for _, opt := range options {
opt(&appliedOptions)
}
v := viper.New()
v.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
v.AutomaticEnv()
v.SetConfigName(appliedOptions.FileName)
for _, path := range appliedOptions.FilePaths {
v.AddConfigPath(path)
}
f.setDefaults(v)
if err := v.ReadInConfig(); err != nil {
return nil, err
}
appEnv := os.Getenv("APP_ENV")
if appEnv != "" {
v.SetConfigName(fmt.Sprintf("%s.%s", appliedOptions.FileName, appEnv))
if err := v.MergeInConfig(); err != nil {
if errors.As(err, &viper.ConfigFileNotFoundError{}) {
return nil, fmt.Errorf("could not load config file for env %s: %w", appEnv, err)
} else {
return nil, fmt.Errorf("could not merge config for env %s: %w", appEnv, err)
}
}
}
for _, key := range v.AllKeys() {
val := v.GetString(key)
if strings.Contains(val, "${") {
v.Set(key, os.ExpandEnv(val))
}
}
return &Config{v}, nil
}
func (f *DefaultConfigFactory) setDefaults(v *viper.Viper) {
v.SetDefault("app.name", DefaultAppName)
v.SetDefault("app.version", DefaultAppVersion)
v.SetDefault("app.debug", false)
}