-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmodule.go
More file actions
109 lines (92 loc) · 2.14 KB
/
Copy pathmodule.go
File metadata and controls
109 lines (92 loc) · 2.14 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
package needle
import (
"context"
"github.com/danpasecinic/needle/internal/reflect"
)
type Module struct {
name string
registers []func(c *Container) error
decorators []decoratorEntry
submodules []*Module
}
type decoratorEntry struct {
key string
decorator func(ctx context.Context, c *Container, instance any) (any, error)
}
func NewModule(name string) *Module {
return &Module{
name: name,
}
}
func (m *Module) Name() string {
return m.name
}
func (m *Module) Include(submodule *Module) *Module {
m.submodules = append(m.submodules, submodule)
return m
}
func ModuleRegister[T any](m *Module, spec Spec[T]) *Module {
m.registers = append(m.registers, func(c *Container) error {
return Register(c, spec)
})
return m
}
func ModuleReplace[T any](m *Module, spec Spec[T]) *Module {
m.registers = append(m.registers, func(c *Container) error {
return Replace(c, spec)
})
return m
}
func ModuleDecorate[T any](m *Module, decorator Decorator[T]) *Module {
key := reflect.TypeKey[T]()
m.decorators = append(
m.decorators, decoratorEntry{
key: key,
decorator: func(ctx context.Context, c *Container, instance any) (any, error) {
typed, ok := instance.(T)
if !ok {
var zero T
return zero, errDecoratorTypeMismatch(reflect.TypeName[T]())
}
return decorator(ctx, c, typed)
},
},
)
return m
}
func (m *Module) apply(c *Container) error {
for _, sub := range m.submodules {
if err := sub.apply(c); err != nil {
return err
}
}
for _, register := range m.registers {
if err := register(c); err != nil {
return err
}
}
for _, d := range m.decorators {
entry := d
c.internal.AddDecorator(
entry.key, func(ctx context.Context, instance any) (any, error) {
return entry.decorator(ctx, c, instance)
},
)
}
return nil
}
func (c *Container) Apply(modules ...*Module) error {
for _, m := range modules {
if err := m.apply(c); err != nil {
return errModuleApplyFailed(m.name, err)
}
}
return nil
}
func errModuleApplyFailed(moduleName string, cause error) *Error {
return newError(
ErrCodeModuleApplyFailed,
"failed to apply module "+moduleName,
cause,
)
}