github.com/influx6/npkg@v0.8.8/nenv/nenv.go (about) 1 package nenv 2 3 import ( 4 "io" 5 "os" 6 "strings" 7 "sync" 8 "time" 9 10 "github.com/influx6/npkg/nerror" 11 "github.com/influx6/npkg/npair" 12 ) 13 14 type Provider interface { 15 Add(key string, value interface{}) 16 } 17 18 // Loader defines a loader function which returns all 19 // associated environment functions as a slice of 20 // key=value pairs. 21 type Loader interface { 22 Register(Provider) error 23 } 24 25 var _ Loader = (*EnvironmentLoader)(nil) 26 27 type ListLoader []string 28 29 func (el ListLoader) Register(p Provider) error { 30 for _, item := range el { 31 var eqIndex = strings.Index(item, "=") 32 if eqIndex == -1 { 33 continue 34 } 35 var key = strings.ToLower(item[:eqIndex]) 36 var value = item[eqIndex+1:] 37 p.Add(key, value) 38 } 39 return nil 40 } 41 42 type EnvReaderLoader struct { 43 File io.Reader 44 } 45 46 func (el *EnvReaderLoader) Register(p Provider) error { 47 var parsedValues, parsedErr = ParseDotEnvReader(el.File) 48 if parsedErr != nil { 49 return nerror.WrapOnly(parsedErr) 50 } 51 52 for key, value := range parsedValues { 53 p.Add(key, value) 54 } 55 return nil 56 } 57 58 type EnvFileLoader struct { 59 File string 60 } 61 62 func (el *EnvFileLoader) Register(p Provider) error { 63 var parsedValues, parsedErr = ReadDotEnvFile(el.File) 64 if parsedErr != nil { 65 return nerror.WrapOnly(parsedErr) 66 } 67 68 for key, value := range parsedValues { 69 p.Add(key, value) 70 } 71 return nil 72 } 73 74 type EnvironmentLoader struct{} 75 76 func (el *EnvironmentLoader) Register(p Provider) error { 77 var envMap = os.Environ() 78 for _, item := range envMap { 79 var eqIndex = strings.Index(item, "=") 80 if eqIndex == -1 { 81 continue 82 } 83 var key = strings.ToLower(item[:eqIndex]) 84 var value = item[eqIndex+1:] 85 p.Add(key, value) 86 } 87 return nil 88 } 89 90 func LoadEnvironment(prefix string) (*EnvStore, error) { 91 var loader EnvironmentLoader 92 return LoadFrom(prefix, &loader) 93 } 94 95 func LoadFrom(prefix string, loader Loader) (*EnvStore, error) { 96 var store = New(prefix) 97 return store, loader.Register(store) 98 } 99 100 // EnvStore defines an implementation which during initial 101 // loading stores all environment keys and values. 102 // 103 // All environment keys are lowercased to avoid to ensure 104 // case insensitivity, so be aware when using such for keys. 105 // 106 // It provides a means of reloading giving values 107 // storing them efficient for retrieval and change. 108 type EnvStore struct { 109 prefix string 110 fl sync.RWMutex 111 cache npair.Field 112 } 113 114 // New returns a new map which contains all environment variables. 115 // 116 // If Prefix is provided then only environment variables with giving prefix 117 // are loaded. Prefixed are expected to be in the format: PREFIX_ENV_VAR. 118 func New(prefix string) *EnvStore { 119 var env EnvStore 120 env.cache = npair.Field{} 121 if len(prefix) > 0 { 122 env.prefix = strings.ToLower(strings.TrimSuffix(prefix, "_")) 123 } 124 return &env 125 } 126 127 func (env *EnvStore) Add(key string, value interface{}) { 128 key = strings.ToLower(key) 129 if len(env.prefix) > 0 && !strings.HasPrefix(key, env.prefix+"_") { 130 return 131 } 132 env.fl.Lock() 133 env.cache[key] = value 134 env.fl.Unlock() 135 } 136 137 // Has returns a true/false if giving key value exists. 138 func (env *EnvStore) Has(key string) bool { 139 env.fl.RLock() 140 defer env.fl.RUnlock() 141 return env.cache.Has(getHash(env.prefix, key)) 142 } 143 144 // Set sets provided key within store and sets the giving environment 145 // variable in to the environment. 146 func (env *EnvStore) Set(key string, value string) { 147 env.Add(getHash(env.prefix, key), value) 148 } 149 150 // GetBool collects the string value of a key if it exists. 151 func (env *EnvStore) GetBool(key string) (bool, bool) { 152 env.fl.RLock() 153 defer env.fl.RUnlock() 154 return env.cache.GetBool(getHash(env.prefix, key)) 155 } 156 157 // GetFloat64 collects the string value of a key if it exists. 158 func (env *EnvStore) GetFloat64(key string) (float64, bool) { 159 env.fl.RLock() 160 defer env.fl.RUnlock() 161 return env.cache.GetFloat64(getHash(env.prefix, key)) 162 } 163 164 // GetFloat32 collects the string value of a key if it exists. 165 func (env *EnvStore) GetFloat32(key string) (float32, bool) { 166 env.fl.RLock() 167 defer env.fl.RUnlock() 168 return env.cache.GetFloat32(getHash(env.prefix, key)) 169 } 170 171 // GetInt8 collects the string value of a key if it exists. 172 func (env *EnvStore) GetInt8(key string) (int8, bool) { 173 env.fl.RLock() 174 defer env.fl.RUnlock() 175 return env.cache.GetInt8(getHash(env.prefix, key)) 176 } 177 178 // GetInt16 collects the string value of a key if it exists. 179 func (env *EnvStore) GetInt16(key string) (int16, bool) { 180 env.fl.RLock() 181 defer env.fl.RUnlock() 182 return env.cache.GetInt16(getHash(env.prefix, key)) 183 } 184 185 // GetInt64 collects the string value of a key if it exists. 186 func (env *EnvStore) GetInt64(key string) (int64, bool) { 187 env.fl.RLock() 188 defer env.fl.RUnlock() 189 return env.cache.GetInt64(getHash(env.prefix, key)) 190 } 191 192 // GetInt32 collects the string value of a key if it exists. 193 func (env *EnvStore) GetInt32(key string) (int32, bool) { 194 env.fl.RLock() 195 defer env.fl.RUnlock() 196 return env.cache.GetInt32(getHash(env.prefix, key)) 197 } 198 199 // GetInt collects the string value of a key if it exists. 200 func (env *EnvStore) GetInt(key string) (int, bool) { 201 env.fl.RLock() 202 defer env.fl.RUnlock() 203 return env.cache.GetInt(getHash(env.prefix, key)) 204 } 205 206 // KeyFor returns the expected name of a giving key from the environment 207 // store. 208 func (env *EnvStore) KeyFor(key string) string { 209 return strings.ToUpper(getHash(env.prefix, key)) 210 } 211 212 // GetString collects the string value of a key if it exists. 213 func (env *EnvStore) GetString(key string) (string, bool) { 214 env.fl.RLock() 215 defer env.fl.RUnlock() 216 return env.cache.GetString(getHash(env.prefix, key)) 217 } 218 219 // GetDuration collects the string value of a key if it exists. 220 func (env *EnvStore) GetDuration(key string) (time.Duration, bool) { 221 env.fl.RLock() 222 defer env.fl.RUnlock() 223 return env.cache.GetDuration(getHash(env.prefix, key)) 224 } 225 226 // Get collects the value of a key if it exists. 227 func (env *EnvStore) Get(key string) (value interface{}, found bool) { 228 env.fl.RLock() 229 defer env.fl.RUnlock() 230 return env.cache.Get(getHash(env.prefix, key)) 231 } 232 233 // getHash returns giving format of key. 234 func getHash(prefix string, key string) string { 235 if len(prefix) == 0 { 236 return strings.ToLower(key) 237 } 238 key = strings.ToLower(key) 239 key = strings.TrimSuffix(key, "_") 240 return strings.ToLower(prefix + "_" + key) 241 }