Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 118 additions & 0 deletions container/container.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package container

import (
"github.com/Masterminds/squirrel"
"github.com/jmoiron/sqlx"
"github.com/nbtca/saturday/repo"
"github.com/nbtca/saturday/service"
"github.com/spf13/viper"
)

// Container holds all application dependencies
type Container struct {
// Database
db *sqlx.DB
sq squirrel.StatementBuilderType

// Repositories
memberRepo repo.MemberRepository
eventRepo repo.EventRepository
clientRepo repo.ClientRepository
roleRepo repo.RoleRepository
dbManager repo.DatabaseManager

// Services
memberService service.MemberServiceInterface
logtoService service.LogtoServiceInterface
eventService service.EventServiceInterface
clientService service.ClientServiceInterface
}

// NewContainer creates and initializes a new dependency injection container
func NewContainer() *Container {
container := &Container{}
container.initializeRepositories()
container.initializeServices()
return container
}

// initializeRepositories sets up all repository instances
func (c *Container) initializeRepositories() {
// Get database connection from global state (for now, during migration)
c.db = repo.GetDB() // We'll need to add this method to implementations.go
c.sq = squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar)

// Initialize repositories
c.memberRepo = repo.NewMemberRepository(c.db, c.sq)
c.eventRepo = repo.NewEventRepository(c.db, c.sq)
c.clientRepo = repo.NewClientRepository(c.db, c.sq)
c.roleRepo = repo.NewRoleRepository(c.db, c.sq)
c.dbManager = repo.NewDatabaseManager()
}

// initializeServices sets up all service instances with their dependencies
func (c *Container) initializeServices() {
// Initialize Logto service
logtoEndpoint := viper.GetString("logto.endpoint")
c.logtoService = service.NewLogtoService(logtoEndpoint)

// Initialize member service with dependencies
c.memberService = service.NewMemberService(
c.memberRepo,
c.roleRepo,
c.logtoService,
)

// TODO: Initialize other services
// c.eventService = service.NewEventService(c.eventRepo, c.memberService)
// c.clientService = service.NewClientService(c.clientRepo)
}

// Getter methods for services

// MemberService returns the member service instance
func (c *Container) MemberService() service.MemberServiceInterface {
return c.memberService
}

// LogtoService returns the logto service instance
func (c *Container) LogtoService() service.LogtoServiceInterface {
return c.logtoService
}

// EventService returns the event service instance
func (c *Container) EventService() service.EventServiceInterface {
return c.eventService
}

// ClientService returns the client service instance
func (c *Container) ClientService() service.ClientServiceInterface {
return c.clientService
}

// Getter methods for repositories (for testing)

// MemberRepository returns the member repository instance
func (c *Container) MemberRepository() repo.MemberRepository {
return c.memberRepo
}

// EventRepository returns the event repository instance
func (c *Container) EventRepository() repo.EventRepository {
return c.eventRepo
}

// ClientRepository returns the client repository instance
func (c *Container) ClientRepository() repo.ClientRepository {
return c.clientRepo
}

// RoleRepository returns the role repository instance
func (c *Container) RoleRepository() repo.RoleRepository {
return c.roleRepo
}

// DatabaseManager returns the database manager instance
func (c *Container) DatabaseManager() repo.DatabaseManager {
return c.dbManager
}
75 changes: 75 additions & 0 deletions container/container_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package container

import (
"testing"

"github.com/nbtca/saturday/repo"
"github.com/nbtca/saturday/service"
)

func TestNewContainer(t *testing.T) {
// This test requires database initialization
// For now, we'll skip if database is not available

// Initialize database for testing
repo.InitDB()
defer repo.CloseDB()

container := NewContainer()

// Test that all services are properly initialized
if container.MemberService() == nil {
t.Error("MemberService should not be nil")
}

if container.LogtoService() == nil {
t.Error("LogtoService should not be nil")
}

// Test that all repositories are properly initialized
if container.MemberRepository() == nil {
t.Error("MemberRepository should not be nil")
}

if container.RoleRepository() == nil {
t.Error("RoleRepository should not be nil")
}
}

func TestContainerServiceTypes(t *testing.T) {
// Initialize database for testing
repo.InitDB()
defer repo.CloseDB()

container := NewContainer()

// Test that services implement the correct interfaces
_, ok := container.MemberService().(service.MemberServiceInterface)
if !ok {
t.Error("MemberService should implement MemberServiceInterface")
}

_, ok = container.LogtoService().(service.LogtoServiceInterface)
if !ok {
t.Error("LogtoService should implement LogtoServiceInterface")
}
}

func TestContainerRepositoryTypes(t *testing.T) {
// Initialize database for testing
repo.InitDB()
defer repo.CloseDB()

container := NewContainer()

// Test that repositories implement the correct interfaces
_, ok := container.MemberRepository().(repo.MemberRepository)
if !ok {
t.Error("MemberRepository should implement MemberRepository interface")
}

_, ok = container.RoleRepository().(repo.RoleRepository)
if !ok {
t.Error("RoleRepository should implement RoleRepository interface")
}
}
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ require (
github.com/MicahParks/keyfunc v1.9.0
github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible
github.com/danielgtaylor/huma/v2 v2.28.0
github.com/gin-contrib/cors v1.6.0
github.com/gin-gonic/gin v1.10.0
github.com/go-chi/chi/v5 v5.2.2
github.com/go-chi/cors v1.2.1
github.com/go-playground/validator/v10 v10.22.1
github.com/go-playground/webhooks/v6 v6.4.0
github.com/go-sql-driver/mysql v1.7.1
Expand Down Expand Up @@ -51,8 +52,6 @@ require (
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fsnotify/fsnotify v1.8.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.5 // indirect
github.com/go-chi/chi/v5 v5.2.2 // indirect
github.com/go-chi/cors v1.2.1 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
Expand Down Expand Up @@ -121,6 +120,7 @@ require (
google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8 // indirect
google.golang.org/grpc v1.67.3 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
gotest.tools/v3 v3.4.0 // indirect
)
Expand Down
3 changes: 1 addition & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,6 @@ github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/
github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/gabriel-vasile/mimetype v1.4.5 h1:J7wGKdGu33ocBOhGy0z653k/lFKLFDPJMG8Gql0kxn4=
github.com/gabriel-vasile/mimetype v1.4.5/go.mod h1:ibHel+/kbxn9x2407k1izTA1S81ku1z/DlgOW2QE0M4=
github.com/gin-contrib/cors v1.6.0 h1:0Z7D/bVhE6ja07lI8CTjTonp6SB07o8bNuFyRbsBUQg=
github.com/gin-contrib/cors v1.6.0/go.mod h1:cI+h6iOAyxKRtUtC6iF/Si1KSFvGm/gK+kshxlCi8ro=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
Expand Down Expand Up @@ -267,6 +265,7 @@ github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgSh
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
Expand Down
9 changes: 5 additions & 4 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ import (
"strings"
"time"

"github.com/nbtca/saturday/container"
"github.com/nbtca/saturday/repo"
"github.com/nbtca/saturday/router"
"github.com/nbtca/saturday/service"
"github.com/nbtca/saturday/util"

"github.com/joho/godotenv"
Expand Down Expand Up @@ -63,10 +63,11 @@ func main() {
repo.InitDB()
defer repo.CloseDB()

service.LogtoServiceApp = service.MakeLogtoService(viper.GetString("logto.endpoint"))
util.Logger.Debug("LogtoService initialized with endpoint: " + viper.GetString("logto.endpoint"))
// Initialize dependency injection container
container := container.NewContainer()
util.Logger.Debug("Dependency injection container initialized")

r := router.SetupRouter()
r := router.SetupRouter(container)

viper.SetDefault("port", 4000)
port := viper.GetInt("port")
Expand Down
Loading