Files
bamort/backend/registry/registry.go

134 lines
4.2 KiB
Go

// Package registry provides a central module self-registration mechanism.
// Modules register their routes and migrations via init() functions,
// keeping each module self-contained without direct cross-module imports.
// main.go blank-imports each module to trigger its init() and then calls
// the Run* helpers here to wire everything together.
package registry
import (
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
// MigrateFunc is a function that runs database migrations for a module.
type MigrateFunc func(db ...*gorm.DB) error
// RouteFunc registers protected routes on an API router group.
type RouteFunc func(r *gin.RouterGroup)
// PublicRouteFunc registers public routes directly on the gin engine.
type PublicRouteFunc func(r *gin.Engine)
// BaseRouteFunc registers base routes (login, register, etc.) on the gin engine.
type BaseRouteFunc func(r *gin.Engine)
// AuthMiddlewareProvider returns a gin.HandlerFunc used for JWT authentication.
type AuthMiddlewareProvider func() gin.HandlerFunc
// InitializerFunc is called once after DB is connected and all migrations have run.
// Use it to load persisted settings into in-memory configuration.
type InitializerFunc func(db *gorm.DB)
var (
routeFuncs []RouteFunc
publicRouteFuncs []PublicRouteFunc
baseRouteFuncs []BaseRouteFunc
migrateFuncs []MigrateFunc
initializerFuncs []InitializerFunc
authProvider AuthMiddlewareProvider
modelInstances []interface{}
)
// RegisterRoutes adds a module's protected route registrar to the registry.
func RegisterRoutes(fn RouteFunc) {
routeFuncs = append(routeFuncs, fn)
}
// RegisterPublicRoutes adds a module's public route registrar to the registry.
func RegisterPublicRoutes(fn PublicRouteFunc) {
publicRouteFuncs = append(publicRouteFuncs, fn)
}
// RegisterBaseRoutes adds a module's unauthenticated base route registrar
// (e.g. login, register, password-reset) to the registry.
func RegisterBaseRoutes(fn BaseRouteFunc) {
baseRouteFuncs = append(baseRouteFuncs, fn)
}
// RegisterMigration adds a module's migration function to the registry.
func RegisterMigration(fn MigrateFunc) {
migrateFuncs = append(migrateFuncs, fn)
}
// RegisterInitializer adds a startup function that is called once after all
// migrations have run. Use it to load persisted settings into config.
func RegisterInitializer(fn InitializerFunc) {
initializerFuncs = append(initializerFuncs, fn)
}
// RegisterModel adds a GORM model instance to the central model registry.
// Each module should register its model instances (e.g. MyModel{}) to allow
// cross-database operations such as test snapshot creation.
func RegisterModel(model interface{}) {
modelInstances = append(modelInstances, model)
}
// GetModels returns all registered GORM model instances.
func GetModels() []interface{} {
return modelInstances
}
// SetAuthMiddleware sets the authentication middleware provider.
// Only one module (user) should call this.
func SetAuthMiddleware(fn AuthMiddlewareProvider) {
authProvider = fn
}
// GetAuthMiddleware returns the registered auth middleware handler.
// Falls back to a no-op pass-through when none has been registered.
func GetAuthMiddleware() gin.HandlerFunc {
if authProvider != nil {
return authProvider()
}
return func(c *gin.Context) { c.Next() }
}
// RunAllBaseRoutes calls all registered base route functions on the engine.
func RunAllBaseRoutes(r *gin.Engine) {
for _, fn := range baseRouteFuncs {
fn(r)
}
}
// RunAllRoutes calls all registered protected route functions on the router group.
func RunAllRoutes(r *gin.RouterGroup) {
for _, fn := range routeFuncs {
fn(r)
}
}
// RunAllPublicRoutes calls all registered public route functions on the engine.
func RunAllPublicRoutes(r *gin.Engine) {
for _, fn := range publicRouteFuncs {
fn(r)
}
}
// RunAllMigrations runs every registered migration function with the provided DB.
func RunAllMigrations(db *gorm.DB) error {
for _, fn := range migrateFuncs {
if err := fn(db); err != nil {
return err
}
}
return nil
}
// RunAllInitializers calls every registered initializer with the connected DB.
// Invoke this once after RunAllMigrations.
func RunAllInitializers(db *gorm.DB) {
for _, fn := range initializerFuncs {
fn(db)
}
}