Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

yaml-validator

Package Overview
Dependencies
Maintainers
1
Versions
18
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

yaml-validator - npm Package Compare versions

Comparing version 2.1.0 to 2.2.0

30

bin/yaml-validator.js

@@ -34,3 +34,3 @@ #!/usr/bin/env node

const optsParser = optionator({
prepend: `${pkg.name} [options] <file>`,
prepend: `${pkg.name} [options] <files>`,
append: `Version ${pkg.version}`,

@@ -87,4 +87,4 @@ options: [

if (opts._.length !== 1) {
console.error('File not specified');
if (opts._.length === 0) {
console.error('File(s) not specified');
console.log(optsParser.generateHelp());

@@ -94,12 +94,18 @@ process.exit(1);

const filepath = path.resolve(opts._[0]);
const resolveFilepath = (input) => {
const output = path.resolve(input);
try {
fs.accessSync(filepath);
}
catch (error) {
console.error(`The file "${filepath}" does not exist`);
process.exit(1);
}
try {
fs.accessSync(output);
}
catch (error) {
console.error(`The file "${output}" does not exist`);
process.exit(1);
}
return output;
};
const files = opts._.map(resolveFilepath);
const options = {

@@ -115,3 +121,3 @@ writeJson: typeof opts.writeJson === 'boolean' ?

const validator = new YamlValidator(options);
validator.validate([filepath]);
validator.validate(files);
process.exitCode = validator.report();

348

index.js

@@ -16,213 +16,215 @@ /**

const YamlValidatore = function YamlValidatore(options) {
this.options = Object.assign({
log: false,
structure: false,
onWarning: null,
writeJson: false
}, options);
class YamlValidatore {
constructor (options) {
this.options = Object.assign({
log: false,
structure: false,
onWarning: null,
writeJson: false
}, options);
this.logs = [];
this.nonValidPaths = []; // list of property paths
this.inValidFilesCount = 0;
};
this.logs = [];
this.nonValidPaths = []; // list of property paths
this.inValidFilesCount = 0;
}
/**
* Store log messages
* possible later use by writing a log file.
* @param {string} msg Error message
* @returns {void}
*/
YamlValidatore.prototype.errored = function errored(msg) {
this.logs.push(msg);
};
/**
* Store log messages
* possible later use by writing a log file.
* @param {string} msg Error message
* @returns {void}
*/
errored(msg) {
this.logs.push(msg);
}
/**
* Check that the given structure is available.
* @param {Object} doc Object loaded from Yaml file
* @param {Object} structure Structure requirements
* @param {string} parent Address in a dot notation
* @returns {Array} List of not found structure paths
*/
YamlValidatore.prototype.validateStructure = function validateStructure(doc, structure, parent) {
let notFound = [],
current = '',
notValid; // false or path
/**
* Check that the given structure is available.
* @param {Object} doc Object loaded from Yaml file
* @param {Object} structure Structure requirements
* @param {string} parent Address in a dot notation
* @returns {Array} List of not found structure paths
*/
validateStructure(doc, structure, parent) {
let notFound = [],
current = '',
notValid; // false or path
parent = parent || '';
parent = parent || '';
Object.keys(structure).forEach(function eachKey(originKey) {
const optional = originKey.endsWith('?');
const key = originKey.replace(/\?$/u, '');
Object.keys(structure).forEach((originKey) => {
const optional = originKey.endsWith('?');
const key = originKey.replace(/\?$/u, '');
current = parent;
if (!check(structure).is('Array')) {
current += (parent.length > 0 ?
'.' :
'') + key;
}
current = parent;
if (!check(structure).is('Array')) {
current += (parent.length > 0 ?
'.' :
'') + key;
}
const item = structure[originKey];
if (item instanceof Array) {
if (check(doc).has(key) && check(doc[key]).is('Array')) {
doc[key].forEach(function eachArray(child, index) {
if (item.length > 1) {
notValid = validateStructure([child], [item[index]], current + '[' + index + ']');
}
else {
notValid = validateStructure([child], item, current + '[' + index + ']');
}
notFound = notFound.concat(notValid);
});
const item = structure[originKey];
if (item instanceof Array) {
if (check(doc).has(key) && check(doc[key]).is('Array')) {
doc[key].forEach((child, index) => {
if (item.length > 1) {
notValid = this.validateStructure([child], [item[index]], current + '[' + index + ']');
}
else {
notValid = this.validateStructure([child], item, current + '[' + index + ']');
}
notFound = notFound.concat(notValid);
});
}
else if (!optional) {
notFound.push(current);
}
}
else if (!optional) {
notFound.push(current);
else if (typeof item === 'string') {
if (!check(doc).has(key) && optional){
notValid = false;
}
else {
notValid = !((check(structure).is('Array') || check(doc).has(key)) && check(doc[key]).is(item));
}
// Key can be a index number when the structure is an array, but passed as a string
notFound.push(notValid ?
current :
false);
}
}
else if (typeof item === 'string') {
if (!check(doc).has(key) && optional){
notValid = false;
else if (typeof item === 'object' && item !== null) {
if (!optional) {
notValid = this.validateStructure(doc[key], item, current);
notFound = notFound.concat(notValid);
}
}
else {
notValid = !((check(structure).is('Array') || check(doc).has(key)) && check(doc[key]).is(item));
});
return notFound.filter(function filterFalse(item) {
return item !== false;
});
}
/**
* Parse the given Yaml data.
* @param {string} filepath Yaml file path
* @param {string} data Yaml data
* @returns {string|null} Parsed Yaml or null on failure
*/
loadData(filepath, data) {
const onWarning = (error) => {
this.errored(filepath + ' > ' + error);
if (typeof this.options.onWarning === 'function') {
this.options.onWarning.call(this, error, filepath);
}
};
let doc;
// Key can be a index number when the structure is an array, but passed as a string
notFound.push(notValid ?
current :
false);
try {
doc = yaml.safeLoad(data, {
onWarning: onWarning
});
}
else if (typeof item === 'object' && item !== null) {
if (!optional) {
notValid = validateStructure(doc[key], item, current);
notFound = notFound.concat(notValid);
}
catch (error) {
const lineNumber = error.message.match(/line (\d+)/u)[1];
this.errored(`Failed to load the Yaml file "${filepath}:${lineNumber}"\n${error.message}`);
console.error(`${filepath}:${lineNumber}\n${error.message}`);
return null;
}
});
return notFound.filter(function filterFalse(item) {
return item !== false;
});
};
return doc;
}
/**
* Parse the given Yaml data.
* @param {string} filepath Yaml file path
* @param {string} data Yaml data
* @returns {string|null} Parsed Yaml or null on failure
*/
YamlValidatore.prototype.loadData = function loadData(filepath, data) {
/**
* Read and parse the given Yaml file.
* @param {string} filepath Yaml file path
* @returns {string|null} Parsed Yaml or null on failure
*/
loadFile(filepath) {
// Verbose output will tell which file is being read
let data;
const _self = this;
const _self = this;
let doc;
try {
data = fs.readFileSync(filepath, 'utf8');
}
catch (err) {
_self.errored(filepath + ' > No such file or directory');
try {
doc = yaml.safeLoad(data, {
onWarning: (error) => {
_self.errored(filepath + ' > ' + error);
if (typeof _self.options.onWarning === 'function') {
_self.options.onWarning.call(_self, error, filepath);
}
}
});
}
catch (error) {
const lineNumber = error.message.match(/line (\d+)/u)[1];
_self.errored(`Failed to load the Yaml file "${filepath}:${lineNumber}"\n${error.message}`);
console.error(`${filepath}:${lineNumber}\n${error.message}`);
return null;
}
return null;
return this.loadData(filepath, data);
}
return doc;
};
/**
* Read the given Yaml file, load and check its structure.
* @param {string} filepath Yaml file path
* @returns {number} 0 when no errors, 1 when errors.
*/
checkFile(filepath) {
const doc = this.loadFile(filepath);
/**
* Read and parse the given Yaml file.
* @param {string} filepath Yaml file path
* @returns {string|null} Parsed Yaml or null on failure
*/
YamlValidatore.prototype.loadFile = function loadFile(filepath) {
// Verbose output will tell which file is being read
let data;
const _self = this;
if (!doc) {
return 1;
}
try {
data = fs.readFileSync(filepath, 'utf8');
}
catch (err) {
_self.errored(filepath + ' > No such file or directory');
if (this.options.writeJson) {
const json = JSON.stringify(doc, null, ' ');
fs.writeFileSync(filepath.replace(/\.y(a)?ml$/iu, '.json'), json, 'utf8');
}
return null;
}
if (this.options.structure) {
const nonValidPaths = this.validateStructure(doc, this.options.structure);
return this.loadData(filepath, data);
};
if (nonValidPaths.length > 0) {
this.errored(filepath + ' is not following the correct structure, missing:');
this.errored(nonValidPaths.join('\n'));
this.nonValidPaths = this.nonValidPaths.concat(nonValidPaths);
/**
* Read the given Yaml file, load and check its structure.
* @param {string} filepath Yaml file path
* @returns {number} 0 when no errors, 1 when errors.
*/
YamlValidatore.prototype.checkFile = function checkFile(filepath) {
const doc = this.loadFile(filepath);
return 1;
}
}
if (!doc) {
return 1;
return 0;
}
if (this.options.writeJson) {
const json = JSON.stringify(doc, null, ' ');
fs.writeFileSync(filepath.replace(/\.y(a)?ml$/iu, '.json'), json, 'utf8');
/**
* Create a report out of this, but in reality also run.
* @param {array} files List of files that have been checked that they exist
* @returns {void}
*/
validate(files) {
const _self = this;
this.inValidFilesCount = files.map((filepath) => {
return _self.checkFile(filepath);
}).reduce((prev, curr) => {
return prev + curr;
}, _self.inValidFilesCount);
}
if (this.options.structure) {
const nonValidPaths = this.validateStructure(doc, this.options.structure);
/**
* Create a report out of this, but in reality also run.
* @returns {number} 0 when no errors, the count of invalid files otherwise.
*/
report() {
if (nonValidPaths.length > 0) {
this.errored(filepath + ' is not following the correct structure, missing:');
this.errored(nonValidPaths.join('\n'));
this.nonValidPaths = this.nonValidPaths.concat(nonValidPaths);
return 1;
if (this.inValidFilesCount > 0) {
this.errored('Yaml format related errors in ' + this.inValidFilesCount + ' files');
}
}
return 0;
};
const len = this.nonValidPaths.length;
this.errored('Total of ' + len + ' structure validation error(s)');
/**
* Create a report out of this, but in reality also run.
* @param {array} files List of files that have been checked that they exist
* @returns {void}
*/
YamlValidatore.prototype.validate = function validate(files) {
const _self = this;
this.inValidFilesCount = files.map(function mapFiles(filepath) {
return _self.checkFile(filepath);
}).reduce(function reduceFiles(prev, curr) {
return prev + curr;
}, _self.inValidFilesCount);
};
if (typeof this.options.log === 'string') {
fs.writeFileSync(this.options.log, this.logs.join('\n'), 'utf8');
}
/**
* Create a report out of this, but in reality also run.
* @returns {number} 0 when no errors, the count of invalid files otherwise.
*/
YamlValidatore.prototype.report = function report() {
if (this.inValidFilesCount > 0) {
this.errored('Yaml format related errors in ' + this.inValidFilesCount + ' files');
return this.inValidFilesCount;
}
}
const len = this.nonValidPaths.length;
this.errored('Total of ' + len + ' structure validation error(s)');
if (typeof this.options.log === 'string') {
fs.writeFileSync(this.options.log, this.logs.join('\n'), 'utf8');
}
return this.inValidFilesCount;
};
module.exports = YamlValidatore;
{
"name": "yaml-validator",
"version": "2.1.0",
"version": "2.2.0",
"description": "Validate Yaml files and enforce a given structure",

@@ -41,10 +41,10 @@ "main": "index.js",

"devDependencies": {
"@types/node": "10.14.6",
"codecov": "3.3.0",
"@types/node": "12.0.3",
"codecov": "3.5.0",
"eslint": "5.16.0",
"eslint-config-paazmaya": "5.2.0",
"nyc": "14.0.0",
"tape": "4.10.1",
"typescript": "3.4.5"
"eslint-config-paazmaya": "5.3.0",
"nyc": "14.1.1",
"tape": "4.10.2",
"typescript": "3.5.1"
}
}

@@ -67,3 +67,3 @@ # yaml-validator

```sh
yaml-validator [options] <file>
yaml-validator [options] <files>

@@ -156,3 +156,3 @@ -h, --help Help and usage instructions

id: 'number',
'location?':{
'location?':{
floor: "string",

@@ -212,2 +212,5 @@ building: "string",

* `v2.2.0` (2019-05-29)
- Internally written as ES2015 Class, instead of ES5 way which polluted `prototype`
- Allows now more than just one input file via command line
* `v2.1.0` (2019-04-27)

@@ -214,0 +217,0 @@ - Use [`npm-shrinkwrap.json`](https://docs.npmjs.com/files/shrinkwrap.json) for locking the working set of 3rd party dependencies

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc