MarketingSystemDataTool/server/internal/config/config.go

152 lines
3.1 KiB
Go

package config
import (
"io"
"os"
"path/filepath"
"strings"
"gopkg.in/yaml.v3"
)
type DB struct {
Host string `yaml:"host"`
Port string `yaml:"port"`
User string `yaml:"user"`
Password string `yaml:"password"`
Name string `yaml:"name"`
}
type App struct {
Port string `yaml:"port"`
MarketingDB DB `yaml:"marketing_db"`
YMTDB DB `yaml:"ymt_db"`
}
type root struct {
App App `yaml:"app"`
}
func Load() App {
env := strings.ToLower(strings.TrimSpace(os.Getenv("APP_ENV")))
paths := []string{}
if env != "" {
paths = append(paths,
"config."+env+".yaml",
filepath.Join("server", "config."+env+".yaml"),
)
}
// no global fallback to config.yaml; rely on APP_ENV or environment variables
var cfg App
for _, p := range paths {
if readYAML(p, &cfg) {
break
}
}
LoadEnv()
if v := os.Getenv("MARKETING_DB_HOST"); v != "" {
cfg.MarketingDB.Host = v
}
if v := os.Getenv("MARKETING_DB_PORT"); v != "" {
cfg.MarketingDB.Port = v
}
if v := os.Getenv("MARKETING_DB_USER"); v != "" {
cfg.MarketingDB.User = v
}
if v := os.Getenv("MARKETING_DB_PASSWORD"); v != "" {
cfg.MarketingDB.Password = v
}
if v := os.Getenv("MARKETING_DB_NAME"); v != "" {
cfg.MarketingDB.Name = v
}
if v := os.Getenv("YMT_DB_HOST"); v != "" {
cfg.YMTDB.Host = v
}
if v := os.Getenv("YMT_DB_PORT"); v != "" {
cfg.YMTDB.Port = v
}
if v := os.Getenv("YMT_DB_USER"); v != "" {
cfg.YMTDB.User = v
}
if v := os.Getenv("YMT_DB_PASSWORD"); v != "" {
cfg.YMTDB.Password = v
}
if v := os.Getenv("YMT_DB_NAME"); v != "" {
cfg.YMTDB.Name = v
}
return cfg
}
func readYAML(path string, out *App) bool {
f, err := os.Open(path)
if err != nil {
return false
}
defer f.Close()
b, err := io.ReadAll(f)
if err != nil {
return false
}
var r root
if err := yaml.Unmarshal(b, &r); err == nil {
if r.App.Port != "" || r.App.MarketingDB.Host != "" || r.App.YMTDB.Host != "" {
*out = r.App
return true
}
}
if err := yaml.Unmarshal(b, out); err != nil {
return false
}
return true
}
func (d DB) DSN() string {
if strings.TrimSpace(d.User) == "" || strings.TrimSpace(d.Host) == "" || strings.TrimSpace(d.Port) == "" || strings.TrimSpace(d.Name) == "" {
return ""
}
return d.User + ":" + d.Password + "@tcp(" + d.Host + ":" + d.Port + ")/" + d.Name + "?parseTime=True&loc=Local&charset=utf8mb4"
}
func LoadEnv() {
env := strings.ToLower(strings.TrimSpace(os.Getenv("APP_ENV")))
paths := []string{}
if env != "" {
paths = append(paths,
".env."+env,
filepath.Join("server", ".env."+env),
)
}
paths = append(paths,
".env.local",
filepath.Join("server", ".env.local"),
)
for _, p := range paths {
f, err := os.Open(p)
if err != nil {
continue
}
b, err := io.ReadAll(f)
f.Close()
if err != nil {
continue
}
lines := strings.Split(string(b), "\n")
for _, ln := range lines {
s := strings.TrimSpace(ln)
if s == "" || strings.HasPrefix(s, "#") {
continue
}
kv := strings.SplitN(s, "=", 2)
if len(kv) != 2 {
continue
}
k := strings.TrimSpace(kv[0])
v := strings.TrimSpace(kv[1])
if k != "" {
os.Setenv(k, v)
}
}
break
}
}