package main import ( "context" "fmt" "io" "log/slog" "os" "strings" _ "github.com/joho/godotenv/autoload" "github.com/earthboundkid/versioninfo/v2" "github.com/urfave/cli/v3" ) func main() { if err := run(os.Args); err != nil { slog.Error("exiting", "err", err) os.Exit(-1) } } func run(args []string) error { app := cli.Command{ Name: "atbin", Usage: "atbin server daemon", Version: versioninfo.Short(), Flags: []cli.Flag{ &cli.StringFlag{ Name: "log-level", Usage: "log verbosity level (eg: warn, info, debug)", Sources: cli.EnvVars("ATBIN_LOG_LEVEL", "GO_LOG_LEVEL", "LOG_LEVEL"), }, }, Commands: []*cli.Command{ &cli.Command{ Name: "serve", Usage: "run the atbin daemon", Action: runServeCmd, Flags: []cli.Flag{ &cli.StringFlag{ Name: "bind", Usage: "specify the local IP/port to bind to", Required: false, Value: ":7700", Sources: cli.EnvVars("ATBIN_BIND"), }, }, }, }, } return app.Run(context.Background(), args) } func configLogger(cmd *cli.Command, writer io.Writer) *slog.Logger { var level slog.Level switch strings.ToLower(cmd.String("log-level")) { case "error": level = slog.LevelError case "warn": level = slog.LevelWarn case "info": level = slog.LevelInfo case "debug": level = slog.LevelDebug default: level = slog.LevelInfo } logger := slog.New(slog.NewJSONHandler(writer, &slog.HandlerOptions{ Level: level, })) slog.SetDefault(logger) return logger } func runServeCmd(ctx context.Context, cmd *cli.Command) error { logger := configLogger(cmd, os.Stdout) srv, err := NewServer( Config{ Logger: logger, Bind: cmd.String("bind"), }, ) if err != nil { return fmt.Errorf("failed to construct server: %v", err) } return srv.Run() }