diff --git a/config/defaults.json b/config/defaults.json index 7745f0e..23b225e 100644 --- a/config/defaults.json +++ b/config/defaults.json @@ -72,6 +72,7 @@ "indexName": "pelias", "typeName": "_doc" }, + "addendum_namespaces": {}, "logger": { "level": "debug", "timestamp": true, diff --git a/index.js b/index.js index 3f7090c..a755724 100644 --- a/index.js +++ b/index.js @@ -1,8 +1,7 @@ const fs = require('fs'); const path = require('path'); const _ = require('lodash'); - -const Joi = require('@hapi/joi'); +const global_schema = require('./schema'); const default_config = require( __dirname + '/config/defaults.json' ); let localpath = process.env.HOME + '/pelias.json'; // default location of pelias.json @@ -23,7 +22,9 @@ function generate( schema, deep ){ const config = getConfig(deep); - if (_.isObject(schema)) { + // Pelias-config is always an object, so we don't expect + // any other joi schema type. + if (_.isObject(schema) && schema.type === 'object') { return getValidatedSchema(config, schema); } @@ -31,7 +32,8 @@ function generate( schema, deep ){ } function getValidatedSchema(config, schema) { - const validationResult = schema.validate(config); + const commonSchema = global_schema.concat(schema); + const validationResult = commonSchema.validate(config); if (validationResult.error) { throw new Error(validationResult.error.details[0].message); diff --git a/schema.js b/schema.js new file mode 100644 index 0000000..8a79d84 --- /dev/null +++ b/schema.js @@ -0,0 +1,9 @@ +const Joi = require('@hapi/joi'); + +module.exports = Joi.object().keys({ + addendum_namespaces: Joi.object().pattern( + Joi.string().min(2), Joi.object().required().keys({ + type: Joi.string().valid('array', 'number', 'string', 'boolean').required() + }) + ) +}).unknown(true); diff --git a/test/expected-deep.json b/test/expected-deep.json index 78917f6..7870dcf 100644 --- a/test/expected-deep.json +++ b/test/expected-deep.json @@ -77,6 +77,7 @@ "indexName": "pelias", "typeName": "_doc" }, + "addendum_namespaces": {}, "logger": { "level": "debug", "timestamp": true, diff --git a/test/generate.js b/test/generate.js index 787964f..e0d83db 100644 --- a/test/generate.js +++ b/test/generate.js @@ -1,4 +1,3 @@ - const path = require('path'); const config = require('../'); const defaults = require('../config/defaults'); @@ -212,14 +211,6 @@ module.exports.generate.paths = function(test) { }; module.exports.generate.validate = (test) => { - test('non-validating schema should throw an error', (t) => { - t.throws(() => { - config.generate(Joi.boolean()); - }, /"value" must be a boolean/); - t.end(); - - }); - test('validating schema should not throw an error', (t) => { const schema = Joi.object().keys({ imports: Joi.object() @@ -284,7 +275,7 @@ module.exports.generate.validate = (test) => { t.end(); }); - test('generateDefaults returns default config always', function(t) { + test('generateDefaults returns default config always', (t) => { // set the PELIAS_CONFIG env var, this config should NOT be used process.env.PELIAS_CONFIG = path.resolve( __dirname + '/../config/env.json' ); @@ -297,7 +288,7 @@ module.exports.generate.validate = (test) => { delete process.env.PELIAS_CONFIG; }); - test('generateCustom returns defaults with custom settings overridden', function(t) { + test('generateCustom returns defaults with custom settings overridden', (t) => { const custom_config = { api: { customValue: 1, //add a new setting diff --git a/test/run.js b/test/run.js index 7f51f4d..59f67de 100644 --- a/test/run.js +++ b/test/run.js @@ -4,7 +4,8 @@ var common = {}; var tests = [ require('./interface.js'), - require('./generate.js') + require('./generate.js'), + require('./schema.js') ]; tests.map(function(t) { diff --git a/test/schema.js b/test/schema.js new file mode 100644 index 0000000..a2688e7 --- /dev/null +++ b/test/schema.js @@ -0,0 +1,126 @@ +const schema = require('../schema'); + +module.exports.tests = {}; + +module.exports.tests.addendum_namespaces_validation = (test) => { + test( 'addendum_namespaces should be of object type', (t) => { + const config = { + addendum_namespaces: { + tariff_zone_ids: '123' + } + }; + + const result = schema.validate(config); + + t.equals(result.error.details.length, 1); + t.equals(result.error.details[0].message, '"addendum_namespaces.tariff_zone_ids" must be of type object'); + t.end(); + + }); + + test( 'addendum_namespaces of type other than array, string , boolean and number, should not be acceptable', (t) => { + const config = { + addendum_namespaces: { + tariff_zone_ids: { + type: 'object' + } + } + }; + + const result = schema.validate(config); + + t.equals(result.error.details.length, 1); + t.equals(result.error.details[0].message, '"addendum_namespaces.tariff_zone_ids.type" must be one of [array, number, string, boolean]'); + t.end(); + + }); + + test( 'addendum_namespaces name should be at least 2 characters', (t) => { + const config = { + addendum_namespaces: { + t: { + type: 'object' + } + } + }; + + const result = schema.validate(config); + + t.equals(result.error.details.length, 1); + t.equals(result.error.details[0].message, '"addendum_namespaces.t" is not allowed'); + t.end(); + }); + + test( 'addendum_namespaces of type array should be acceptable', (t) => { + const config = { + addendum_namespaces: { + tariff_zone_ids: { + type: 'array' + } + } + }; + + const result = schema.validate(config); + + t.notOk(result.error); + t.end(); + + }); + + test( 'addendum_namespaces of type string should be acceptable', (t) => { + const config = { + addendum_namespaces: { + tariff_zone_ids: { + type: 'string' + } + } + }; + + const result = schema.validate(config); + + t.notOk(result.error); + t.end(); + }); + + test( 'addendum_namespaces of type number should be acceptable', function(t) { + const config = { + addendum_namespaces: { + tariff_zone_ids: { + type: 'number' + } + } + }; + + const result = schema.validate(config); + + t.notOk(result.error); + t.end(); + }); + + test( 'addendum_namespaces of type boolean should be acceptable', function(t) { + const config = { + addendum_namespaces: { + tariff_zone_ids: { + type: 'boolean' + } + } + }; + + const result = schema.validate(config); + + t.notOk(result.error); + t.end(); + }); + +}; + +module.exports.all = (tape, common) => { + + function test(name, testFunction) { + return tape('configValidation: ' + name, testFunction); + } + + for( var testCase in module.exports.tests ){ + module.exports.tests[testCase](test, common); + } +};