// Package bootstrap é o composition root: monta o app.Service com os adapters // reais. Usado pela api, pelo worker e pela CLI. package bootstrap import ( "context" "fmt" "log/slog" "github.com/jackc/pgx/v5/pgxpool" "botpontos/internal/adapters/crypto" "botpontos/internal/adapters/feriados" "botpontos/internal/adapters/pontomais" "botpontos/internal/adapters/postgres" "botpontos/internal/adapters/telegram" "botpontos/internal/app" "botpontos/internal/config" ) // Built é o serviço montado com todos os adapters reais. type Built struct { Service *app.Service Pool *pgxpool.Pool Telegram *telegram.Client } // Build abre o banco e monta o serviço com os adapters reais. func Build(ctx context.Context, cfg config.Config, logger *slog.Logger) (*Built, error) { if err := cfg.RequireCrypto(); err != nil { return nil, err } keyring, err := crypto.NewKeyring(cfg.Crypto.Key, int16(cfg.Crypto.KeyVersion), cfg.Crypto.PreviousKey, int16(cfg.Crypto.PreviousKeyVersion)) if err != nil { return nil, fmt.Errorf("chave de criptografia: %w", err) } pool, err := postgres.OpenPool(ctx, cfg.DB, logger) if err != nil { return nil, err } tg := telegram.NewClient(cfg.Telegram.Token) var holidays app.HolidayProvider if client := feriados.NewClient(cfg.Holidays.BaseURL, cfg.Holidays.APIKey, cfg.Holidays.Location); client.Configured() { holidays = client } svc := app.New(app.Deps{ Store: postgres.NewStore(pool), Points: pontomais.NewClient(cfg.PontoMais.AuthURL, cfg.PontoMais.HistoryURL, cfg.PontoMais.Timeout, keyring), Messenger: tg, Holidays: holidays, Cipher: keyring, Config: cfg, Logger: logger, }) return &Built{Service: svc, Pool: pool, Telegram: tg}, nil }