mirror of
https://github.com/steveiliop56/tinyauth.git
synced 2026-07-13 21:41:12 +00:00
173 lines
4.4 KiB
Go
173 lines
4.4 KiB
Go
package main
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"io/fs"
|
|
"log/slog"
|
|
"os"
|
|
"reflect"
|
|
"strings"
|
|
|
|
"github.com/tinyauthapp/tinyauth/internal/model"
|
|
)
|
|
|
|
type ConfigOptions struct {
|
|
Env string
|
|
Flag string
|
|
YAML string
|
|
}
|
|
type MarkdownEntry struct {
|
|
Options ConfigOptions
|
|
Description string
|
|
Default any
|
|
}
|
|
|
|
func generateMarkdown() {
|
|
cfg := model.NewDefaultConfiguration(model.RuntimeEnvUnknown)
|
|
entries := make([]MarkdownEntry, 0)
|
|
|
|
root := reflect.TypeOf(cfg).Elem()
|
|
rootValue := reflect.ValueOf(cfg).Elem()
|
|
rootPath := "tinyauth."
|
|
|
|
walkAndBuild(root, rootValue, rootPath, &entries, buildMdEntry, buildMdMapEntry, buildMdChildPath)
|
|
compiled := compileMd(entries)
|
|
|
|
err := os.Remove("config.gen.md")
|
|
if err != nil && !errors.Is(err, fs.ErrNotExist) {
|
|
slog.Error("failed to remove example env file", "error", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
err = os.WriteFile("config.gen.md", compiled, 0644)
|
|
if err != nil {
|
|
slog.Error("failed to write example env file", "error", err)
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
func buildMdEntry(child reflect.StructField, childValue reflect.Value, parentPath string, entries *[]MarkdownEntry) {
|
|
desc := child.Tag.Get("description")
|
|
tag := child.Tag.Get("yaml")
|
|
gen := child.Tag.Get("gen")
|
|
|
|
if tag == "-" && gen != "include" {
|
|
return
|
|
}
|
|
|
|
tag = strings.TrimSuffix(tag, ",omitempty")
|
|
|
|
value := childValue.Interface()
|
|
|
|
configOptions := ConfigOptions{
|
|
Env: strings.ToUpper(strings.ReplaceAll(parentPath, ".", "_")) + strings.ToUpper(child.Name),
|
|
Flag: fmt.Sprintf("--%s%s", strings.TrimPrefix(parentPath, "tinyauth."), strings.ToLower(child.Name)),
|
|
}
|
|
|
|
if tag != "-" && tag != "" {
|
|
configOptions.YAML = strings.TrimPrefix(parentPath, "tinyauth.") + tag
|
|
}
|
|
|
|
entry := MarkdownEntry{
|
|
Options: configOptions,
|
|
Description: desc,
|
|
}
|
|
|
|
switch childValue.Kind() {
|
|
case reflect.Slice:
|
|
sl, ok := value.([]string)
|
|
if !ok {
|
|
slog.Error("invalid default value", "value", value)
|
|
return
|
|
}
|
|
entry.Default = fmt.Sprintf("`%s`", strings.Join(sl, ","))
|
|
default:
|
|
entry.Default = fmt.Sprintf("`%v`", value)
|
|
}
|
|
*entries = append(*entries, entry)
|
|
}
|
|
|
|
func buildMdMapEntry(child reflect.StructField, parentPath string, entries *[]MarkdownEntry) {
|
|
fieldType := child.Type
|
|
|
|
if fieldType.Key().Kind() != reflect.String {
|
|
slog.Info("unsupported map key type", "type", fieldType.Key().Kind())
|
|
return
|
|
}
|
|
|
|
tag := child.Tag.Get("yaml")
|
|
gen := child.Tag.Get("gen")
|
|
|
|
if tag == "-" && gen != "include" {
|
|
return
|
|
}
|
|
|
|
tag = strings.TrimSuffix(tag, ",omitempty")
|
|
|
|
mapPath := parentPath + tag + ".[name]."
|
|
valueType := fieldType.Elem()
|
|
|
|
if valueType.Kind() == reflect.Struct {
|
|
zeroValue := reflect.New(valueType).Elem()
|
|
walkAndBuild(valueType, zeroValue, mapPath, entries, buildMdEntry, buildMdMapEntry, buildMdChildPath)
|
|
}
|
|
}
|
|
|
|
func buildMdChildPath(parent string, child string) string {
|
|
return parent + strings.ToLower(child) + "."
|
|
}
|
|
|
|
func compileMd(entries []MarkdownEntry) []byte {
|
|
buffer := strings.Builder{}
|
|
|
|
buffer.WriteString("{/* This part is automatically generated by gen/gen_md.go in the main repository. DO NOT EDIT. */}\n\n")
|
|
buffer.WriteString("import { Tabs, TabItem } from '@astrojs/starlight/components';\n\n")
|
|
buffer.WriteString("<Tabs>\n")
|
|
|
|
renderTabItem(&buffer, entries, "Environment")
|
|
renderTabItem(&buffer, entries, "Flags")
|
|
renderTabItem(&buffer, entries, "YAML")
|
|
|
|
buffer.WriteString("</Tabs>\n")
|
|
|
|
return []byte(buffer.String())
|
|
}
|
|
|
|
func renderTabItem(buffer *strings.Builder, entries []MarkdownEntry, section string) {
|
|
buffer.WriteString(fmt.Sprintf(" <TabItem label=\"%s\">\n", section))
|
|
buffer.WriteString(" ### main\n\n")
|
|
buffer.WriteString(" | Option | Description | Default |\n")
|
|
buffer.WriteString(" | - | - | - |\n")
|
|
|
|
configType := strings.ToLower(section)
|
|
previousSection := ""
|
|
|
|
for _, entry := range entries {
|
|
section := strings.Split(entry.Options.YAML, ".")[0]
|
|
var option string
|
|
switch configType {
|
|
case "yaml":
|
|
option = entry.Options.YAML
|
|
case "flags":
|
|
option = entry.Options.Flag
|
|
case "environment":
|
|
option = entry.Options.Env
|
|
}
|
|
if option == "" {
|
|
continue
|
|
}
|
|
if strings.Count(entry.Options.YAML, ".") >= 1 {
|
|
if section != previousSection {
|
|
buffer.WriteString("\n ### " + strings.ToLower(section) + "\n\n")
|
|
buffer.WriteString(" | Option | Description | Default |\n")
|
|
buffer.WriteString(" | - | - | - |\n")
|
|
previousSection = section
|
|
}
|
|
}
|
|
fmt.Fprintf(buffer, " | `%s` | %s | %s |\n", option, entry.Description, entry.Default)
|
|
}
|
|
|
|
buffer.WriteString(" </TabItem>\n")
|
|
}
|