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  }