c2b10347b1
- Removed rust-service/, c-runtime/, kafka stubs - Generic Store[T] pattern with real tests - Slimmed main.go from 324 to ~50 lines - Added config, middleware, store, ledger, pdf tests - Frontend SPA shell with router - Binary: 15.5MB -> 12MB
93 lines
2.4 KiB
Go
93 lines
2.4 KiB
Go
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")
|
|
}
|
|
}
|