add initial application structure with configuration, logging, and health check endpoints

This commit is contained in:
kever
2026-01-14 23:58:00 +08:00
commit fed727e593
31 changed files with 770 additions and 0 deletions

142
cmd/gen/controllers/main.go Normal file
View File

@@ -0,0 +1,142 @@
package main
import (
"bytes"
"fmt"
"go/format"
"os"
"path/filepath"
"regexp"
"sort"
)
func main() {
controllerDir, err := findControllerDir()
if err != nil {
fatal(err)
}
ctors, err := findControllerCtors(controllerDir)
if err != nil {
fatal(err)
}
content, err := renderModule(ctors)
if err != nil {
fatal(err)
}
outPath := filepath.Join(controllerDir, "module.go")
if err := os.WriteFile(outPath, content, 0o644); err != nil {
fatal(err)
}
}
func findControllerDir() (string, error) {
wd, err := os.Getwd()
if err != nil {
return "", err
}
if exists(filepath.Join(wd, "module.go")) && exists(filepath.Join(wd, "routes.go")) {
return wd, nil
}
candidate := filepath.Join(wd, "internal", "controller")
if exists(filepath.Join(candidate, "module.go")) {
return candidate, nil
}
return "", fmt.Errorf("could not locate internal/controller")
}
func findControllerCtors(dir string) ([]string, error) {
entries, err := os.ReadDir(dir)
if err != nil {
return nil, err
}
ctorRe := regexp.MustCompile(`(?m)^func\s+(New[A-Za-z0-9_]*Controller)\s*\(`)
seen := make(map[string]struct{})
for _, entry := range entries {
if entry.IsDir() {
continue
}
name := entry.Name()
if !hasSuffix(name, "_controller.go") {
continue
}
if name == "module.go" {
continue
}
path := filepath.Join(dir, name)
data, err := os.ReadFile(path)
if err != nil {
return nil, err
}
matches := ctorRe.FindAllSubmatch(data, -1)
for _, m := range matches {
if len(m) < 2 {
continue
}
seen[string(m[1])] = struct{}{}
}
}
var ctors []string
for k := range seen {
ctors = append(ctors, k)
}
sort.Strings(ctors)
return ctors, nil
}
func renderModule(ctors []string) ([]byte, error) {
var buf bytes.Buffer
buf.WriteString("// Code generated by cmd/gen/controllers; DO NOT EDIT.\n")
buf.WriteString("package controller\n\n")
buf.WriteString("import \"go.uber.org/fx\"\n\n")
buf.WriteString("var Module = fx.Options(\n")
if len(ctors) > 0 {
buf.WriteString("\tfx.Provide(\n")
for _, ctor := range ctors {
buf.WriteString("\t\t")
buf.WriteString(ctor)
buf.WriteString(",\n")
}
buf.WriteString("\t),\n")
}
buf.WriteString("\tfx.Invoke(\n\t\tRegisterRoutes,\n\t),\n")
buf.WriteString(")\n")
formatted, err := format.Source(buf.Bytes())
if err != nil {
return nil, err
}
return formatted, nil
}
func exists(path string) bool {
info, err := os.Stat(path)
if err != nil {
return false
}
return !info.IsDir()
}
func hasSuffix(s, suffix string) bool {
return len(s) >= len(suffix) && s[len(s)-len(suffix):] == suffix
}
func fatal(err error) {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}

22
cmd/server/main.go Normal file
View File

@@ -0,0 +1,22 @@
package main
import (
"context"
"log"
"epic-ent/internal/bootstrap"
)
func main() {
app := bootstrap.NewApp()
if err := app.Start(context.Background()); err != nil {
log.Fatalf("failed to start app: %v", err)
}
<-app.Done()
if err := app.Stop(context.Background()); err != nil {
log.Printf("failed to stop app: %v", err)
}
}