Variables Inheritance
View SourceThis documentation describes how Nvir figures out which value to use when a variable uses interpolation with other variables in a dotenv file.
GREETING=Hello $USERNAME!
System inheritance
When loading multiple files, Nvir will load the files in a deterministic order and splits those files into "regular" and "overwrite" files.
See the file loading documentation for more details. The important part here is that it changes the inheritance behaviour.
System inheritance for regular files
Regular files do not overwrite the system environment, so the variables used in interpolation always use the actual system environment variables first, and then falls back to the variables defined in the dotenv files.
In this example with a regular file, the WHO=moon
variable will not be set in
the environment as it is already defined in the system environment as
WHO=world
.
Nvir will respect that logic when building interpolated values:
# System state:
# WHO=world
# .env, a regular file.
WHO=moon
GREETING=hello $WHO # Will use WHO=world from system since we are not overwriting
# Result:
# GREETING=hello world
If the variable does not already exist in the system, then it will use
WHO=moon
for interpolation because it will also define the variable in the
runtime environment.
System inheritance for overwrite files
When dealing with overwrite files, the logic is simpler, each variable is always defined to the latest seen value, in interpolation as well as in the final set of variables added to the runtime environment.
Multiple files
With multiple files, we use the latest value. In this example the variable is not already defined in the system:
# .env
WHO=world
# .env.dev
WHO=mars
GREETING=hello $WHO # This defines GREETING=hello mars
# .env.dev.2
WHO=moon
GREETING=hello $WHO # this defines GREETING=hello moon
# With loading order of .env, .env.dev, .env.dev.2
# we will have the following:
# WHO=moon
# GREETING=hello moon
So, "regular" files do not overwrite the system environment, but they act as a group and overwrite themselves as if they were a single file.
If the variable is already defined in the system, the values from all regular files are ignored just as in the single-file example.
Important edge case
When a variable used in interpolation is later redefined in subsequent files, dependent variables that used its value will not use the last defined value:
# .env
WHO=world
# .env.dev
WHO=mars
GREETING=hello $WHO # GREETING is defined here, using WHO=mars
# .env.dev.2
WHO=moon # WHO is updated, but GREETING keeps its value
# since it's not redefined here
# Final result:
# WHO=moon
# GREETING=hello mars # The result is not "hello moon"
This may cause inconsistencies if you code depends on the values of both
GREETING
and WHO
.