-
Notifications
You must be signed in to change notification settings - Fork 2
English__Data Sources__Dictionary
wj-config
provides the Dictionary
data source that allows the use of flat configuration sources, which can come
from varied places. It is actually the base class for the Environment
and Single Value data sources.
A flat data source is a data source with no hierarchy. This means an object that has keys (properties), and that the values of said properties are not objects with keys; values are scalar values like strings, numbers or Booleans. The following is an example of a flat object in JavaScript, and it contrasts it with a non-flat object:
const flatObject = {
KeyA: 123,
KeyB: 'A string',
KeyC: true,
KeyD: false
};
const nonFlatObject = {
KeyA: 456,
KeyB: {
SubKeyB_KeyA: 'A string'
},
KeyC: true
};
The second object in the example does not qualify to be a dictionary data source because the value of property KeyB
is itself an object.
If you have been reading this wiki, you know that wj-config
produces a hierarchical configuration object, and that
its hierarchy is dictated by the data sources. If this is true, and since there is this Dictionary
data source, it
must be able to contribute to hierarchy, even when itself is not allowed to have a hierarchy.
This data source allows the dictionary keys to specify the hierarchy by using a hierarchy separator. By default, the
Dictionary
data source expects :
to be the hierarchy separator. The following is an example of a dictionary
object that can be used with the Dictionary
data source:
const myDic = {
'KeyA': 456,
'KeyB:SubKeyB_KeyA': 'A string',
'KeyC': true
};
This example is actually the flattened version of the non-flat object found in the first example. The Dictionary
data source will parse the property names (keys) and will split the values at the places where the hierarchy separator
is found, which is the colon (:
) by default.
As with all other data sources, there is a specialized addDictionary()
method in the configuration builder that
assists with this job. This function defines three parameters in the form of 2 overloads:
addDictionary<NewT extends Record<string, any>>(
dictionary: Record<string, ConfigurationValue> | (() => Promise<Record<string, ConfigurationValue>>),
hierarchySeparator?: string,
prefix?: string
): IBuilder<MergeResult<T, NewT>>;
addDictionary<NewT extends Record<string, any>>(
dictionary: Record<string, ConfigurationValue> | (() => Promise<Record<string, ConfigurationValue>>),
hierarchySeparator?: string,
predicate?: Predicate<string>
): IBuilder<MergeResult<T, NewT>>;
- The dictionary object, or a function that returns the dictionary object.
- An optional string that will be used as hierarchy separator, which will be
:
if nothing is specified. - An optional string to be interpreted as a prefix, or a predicate function.
The first one is the main data parameter. As with all other data sources, it may take the dictionary object directly or it may take a function that returns the dictionary object. The function approach is the recommended approach when doing any form of conditional configuration if obtaining the dictionary object will incur in potentially-wasted CPU cycles.
The second parameter has already been explained extensively; it is used to define hierarchies in a dictioanry (flat)
object. Its default value is a colon (:
) but any string can be specified here.
The final parameter works as a filter. This filter can be provided in one of two forms: A string, or a predicate function. The former triggers prefix logic, which means that only the properties whose name starts with the given prefix are allowed to contribute to the final configuration object. The latter allows the developer to put whatever logic is required to determine which properties will end up contributing to the final configuration object.
The following code snippets show the two filtering mechanisms:
const config = await wjConfig()
.addDictionary(myDic, ':', 'CNFG_')
...
.build();
const config = await wjConfig()
.addDictionary(myDic, ':', n => n.includes('TopSecret'))
...
.build();
The first code snippet tells the dictionary data source to only use the properties whose name start with the prefix
CNFG_
; the second code snippet provides a function that receives the property name and returns true
(meaning
include the property in the final configuration object) if the property name contains the string TopSecret
.
The first one is the most common one, but the predicate function allows the developer to run arbitrary checks and is therefore the ultimate filtering tool.
The following is the list of requirements when using dictionary data sources:
- A hierarchy separator must be provided.
- The hierarchy separator must be a string.
- The prefix (or predicate function) is optional.
- The dictionary object may be
null
orundefined
. This is valid. - When the dictionary object is provided directly, it is immediately validated to determine if it is a flat object, and if not, then an error will be thrown, right there on the spot.
- When the dictionary object is not directly provided and instead a function that returns it is provided, the resulting object will not undergo flatness validation. Instead, the internal function that inflates the object will throw an error if it finds a hierarchy (a non-scalar/non-leaf/node property value).
Hopefully the above list is clear enough as to not need futher explanation. If anything is unclear, drop an issue in the project's repository.
This data source is the only out-of-the-box data source that attempts to convert string values to other data types.
Any property value of type string in the dictionary object will undergo the following parsing algorithm:
-
null
andundefined
values are left alone. - The strings
true
andfalse
are converted to their Boolean equivalents. - The string value is tested with a regular expression to determine if it is an integer. It can be in decimal or hexadecimal notation (0x[0-9a-fA-F]+).
- The string value is tested with a regular expression to determine if it is a floating-point value. Only decimal notation is allowed.
- If none of the above attempts yield fruits, then the original string value is kept as-is.
Contents
- English
- Theory
- JavaScript Concepts
- Data Sources
- Español
- Teoría