refactor: introduce adapter pattern for AI provider (OpenAI)

- Add internal/adapters/ai/types.go with neutral shared types
  (Recipe, DayPlan, RecognizedItem, IngredientClassification, etc.)
- Remove types from internal/adapters/openai/ — adapter now uses ai.*
- Define Recognizer interface in recognition package
- Define MenuGenerator interface in menu package
- Define RecipeGenerator interface in recommendation package
- Handler structs now hold interfaces, not *openai.Client
- Add wire.Bind entries for the three new interface bindings

To swap OpenAI for another provider: implement the three interfaces
using ai.* types and change the wire.Bind lines in cmd/server/wire.go.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
dbastrikin
2026-03-15 21:27:04 +02:00
parent 19a985ad49
commit fee240da7d
8 changed files with 217 additions and 194 deletions

View File

@@ -13,6 +13,7 @@ import (
"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/openai"
"github.com/food-ai/backend/internal/adapters/pexels"
"github.com/food-ai/backend/internal/product"
"github.com/food-ai/backend/internal/recipe"
@@ -104,8 +105,11 @@ func initRouter(appConfig *config.Config, pool *pgxpool.Pool) (http.Handler, err
wire.Bind(new(recommendation.PhotoSearcher), new(*pexels.Client)),
wire.Bind(new(recommendation.UserLoader), new(*user.Repository)),
wire.Bind(new(recommendation.ProductLister), new(*product.Repository)),
wire.Bind(new(recognition.IngredientRepository), new(*ingredient.Repository)),
wire.Bind(new(middleware.AccessTokenValidator), new(*jwtAdapter)),
wire.Bind(new(recognition.IngredientRepository), new(*ingredient.Repository)),
wire.Bind(new(recognition.Recognizer), new(*openai.Client)),
wire.Bind(new(menu.MenuGenerator), new(*openai.Client)),
wire.Bind(new(recommendation.RecipeGenerator), new(*openai.Client)),
wire.Bind(new(middleware.AccessTokenValidator), new(*jwtAdapter)),
)
return nil, nil
}