Added a validate command to the CLI.

This command is a way to test the config file. Eventually it'll probably
be removed and the schema validation will run on every other command. I
have to determine how useful this is and how performance might be
affected.
This commit is contained in:
David Diaz 2018-05-01 12:57:53 -06:00
parent 0a7fbc90ff
commit 2d57bc7bbe
6 changed files with 75 additions and 13 deletions

View File

@ -6,13 +6,17 @@ const { Command, flags } = require('@oclif/command');
const Beau = require('../../src/beau'); const Beau = require('../../src/beau');
class Base extends Command { class Base extends Command {
loadConfig(configFile) { openConfigFile(configFile) {
if (!fs.existsSync(configFile)) { if (!fs.existsSync(configFile)) {
this.error(`The config file, ${configFile} was not found.`); this.error(`The config file, ${configFile} was not found.`);
this.exit(1); this.exit(1);
} }
const config = yaml.safeLoad(fs.readFileSync(configFile, 'utf-8')); return yaml.safeLoad(fs.readFileSync(configFile, 'utf-8'));
}
loadConfig(configFile) {
const config = this.openConfigFile(configFile);
const env = dotenv.config().parsed || {}; const env = dotenv.config().parsed || {};
return new Beau(config, env); return new Beau(config, env);

View File

@ -0,0 +1,34 @@
const clc = require('cli-color');
const fs = require('fs');
const yaml = require('js-yaml');
const { flags } = require('@oclif/command');
const Base = require('../base');
const { validate } = require('../../../src/schema.js');
class ValidateCommand extends Base {
async run() {
const { flags, args } = this.parse(ValidateCommand);
const configFile = args.alias || flags.config;
const config = this.openConfigFile(configFile);
let result = await validate(config);
if (result.valid) {
this.log(`${configFile} is valid.`);
} else {
this.error(result.message);
}
}
}
ValidateCommand.description = `Validates the given configuration file against Beau's configuration schema.`;
ValidateCommand.flags = { ...Base.flags };
ValidateCommand.args = [
{
name: 'alias',
required: false,
description: `The configuration file to validate.`
}
];
module.exports = ValidateCommand;

View File

@ -1,7 +1,7 @@
endpoint: http://localhost:10080 endpoint: http://localhost:10080
plugins: plugins:
- beau-jwt: - jwt:
data: data:
userId: 12 userId: 12
name: Sergio name: Sergio

10
package-lock.json generated
View File

@ -3939,7 +3939,7 @@
"resolved": "https://registry.npmjs.org/isemail/-/isemail-3.1.2.tgz", "resolved": "https://registry.npmjs.org/isemail/-/isemail-3.1.2.tgz",
"integrity": "sha512-zfRhJn9rFSGhzU5tGZqepRSAj3+g6oTOHxMGGriWNJZzyLPUK8H7VHpqKntegnW8KLyGA9zwuNaCoopl40LTpg==", "integrity": "sha512-zfRhJn9rFSGhzU5tGZqepRSAj3+g6oTOHxMGGriWNJZzyLPUK8H7VHpqKntegnW8KLyGA9zwuNaCoopl40LTpg==",
"requires": { "requires": {
"punycode": "2.1.0" "punycode": "2.x.x"
}, },
"dependencies": { "dependencies": {
"punycode": { "punycode": {
@ -4807,9 +4807,9 @@
"resolved": "https://registry.npmjs.org/joi/-/joi-13.2.0.tgz", "resolved": "https://registry.npmjs.org/joi/-/joi-13.2.0.tgz",
"integrity": "sha512-VUzQwyCrmT2lIpxBCYq26dcK9veCQzDh84gQnCtaxCa8ePohX8JZVVsIb+E66kCUUcIvzeIpifa6eZuzqTZ3NA==", "integrity": "sha512-VUzQwyCrmT2lIpxBCYq26dcK9veCQzDh84gQnCtaxCa8ePohX8JZVVsIb+E66kCUUcIvzeIpifa6eZuzqTZ3NA==",
"requires": { "requires": {
"hoek": "5.0.3", "hoek": "5.x.x",
"isemail": "3.1.2", "isemail": "3.x.x",
"topo": "3.0.0" "topo": "3.x.x"
}, },
"dependencies": { "dependencies": {
"hoek": { "hoek": {
@ -7218,7 +7218,7 @@
"resolved": "https://registry.npmjs.org/topo/-/topo-3.0.0.tgz", "resolved": "https://registry.npmjs.org/topo/-/topo-3.0.0.tgz",
"integrity": "sha512-Tlu1fGlR90iCdIPURqPiufqAlCZYzLjHYVVbcFWDMcX7+tK8hdZWAfsMrD/pBul9jqHHwFjNdf1WaxA9vTRRhw==", "integrity": "sha512-Tlu1fGlR90iCdIPURqPiufqAlCZYzLjHYVVbcFWDMcX7+tK8hdZWAfsMrD/pBul9jqHHwFjNdf1WaxA9vTRRhw==",
"requires": { "requires": {
"hoek": "5.0.3" "hoek": "5.x.x"
}, },
"dependencies": { "dependencies": {
"hoek": { "hoek": {

View File

@ -35,7 +35,10 @@
"oclif": { "oclif": {
"commands": "./bin/cli/commands", "commands": "./bin/cli/commands",
"bin": "beau", "bin": "beau",
"plugins": ["@oclif/plugin-help", "@oclif/plugin-warn-if-update-available"] "plugins": [
"@oclif/plugin-help",
"@oclif/plugin-warn-if-update-available"
]
}, },
"jest": { "jest": {
"testEnvironment": "node", "testEnvironment": "node",

View File

@ -1,6 +1,13 @@
const Joi = require('joi'); const Joi = require('joi');
const { requestRegex } = require('./shared.js'); const { requestRegex } = require('./shared.js');
const pluginSchema = [
Joi.string(),
Joi.object()
.keys(null)
.max(1)
];
const requestSchema = [ const requestSchema = [
Joi.object() Joi.object()
.keys({ .keys({
@ -11,7 +18,9 @@ const requestSchema = [
ALIAS: Joi.string().required(), ALIAS: Joi.string().required(),
FORMDATA: Joi.object().keys(null) FORMDATA: Joi.object().keys(null)
}) })
.or('FORM', 'PAYLOAD', 'FORMDATA') .without('FORM', ['PAYLOAD', 'FORMDATA'])
.without('PAYLOAD', ['FORM', 'FORMDATA'])
.without('FORMDATA', ['FORM', 'PAYLOAD'])
.rename(/headers/i, 'HEADERS', { override: true }) .rename(/headers/i, 'HEADERS', { override: true })
.rename(/payload/i, 'PAYLOAD', { override: true }) .rename(/payload/i, 'PAYLOAD', { override: true })
.rename(/params/i, 'PARAMS', { override: true }) .rename(/params/i, 'PARAMS', { override: true })
@ -36,7 +45,7 @@ const schema = Joi.object()
.keys({ .keys({
VERSION: Joi.number().integer(), VERSION: Joi.number().integer(),
ENDPOINT: Joi.string().uri(), ENDPOINT: Joi.string().uri(),
PLUGINS: Joi.array().items([Joi.string(), Joi.object().keys(null)]), PLUGINS: Joi.array().items(pluginSchema),
DEFAULTS: Joi.object(), DEFAULTS: Joi.object(),
ENVIRONMENT: Joi.object(), ENVIRONMENT: Joi.object(),
HOSTS: Joi.array().items(hostSchema), HOSTS: Joi.array().items(hostSchema),
@ -51,8 +60,20 @@ const schema = Joi.object()
.rename(/environment/i, 'ENVIRONMENT', { override: true }) .rename(/environment/i, 'ENVIRONMENT', { override: true })
.rename(/cookiejar/i, 'COOKIEJAR', { override: true }); .rename(/cookiejar/i, 'COOKIEJAR', { override: true });
const validate = function(config) { const validate = async function(config) {
return Joi.validate(config, schema, { allowUnknown: true }); try {
let results = await Joi.validate(config, schema, {
allowUnknown: true
});
return { valid: true };
} catch ({ name, details }) {
return {
valid: false,
message: `${name}: \n ${details
.map(d => d.message + ' @ ' + d.path)
.join(' \n ')}`
};
}
}; };
module.exports = { schema, validate }; module.exports = { schema, validate };