-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathprovider.go
More file actions
158 lines (131 loc) · 3.5 KB
/
provider.go
File metadata and controls
158 lines (131 loc) · 3.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
package needle
import (
"context"
"github.com/danpasecinic/needle/internal/container"
"github.com/danpasecinic/needle/internal/reflect"
"github.com/danpasecinic/needle/internal/scope"
)
type Provider[T any] func(ctx context.Context, r Resolver) (T, error)
type ProviderOption func(*providerConfig)
type providerConfig struct {
name string
dependencies []string
onStart []container.Hook
onStop []container.Hook
scope scope.Scope
poolSize int
lazy bool
}
func Provide[T any](c *Container, provider Provider[T], opts ...ProviderOption) error {
if len(opts) == 0 {
key := reflect.TypeKey[T]()
resolver := c.resolver
wrappedProvider := func(ctx context.Context, r container.Resolver) (any, error) {
return provider(ctx, resolver)
}
return c.internal.Register(key, wrappedProvider, nil)
}
cfg := &providerConfig{}
for _, opt := range opts {
opt(cfg)
}
key := reflect.TypeKey[T]()
if cfg.name != "" {
key = reflect.TypeKeyNamed[T](cfg.name)
}
resolver := c.resolver
wrappedProvider := func(ctx context.Context, r container.Resolver) (any, error) {
return provider(ctx, resolver)
}
if err := c.internal.Register(key, wrappedProvider, cfg.dependencies); err != nil {
return err
}
for _, hook := range cfg.onStart {
c.internal.AddOnStart(key, hook)
}
for _, hook := range cfg.onStop {
c.internal.AddOnStop(key, hook)
}
if cfg.scope != scope.Singleton {
c.internal.SetScope(key, cfg.scope)
}
if cfg.poolSize > 0 {
c.internal.SetPoolSize(key, cfg.poolSize)
}
if cfg.lazy {
c.internal.SetLazy(key, true)
}
return nil
}
func ProvideValue[T any](c *Container, value T, opts ...ProviderOption) error {
cfg := &providerConfig{}
for _, opt := range opts {
opt(cfg)
}
key := reflect.TypeKey[T]()
if cfg.name != "" {
key = reflect.TypeKeyNamed[T](cfg.name)
}
if err := c.internal.RegisterValue(key, value); err != nil {
return err
}
for _, hook := range cfg.onStart {
c.internal.AddOnStart(key, hook)
}
for _, hook := range cfg.onStop {
c.internal.AddOnStop(key, hook)
}
return nil
}
func ProvideNamed[T any](c *Container, name string, provider Provider[T], opts ...ProviderOption) error {
if len(opts) == 0 {
key := reflect.TypeKeyNamed[T](name)
resolver := c.resolver
wrappedProvider := func(ctx context.Context, r container.Resolver) (any, error) {
return provider(ctx, resolver)
}
return c.internal.Register(key, wrappedProvider, nil)
}
opts = append(opts, WithName(name))
return Provide(c, provider, opts...)
}
func ProvideNamedValue[T any](c *Container, name string, value T, opts ...ProviderOption) error {
opts = append(opts, WithName(name))
return ProvideValue(c, value, opts...)
}
func WithName(name string) ProviderOption {
return func(cfg *providerConfig) {
cfg.name = name
}
}
func WithDependencies(deps ...string) ProviderOption {
return func(cfg *providerConfig) {
cfg.dependencies = deps
}
}
func WithOnStart(hook Hook) ProviderOption {
return func(cfg *providerConfig) {
cfg.onStart = append(cfg.onStart, container.Hook(hook))
}
}
func WithOnStop(hook Hook) ProviderOption {
return func(cfg *providerConfig) {
cfg.onStop = append(cfg.onStop, container.Hook(hook))
}
}
func WithScope(s Scope) ProviderOption {
return func(cfg *providerConfig) {
cfg.scope = s
}
}
func WithPoolSize(size int) ProviderOption {
return func(cfg *providerConfig) {
cfg.scope = scope.Pooled
cfg.poolSize = size
}
}
func WithLazy() ProviderOption {
return func(cfg *providerConfig) {
cfg.lazy = true
}
}