A lightweight configuration library.
Whether to be used as configuration for an entire application or just for small objects with convenience methods, this library provides a configuration solution that is easy to use and extend.
For further insights, read on.
To install this library use your favorite package manager. No additional steps are required to start using the library.
npm install @n7e/configuration
This library is implemented in TypeScript but can be used with JavaScript without any additional steps.
The protagonist of this library is the configuration object. Configuration
objects lets you retrieve and manipulate configuration values. All configuration
objects implement the Configuration
interface. To reference it simply import
it and use it as a type.
import { Configuration } from "@n7e/configuration";
function doSomethingWith(configuration: Configuration): void {
// ...
}
Configuration
is just an interface describing the functionality of a
configuration object. To create configuration objects use a
configuration builder.
Key paths are used to reference values in configuration objects. To reference
leaf values in nested objects the key in each subsequent object is separated
with a .
.
The key path for the value "value"
in the following structure looks like:
nested.key
.
{
nested: {
key: "value"
}
}
To check whether a configuration value is present in a configuration object use the has
method:
if (configuration.has("key")) {
// ...
}
Even if the value at the given key path is null or undefined the value is considered to be present.
To retrieve configuration values from a configuration object use the get
method:
const value = configuration.get("key");
The value will be of any type found at the given key path. So if the key path does not reference a leaf the type will be that of an object.
If the key path does not reference a value undefined
will be returned. You can
supply a desired value to use in case of an absent value:
const value = configuration.get("key", "default value");
If the key path does not reference a value "default value" will be returned.
To set a configuration value use the set
method. Values can be of any type:
configuration.set("key", "value");
The key path will reference the given value. If the key path is nested the necessary intermediary objects will be created in the configuration object. To illustrate this suppose we start with an empty configuration object and add a value to a nested key path:
configuration.set("nested.key", "value");
The value referenced by the key path "nested" will be {key: "value"}
.
To remove a value from a configuration source use the remove
method:
configuration.remove("key");
To clear all values from a configuration object use the clear
method.
configuration.clear();
To create configuration objects you should use a ConfigurationBuilder
.
To define what configuration values makes up the final configuration object you can add any number of configuration sources.
configurationBuilder
.addConfigurationSource(jsonFileConfigurationSource)
.addConfigurationSource(restConfigurationSource)
.addConfigurationSource(someOtherConfigurationSource);
A configuration builder can be passed around and incrementally augmented to eventually produce a desired configuration object.
const configuration = await configurationBuilder.build();
ConfigurationBuilder
is just an interface describing the functionality of a
configuration builder. To create a configuration builder instance you need to
reference a specific implementation.
Configuration sources provide configuration builders with the values to build configuration objects from. The asynchronous nature of configuration sources allows for configuration values to be retrieved from any number of external resources.
ConfigurationSource
is just an interface describing the functionality of a
configuration source. To create a configuration source instances you need to
reference a specific implementation.
There's a provided implementation of ConfigurationSource
that provides
configuration values from a plain JavaScript object. The final configuration
object will contain the values of any object provided to the constructor.
import { ObjectConfigurationSource } from "@n7e/configuration";
configurationBuilder.addConfigurationSource(new ObjectConfigurationSource({key: "value"}));
There's a provided implementation of ConfigurationBuilder
ready to use.
import { DefaultConfigurationBuilder } from "@n7e/configuration";
const configurationBuilder = new DefaultConfigurationBuilder();
// Add any desired configuration sources...
const configuration = await configurationBuilder.build();
Configuration sections are essentially configuration objects operating in isolation on a specific key path. Any and all operations on the configuration section will only affect the specified key path.
This can be useful when you want to enable some procedure to modify configuration but don't want to give the procedure access to the entire configuration object.
setRelevantConfigurationValues(configurationSectionFactory.createConfigurationSection("nested", configuration));
function setRelevantConfigurationValues(configuration: Configuration): void {
configuration.set("key", "value");
}
Calling all()
on the provided configuration object after the procedure call
will yield the following value:
{
nested: {
key: "value"
}
}
To create a configuration section use a configuration section factory.
Configuration section factories has the ability to create configuration sections.
ConfigurationSectionFactory
is just an interface describing the functionality
of a configuration section factory. To create a configuration section factory
instance you need to reference a specific
implementation.
There's a provided default implementation of ConfigurationSectionFactory
.
import { DefaultConfigurationSectionFactory } from "@n7e/configuration";
const configurationSectionFactory = new DefaultConfigurationSectionFactory();
/*
* The created configuration section will operate on the "section" key path of
* the provided configuration object.
*/
const configurationSection = configurationSectionFactory.createConfigurationSection("section", configuration);