Skip to main content

Configurator API

Overview

The Configurator class fills a coordination role, and leverages several other classes to compose its functionality.

  • The ConfigurationSchema defines the configurable fields.

  • A TypeRegistry holds type resolvers

  • A ValidatorRegistry registry holds field validators.

  • A list of ConfigurationSource implementations are used to discover user settings, and convert them to field path assignments to be processed and validated by the schema.

  • The Configurator is primarily concerned with choreographing the data flow through this pipeline.

Constructor

new Configurator(options)

ParamTypeDescription
[options]objectOptional settings (described below)
[options.schema]ConfigurationSchemaUser-provided schema; a new empty schema will be used if undefined
[options.types]TypeRegistryoverride for default type resolver registry
[options.validators]ValidatorRegistryoverride for default validator registry
[options.sources]Array<ConfigurationSource>* User-provided source list; omit to use defaults
[options.configEnabled]boolean* Whether to enable configuration file parsing and use the options below (default: true)
[options.configField]string* Defaults to "config"; if defined, adds this field name to hold a config file path
[options.configFlag]string* Flag hint for CommandLineSource; Defaults to "C"; used only if configEnabled
[options.configDescription]string* Help text for configField ("configuration file to load")
[options.configValueDescription]string* Help text describing configField value type ("path")

(*) advanced extension; not commonly needed

You can add fields to the default schema created by the Configurator constructor, or you can pass in a schema you have already set up.

If you want to provide an additional ConfigurationSource, you can either register it individually, or you can provide a complete list of all sources to use. Note that the order of sources does not matter; the internal sequence property is used to sort their relative priority.

If configEnabled is true (which it is, by default), an additional field is added to the root schema that will hold the pathname to a config file. The default is to have a field name of config, settable by --config <path> or -C <path> on the command line, or APPNAME_CONFIG=path as an environment variable. If these defaults conflict, you can change the field.

Methods

async configure(context: object, strict = true) : Promise<object>

returns object (a validated configuration object)

This call runs the complete configuration pipeline:

  1. Obtain field assignment requests from all registered sources.
  2. Merge the field assignment requests by source priority.
  3. Resolve each field assignment value by type, and build a configuration object.
  4. Validate and return the configuration object.

The context parameter is an object used to pass information to the ConfigurationSource implementations; since the Configurator doesn't have any special knowledge of individual sources, the "contract" of what goes in the context is defined per-source. (In general, each source has a default context field name it uses. See the individual source documentation for details.)

The context may also be mutated by the sources, allowing them to pass information downstream.

ParamTypeDescription
contextobjectContext passed to each ConfigurationSource
[context.appName]stringName of your app; technically optional, but highly recommended.
[context.overrides]objectUsed by a high-priority instance of ObjectSource to override all other sources
[context.argv]array* Private to CommandLineSource; overrides default use of process.argv.
[context.env]object* Private to EnvironmentVariableSource; overrides default use of process.env
[context.defaults]object* Used by a low-priority instance of ObjectSource to hold application defaults (only use to replace schema defaults)
[context.config]string* Mid-configuration field used by JsonFileSource, but generally only set when discovered by sources earlier in the sequence
[context.____]** The context object is an open object subject to interpretation by the sources
[strict]booleanIf false, unknown configuration settings are ignored; if true (the default), they will throw an error

(*) Not generally needed. Note that all built-in ConfigurationSource implementations provide a means to change the default context field they read.

(Some notable default context fields are appName for your application name, env to override environment variables, argv to override command line options, and config which sources can use to pass a config file path that was discovered mid-pipeline.

registerConfigurationSource(source: ConfigurationSource)

Add a ConfigurationSource to the list used by this Configurator. Sources are checked that they implement the base class that provides a name and sequence number.

ParamTypeDescription
sourceConfigurationSourceSource to register

async processAssignments(fpaList, options:object):object

Process field-path assignment maps generated from sequence of ConfigurationSource implementations. Generates a candidate configuration object, then calls validate on it.

Returns the validated object, or throws if there are errors.

This method is public, but not generally used unless you are extending Configurator.

ParamTypeDescription
fpaListArray<Map<string,any>>list of field-path assignment maps, in source sequence order
[options]objectassignment options
[options.strict]booleanstrict validation (default: true)
[options.configuration]objectinitial configuration object

async validate(inputConfig:object, options:object):object

Validate a candidate configuration object against the schema.

Returns the validated object, or throws if there are errors.

ParamTypeDescription
inputConfigobjectobject to validate against the schema
[options]objectvalidation options, described below
[options.typecheck]booleanwhether to also typecheck during validation (defaults to true)
[options.strict]booleanenable strict validation (defaults to false)
[options.populateDefaults]booleanenable fallback defaults mode (defaults to false)

You can skip typechecking if you have already typechecked the assignments .

The strict option will throw an error if unknown fields exist in the object, or if any types are unknown.

The populateDefaults option provides a fallback method to setting fields in implementations where the DefaultsSource was not used.

This method is public, but not generally used unless you are extending Configurator.

Accessors

AccessorTypeDescription
schemaConfigurationSchemaSchema in use by this Configurator
sourcesArray<ConfigurationSource>List of sources registered
typesTypeRegistryTypes used by this Configurator
validatorsValidatorRegistryValidators used by this Configurator

You can use the schema accessor to add your fields after the Configurator is constructed, e.g. these are functionally equivalent:


const types = new TypeRegistry();
types.defineType('BigInt', (value) => BigInt(value))

const validators = new ValidatorRegistry();
validators.register()

const schema = new ConfigurationSchema();
schema.field('verbose', {type: 'boolean'})



const config = new Configurator({schema}).configure();

and

const configurator = new Configurator();
configurator.schema.field('verbose', {type: 'boolean'});

const config = await configurator.configure();

However, the former pattern lends itself to potential reuse of schemas.

Similarly, types and validators can be updated any time before calling configure.