(FIX): Created a decent dependency inject architecture.

The system allows services and repositories to be created in the main
server definition and then store them in the context. They can then be
retrieved and mapped onto the injection type and accessed in the
handlers. The handlers can then use the deps to call services. Each
service is initialized with the required repositories so they can be
accessed directly.
This commit is contained in:
Hayden Hargreaves 2025-06-14 12:30:17 -07:00
parent 3c4710bb48
commit 71e32f1fd7
4 changed files with 61 additions and 1 deletions

View File

@ -5,5 +5,8 @@ import "github.com/haydenhargreaves/Potion/internal/app/server"
const PORT = 3000
func main() {
server.Init(PORT).ConfigureAuth().Setup().Start()
s := server.Init(PORT).ConfigureAuth().ConnectDatabase().Setup()
defer s.DB.Close()
s.Start()
}

1
go.mod
View File

@ -29,6 +29,7 @@ require (
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.2.10 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/lib/pq v1.10.9 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect

View File

@ -0,0 +1,15 @@
package server
import (
"github.com/gin-gonic/gin"
domain "github.com/haydenhargreaves/Potion/internal/domain/server"
)
// DepedencyInjectionMiddleware injects the dependencies into the context set. This is a middleware
// that is used to apply the required services.
func DepedencyInjectionMiddleware(deps *domain.InjectedDependencies) gin.HandlerFunc {
return func(ctx *gin.Context) {
ctx.Set("deps", deps)
ctx.Next()
}
}

View File

@ -1,6 +1,7 @@
package server
import (
"database/sql"
"fmt"
"os"
@ -8,14 +9,20 @@ import (
"github.com/gin-contrib/cors"
"github.com/gin-gonic/gin"
"github.com/haydenhargreaves/Potion/internal/app/handlers"
"github.com/haydenhargreaves/Potion/internal/app/service"
domain "github.com/haydenhargreaves/Potion/internal/domain/server"
"github.com/haydenhargreaves/Potion/internal/infrastructure/auth"
"github.com/haydenhargreaves/Potion/internal/infrastructure/database/repository"
"github.com/joho/godotenv"
_ "github.com/lib/pq"
)
type Server struct {
port int
Router *gin.Engine
config cors.Config
DB *sql.DB
}
// Init initializes the server with the provided port. CORS settings are defined here.
@ -66,12 +73,46 @@ func (s *Server) ConfigureAuth() *Server {
return s
}
func (s *Server) ConnectDatabase() *Server {
err := godotenv.Load(".env")
if err != nil {
panic("Could not load env file")
}
var connUrl string = os.Getenv("DATABASE_URL")
db, err := sql.Open("postgres", connUrl)
if err != nil {
panic("Could not connect to database: " + err.Error())
}
if err = db.Ping(); err != nil {
panic("Error pinging database: " + err.Error())
}
s.DB = db
return s
}
// Start starts the server on the port provided when the server was initialized
func (s *Server) Start() {
s.Router.Run(fmt.Sprintf(":%d", s.port))
}
func (s *Server) Setup() *Server {
// Initialize and inject dependencies
userRepo := repository.NewUserRepository(s.DB)
userService := service.NewUserService(userRepo)
authService := service.NewAuthService(userRepo)
deps := &domain.InjectedDependencies{
UserService: userService,
AuthService: authService,
}
s.Router.Use(DepedencyInjectionMiddleware(deps))
// Wrap all routes with a version
router_v1 := s.Router.Group("/v1")