refac: fixed, better, smarter, correct dependency injection

This commit is contained in:
Florian Sylvain
2025-03-29 00:51:01 +01:00
parent d895477b8c
commit a77a5ad314
35 changed files with 169 additions and 144 deletions
+81 -23
View File
@@ -1,15 +1,42 @@
package api
import (
"GoCMS/adapters/secondary/gateways"
"GoCMS/adapters/secondary/gateways/models"
"GoCMS/useCases"
"fmt"
"os"
"path/filepath"
"reflect"
"runtime"
"github.com/glebarez/sqlite"
"go.uber.org/dig"
"gorm.io/gorm"
"os"
"path/filepath"
)
type UseCaseDefinition struct {
Constructor interface{}
FieldName string
}
var useCaseDefinitions = []UseCaseDefinition{
{useCases.NewCreatePostUseCase, "CreatePostUseCase"},
{useCases.NewGetPostUseCase, "GetPostUseCase"},
{useCases.NewListPostsUseCase, "ListPostsUseCase"},
{useCases.NewUpdatePostUseCase, "UpdatePostUseCase"},
{useCases.NewDeletePostUseCase, "DeletePostUseCase"},
{useCases.NewGetUserUseCase, "GetUserUseCase"},
{useCases.NewCreateUserUseCase, "CreateUserUseCase"},
{useCases.NewUpdateUserUseCase, "UpdateUserUseCase"},
{useCases.NewDeleteUserUseCase, "DeleteUserUseCase"},
{useCases.NewListUsersUseCase, "ListUsersUseCase"},
{useCases.NewGetPageUseCase, "GetPageUseCase"},
{useCases.NewSendMailUseCase, "SendMailUseCase"},
{useCases.NewCreateImageUseCase, "CreateImageUseCase"},
{useCases.NewDeleteImageUseCase, "DeleteImageUseCase"},
}
type UseCases struct {
CreatePostUseCase *useCases.CreatePostUseCase
GetPostUseCase *useCases.GetPostUseCase
@@ -45,29 +72,60 @@ func InitContainer() {
digContainer := dig.New()
database := getDb()
_ = database.AutoMigrate(&models.Post{}, &models.User{})
_ = digContainer.Provide(func() *gorm.DB { return database })
if err := database.AutoMigrate(&models.Post{}, &models.User{}); err != nil {
panic("Failed to migrate database: " + err.Error())
}
_ = digContainer.Provide(func(db *gorm.DB) *UseCases {
return &UseCases{
CreatePostUseCase: useCases.NewCreatePostUseCase(db),
GetPostUseCase: useCases.NewGetPostUseCase(db),
ListPostsUseCase: useCases.NewListPostsUseCase(db),
UpdatePostUseCase: useCases.NewUpdatePostUseCase(db),
DeletePostUseCase: useCases.NewDeletePostUseCase(db),
GetUserUseCase: useCases.NewGetUserUseCase(db),
CreateUserUseCase: useCases.NewCreateUserUseCase(db),
UpdateUserUseCase: useCases.NewUpdateUserUseCase(db),
DeleteUserUseCase: useCases.NewDeleteUserUseCase(db),
ListUsersUseCase: useCases.NewListUsersUseCase(db),
GetPageUseCase: useCases.NewGetPageUseCase(),
SendMailUseCase: useCases.NewSendMailUseCase(),
CreateImageUseCase: useCases.NewCreateImageUseCase(db),
DeleteImageUseCase: useCases.NewDeleteImageUseCase(db),
if err := digContainer.Provide(func() *gorm.DB { return database }); err != nil {
panic("Failed to provide database: " + err.Error())
}
provideRepositories(digContainer)
for _, def := range useCaseDefinitions {
if err := digContainer.Provide(def.Constructor); err != nil {
funcName := runtime.FuncForPC(reflect.ValueOf(def.Constructor).Pointer()).Name()
panic(fmt.Sprintf("Failed to provide %s: %v", funcName, err))
}
})
err := digContainer.Invoke(func(useCases *UseCases) { Container = useCases })
if err != nil {
}
if err := digContainer.Provide(func(values ...any) *UseCases {
container := &UseCases{}
containerValue := reflect.ValueOf(container).Elem()
for i, value := range values {
fieldName := useCaseDefinitions[i].FieldName
field := containerValue.FieldByName(fieldName)
if field.IsValid() && field.CanSet() {
field.Set(reflect.ValueOf(value))
} else {
panic(fmt.Sprintf("Failed to set field %s", fieldName))
}
}
return container
}, dig.As(new(*UseCases))); err != nil {
panic("Failed to provide container constructor: " + err.Error())
}
if err := digContainer.Invoke(func(useCases *UseCases) { Container = useCases }); err != nil {
panic("Unable to invoke container: " + err.Error())
}
}
func provideRepositories(container *dig.Container) {
repositories := []any{
gateways.NewPostRepository,
gateways.NewUserRepository,
gateways.NewImageRepository,
gateways.NewMailRepository,
gateways.NewPageRepository,
}
for _, repo := range repositories {
if err := container.Provide(repo); err != nil {
funcName := runtime.FuncForPC(reflect.ValueOf(repo).Pointer()).Name()
panic(fmt.Sprintf("Failed to provide repository %s: %v", funcName, err))
}
}
}