rentease/main.go
Ruidy 9b2510460a
Some checks are pending
CI / checks (push) Waiting to run
feat: store invoice PDFs in minio
2026-03-20 23:58:57 +01:00

136 lines
3.8 KiB
Go

package main
import (
"context"
"fmt"
"log/slog"
"os"
"os/signal"
"github.com/getsentry/sentry-go"
"github.com/rjNemo/rentease/assets"
"github.com/rjNemo/rentease/internal/config"
"github.com/rjNemo/rentease/internal/driver/database"
"github.com/rjNemo/rentease/internal/driver/logger"
"github.com/rjNemo/rentease/internal/driver/parser"
"github.com/rjNemo/rentease/internal/driver/pdf"
"github.com/rjNemo/rentease/internal/driver/storage"
stripeclient "github.com/rjNemo/rentease/internal/driver/stripe"
bookingRepo "github.com/rjNemo/rentease/internal/repository/booking"
"github.com/rjNemo/rentease/internal/server"
"github.com/rjNemo/rentease/internal/service/auth"
"github.com/rjNemo/rentease/internal/service/booking"
"github.com/rjNemo/rentease/internal/service/payment"
)
func main() {
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
defer cancel()
baseLogger := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{AddSource: true}))
appConfig, err := config.New(ctx)
if err != nil {
baseLogger.Error("configuration error", slog.Any("error", err))
}
appLogger := logger.New(appConfig.LogLevel)
slog.SetDefault(appLogger)
if err := run(ctx, appConfig, appLogger); err != nil {
appLogger.Error("server exited", slog.Any("error", err))
os.Exit(1)
}
}
func run(ctx context.Context, appConfig *config.Config, appLogger *slog.Logger) error {
// init sentry
if err := sentry.Init(sentry.ClientOptions{
Dsn: appConfig.SentryDsn,
EnableTracing: true,
TracesSampleRate: 1.0,
}); err != nil {
return fmt.Errorf("error initializing sentry %w", err)
}
// init database
db, err := database.New(appConfig.DatabaseURL)
if err != nil {
return fmt.Errorf("error connecting to the database %w", err)
}
if err = database.Migrate(db, &booking.Booking{}, &booking.Item{}, &booking.Payment{}, &booking.InvoiceDocument{}); err != nil {
return fmt.Errorf("error migrating the database %w", err)
}
bookingStore := bookingRepo.NewPgStore(db)
// build pdf client
pc, err := pdf.NewPdfClient()
if err != nil {
return fmt.Errorf("error starting pdf client %w", err)
}
invoiceStorage, err := storage.NewMinioInvoiceStorage(appConfig)
if err != nil {
return fmt.Errorf("error starting invoice storage %w", err)
}
parsingClient := parser.NewBookingAgentParser(appConfig.OpenAIModel)
var stripeClient payment.StripeClient
if appConfig.StripeSecretKey != "" {
opts := []stripeclient.Option{}
client, err := stripeclient.New(appConfig.StripeSecretKey, opts...)
if err != nil {
return fmt.Errorf("error creating stripe client: %w", err)
}
stripeClient = client
}
bookingService, err := booking.NewService(appLogger, bookingStore, parsingClient, pc, invoiceStorage, appConfig.InvoiceShareURLTTL)
if err != nil {
return fmt.Errorf("error creating booking service: %w", err)
}
paymentService, err := payment.NewService(appLogger, bookingStore, stripeClient)
if err != nil {
return fmt.Errorf("error creating payment service: %w", err)
}
// build authentication service
as, err := auth.NewService(
appConfig.SessionSecret,
appConfig.Admin,
appConfig.AdminSecret,
appConfig.APIKey,
)
if err != nil {
return fmt.Errorf("error starting auth service %w", err)
}
port := appConfig.Port
origins := appConfig.Origins
srv, err := server.New(
bookingService,
paymentService,
as,
config.NewHost(), // TODO: move to the database at some point
server.WithPort(port),
server.WithFileSystem(assets.Static),
server.WithDebug(appConfig.Debug),
server.WithSecretKey(appConfig.SecretKey),
server.WithOrigins(origins),
server.WithStripeWebhookSecret(appConfig.StripeWebhookSecret),
)
if err != nil {
return fmt.Errorf("error starting server %w", err)
}
srv.Start(ctx)
return nil
}