package main import ( "net/http" "time" "github.com/food-ai/backend/internal/auth" "github.com/food-ai/backend/internal/infra/config" "github.com/food-ai/backend/internal/diary" "github.com/food-ai/backend/internal/dish" "github.com/food-ai/backend/internal/adapters/openai" "github.com/food-ai/backend/internal/home" "github.com/food-ai/backend/internal/ingredient" "github.com/food-ai/backend/internal/menu" "github.com/food-ai/backend/internal/infra/middleware" "github.com/food-ai/backend/internal/adapters/pexels" "github.com/food-ai/backend/internal/product" "github.com/food-ai/backend/internal/recipe" "github.com/food-ai/backend/internal/recognition" "github.com/food-ai/backend/internal/recommendation" "github.com/food-ai/backend/internal/savedrecipe" "github.com/food-ai/backend/internal/cuisine" "github.com/food-ai/backend/internal/infra/server" "github.com/food-ai/backend/internal/tag" "github.com/food-ai/backend/internal/units" "github.com/food-ai/backend/internal/user" "github.com/jackc/pgx/v5/pgxpool" ) // --------------------------------------------------------------------------- // Newtypes for config primitives — prevents Wire type collisions. // --------------------------------------------------------------------------- // Newtypes for list handlers — prevents Wire type collisions on http.HandlerFunc. type unitsListHandler http.HandlerFunc type cuisineListHandler http.HandlerFunc type tagListHandler http.HandlerFunc // --------------------------------------------------------------------------- type openaiAPIKey string type pexelsAPIKey string type jwtSecret string type jwtAccessDuration time.Duration type jwtRefreshDuration time.Duration type allowedOrigins []string // --------------------------------------------------------------------------- // Config extractors // --------------------------------------------------------------------------- func newOpenAIAPIKey(appConfig *config.Config) openaiAPIKey { return openaiAPIKey(appConfig.OpenAIAPIKey) } func newPexelsAPIKey(appConfig *config.Config) pexelsAPIKey { return pexelsAPIKey(appConfig.PexelsAPIKey) } func newJWTSecret(appConfig *config.Config) jwtSecret { return jwtSecret(appConfig.JWTSecret) } func newJWTAccessDuration(appConfig *config.Config) jwtAccessDuration { return jwtAccessDuration(appConfig.JWTAccessDuration) } func newJWTRefreshDuration(appConfig *config.Config) jwtRefreshDuration { return jwtRefreshDuration(appConfig.JWTRefreshDuration) } func newAllowedOrigins(appConfig *config.Config) allowedOrigins { return allowedOrigins(appConfig.AllowedOrigins) } // newFirebaseCredentialsFile is the only string that reaches NewFirebaseAuthOrNoop, // so no newtype is needed here. func newFirebaseCredentialsFile(appConfig *config.Config) string { return appConfig.FirebaseCredentialsFile } // --------------------------------------------------------------------------- // Constructor wrappers for functions that accept primitive newtypes // --------------------------------------------------------------------------- func newOpenAIClient(key openaiAPIKey) *openai.Client { return openai.NewClient(string(key)) } func newPexelsClient(key pexelsAPIKey) *pexels.Client { return pexels.NewClient(string(key)) } func newJWTManager( secret jwtSecret, accessDuration jwtAccessDuration, refreshDuration jwtRefreshDuration, ) *auth.JWTManager { return auth.NewJWTManager(string(secret), time.Duration(accessDuration), time.Duration(refreshDuration)) } // --------------------------------------------------------------------------- // List handler providers // --------------------------------------------------------------------------- func newUnitsListHandler(pool *pgxpool.Pool) unitsListHandler { return unitsListHandler(units.NewListHandler(pool)) } func newCuisineListHandler(pool *pgxpool.Pool) cuisineListHandler { return cuisineListHandler(cuisine.NewListHandler(pool)) } func newTagListHandler(pool *pgxpool.Pool) tagListHandler { return tagListHandler(tag.NewListHandler(pool)) } // --------------------------------------------------------------------------- // newRouter wraps server.NewRouter to accept newtypes. func newRouter( pool *pgxpool.Pool, authHandler *auth.Handler, userHandler *user.Handler, recommendationHandler *recommendation.Handler, savedRecipeHandler *savedrecipe.Handler, ingredientHandler *ingredient.Handler, productHandler *product.Handler, recognitionHandler *recognition.Handler, menuHandler *menu.Handler, diaryHandler *diary.Handler, homeHandler *home.Handler, dishHandler *dish.Handler, recipeHandler *recipe.Handler, authMiddleware func(http.Handler) http.Handler, origins allowedOrigins, unitsHandler unitsListHandler, cuisineHandler cuisineListHandler, tagHandler tagListHandler, ) http.Handler { return server.NewRouter( pool, authHandler, userHandler, recommendationHandler, savedRecipeHandler, ingredientHandler, productHandler, recognitionHandler, menuHandler, diaryHandler, homeHandler, dishHandler, recipeHandler, authMiddleware, []string(origins), http.HandlerFunc(unitsHandler), http.HandlerFunc(cuisineHandler), http.HandlerFunc(tagHandler), ) } // --------------------------------------------------------------------------- // jwtAdapter — adapts *auth.JWTManager to middleware.AccessTokenValidator. // --------------------------------------------------------------------------- type jwtAdapter struct { jwtManager *auth.JWTManager } func newJWTAdapter(jm *auth.JWTManager) *jwtAdapter { return &jwtAdapter{jwtManager: jm} } func (adapter *jwtAdapter) ValidateAccessToken(tokenStr string) (*middleware.TokenClaims, error) { claims, validationError := adapter.jwtManager.ValidateAccessToken(tokenStr) if validationError != nil { return nil, validationError } return &middleware.TokenClaims{ UserID: claims.UserID, Plan: claims.Plan, }, nil } // newAuthMiddleware wraps middleware.Auth for Wire injection. func newAuthMiddleware(validator middleware.AccessTokenValidator) func(http.Handler) http.Handler { return middleware.Auth(validator) } // --------------------------------------------------------------------------- // Interface assertions (compile-time checks) // --------------------------------------------------------------------------- var _ middleware.AccessTokenValidator = (*jwtAdapter)(nil) var _ menu.PhotoSearcher = (*pexels.Client)(nil) var _ menu.UserLoader = (*user.Repository)(nil) var _ menu.ProductLister = (*product.Repository)(nil) var _ menu.RecipeSaver = (*dish.Repository)(nil) var _ recommendation.PhotoSearcher = (*pexels.Client)(nil) var _ recommendation.UserLoader = (*user.Repository)(nil) var _ recommendation.ProductLister = (*product.Repository)(nil) var _ recognition.IngredientRepository = (*ingredient.Repository)(nil) var _ user.UserRepository = (*user.Repository)(nil)