// Copyright 2024 Patial Tech. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package config import ( "fmt" "os" "path/filepath" "reflect" "strconv" "strings" "gitserver.in/patialtech/rano/config/dotenv" "gitserver.in/patialtech/rano/util/logger" ) const ( // projDir need to be same as project code root dir name projDir = "rano" EnvDev = "development" EnvProd = "production" EnvStage = "staging" AuthUserCtxKey = "AuthUser" ) var ( conf *Config AppEnv Env = EnvDev ) type ( Env string Config struct { basePath string WebPort int `env:"WEB_PORT"` WebURL string `env:"WEB_URL"` GraphPort int `env:"GRAPH_PORT"` GraphURL string `env:"GRAPH_URL"` DbURL string `env:"DB_URL"` MailerTplDir string `env:"MAILER_TEMPLATES_DIR"` MailerFrom string `env:"MAILER_FROM_ADDRESS"` } ) func init() { var base string if AppEnv == EnvDev { wd, _ := os.Getwd() idx := strings.Index(wd, projDir) if idx > -1 { base = filepath.Join(wd[:idx], projDir) } } else { base, _ = os.Executable() } envVar, err := dotenv.Read(base, fmt.Sprintf(".env.%s", AppEnv)) if err != nil { panic(err) } conf = &Config{basePath: base} conf.loadEnv(envVar) } // Read config for Env func Read() *Config { if conf == nil { panic("config not initialized") } return conf } func (c *Config) loadEnv(vars map[string]string) { if c == nil { return } val := reflect.Indirect(reflect.ValueOf(c)) for i := 0; i < val.NumField(); i++ { f := val.Type().Field(i) tag := f.Tag.Get("env") if tag == "" { continue } v, found := vars[tag] if !found { logger.Warn("var %q not found in file .env.%s", tag, AppEnv) continue } field := val.FieldByName(f.Name) if !field.IsValid() { continue } switch f.Type.Kind() { case reflect.Int: if intV, err := strconv.ParseInt(v, 10, 64); err != nil { panic(err) } else { field.SetInt(intV) } default: field.SetString(v) } } }