Research
Security News
Threat Actor Exposes Playbook for Exploiting npm to Build Blockchain-Powered Botnets
A threat actor's playbook for exploiting the npm ecosystem was exposed on the dark web, detailing how to build a blockchain-powered botnet.
@mocks-server/config
Advanced tools
Modular configuration provider. Read it from file, environment and arguments
Modular configuration provider. Reads and validates configuration from:
As a summary, it also provides:
Different namespaces can be created for each different element in the architecture. So, each different component is the unique who knows about its own options, but the user can define options for all components at a time, and using the same methods.
This module provides configuration to Mocks Server components and plugins, but it may be used anywhere else because it is fully configurable.
A brief example:
const Config = require("@mocks-server/config");
// Create config
const config = new Config({ moduleName: "mocks" });
// Create namespace
const namespace = config.addNamespace("fooNamespace");
// Create option
const option = namespace.addOption({
name: "fooOption",
type: "string",
default: "foo-value",
});
// Load configuration
config.load().then(() => {
// Read value
console.log(option.value);
// Set value
option.value = "foo-new-value";
});
// Listen to onChange events
option.onChange((newValue) => {
console.log(`Option has a new value: ${newValue}`);
});
Once options and namespaces are added, and the load
method is called, the library searches for values for the options in next sources, sorted from lower to higher priority:
default
property. That value will be assigned if no other one is found.load
or init
methods.process.cwd()
. Cosmiconfig is used to provide this feature, so it is compatible with next files formats:
[moduleName]
property in a package.json
file.[moduleName]rc file with JSON or YAML syntax.
.[moduleName]rc.json
, .[moduleName]rc.yaml
, .[moduleName].yml
, .[moduleName]rc.js
, or .[moduleName]rc.cjs
file.[moduleName].config.js
or [moduleName].config.cjs
CommonJS module exporting the object.[moduleName].config.js
or [moduleName].config.cjs
CommonJS module exporting a function. It receives programmatic configuration as first argument.[moduleName].config.js
or [moduleName].config.cjs
CommonJS module exporting an async function. It receives programmatic configuration as first argument.Options can be added to a namespace, or to the root config object. Both config
and namespaces have an addOption
method for creating them. Check the API chapter for further info.
Options can be of one of next types: string
, boolean
, number
, object
or array
. This library automatically converts the values from command line arguments and environment variables to the expected type when possible. If the conversion is not possible or the validation fails an error is thrown. Validation errors provide enough context to users to let them know the option that failed. This library uses ajv
and better-ajv-errors
for validations.
Here is an example of how to add an option to the root config object, and then you have information about how the option would be set from different sources:
const config = new Config({ moduleName: "mocks" });
config.addOption({ name: "optionA", type: "string", default: "foo" });
{
optionA: "foo-value"
}
moduleName
option must be prepended to the option name, using "screaming snake case".MODULE_NAME_OPTION_A="foo-value"
--optionA="foo-value"
Different isolated namespaces can be created to provide configuration to different components in the architecture. For example, Mocks Server uses config namespaces in order to allow plugins to define their own options without having conflicts with core options or other plugins options.
const config = new Config({ moduleName: "moduleName" });
config
.addNamespace("namespaceA")
.addOption({ name: "optionA", type: "string", default: "foo" });
When a namespace is created, its name must also be used when providing the configuration to its options. Next patterns are used to define the namespace of an option:
{
namespaceA: {
optionA: "foo-value"
}
}
moduleName
option and the namespace name must be prepended to the option name, using "screaming snake case".MODULE_NAME_NAMESPACE_A_OPTION_A="foo-value"
--namespaceA.optionA="foo-value"
Namespaces can be nested, so they can contain also another namespaces apart of options. The previous rules about how to use namespaces when giving values to options are also valid for nested namespaces. For example:
const config = new Config({ moduleName: "mocks" });
config
.addNamespace("namespaceA")
.addNamespace("namespaceB")
.addOption({ name: "optionA", type: "string", default: "foo" });
{
namespaceA: {
namespaceB: {
optionA: "foo-value"
}
}
}
MOCKS_NAMESPACE_A_NAMESPACE_B_OPTION_A="foo-value"
--namespaceA.namespaceB.optionA="foo-value"
Options of type string
are not parsed in any way.
const config = new Config({ moduleName: "moduleName" });
const option = config.addOption({
name: "optionA",
type: "string",
});
await config.load();
Examples about how to define options of type string
from sources:
{"optionA": "foo-value"}
MODULE_NAME_OPTION_A=foo-value
node myProgram.js --optionA=foo-value
Options of type boolean
are parsed when they are defined in environment variables, and they have a special format when defined in arguments:
const option = config.addOption({
name: "optionA",
type: "boolean",
default: true,
});
await config.load();
Examples about how to define options of type string
from sources:
{"optionA": false}
0
and false
strings will be parsed into boolean false
: MODULE_NAME_OPTION_A=false
, or MODULE_NAME_OPTION_A=0
.true
: MODULE_NAME_OPTION_A=true
, MODULE_NAME_OPTION_A=1
or MODULE_NAME_OPTION_A=foo
.true
, then the --no-
prefix added to the option name will produce the option to have a false
value: node myProgram.js --no-optionA
false
default value, then the option name will be set it as true
: node myProgram.js --optionA
Options of type number
are parsed when they are defined in environment variables or command line arguments.
const option = config.addOption({
name: "optionA",
type: "number"
});
await config.load();
Examples about how to define options of type number
from sources:
{"optionA": 5}
MODULE_NAME_OPTION_A=5
, or MODULE_NAME_OPTION_A=5.65
.node myProgram.js --optionA=6.78
Options of type object
are parsed from JSON strings when they are defined in environment variables or command line arguments. It is important to mention that objects are merged when they are defined in different sources when loading the configuration.
const option = config.addOption({
name: "optionA",
type: "object"
});
await config.load();
Examples about how to define options of type object
from sources:
{"optionA": { foo: "foo", foo2: ["1", 2 ]}}
MODULE_NAME_OPTION_A={"foo":"foo","foo2":["1",2]}}
node myProgram.js --optionA={"foo":"foo","foo2":["1",2]}}
Options of type array
are parsed from JSON strings when they are defined in environment variables. For defining them in command line arguments, multiple arguments should be provided. As in the case of objects, arrays are merged when they are defined in multiple sources when loading the configuration. The result of defining it environment variables and in arguments would be both arrays concated, for example. This behavior can be disabled using the mergeArrays
option of the Config
class.
const option = config.addOption({
name: "optionA",
type: "array",
itemsType: "string"
});
await config.load();
Examples about how to define options of type object
from sources:
{"optionA": ["foo","foo2"]}
MODULE_NAME_OPTION_A=["foo","foo2"]
node myProgram.js --optionA foo foo2
The contents of the array are also converted to its correspondent type when the itemsType
option is provided.
The library registers some options that can be used to determine the behavior of the library itself. As the rest of the configuration created by the library, these options can be set using configuration file, environment variables, command line arguments, etc. But there are some of them that can be defined only in some specific sources because they affect to reading that sources or not.
All of the built-in options are defined in the config
namespace:
config.readFile
(Boolean): Default: true
. Determines whether the configuration file should be read or not. Obviously, it would be ignored if it is defined in the configuration file.config.readArguments
(Boolean): Default: true
. Determines whether the arguments are read or not. It can be defined only using programmatic configuration.config.readEnvironment
(Boolean): Default: true
. Determines whether the environment variables are read or not. It can be defined using programmatic configuration or command line arguments.config.fileSearchPlaces
(Array): Default from cosmiconfig. An array of places to search for the configuration file. It can be defined in any source, except configuration files.config.allowUnknownArguments
(Boolean): Default false
. An array of places to search for the configuration file. It can be defined in any source, except configuration files.Once the config
instance has been created, normally you should only call to the config.load
method to load all of the configuration, apply the validations and let the library start emitting events. But for more complex use cases there is available also another method: config.init
.
You can call to the config.init
method at any time before calling to config.load
, and all configuration sources will be preloaded and values will be assigned to the options that have been already created. In this step, the validation is not executed, so you can add more namespaces or options based on some of that configuration afterwards. For example, Mocks Server first load the configuration that defines the plugins to be loaded using the init
method, then it loads them and let them add their own options, and then it executes the config.load
method. In this step the validation is executed, so unknown configuration properties would produce an error. Option events are not emitted until the load
method has finished.
const config = new Config({ moduleName: "mocks", mergeArrays: false });
Config(options)
. Returns a config
instance.
options
(Object): Containing any of next properties:
moduleName
: Used as prefix for environment variables names and config file names.mergeArrays
: Default true
. When an option is of type array
or object
, this option defines whether arrays with different values coming from different sources are concated or not. If not, the value defined in the source with higher priority would be used.init(programmaticConfig)
: Async. Read configuration and assign it to the correspondent options but do not execute validation. Allows to read partial configuration before adding more namespaces or options. Events are not still emitted.
programmaticConfig
(Object): Optional. Initial configuration to be set in options. It overwrite option defaults, but it is overwritten by config from files, environment and arguments.load(programmaticConfig)
: Async. Assign configuration to the correspondent options. It executes the init
method internally if it was not done before.
programmaticConfig
(Object): Optional. If init
was called before, it is ignored, otherwise, it is passed to the init
method.addNamespace(name)
: Add namespace to the root. Returns a namespace instance.
name
(String): Name for the namespace.addOption(optionProperties)
: Equivalent to the addOption
method in namespaces, but it add the option to the root. Returns an option instance.
optionProperties
(Object): Properties defining the option. See the addOption
method in namespaces for further info.addOptions(optionsProperties)
: Add many options. Returns an array of option instances.
optionsProperties
(Array): Array of optionProperties
.namespace(name)
: Returns the namespace instance in the root config with name equal to name
.option(optionName)
: Returns the option instances in the root config with name equal to optionName
.set(configuration)
: Set configuration properties to each correspondent namespace and options.
configuration
(Object): Object with programmatic configuration. Levels in the object correspond to namespaces names, and last level keys correspond to option names.validate(configuration, options)
: Allows to prevalidate a configuration before setting it, for example. It returns an object with valid
and errors
properties. See AJV docs for further info.
configuration
(Object): Object with configuration. Levels in the object correspond to namespaces names, and last level keys correspond to option names.options
(Object): Object with extra options for validation:
allowAdditionalProperties
(Boolean): Default false
. If true, additional properties in the configuration would not produce validation errors.value
: Getter returning the current values from all namespaces and options as an object. Levels in the object correspond to namespaces names, and last level keys correspond to option names. It can be also used as setter as an alias of the set
method, with default options.loadedFile
: Getter returning the file path of the loaded configuration file. It returns null
if no configuration file was loaded.namespaces
: Getter returning array with all root namespaces.options
: Getter returning array with all root options.const namespace = config.addNamespace("name");
addNamespace(name)
: Add another namespace to the current namespace. Returns a namespace instance.
name
(String): Name for the namespace.addOption(optionProperties)
: Adds an option to the namespace. Returns an option instance.
optionProperties
(Object): Properties defining the option.
name
(String): Name for the option.description
(String): Optional. Used in help, traces, etc.type
(String). One of string
, boolean
, number
, array
or object
. Used to apply type validation when loading configuration and in option.value
setter.itemsType
(String). Can be defined only when type
is array
. It must be one of string
, boolean
, number
or object
.default
- Optional. Default value. Its type depends on the type
option.extraData
- (Object). Optional. Useful to store any extra data you want in the option. For example, Mocks Server uses it to define whether an option must be written when creating the configuration scaffold or not.addOptions(optionsProperties)
: Add many options. Returns an array of option instances.
optionsProperties
(Array): Array of optionProperties
.namespace(name)
: Returns the namespace instance in this namespace with name equal to name
.option(optionName)
: Returns the option instances in this namespace with name equal to optionName
.name
: Getter returning the namespace name.namespaces
: Getter returning an array with children namespaces.options
: Getter returning an array object with children options.set(configuration)
: Set configuration properties to each correspondent child namespace and options.
configuration
(Object): Object with configuration. Levels in the object correspond to child namespaces names, and last level keys correspond to option names.value
: Getter returning the current values from all child namespaces and options as an object. Levels in the object correspond to namespaces names, and last level keys correspond to option names. It can be also used as setter as an alias of the set
method, with default options.const option = namespace.addOption("name");
const rootOption = config.addOption("name2");
value
: Getter of the current value. It can be also used as setter as an alias of the set
method, with default options..set(value)
: Set value.onChange(callback)
: Allows to add a listener that will be executed whenever the value changes. It only emit events after calling to the config.start
method. It returns a function that removes the listener once executed.
callback(value)
(Function): Callback to be executed whenever the option value changes. It receives the new value as first argument.name
: Getter returning the option name.type
: Getter returning the option type.description
: Getter returning the option description.extraData
: Getter returning the option extra data.default
: Getter returning the option default value.FAQs
Modular configuration provider. Read it from file, environment and arguments
The npm package @mocks-server/config receives a total of 26,201 weekly downloads. As such, @mocks-server/config popularity was classified as popular.
We found that @mocks-server/config demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
A threat actor's playbook for exploiting the npm ecosystem was exposed on the dark web, detailing how to build a blockchain-powered botnet.
Security News
NVD’s backlog surpasses 20,000 CVEs as analysis slows and NIST announces new system updates to address ongoing delays.
Security News
Research
A malicious npm package disguised as a WhatsApp client is exploiting authentication flows with a remote kill switch to exfiltrate data and destroy files.