| 
					
				 | 
			
			
				@@ -0,0 +1,175 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+package penv 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import ( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	"flag" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	"fmt" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	"os" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	"reflect" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	"strconv" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	"strings" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	"golang.org/x/text/cases" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	"golang.org/x/text/language" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+var Prefix = "ENV_" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+type DumpVar struct { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	Name     string 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	NameEnv  string 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	NameFlag string 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	Desc     string 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	Type     string 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	Value    string 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	Secret   bool 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+func generate(name string) string { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	n := "" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	prevBig := true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	for i, char := range name { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if i > 0 && string(char) == strings.ToUpper(string(char)) && !prevBig { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			n += "_" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if string(char) == strings.ToUpper(string(char)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			prevBig = true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			prevBig = false 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		n += string(char) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return n 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+func generateEnvName(name string) string { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return strings.ToUpper(Prefix + generate(name)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+func generateFlagName(name string) string { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return strings.ToLower(generate(name)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+func stringToInt(value string) (int, error) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return strconv.Atoi(value) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+func stringToInt64(value string) (int64, error) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return strconv.ParseInt(value, 10, 64) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+func DumpConfig(config any) map[string]DumpVar { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	res := map[string]DumpVar{} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	v := reflect.ValueOf(config).Elem() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	t := v.Type() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	for i := 0; i < t.NumField(); i++ { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		nameEnv := generateEnvName(t.Field(i).Name) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		fieldType := t.Field(i).Type.Kind().String() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		nameFlag := generateFlagName(t.Field(i).Name) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		description := t.Field(i).Tag.Get("description") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if description == "" { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			description = "No description" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		secret := t.Field(i).Tag.Get("secret") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if fieldType == "string" { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			res[t.Field(i).Name] = DumpVar{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				Name:     t.Field(i).Name, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				NameEnv:  nameEnv, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				NameFlag: nameFlag, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				Desc:     description, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				Type:     cases.Title(language.English).String(fieldType), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				Value:    *v.Field(i).Addr().Interface().(*string), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				Secret:   secret == "1" || secret == "true", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} else if fieldType == "int" { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			res[t.Field(i).Name] = DumpVar{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				Name:     t.Field(i).Name, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				NameEnv:  nameEnv, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				NameFlag: nameFlag, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				Desc:     description, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				Type:     cases.Title(language.English).String(fieldType), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				Value:    fmt.Sprintf("%d", *v.Field(i).Addr().Interface().(*int)), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				Secret:   secret == "1" || secret == "true", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} else if fieldType == "int64" { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			res[t.Field(i).Name] = DumpVar{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				Name:     t.Field(i).Name, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				NameEnv:  nameEnv, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				NameFlag: nameFlag, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				Desc:     description, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				Type:     cases.Title(language.English).String(fieldType), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				Value:    fmt.Sprintf("%d", *v.Field(i).Addr().Interface().(*int64)), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				Secret:   secret == "1" || secret == "true", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return res 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+func ProcessConfig(config any) error { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	v := reflect.ValueOf(config).Elem() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	t := v.Type() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// Process flags 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	for i := 0; i < t.NumField(); i++ { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		nameEnv := generateEnvName(t.Field(i).Name) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		nameFlag := generateFlagName(t.Field(i).Name) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		fieldType := t.Field(i).Type.Kind().String() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		defvalue := t.Field(i).Tag.Get("default") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		description := t.Field(i).Tag.Get("description") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if description == "" { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			description = "No description" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if fieldType == "string" { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			value := v.Field(i).Addr().Interface().(*string) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			flag.StringVar(value, nameFlag, defvalue, "Or "+nameEnv+": "+description) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} else if fieldType == "int" { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			if ndefvalue, err := stringToInt(defvalue); err == nil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				value := v.Field(i).Addr().Interface().(*int) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				flag.IntVar(value, nameFlag, ndefvalue, "Or "+nameEnv+": "+description) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			} else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				return err 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} else if fieldType == "int64" { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			if ndefvalue, err := stringToInt64(defvalue); err == nil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				value := v.Field(i).Addr().Interface().(*int64) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				flag.Int64Var(value, nameFlag, ndefvalue, "Or "+nameEnv+": "+description) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			} else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				return err 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	flag.Parse() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// Process ENVs 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	for i := 0; i < t.NumField(); i++ { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		nameEnv := generateEnvName(t.Field(i).Name) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		fieldType := t.Field(i).Type.Kind().String() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if os.Getenv(nameEnv) != "" { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			if fieldType == "string" { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				value := v.Field(i).Addr().Interface().(*string) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				*value = os.Getenv(nameEnv) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			} else if fieldType == "int" { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				if nvalue, err := stringToInt(os.Getenv(nameEnv)); err == nil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					value := v.Field(i).Addr().Interface().(*int) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					*value = nvalue 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				} else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					return err 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			} else if fieldType == "int64" { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				if nvalue, err := stringToInt64(os.Getenv(nameEnv)); err == nil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					value := v.Field(i).Addr().Interface().(*int64) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					*value = nvalue 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				} else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					return err 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return nil 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 |