budgit/internal/app/app.go
2026-01-14 21:51:08 +00:00

102 lines
3.3 KiB
Go

package app
import (
"fmt"
"git.juancwu.dev/juancwu/budgit/internal/config"
"git.juancwu.dev/juancwu/budgit/internal/db"
"git.juancwu.dev/juancwu/budgit/internal/event"
"git.juancwu.dev/juancwu/budgit/internal/repository"
"git.juancwu.dev/juancwu/budgit/internal/service"
"github.com/jmoiron/sqlx"
)
type App struct {
Cfg *config.Config
DB *sqlx.DB
EventBus *event.Broker
UserService *service.UserService
AuthService *service.AuthService
EmailService *service.EmailService
ProfileService *service.ProfileService
SpaceService *service.SpaceService
TagService *service.TagService
ShoppingListService *service.ShoppingListService
ExpenseService *service.ExpenseService
InviteService *service.InviteService
}
func New(cfg *config.Config) (*App, error) {
database, err := db.Init(cfg.DBDriver, cfg.DBConnection)
if err != nil {
return nil, fmt.Errorf("failed to initialize database: %w", err)
}
err = db.RunMigrations(database.DB, cfg.DBDriver)
if err != nil {
return nil, fmt.Errorf("failed to run migrations: %w", err)
}
eventBus := event.NewBroker()
emailClient := service.NewEmailClient(cfg.MailerSMTPHost, cfg.MailerSMTPPort, cfg.MailerIMAPHost, cfg.MailerIMAPPort, cfg.MailerUsername, cfg.MailerPassword)
// Repositories
userRepository := repository.NewUserRepository(database)
profileRepository := repository.NewProfileRepository(database)
tokenRepository := repository.NewTokenRepository(database)
spaceRepository := repository.NewSpaceRepository(database)
tagRepository := repository.NewTagRepository(database)
shoppingListRepository := repository.NewShoppingListRepository(database)
listItemRepository := repository.NewListItemRepository(database)
expenseRepository := repository.NewExpenseRepository(database)
invitationRepository := repository.NewInvitationRepository(database)
// Services
userService := service.NewUserService(userRepository)
spaceService := service.NewSpaceService(spaceRepository)
emailService := service.NewEmailService(
emailClient,
cfg.MailerEmailFrom,
cfg.AppURL,
cfg.AppName,
cfg.IsProduction(),
)
authService := service.NewAuthService(
emailService,
userRepository,
profileRepository,
tokenRepository,
spaceService,
cfg.JWTSecret,
cfg.JWTExpiry,
cfg.TokenMagicLinkExpiry,
cfg.IsProduction(),
)
profileService := service.NewProfileService(profileRepository)
tagService := service.NewTagService(tagRepository)
shoppingListService := service.NewShoppingListService(shoppingListRepository, listItemRepository, eventBus)
expenseService := service.NewExpenseService(expenseRepository, eventBus)
inviteService := service.NewInviteService(invitationRepository, spaceRepository, userRepository, emailService)
return &App{
Cfg: cfg,
DB: database,
EventBus: eventBus,
UserService: userService,
AuthService: authService,
EmailService: emailService,
ProfileService: profileService,
SpaceService: spaceService,
TagService: tagService,
ShoppingListService: shoppingListService,
ExpenseService: expenseService,
InviteService: inviteService,
}, nil
}
func (a *App) Close() error {
if a.DB != nil {
return a.DB.Close()
}
return nil
}