Skip to content

Commit

Permalink
Refactor parameters validation in chlg-release
Browse files Browse the repository at this point in the history
  • Loading branch information
fldubois committed Sep 27, 2016
1 parent d9eab69 commit 1ad296c
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 43 deletions.
2 changes: 1 addition & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@
// disallow specified global variables
"no-restricted-globals": "off",
// disallow var declarations from shadowing variables in the outer scope
"no-shadow": "error",
"no-shadow": ["error", {"allow": ["error"]}],
// disallow identifiers from shadowing restricted names
"no-shadow-restricted-names": "error",
// disallow the use of undeclared variables unless mentioned in /*global */ comments
Expand Down
126 changes: 84 additions & 42 deletions lib/chlg-release.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
var fs = require('fs');
var os = require('os');
var path = require('path');

var async = require('async');
var semver = require('semver');

var StreamInsert = require('stream-insert');
Expand All @@ -18,43 +20,43 @@ var formatter = require('./format/raw');

var search = /## \[Unreleased\]/;

/**
* @typedef {object} Options
* @property {string} [file=CHANGELOG.md] - The change log file name/path.
* @property {string} [date=now] - Force a specific release date, default to the current date.
*/
var validators = {
file: function (file, callback) {
return callback(null, file);
},
date: function (input, callback) {
var date = (typeof input === 'string') ? dates.parse(input) : new Date();

if (typeof input === 'string' && date === null) {
return callback(new Error('Date format must be YYYY-MM-DD'));
}

if (date !== null && isNaN(date.getTime())) {
return callback(new Error('Invalid date: ' + input));
}

return callback(null, date);
}
};

/**
* Add a new release to the change log containing all current messages.
* Gets the next release for the specified change log.
* If a release number is passed, checks if the number is superior to the last release in the file.
* If an increment is passed, returns the release number incremented from the last release in the file.
* It also checks if the release date is superior to the last release date in the file.
*
* @param {string} release - Release number (semver version) or increment (major, minor or patch)
* @param {Options} [options] - Options
* @param {Function} callback - Callback invoked with an optional error when the release has been added in change log
* @param {string} release - Release number or increment (major, minor or patch)
* @param {Date} date - Release date
* @param {string} file - Change log file name/path
* @param {Function} callback - Callback invoked with an optional error and and the next release number
*/
module.exports = function chlgRelease(release, options, callback) {
if (typeof options === 'function') {
callback = options;
options = {};
}

function getNextRelease(release, date, file, callback) {
var increment = (['major', 'minor', 'patch'].indexOf(release) !== -1);

if (!increment && semver.valid(release) === null) {
return callback(new Error('‘' + release + '’ is not valid semver version'));
}

var file = options.file || defaults.file;
var tmp = path.join(os.tmpdir(), 'chlg-' + Date.now() + '.md');
var date = options.date ? dates.parse(options.date) : new Date();

if (date === null) {
return callback(new Error('Date format must be YYYY-MM-DD'));
}

if (isNaN(date.getTime())) {
return callback(new Error('Invalid date: ' + options.date));
}

chlgShow({file: file, releases: ['all']}, function (error, logs) {
if (error) {
return callback(error);
Expand All @@ -65,32 +67,72 @@ module.exports = function chlgRelease(release, options, callback) {
if (releases.length > 1) {
var latest = releases[1];

if (logs[latest].date.getTime() >= date.getTime()) {
return callback(new Error('The release date is prior to the last (' + dates.format(logs[latest].date) + ')'));
}

if (increment) {
release = semver.inc(latest, release);
return callback(null, semver.inc(latest, release));
}

if (!semver.gt(release, latest)) {
return callback(new Error('Last release (' + latest + ') is greater than ' + release));
} else if (logs[latest].date.getTime() >= date.getTime()) {
return callback(new Error('The release date is prior to the last (' + dates.format(logs[latest].date) + ')'));
}
} else if (increment) {
release = semver.inc('0.0.0', release);
return callback(null, semver.inc('0.0.0', release));
}

var insert = '\n' + formatter.release(release, date);
return callback(null, release);
});
}

/**
* @typedef {object} Options
* @property {string} [file=CHANGELOG.md] - The change log file name/path.
* @property {string} [date=now] - Force a specific release date, default to the current date.
*/

/**
* Add a new release to the change log containing all current messages.
*
* @param {string} release - Release number (semver version) or increment (major, minor or patch)
* @param {Options} [options] - Options
* @param {Function} callback - Callback invoked with an optional error when the release has been added in change log
*/
module.exports = function chlgRelease(release, options, callback) {
if (typeof options === 'function') {
callback = options;
options = {};
}

async.parallel({
file: async.apply(validators.file, options.file || defaults.file),
date: async.apply(validators.date, options.date)
}, function (error, results) {
if (error) {
return callback(error);
}

var stream = fs.createReadStream(file, {encoding: 'utf8'})
.on('error', callback)
.pipe(new StreamInsert(insert, search))
.on('error', callback)
.pipe(fs.createWriteStream(tmp))
.on('error', callback);
getNextRelease(release, results.date, results.file, function (error, nextRelease) {
if (error) {
return callback(error);
}

stream.on('finish', function () {
fs.createReadStream(tmp, {encoding: 'utf8'}).pipe(fs.createWriteStream(file)).on('finish', function () {
fs.unlink(tmp, callback);
}).on('error', callback);
var tmp = path.join(os.tmpdir(), 'chlg-' + Date.now() + '.md');
var insert = '\n' + formatter.release(nextRelease, results.date);

var stream = fs.createReadStream(results.file, {encoding: 'utf8'})
.on('error', callback)
.pipe(new StreamInsert(insert, search))
.on('error', callback)
.pipe(fs.createWriteStream(tmp))
.on('error', callback);

stream.on('finish', function () {
fs.createReadStream(tmp, {encoding: 'utf8'}).pipe(fs.createWriteStream(results.file)).on('finish', function () {
fs.unlink(tmp, callback);
}).on('error', callback);
});
});
});
};

0 comments on commit 1ad296c

Please sign in to comment.