-
Notifications
You must be signed in to change notification settings - Fork 2
English__Theory__Condition Data Sources
Whenever a data source is added during configuration building, it gets stored in a collection and will participate in the final configuration object.
There will be times, however, where we might want to exclude certain data sources based on some arbitrary condition that the developer knows (meaning the configuration builder doesn't know). How can the developer add a data source conditionally?
Any developer could probably go with something like this:
import wjConfig, { buildEnvironment } from "wj-config";
const env = buildEnvironment(window.env.MY_APP_ENVIRONMENT, ['Dev', 'PreProd', 'Prod']);
const builder = wjConfig();
if (someFunctionThatReturnsTrueIfTheDataSourceShouldBeAdded()) {
builder.addXXX(...);
}
export default await builder
.includeEnvironment(env)
.createUrlFunctions('api')
.build()
;
The above definitely works, but kills the fluent syntax of the configuration builder. Furthermore in v3 that had its TypeScript support re-written, the builder variable changes types as sources are added, yielding errors whenever the builder function is re-assigned.
There's a more succint way of doing this, though, and is to condition the data sources using the builder's when()
function:
import wjConfig, { buildEnvironment } from "wj-config";
const env = buildEnvironment(window.env.MY_APP_ENVIRONMENT, ['Dev', 'PreProd', 'Prod']);
const config = wjConfig()
.addXXX(...)
.when(e => someFunctionThatReturnsTrueIfTheDataSourceShouldBeAdded())
.includeEnvironment(env)
.createUrlFunctions('api')
.build()
;
export default await config;
The above reads like this:
Add the XXX data source only when
someFunctionThatReturnsTrueIfTheDataSourceShouldBeAdded()
returns true.
The when()
function applies to the last-added data source and its call must come immediately after adding the data
source or immediately after naming the data source using the builder's name()
function, which incidentally goes by
the same rules.
If you read the previous example carefully, you'll notice that the function signature declares the e
parameter. But
what is this about? Well, e
carries the environment object (an object of type IEnvironment
), but only if a call to
the builder's includeEnvironment()
function is made. If this call does not exist, then e
will be undefined
.
Feel free to use the information and functions provided by the environment object to your benefit in any way you see fit, or feel free to completely ignore it. It is there for your convenience and it is in no way required.
As seen in the per-environment configuration document, conditioning data sources means that sometimes a data source may not qualify and therefore may not participate in the final configuration. This means that the application should not incur in expenses related to unqualified data sources.
The section linked in the URL above has a clear example: A NodeJS application that loads environment-specific JSON files from disk. The original examples incurred in the expense of loading all files, even when only one was needed in the end because there's only one active environment at a time.
To avoid performance hits like this, all data source functions accept a function that provides the data source's data
as opposed to passing the data source's data directly. For example, the builder's addObject()
function accepts the
object or accepts a function that returns the object.
So, to avoid performance hits and unnecessary work for unqualified data sources, use the function version for all
conditioned data sources. The following table describes the function variants of all the builder's addXXX()
functions:
Builder Function | Function Argument's Signature | Description |
---|---|---|
addComputed() |
() => Object |
The function returns the object source of configuration data. |
addDictionary() |
() => Object |
The function returns the flat object source of configuration data. |
addEnvironment() |
() => Object |
The function returns the flat object with environment variables. |
addFetched() |
() => URL | RequestInfo |
The function returns the URL or RequestInfo object used by fetch() . |
addJson() |
() => string |
The function returns the JSON source of configuration data. |
addSingleValue() |
() => [string, ConfigurationValue] |
The function returns a tuple (2-element array) where the first element is the value's key and the second element is the actual configuration value. |
By using a function as the provider of the data source's data one is assured the function will only run if the data source qualifies (passes any conditional set upon it), effectively avoiding the work if the data source won't be needed. For the NodeJS example mentioned above, this means that only one environment-specific JSON file will be read from disk.
Contents
- English
- Theory
- JavaScript Concepts
- Data Sources
- Español
- Teoría