Files
boc/backend/main.go
T

93 lines
2.4 KiB
Go
Raw Normal View History

package main
import (
"context"
"net/http"
"os"
"os/signal"
"syscall"
"time"
"github.com/go-chi/chi/v5"
chimw "github.com/go-chi/chi/v5/middleware"
"github.com/rs/zerolog"
"github.com/rs/zerolog/hlog"
"boc/config"
"boc/db"
"boc/handlers"
"boc/ledger"
"boc/middleware"
"boc/store"
)
func main() {
logger := zerolog.New(os.Stdout).With().Timestamp().Logger()
cfg := config.Load()
database, err := db.Connect(cfg.DBURL)
if err != nil {
logger.Fatal().Err(err).Msg("database connect failed")
}
defer database.Close()
if err := db.RunMigrations(database, cfg.MigrationsDir); err != nil {
logger.Fatal().Err(err).Msg("migrations failed")
}
_ = store.New(database) // TODO: wire to handlers when migrated
auth := &handlers.AuthHandler{DB: database, JWTSecret: []byte(cfg.JWTSecret)}
ledgerH := ledger.NewHandler()
r := chi.NewRouter()
r.Use(middleware.CORS)
r.Use(hlog.NewHandler(logger))
r.Use(hlog.RequestIDHandler("req_id", "X-Request-ID"))
r.Use(middleware.Logger(logger))
r.Use(chimw.Recoverer)
r.Get("/health", handlers.NewHealthHandler())
r.Post("/api/v1/auth/login", auth.Login)
r.Group(func(r chi.Router) {
r.Use(middleware.Auth(cfg))
r.Get("/api/v1/auth/me", auth.Me)
// Ledger (proxy to aamos-ledger)
r.Get("/api/v1/finance/balance", ledgerH.GetBalanceSheet)
r.Get("/api/v1/finance/income", ledgerH.GetIncomeStatement)
r.Get("/api/v1/finance/moms", ledgerH.GetMomsReport)
r.Get("/api/v1/finance/accounts", ledgerH.GetAccounts)
r.Get("/api/v1/finance/invoices", ledgerH.GetInvoices)
// TODO: Migrate remaining handlers to generic store pattern
// CRM, Sales, Finance, HR, Legal, Marketing, Support, Analytics, Automation
})
srv := &http.Server{
Addr: ":" + cfg.Port,
Handler: r,
ReadTimeout: 15 * time.Second,
WriteTimeout: 30 * time.Second,
IdleTimeout: 120 * time.Second,
}
go func() {
logger.Info().Str("addr", srv.Addr).Msg("BOC server starting")
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
logger.Fatal().Err(err).Msg("listen error")
}
}()
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
logger.Info().Msg("shutting down")
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
if err := srv.Shutdown(ctx); err != nil {
logger.Error().Err(err).Msg("shutdown error")
}
}