Open dcormier opened 4 years ago
This is closely related to #184. I'm not fully sure the implications of allowing the provider function to be dynamic.
For this case, you could use a slightly different provider function in your injector that instantiates the DynamoDB API:
func ProvideDDBClient(cfg Config, awsSession client.ConfigProvider) dynamodbiface.DynamoDBAPI {
return dynamodbclient.New(awsSession, ddbEndpoint)
}
func Inject(cfg Config) (Server, func(), error) (
wire.Build(
// ...
ProvideDDBClient,
// ...
)
return Server{}, nil, nil
}
ddbEndpoint
is not in scope in that ProvideDDBClient
example. Additionally, my goal is for this function (ProvideDDBClient
) to live in a shared package, while Config
is specific to the consumer of that shared package.
I'm aware that something like this could be done (which maybe is what you meant?), but my goal is to reduce repeated code by putting it in shared packages.
func provideDDBClient(cfg Config, awsSession client.ConfigProvider) dynamodbiface.DynamoDBAPI {
return dynamodbclient.New(awsSession, cfg.DDBEndpoint)
}
func Inject(cfg Config) (Server, func(), error) (
wire.Build(
// ...
provideDDBClient,
// ...
)
return Server{}, nil, nil
}
While I'm using a single provider function as an example, in reality I have many that I would like to make available in packages shared across a set of projects we're working on. It would significantly simplify my wire.Build
setup for multiple projects.
This is still tagged as needs info
. Is there more expected from me, here?
It'd be nice to see a solution for this. My use case is a provider that can be built with functional options. Something like this:
type Value struct {}
type ValueProvider func() (*Value, func(), error)
func ProviderWithOptions(options ...ProviderOption) ValueProvider {
return func() (*Value, func(), error) {
// ...
}
}
I'd like to be able to use it inline in a wire.Build
call like this:
ProviderWithOptions(WithOptionA(), WithOptionB())
My goal is to allow some customization of the provider, especially for things like migrations in a large codebase, or behavior that needs to be otherwise toggled or configured at build time. This isn't possible, currently. I need to wrap the customization in a provider function to appease wire
:
func provider() (*Value, func(), error) {
return ProviderWithOptions(WithOptionA())()
}
This gets especially cumbersome and boilerplatey when the provider has dependencies, as the type signature needs to be repeated in a number of places, and dependencies need to be manually passed in from the func
to the invocation of the built provider function.
Regarding this concern:
I'm not fully sure the implications of allowing the provider function to be dynamic.
I feel like I can achieve a lot of potentially-scary dynamic behavior with the workaround, so it'd be nice to not have to write the workaround.
Describe the bug
Calling a function that returns a function in
wire.Build
results in theunknown pattern
error.To Reproduce
This may be in a shared package, to be used across multiple projects, for example.
Elsewhere, that would be called in
wire.Build
like so:Expected behavior
Running wire would result in a properly generated
Inject
function.Version
v0.4.0
Additional context
The package that has the
Provide*
function doesn't (and shouldn't) know where its arguments come from. It's up to the caller to load them from file, environment, or just hard code them. But thatProvide*
function will return a closure that's to be used bywire.Build
.For what it's worth, this works with fx.