Files
goyco/cmd/goyco/main.go

140 lines
3.4 KiB
Go

// @title Goyco API
// @version 0.1.0
// @description Goyco is a Y Combinator-style news aggregation platform API.
// @contact.name Goyco Team
// @contact.email sandro@cazzaniga.fr
// @license.name GPLv3
// @license.url https://www.gnu.org/licenses/gpl-3.0.html
// @host localhost:8080
// @schemes http
// @BasePath /api
package main
import (
"errors"
"flag"
"fmt"
"log"
"os"
"goyco/cmd/goyco/commands"
"goyco/docs"
"goyco/internal/config"
"goyco/internal/version"
)
func main() {
loadDotEnv()
commands.SetRunServer(runServerImpl)
if len(os.Args) > 1 && os.Args[len(os.Args)-1] == "--daemon" {
args := os.Args[1 : len(os.Args)-1]
if err := commands.RunDaemonProcessDirect(args); err != nil {
log.Fatalf("daemon error: %v", err)
}
return
}
if err := run(os.Args[1:]); err != nil {
log.Fatalf("error: %v", err)
}
}
func run(args []string) error {
cfg, err := config.Load()
if err != nil {
return fmt.Errorf("load configuration: %w", err)
}
validator := commands.NewConfigValidator(nil)
if err := validator.ValidateConfiguration(cfg); err != nil {
return fmt.Errorf("configuration validation failed: %w", err)
}
docs.SwaggerInfo.Title = fmt.Sprintf("%s API", cfg.App.Title)
docs.SwaggerInfo.Description = "Y Combinator-style news board API."
docs.SwaggerInfo.Version = version.Version
docs.SwaggerInfo.BasePath = "/api"
docs.SwaggerInfo.Host = fmt.Sprintf("%s:%s", cfg.Server.Host, cfg.Server.Port)
docs.SwaggerInfo.Schemes = []string{"http"}
if cfg.Server.EnableTLS {
docs.SwaggerInfo.Schemes = append(docs.SwaggerInfo.Schemes, "https")
}
rootFS := flag.NewFlagSet("goyco", flag.ContinueOnError)
rootFS.SetOutput(os.Stderr)
rootFS.Usage = printRootUsage
showHelp := rootFS.Bool("help", false, "show this help message")
jsonOutput := rootFS.Bool("json", cfg.CLI.JSONOutputDefault, "output results in JSON format")
if err := rootFS.Parse(args); err != nil {
if errors.Is(err, flag.ErrHelp) {
return nil
}
return fmt.Errorf("failed to parse arguments: %w", err)
}
if *showHelp {
printRootUsage()
return nil
}
commands.SetJSONOutput(*jsonOutput)
remaining := rootFS.Args()
if len(remaining) == 0 {
printRootUsage()
return nil
}
return dispatchCommand(cfg, remaining[0], remaining[1:])
}
func dispatchCommand(cfg *config.Config, name string, args []string) error {
switch name {
case "run":
return handleRunCommand(cfg, args)
case "start":
return commands.HandleStartCommand(cfg, args)
case "stop":
return commands.HandleStopCommand(cfg, args)
case "status":
return commands.HandleStatusCommand(cfg, name, args)
case "user":
return commands.HandleUserCommand(cfg, name, args)
case "post":
return commands.HandlePostCommand(cfg, name, args)
case "prune":
return commands.HandlePruneCommand(cfg, name, args)
case "migrate", "migrations":
return commands.HandleMigrateCommand(cfg, name, args)
case "seed":
return commands.HandleSeedCommand(cfg, name, args)
case "help", "-h", "--help":
printRootUsage()
return nil
default:
printRootUsage()
return fmt.Errorf("unknown command: %s", name)
}
}
func handleRunCommand(cfg *config.Config, args []string) error {
fs := newFlagSet("run", printRunUsage)
if err := parseCommand(fs, args, "run"); err != nil {
if errors.Is(err, commands.ErrHelpRequested) {
return nil
}
return err
}
if fs.NArg() > 0 {
printRunUsage()
return errors.New("unexpected arguments for run command")
}
return runServer(cfg, false)
}