Skip to main content

JsonFileSource

The JsonFileSource implementation of ConfigurationSource extends ObjectSource, but it simply first loads the data from a JSON file.

The default context field used to define the file path to load is context.config, but this can be changed by initializing the constructor with a different contextFieldName option.

(This same field name is used to pass the actual configuration to the base class ObjectSource.load!)

Alternative file formats are not included by default in order to keep package size down, but are easy to write:

% npm install yaml

import { ObjectSource } from './object-source.js';
import { ConfigurationSource } from './configuration-source.js';
import { ConfiguratorError } from '../configurator-error.js';
import { promises as fs } from 'fs';
import { YAML } from 'yaml'

export class YamlFileSource extends ObjectSource {
constructor(options) {
super(
{
...options,
sequence: options?.sequence || ConfigurationSource.DefaultSequence.CONFIGURATION,
contextFieldName: options?.contextFieldName ?? 'config'
})
}

async load(schema, context) {

// intercept context field as a filename and rewrite it as an object

let filename = context[this.contextFieldName];

if (filename && typeof filename !== 'string') {
throw new ConfiguratorError(`Invalid configuration path ${filename}`);
}

if (!filename || typeof filename !== 'string' || !filename.toLowerCase().endsWith('.yaml')) {
// as we've divided up config file loading, we'll assume another parser will load it
return new Map();
}

try {
const data = await fs.readFile(filename, 'utf8');
return super.load(schema, {[this.contextFieldName]: YAML.parse(data)});
}
catch (error) {
if (error.code === 'ENOENT') {
throw new ConfiguratorError(`Configuration path ${filename} not found`);
}
else if (error.code === 'EISDIR') {
throw new ConfiguratorError(`Configuration path ${filename} is a directory not a YAML file`);
}
else {
throw new ConfiguratorError(`Error loading YAML configuration file: ${error.message}`, {cause: error});
}
}
}


}