Skip to content

Commit

Permalink
set new configuration item mode and make askCredential optional
Browse files Browse the repository at this point in the history
Also this it moves the responsibility to throw ValidationError's from
prompt to lib/validation
  • Loading branch information
AdrienHorgnies authored and AdrienHorgnies committed Sep 29, 2017
1 parent c9fffd7 commit 9f90aa5
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 12 deletions.
18 changes: 18 additions & 0 deletions constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,23 @@ const packageInfo = require('./package.json');
*/
const configFile = '.db-config.json';

/**
* defines how the program must behave
* - automatic: the whole process happens without user intervention
* the program will fail if the configuration isn't full and correct
*
* - default: the selection happens without user intervention
* the program will ask user help if it needs some (like missing or incorrect login)
*
* manual: the program prompts the user for each possible choice
*
* @type {{automatic: string, default: string, manual: string}}
*/
const modes = {
automatic: 'automatic',
default: 'default',
manual: 'manual',
};

/**
* Messages displayed to the user
Expand Down Expand Up @@ -47,6 +64,7 @@ const headers = {

module.exports = {
configFile,
modes,
messages,
headers
};
9 changes: 8 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,16 @@ const msg = cst.messages;
* load configuration file, validate and clean it
*
* @resolves {askCredentials({dbms, host, port, user, password, schema})} configuration with any property possibly missing
* if mode === 'automatic', skips askCredentials and go to openSession
*/
const getConfiguration = () => prompt.loadConfigurationFile()
.then(configuration => askCredentials(configuration));
.then((configuration) => {
// automatic mode doesn't askCredentials
if (configuration.mode !== cst.modes.automatic) {
return askCredentials(configuration);
}
return openSession(configuration);
});


/**
Expand Down
50 changes: 46 additions & 4 deletions lib/validation.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// validation framework
const joi = require('joi');
const db = require('./db-commons');
const cst = require('../constants');

/**
* Validate user input against rules
Expand All @@ -21,6 +22,14 @@ const validationFromJoi = rule =>
return true;
};

/**
* create a validation library for inquirer from a joi schema.
* the resulting object shares the same keys as the input schema but replace each joi rule with a validation method
* compatible with the inquirer framework
*
* @param schema joi schema to transform
* @return {{key: function}}
*/
const fromJoiToInquirer = (schema) => {
const inquirer = {};
Object.keys(schema).forEach((key) => {
Expand All @@ -29,7 +38,13 @@ const fromJoiToInquirer = (schema) => {
return inquirer;
};

const subSchema = {
/**
* schema for the configuration according to the joi validation framework
*
* @type {{mode, dbms, host, port, user, password, schema}}
*/
const schema = {
mode: joi.string().valid(Object.keys(cst.modes)),
dbms: joi.string().valid(Object.keys(db.dbmsList)),
host: joi.string().hostname(),
port: joi.number().min(0).max(65535),
Expand All @@ -38,12 +53,39 @@ const subSchema = {
schema: joi.string(),
};

const inquirer = fromJoiToInquirer(subSchema);
/**
* validation methods usable by the prompt framework inquirer,
* one method for each key of the schema object
*/
const inquirer = fromJoiToInquirer(schema);

/**
*
* @param configuration that must respect the schema
* also there can't be any extraneous keys
* if configuration.mode is 'automatic', validation will fail on absent keys
* @return {{mode, dbms, host, port, user, password, schema}}
* @throws {Error} ValidationError if the configuration doesn't satisfy the schema rules
* get all validationError's rather than stopping at the first one
*/
const validateConfiguration = (configuration) => {
let validator = joi.object(schema).unknown(false);
if (configuration.mode === cst.modes.automatic) {
validator = validator.requiredKeys(Object.keys(schema));
}

const { error, value } = validator.validate(configuration, { abortEarly: false });

if (error) {
throw error;
}

return value;
};

const configuration = joi.object(subSchema).unknown(false);

module.exports = {
validationFromJoi,
inquirer,
configuration,
validateConfiguration,
};
8 changes: 1 addition & 7 deletions prompt.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,13 +116,7 @@ const loadConfigurationFile = () => fse.pathExists(cst.configFile)
log.info(cst.messages.noConfig);
return {};
})
.then((config) => {
const { error, value } = validation.configuration.validate(config, { abortEarly: false });
if (error) {
throw error;
}
return value;
});
.then(config => validation.validateConfiguration(config));


/**
Expand Down

0 comments on commit 9f90aa5

Please sign in to comment.