-
-
Notifications
You must be signed in to change notification settings - Fork 6
Adding support for validations and cache in Env provider #24
Comments
I agree that it's safe to cache env variables, since they don't change at runtime. About validating, this feature would help new project members to correctly setup a server environment with a large code base. However, at the same time, I don't think it's something relevant to consider and it would be one more thing to maintain. Let's wait and see what other people think about it. |
@iagobruno Thanks for the feedback. I believe, the surface area for validating env variables is quite small, so shouldn't be a big deal to manage them. |
perfect 🥇 |
I overall like the proposal 👍 |
Completed in https://github.com/adonisjs/env/releases/tag/v2.0.0 |
The RFC is a proposal to add validations and caching the environment variables for better performance. Also, since we are validating environment variables at runtime, we should also strive to get the static analysis working as well.
Why cache environment variables?
Accessing environment variables using
process.env
has a huge performance impact on your application boot time (assuming, most of the calls are during the boot cycle).Since environment variables are not something you will/should mutate during the application lifecycle. It is relatively safe to cache their original value and provide a method to clear the cache (incase someone needs it).
The caching process can be quite simple as explained below:
Env.get
method. We will only cache, if it is notundefined
..env
file. We can cache the values right away, instead of waiting for the first access call.Env.clearCache(key?)
. This can be useful during the tests.Validating environment variables
Environment variables are something that we blindly trust and assume will be available in the right shape during the application runtime.
Since environment variables are completely under our control. It is relatively safe to trust them blindly. However, if an environment is missing, the exceptions raised by your code can be confusing and hard to debug. For example:
The Problem
The following code snippet relies on the
NODE_ENV
environment variable. If the variable is missing, the exception raised by the code doesn't help in figuring out the root problem right away.Of course, you can/should write code that does check for the existence of the variable before performing transformations on it.
But, imagine writing all these conditionals everywhere in your code. We can do better here. After all, we use frameworks for some reasons.
Solution
Let's add support for validating the environment variables as soon as the application is booted and throw meaningful errors to fix them.
The
Env
module can expose a.validate
method. It accepts an object of key-value pair, where the value is the set of validations to run. For example:Things to notice here:
string
,number
,boolean
.Env.schema
methods are not enough. One can define an inline function as well.Support for intellisense
Wouldn't it be frustrating, if runtime validations do ensure that the environment variables are correct, but typescript has no information about it? For example:
Env.get('NODE_ENV')
has a return type ofundefined | string
.Env.get('PORT')
again has a return type ofstring
, whereas it should be anumber
We can fix this problem literally by writing less than 10 lines of code. The Env module has the following interface (Just keeping the
get
method for simplicity)If we can have an interface that holds the concrete types for each key, then the
get
method can use it as follows:Demo
Now the question is, how to generate this interface automatically without manually maintaining it and then living in the fear that the runtime validations and the interface can go out of sync.
How about making the
validate
method generate this interface (or types) for us?Validate method signature
The
validate
method uses generics to return the concrete data types for every validated key.Export validate output from a module
Next step is to export the output of
Env.validate
. Let's assume we decide to validate the variables insidestart/validateEnv.ts
file.Now, using declaration merging we can create
EnvTypes
from the return value ofEnv.validate
. The following code will go insidecontracts/env.ts
file.Here's link to the simplified version of it inside TS Playground.
The text was updated successfully, but these errors were encountered: