Closed xenoterracide closed 4 years ago
I assume the goal if this is property injection (rather than constructor)?
no, you can do this on the constructor, also with setter injection (note: I disagree with direct field injection)
(note: I disagree with direct field injection)
👍
Could you give an example use case and sample code of how this may look like with TypeScript and Tsyringe?
updated OP, better?
here's a significantly less powerful workaround (and possibly bad) that doesn't support override of other property sources innately, or even defining ones outside of the env.
export type EnvMetaData = {
name: string;
optional: boolean;
};
const envMeta: Array<EnvMetaData> = [];
function env(name: string, { optional = false } = {}) {
const meta: EnvMetaData = { name, optional };
envMetadata().push(meta);
return Reflect.metadata(Symbol.for('env'), meta);
}
// wrap in case we figure out how to do it with a reflection api
export function envMetadata(): Array<EnvMetaData> {
return envMeta;
}
...
registerEnv(): void {
if (process.env.NODE_ENV === 'development') {
dotenv.config();
}
envMetadata().forEach((meta) => {
if (!meta.optional) {
assert(process.env[meta.name], `${meta.name} is not set`);
}
this.container.register(
Symbol.for(meta.name),
{ useValue: process.env[meta.name] },
);
});
}
used like
@env('STRIPE_PUBLISHABLE_KEY')
static readonly StripePk = Symbol.for('STRIPE_PUBLISHABLE_KEY');
p.s. if you know how to fix this so it gets it from metadata that'd be great! or if there's a way to not duplicate the STRIPE_PUBLISHABLE_KEY
part
@Xapphire13 interest in patches for this using this @env
?
@xenoterracide, does the new Transform (@injectWithTransform
) functionality fix this issue for you? You could create a service that exposes the environment, and then a transformer that takes the environment object and selects a value from it.
eh, I kinda switched from tsyringe a while ago.
another spring/boot feature that would be nice, is "property sources", what a property source is, is a location of "properties" like
foo.bar=baz
I imagine this wouldn't be exactly the same for typescript, though it could be.. I imagine the source of this would be eitherjson
, or an.env
, though spring core itself isn't prescriptive and only supports a few things out of the box.or you could override this with a
env
and if both existed the env var would override the json file.
then you could inject it as so (spring also supports type conversion)
you'd need some sort of collection in the registry, probably something like
reference for how to use the feature
https://www.baeldung.com/properties-with-spring
and upstream documentation
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/PropertySource.html https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/core/env/PropertySource.html https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-external-config
I'm really not hoping for the prescriptiveness of spring boot, but maybe just simply the ability to define a collection of property sources and inject values (note: property source values are not in springs container)
probably worth noting spring boot also has this feature https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-external-config-typesafe-configuration-properties