Open xenoterracide opened 4 years ago
Could you provide a bit more context on what a bean is? Do you have links to documentation or anything?
a bean in java simply refers to any "managed object", it's a weird nomenclature but I haven't a better term off the top of my head (maybe a component), any arbitrary object the container can resolve. In this case what I'm looking for is a decentralized way of writing register calls
, I imagine they would be providers...
so instead of writing
container.register(Beans.APOLLO_SERVER, {
useFactory: instanceCachingFactory((c) => {
const config = c.resolve<Config>(Beans.APOLLO_CONFIG);
return new ApolloServer({
...config,
cors: {
origin: process.env.CORS_ORIGINS!.split(','),
},
});
}),
});
... followed by a dozen or so similar registers
you could write, e.g. (note no direct reference to container is required, and having a big single method is discouraged)
@bean(Beans.APOLLO_SERVER)
appolloServer( c: DependencyContainer ) {
return new ApolloServer({
...config,
cors: {
origin: process.env.CORS_ORIGINS!.split(','),
},
});
}),
});
}
bean is probably not a term you want to copy from the java world, I'm not sure what other containers use though.
Does the @registry
decorator meet your needs?
I would say no, because it encourages a big block of code at the top of a class, instead of a big method, the problem more or less remains, things aren't broke up. Sure I suppose I could create a ton of classes.
hmm... I thought for sure I commented on this (maybe it's on another ticket)... I have an implementation that is satisfactory but incomplete.
export function factory(explicit?: symbol, { singleton = true, container = rootContainer() } = {}) {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const token = !!explicit ? explicit : Symbol.for(propertyKey);
const factory = (c: DependencyContainer) => descriptor.value.apply(target, [c]);
const finalFactory = singleton ? instanceCachingFactory(factory) : factory;
container.register(token, { useFactory: finalFactory });
};
}
and can then be used as follows
export default class StripeConfig {
@factory(InjectToken.Stripe)
stripe(c: DependencyContainer): Stripe {
return new Stripe(c.resolve<string>(InjectToken.StripeSk));
}
}
@registry([
{ token: InjectToken.ConfigStripe, useClass: StripeConfig }, // technically it doesn't *need* to be registered, but this would be the spring convention.
])
it's missing some spring capabilities of @Bean
and @Configuration
but I think that could be enhanced later.
if patches are welcome/desired I could try to do that here.
@Xapphire13 any interest in a patch for this @factory? I've enhanced it a little bit more since I wrote this.
export function factory(
explicit: symbol | constructor<any>,
{
singleton = true,
container = rootContainer(),
} = {},
) {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const token = typeof explicit === 'symbol' ? explicit : Symbol.for(propertyKey);
const factory = (c: DependencyContainer) => descriptor.value.apply(target, [c]);
const finalFactory = singleton ? instanceCachingFactory(factory) : factory;
container.register(token, { useFactory: finalFactory });
if (token !== explicit) {
container.registerType(token, explicit);
}
};
}
instead of calling
.register
to do multiple ... beans (for lack of a better term) that cannot be annotated with @injectable due to ownership, or interface-ness, it would be nice to be able to have spring likenote: in spring MyConfig also becomes a registered "bean".