feat: init project
This commit is contained in:
51
cmd/root.go
Normal file
51
cmd/root.go
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
Copyright © 2025 NAME HERE <EMAIL ADDRESS>
|
||||
|
||||
*/
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
|
||||
|
||||
// rootCmd represents the base command when called without any subcommands
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "database_render",
|
||||
Short: "A brief description of your application",
|
||||
Long: `A longer description that spans multiple lines and likely contains
|
||||
examples and usage of using your application. For example:
|
||||
|
||||
Cobra is a CLI library for Go that empowers applications.
|
||||
This application is a tool to generate the needed files
|
||||
to quickly create a Cobra application.`,
|
||||
// Uncomment the following line if your bare application
|
||||
// has an action associated with it:
|
||||
// Run: func(cmd *cobra.Command, args []string) { },
|
||||
}
|
||||
|
||||
// Execute adds all child commands to the root command and sets flags appropriately.
|
||||
// This is called by main.main(). It only needs to happen once to the rootCmd.
|
||||
func Execute() {
|
||||
err := rootCmd.Execute()
|
||||
if err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
// Here you will define your flags and configuration settings.
|
||||
// Cobra supports persistent flags, which, if defined here,
|
||||
// will be global for your application.
|
||||
|
||||
// rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.database_render.yaml)")
|
||||
|
||||
// Cobra also supports local flags, which will only run
|
||||
// when this action is called directly.
|
||||
rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
|
||||
}
|
||||
|
||||
|
||||
137
cmd/server/main.go
Normal file
137
cmd/server/main.go
Normal file
@@ -0,0 +1,137 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/gofiber/fiber/v3/middleware/cors"
|
||||
"github.com/gofiber/fiber/v3/middleware/recover"
|
||||
"github.com/rogeecn/database_render/internal/config"
|
||||
"github.com/rogeecn/database_render/internal/database"
|
||||
"github.com/rogeecn/database_render/internal/handler"
|
||||
"github.com/rogeecn/database_render/internal/repository"
|
||||
"github.com/rogeecn/database_render/internal/service"
|
||||
"github.com/rogeecn/database_render/internal/template"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Initialize structured logging
|
||||
opts := &slog.HandlerOptions{
|
||||
Level: slog.LevelInfo,
|
||||
}
|
||||
logger := slog.New(slog.NewJSONHandler(os.Stdout, opts))
|
||||
slog.SetDefault(logger)
|
||||
|
||||
// Load configuration
|
||||
cfg, err := config.LoadConfig("")
|
||||
if err != nil {
|
||||
slog.Error("failed to load configuration", "error", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Initialize database
|
||||
db, err := database.NewConnectionManager(cfg)
|
||||
if err != nil {
|
||||
slog.Error("failed to initialize database", "error", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer func() {
|
||||
if err := db.Close(); err != nil {
|
||||
slog.Error("failed to close database", "error", err)
|
||||
}
|
||||
}()
|
||||
|
||||
// Initialize repository and services
|
||||
repo := repository.NewDataRepository(db, cfg)
|
||||
svc := service.NewDataService(repo, cfg)
|
||||
if err := svc.ValidateConfiguration(); err != nil {
|
||||
slog.Error("configuration validation failed", "error", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Initialize renderer
|
||||
renderer, err := template.NewRenderer(svc, cfg)
|
||||
if err != nil {
|
||||
slog.Error("failed to initialize renderer", "error", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Initialize handlers
|
||||
dataHandler := handler.NewDataHandler(svc)
|
||||
|
||||
// Initialize Fiber app
|
||||
app := fiber.New(fiber.Config{
|
||||
ReadTimeout: 30 * time.Second,
|
||||
WriteTimeout: 30 * time.Second,
|
||||
IdleTimeout: 60 * time.Second,
|
||||
ErrorHandler: renderer.ErrorHandler,
|
||||
Views: nil, // Using custom renderer
|
||||
})
|
||||
|
||||
// Setup middleware
|
||||
app.Use(recover.New())
|
||||
app.Use(cors.New(cors.Config{
|
||||
AllowOrigins: []string{"*"},
|
||||
AllowMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
|
||||
AllowHeaders: []string{"Origin", "Content-Type", "Accept"},
|
||||
}))
|
||||
|
||||
// Setup routes
|
||||
// API routes
|
||||
dataHandler.SetupRoutes(app)
|
||||
|
||||
// Template routes
|
||||
app.Get("/", func(c fiber.Ctx) error {
|
||||
tableName := c.Query("table")
|
||||
if tableName == "" {
|
||||
return renderer.RenderIndex(c)
|
||||
}
|
||||
return renderer.RenderList(c, tableName)
|
||||
})
|
||||
|
||||
// Setup static file serving
|
||||
renderer.ServeStatic(app)
|
||||
|
||||
// Health check endpoint
|
||||
app.Get("/health", func(c fiber.Ctx) error {
|
||||
return c.JSON(map[string]string{
|
||||
"status": "ok",
|
||||
"timestamp": time.Now().Format(time.RFC3339),
|
||||
})
|
||||
})
|
||||
|
||||
// Start server
|
||||
port := cfg.App.Port
|
||||
if port == 0 {
|
||||
port = 8080
|
||||
}
|
||||
|
||||
// Start server in a goroutine
|
||||
go func() {
|
||||
slog.Info("starting server", "port", port)
|
||||
if err := app.Listen(fmt.Sprintf(":%d", port)); err != nil {
|
||||
slog.Error("server error", "error", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}()
|
||||
|
||||
// Wait for interrupt signal to gracefully shutdown the server
|
||||
quit := make(chan os.Signal, 1)
|
||||
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
|
||||
<-quit
|
||||
|
||||
slog.Info("shutting down server...")
|
||||
|
||||
// Shutdown server
|
||||
if err := app.Shutdown(); err != nil {
|
||||
slog.Error("server shutdown error", "error", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
slog.Info("server gracefully stopped")
|
||||
}
|
||||
Reference in New Issue
Block a user