mirror of
https://github.com/bitmagnet-io/bitmagnet.git
synced 2026-07-28 23:13:43 -04:00
297 lines
7.0 KiB
Go
297 lines
7.0 KiB
Go
package builder
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/bitmagnet-io/bitmagnet/internal/auth/rbac"
|
|
"github.com/bitmagnet-io/bitmagnet/internal/config/param"
|
|
config_registry "github.com/bitmagnet-io/bitmagnet/internal/config/registry"
|
|
"github.com/bitmagnet-io/bitmagnet/internal/config/resolver"
|
|
"github.com/bitmagnet-io/bitmagnet/internal/health"
|
|
"github.com/bitmagnet-io/bitmagnet/internal/httpserver"
|
|
"github.com/bitmagnet-io/bitmagnet/internal/plugin"
|
|
"github.com/bitmagnet-io/bitmagnet/internal/queue/handler"
|
|
"github.com/bitmagnet-io/bitmagnet/internal/ref"
|
|
workers_registry "github.com/bitmagnet-io/bitmagnet/internal/workers/registry"
|
|
"github.com/bitmagnet-io/bitmagnet/internal/workers/runner"
|
|
"github.com/bitmagnet-io/bitmagnet/internal/workers/worker"
|
|
"github.com/bitmagnet-io/bitmagnet/pkg/i18n"
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/prometheus/client_golang/prometheus"
|
|
"go.uber.org/fx"
|
|
"go.uber.org/zap/zapcore"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
type builder[Deps any] struct {
|
|
ref ref.Ref
|
|
activation plugin.Activation
|
|
dependencies []ref.Ref
|
|
params []config_registry.Param
|
|
i18nProviders []i18n.MessageProvider
|
|
errors ref.Map[error]
|
|
fxOptions []fx.Option
|
|
commands []plugin.Command
|
|
}
|
|
|
|
func NewPlugin[Deps any](rf ref.Ref, options ...Option[Deps]) plugin.Plugin {
|
|
b := &builder[Deps]{
|
|
ref: rf,
|
|
activation: plugin.ActivationAuto,
|
|
errors: ref.NewMap[error](),
|
|
}
|
|
|
|
for _, option := range options {
|
|
option(b)
|
|
}
|
|
|
|
var activationRef ref.Nullable
|
|
|
|
params := b.params
|
|
|
|
if b.activation != plugin.ActivationAlways {
|
|
activationRef = ref.NewNullable(rf.MustSub(plugin.KeyActivation))
|
|
params = append(params, config_registry.Param{
|
|
Ref: activationRef.Ref,
|
|
Plugin: rf,
|
|
Untyped: param.MustNew(
|
|
param.Description[plugin.Activation]("Activation"),
|
|
param.EnumValues(
|
|
plugin.ActivationEnabled,
|
|
plugin.ActivationDisabled,
|
|
plugin.ActivationAuto,
|
|
),
|
|
param.Default(b.activation),
|
|
),
|
|
})
|
|
}
|
|
|
|
return plugin.NewPlugin(
|
|
rf,
|
|
activationRef,
|
|
b.dependencies,
|
|
params,
|
|
b.errors,
|
|
i18n.MessageProviders(b.i18nProviders...),
|
|
b.commands,
|
|
fx.Options(b.fxOptions...),
|
|
)
|
|
}
|
|
|
|
type Option[Deps any] func(*builder[Deps])
|
|
|
|
func WithOptions[Deps any](options ...Option[Deps]) Option[Deps] {
|
|
return func(b *builder[Deps]) {
|
|
for _, option := range options {
|
|
option(b)
|
|
}
|
|
}
|
|
}
|
|
|
|
func WithDescription[Deps any](description string) Option[Deps] {
|
|
return func(b *builder[Deps]) {
|
|
WithI18nMessage[Deps](
|
|
b.ref,
|
|
"description for plugin: "+b.ref.String(),
|
|
i18n.WithOther(description),
|
|
)(b)
|
|
}
|
|
}
|
|
|
|
func WithDependencies[Deps any](dependencies ...ref.Ref) Option[Deps] {
|
|
return func(b *builder[Deps]) {
|
|
b.dependencies = append(b.dependencies, dependencies...)
|
|
}
|
|
}
|
|
|
|
func WithActivation[Deps any](activation plugin.Activation) Option[Deps] {
|
|
return func(b *builder[Deps]) {
|
|
b.activation = activation
|
|
}
|
|
}
|
|
|
|
func WithConfig[Deps any, T any](ref ref.Ref, p param.Param[T]) Option[Deps] {
|
|
return WithOptions(
|
|
func(b *builder[Deps]) {
|
|
b.params = append(b.params, config_registry.Param{
|
|
Ref: ref,
|
|
Plugin: b.ref,
|
|
Untyped: p,
|
|
})
|
|
},
|
|
WithFxOption[Deps](
|
|
fx.Provide(
|
|
func(allResolved resolver.Resolved) (T, error) {
|
|
var (
|
|
resolved *resolver.Param
|
|
value T
|
|
ok bool
|
|
)
|
|
|
|
resolved, ok = allResolved.Param(ref)
|
|
if !ok {
|
|
return value, errors.New("missing from resolved")
|
|
}
|
|
|
|
value, ok = resolved.Value().(T)
|
|
if !ok {
|
|
return value, fmt.Errorf(
|
|
"failed to cast from %T to %T",
|
|
resolved.Value(),
|
|
value,
|
|
)
|
|
}
|
|
|
|
return value, nil
|
|
},
|
|
),
|
|
),
|
|
)
|
|
}
|
|
|
|
func WithI18nMessage[Deps any](ref ref.Ref, description string, options ...i18n.MessageOption) Option[Deps] {
|
|
return WithI18nProvider[Deps](i18n.NewMessageProvider(
|
|
i18n.NewMessage(ref.String(), description, options...),
|
|
))
|
|
}
|
|
|
|
func WithI18nProvider[Deps any](provider i18n.MessageProvider) Option[Deps] {
|
|
return func(builder *builder[Deps]) {
|
|
builder.i18nProviders = append(builder.i18nProviders, provider)
|
|
}
|
|
}
|
|
|
|
func WithError[Deps any](ref ref.Ref, err error) Option[Deps] {
|
|
return func(builder *builder[Deps]) {
|
|
builder.errors.Set(ref, err)
|
|
}
|
|
}
|
|
|
|
func WithFxOption[Deps any](options ...fx.Option) Option[Deps] {
|
|
return func(b *builder[Deps]) {
|
|
b.fxOptions = append(b.fxOptions, options...)
|
|
}
|
|
}
|
|
|
|
func WithGinOption[Deps any](ref ref.Ref, phase httpserver.Phase, provider func(Deps) gin.OptionFunc) Option[Deps] {
|
|
return WithFxOption[Deps](fx.Provide(
|
|
fx.Annotate(
|
|
func(deps Deps) httpserver.Option {
|
|
return httpserver.NewOption(ref.String(), phase, provider(deps))
|
|
},
|
|
fx.ResultTags(`group:"http_server_options"`),
|
|
),
|
|
))
|
|
}
|
|
|
|
func WithGormPlugin[Deps any](provider func(Deps) gorm.Plugin) Option[Deps] {
|
|
return WithFxOption[Deps](fx.Provide(
|
|
fx.Annotate(
|
|
provider,
|
|
fx.ResultTags(`group:"gorm_plugins"`),
|
|
),
|
|
))
|
|
}
|
|
|
|
func WithZapCore[Deps any](provider func(Deps) zapcore.Core) Option[Deps] {
|
|
return WithFxOption[Deps](fx.Provide(
|
|
fx.Annotate(
|
|
provider,
|
|
fx.ResultTags(`group:"zap_cores"`),
|
|
),
|
|
))
|
|
}
|
|
|
|
func WithWorker[Deps any](provider func(Deps) (runner.Provider, worker.Option)) Option[Deps] {
|
|
return func(b *builder[Deps]) {
|
|
b.fxOptions = append(b.fxOptions, fx.Provide(
|
|
fx.Annotate(
|
|
func(deps Deps) workers_registry.Option {
|
|
runner, option := provider(deps)
|
|
|
|
if option == nil {
|
|
option = worker.Options()
|
|
}
|
|
|
|
return workers_registry.WithWorker(
|
|
b.ref,
|
|
runner,
|
|
option,
|
|
)
|
|
},
|
|
fx.ResultTags(`group:"worker_options"`),
|
|
),
|
|
))
|
|
}
|
|
}
|
|
|
|
func WithHealthCheckerOption[Deps any](provider func(Deps) health.CheckerOption) Option[Deps] {
|
|
return WithFxOption[Deps](fx.Provide(
|
|
fx.Annotate(
|
|
provider,
|
|
fx.ResultTags(`group:"health_check_options"`),
|
|
),
|
|
))
|
|
}
|
|
|
|
func WithQueueHandler[Deps any](provider func(Deps) handler.Handler) Option[Deps] {
|
|
return WithFxOption[Deps](fx.Provide(
|
|
fx.Annotate(
|
|
provider,
|
|
fx.ResultTags(`group:"queue_handlers"`),
|
|
),
|
|
))
|
|
}
|
|
|
|
func WithPrometheusCollector[Deps any](provider func(Deps) prometheus.Collector) Option[Deps] {
|
|
return WithFxOption[Deps](fx.Provide(
|
|
fx.Annotate(
|
|
provider,
|
|
fx.ResultTags(`group:"prometheus_collectors"`),
|
|
),
|
|
))
|
|
}
|
|
|
|
func WithCliCommand[Deps any](
|
|
commands ...plugin.Command,
|
|
) Option[Deps] {
|
|
return func(b *builder[Deps]) {
|
|
b.commands = append(b.commands, commands...)
|
|
}
|
|
}
|
|
|
|
func WithAuthObjectActions[Deps any](
|
|
provider func(Deps) []rbac.ObjectAction,
|
|
) Option[Deps] {
|
|
return WithFxOption[Deps](
|
|
fx.Provide(
|
|
fx.Annotate(
|
|
func(deps Deps) rbac.ObjectActionProvider {
|
|
return func() []rbac.ObjectAction {
|
|
return provider(deps)
|
|
}
|
|
},
|
|
fx.ResultTags(`group:"auth_object_actions"`),
|
|
),
|
|
),
|
|
)
|
|
}
|
|
|
|
func WithPermissionProvider[Deps any](
|
|
provider func(Deps) []rbac.Permission,
|
|
) Option[Deps] {
|
|
return WithFxOption[Deps](
|
|
fx.Provide(
|
|
fx.Annotate(
|
|
func(deps Deps) rbac.PermissionProvider {
|
|
return func() []rbac.Permission {
|
|
return provider(deps)
|
|
}
|
|
},
|
|
fx.ResultTags(`group:"auth_permissions"`),
|
|
),
|
|
),
|
|
)
|
|
}
|