mirror of
https://github.com/steveiliop56/tinyauth.git
synced 2026-02-22 00:42:03 +00:00
132 lines
3.0 KiB
Go
132 lines
3.0 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"fmt"
|
|
"io/fs"
|
|
"log/slog"
|
|
"os"
|
|
"reflect"
|
|
"strings"
|
|
|
|
"github.com/steveiliop56/tinyauth/internal/config"
|
|
)
|
|
|
|
type EnvEntry struct {
|
|
Name string
|
|
Description string
|
|
Value any
|
|
}
|
|
|
|
func generateExampleEnv() {
|
|
cfg := config.NewDefaultConfiguration()
|
|
entries := make([]EnvEntry, 0)
|
|
|
|
root := reflect.TypeOf(cfg).Elem()
|
|
rootValue := reflect.ValueOf(cfg).Elem()
|
|
rootPath := "TINYAUTH_"
|
|
|
|
walkAndBuild(root, rootValue, rootPath, &entries, buildEnvEntry, buildEnvMapEntry, buildEnvChildPath)
|
|
compiled := compileEnv(entries)
|
|
|
|
err := os.Remove(".env.example")
|
|
if err != nil && !errors.Is(err, fs.ErrNotExist) {
|
|
slog.Error("failed to remove example env file", "error", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
err = os.WriteFile(".env.example", compiled, 0644)
|
|
if err != nil {
|
|
slog.Error("failed to write example env file", "error", err)
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
func buildEnvEntry(child reflect.StructField, childValue reflect.Value, parentPath string, entries *[]EnvEntry) {
|
|
desc := child.Tag.Get("description")
|
|
tag := child.Tag.Get("yaml")
|
|
|
|
if tag == "-" {
|
|
return
|
|
}
|
|
|
|
value := childValue.Interface()
|
|
|
|
entry := EnvEntry{
|
|
Name: parentPath + strings.ToUpper(child.Name),
|
|
Description: desc,
|
|
}
|
|
|
|
switch childValue.Kind() {
|
|
case reflect.Slice:
|
|
sl, ok := value.([]string)
|
|
if !ok {
|
|
slog.Error("invalid default value", "value", value)
|
|
return
|
|
}
|
|
entry.Value = strings.Join(sl, ",")
|
|
case reflect.String:
|
|
st, ok := value.(string)
|
|
if !ok {
|
|
slog.Error("invalid default value", "value", value)
|
|
return
|
|
}
|
|
if st != "" {
|
|
entry.Value = fmt.Sprintf(`"%s"`, st)
|
|
} else {
|
|
entry.Value = ""
|
|
}
|
|
default:
|
|
entry.Value = value
|
|
}
|
|
*entries = append(*entries, entry)
|
|
}
|
|
|
|
func buildEnvMapEntry(child reflect.StructField, parentPath string, entries *[]EnvEntry) {
|
|
fieldType := child.Type
|
|
|
|
if fieldType.Key().Kind() != reflect.String {
|
|
slog.Info("unsupported map key type", "type", fieldType.Key().Kind())
|
|
return
|
|
}
|
|
|
|
mapPath := parentPath + strings.ToUpper(child.Name) + "_name_"
|
|
valueType := fieldType.Elem()
|
|
|
|
if valueType.Kind() == reflect.Struct {
|
|
zeroValue := reflect.New(valueType).Elem()
|
|
walkAndBuild(valueType, zeroValue, mapPath, entries, buildEnvEntry, buildEnvMapEntry, buildEnvChildPath)
|
|
}
|
|
}
|
|
|
|
func buildEnvChildPath(parent string, child string) string {
|
|
return parent + strings.ToUpper(child) + "_"
|
|
}
|
|
|
|
func compileEnv(entries []EnvEntry) []byte {
|
|
buffer := bytes.Buffer{}
|
|
buffer.WriteString("# Tinyauth example configuration\n\n")
|
|
|
|
previousSection := ""
|
|
|
|
for _, entry := range entries {
|
|
if strings.Count(entry.Name, "_") > 1 {
|
|
section := strings.Split(strings.TrimPrefix(entry.Name, "TINYAUTH_"), "_")[0]
|
|
if section != previousSection {
|
|
buffer.WriteString("\n# " + strings.ToLower(section) + " config\n\n")
|
|
previousSection = section
|
|
}
|
|
}
|
|
buffer.WriteString("# ")
|
|
buffer.WriteString(entry.Description)
|
|
buffer.WriteString("\n")
|
|
buffer.WriteString(entry.Name)
|
|
buffer.WriteString("=")
|
|
fmt.Fprintf(&buffer, "%v", entry.Value)
|
|
buffer.WriteString("\n")
|
|
}
|
|
|
|
return buffer.Bytes()
|
|
}
|