Files
2025-04-25 11:20:31 +03:00

121 lines
2.4 KiB
Go

package modules
import (
"fmt"
"github.com/mitchellh/mapstructure"
"go.uber.org/fx"
"go.uber.org/zap"
)
type ModuleConfiguration interface {
Extract(destination any) error
}
var registry map[string]Module = map[string]Module{}
func RegisterModule(module Module) {
registry[module.Name()] = module
}
func GetModule(name string) Module {
return registry[name]
}
type Module interface {
Name() string
Create(id string, moduleConfiguration map[string]interface{}) (fx.Option, error)
}
type ModuleFactoryContext interface {
Id() string
Kind() string
NameTag() string
GroupTag() string
ConfigureLogger(logger *zap.Logger) *zap.Logger
ExtractConfig(destination any) error
AddOption(option fx.Option)
Provide(constructors ...interface{})
Invoke(funcs ...interface{})
}
type simpleFactoryContext struct {
id string
kind string
config map[string]interface{}
options []fx.Option
}
func (s *simpleFactoryContext) Kind() string {
return s.kind
}
func (s *simpleFactoryContext) ConfigureLogger(logger *zap.Logger) *zap.Logger {
return logger.Named(fmt.Sprintf("%s[%s]", s.Kind(), s.id))
}
func (s *simpleFactoryContext) Provide(constructors ...interface{}) {
s.AddOption(fx.Provide(constructors...))
}
func (s *simpleFactoryContext) Invoke(funcs ...interface{}) {
s.AddOption(fx.Invoke(funcs...))
}
func (s *simpleFactoryContext) Id() string {
return s.id
}
func (s *simpleFactoryContext) NameTag() string {
return fmt.Sprintf(`name:"%s"`, s.id)
}
func (s *simpleFactoryContext) GroupTag() string {
return fmt.Sprintf(`group:"%s"`, s.id)
}
func (s *simpleFactoryContext) ExtractConfig(destination any) error {
return mapstructure.Decode(s.config, destination)
}
func (s *simpleFactoryContext) AddOption(option fx.Option) {
s.options = append(s.options, option)
}
type simpleFactory = func(context ModuleFactoryContext) error
type simple struct {
name string
factory simpleFactory
}
func (s simple) Name() string {
return s.name
}
func (s simple) Create(id string, config map[string]interface{}) (fx.Option, error) {
ctx := &simpleFactoryContext{
options: make([]fx.Option, 0),
config: config,
id: id,
kind: s.name,
}
err := s.factory(ctx)
if err != nil {
return nil, err
}
return fx.Options(ctx.options...), nil
}
func SimpleModule(name string, factory simpleFactory) Module {
module := &simple{name: name, factory: factory}
RegisterModule(module)
return module
}