csvutil
Version:
256 lines (211 loc) • 7.44 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.render = render;
exports.diff = diff;
exports.handleConfig = handleConfig;
var _fs = require('fs');
var _fs2 = _interopRequireDefault(_fs);
var _ramda = require('ramda');
var _ramda2 = _interopRequireDefault(_ramda);
var _rx = require('rx');
var _rx2 = _interopRequireDefault(_rx);
var _rxNode = require('rx-node');
var _rxNode2 = _interopRequireDefault(_rxNode);
var _bluebird = require('bluebird');
var _bluebird2 = _interopRequireDefault(_bluebird);
var _csv = require('csv');
var _csv2 = _interopRequireDefault(_csv);
var _eol = require('eol');
var _eol2 = _interopRequireDefault(_eol);
var _logger = require('./logger');
var _config = require('./config');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function observableForReadstream(readStream) {
return _ramda2.default.pipe(function (s) {
return s.pipe(_csv2.default.parse({ delimiter: ',' }));
}, _rxNode2.default.fromReadableStream.bind(_rxNode2.default))(readStream);
}
function observableTupleForFile(filePath) {
var readStream = _fs2.default.createReadStream(filePath);
return {
observable: observableForReadstream(readStream),
closeStream: function closeStream() {
readStream.push('');
}
};
}
function twoRowsAreEqualIgnoringLineEndings(rowA, rowB) {
var mapper = _ramda2.default.map(function (v) {
return _eol2.default.auto(v.toString());
});
var a = mapper(rowA);
var b = mapper(rowB);
return _ramda2.default.equals(a, b);
}
function observableTupleForFiles(filePathA, filePathB) {
var count = 0;
var a = observableTupleForFile(filePathA);
var b = observableTupleForFile(filePathB);
var observable = _rx2.default.Observable.zip(a.observable, b.observable, function (rowA, rowB) {
if (count === 0 && !twoRowsAreEqualIgnoringLineEndings(rowA, rowB)) {
throw new Error('header rows do not match');
}
count++;
return { rowA: rowA, rowB: rowB };
});
return {
observable: observable,
closeStream: function closeStream() {
a.closeStream();
b.closeStream();
}
};
}
function fileExists(filePath, argumentName) {
var f = filePath || '';
return new _bluebird2.default(function (resolve, reject) {
_fs2.default.access(f, _fs2.default.F_OK, function (err) {
if (err) {
reject(new Error(argumentName + ': file at \'' + f + '\' not accessible'));
} else {
resolve(true);
}
});
});
}
function render(config) {
var pathA = config.pathA;
var rows = config.rows;
var output = config.output;
var width = config.width;
var buildStringBuffer = config.buildStringBuffer;
// State
var rowCount = 0;
var renderCount = 0;
var stringBuffer = '';
// Handlers
var _getLogger = (0, _logger.getLogger)(output);
var logHeader = _getLogger.logHeader;
var logValues = _getLogger.logValues;
var handleRow = function handleRow(rowA) {
var args = {
rowA: rowA,
width: width,
bufferFunction: buildStringBuffer ? function (str) {
stringBuffer += str + '\n';
} : null,
rowIndex: rowCount,
showRowIndex: false
};
if (rowCount === 0) {
logHeader(args);
} else {
logValues(args);
renderCount++;
}
rowCount++;
return rowA;
};
return fileExists(pathA, 'path-a').then(function () {
return new _bluebird2.default(function (resolve, reject) {
var _observableTupleForFi = observableTupleForFile(pathA);
var observable = _observableTupleForFi.observable;
var closeStream = _observableTupleForFi.closeStream;
var shouldTake = function shouldTake() {
var take = rowCount < rows + 1 || rows <= 0;
if (!take) {
closeStream();
}
return take;
};
var handleError = function handleError(err) {
reject(err);
};
var handleCompletion = function handleCompletion() {
resolve({
success: true,
rendered_rows: renderCount,
fileA: pathA,
stringBuffer: stringBuffer
});
};
observable.takeWhile(shouldTake).subscribe(handleRow, handleError, handleCompletion);
});
});
}
function diff(config) {
var pathA = config.pathA;
var pathB = config.pathB;
var rows = config.rows;
var output = config.output;
var width = config.width;
var buildStringBuffer = config.buildStringBuffer;
// State
var rowCount = 0;
var diffCount = 0;
var stringBuffer = '';
// Handlers
var _getLogger2 = (0, _logger.getLogger)(output);
var logHeader = _getLogger2.logHeader;
var logDiff = _getLogger2.logDiff;
var logSummary = _getLogger2.logSummary;
var handleTuple = function handleTuple(tuple) {
var rowA = tuple.rowA;
var rowB = tuple.rowB;
var rowsAreEqual = _ramda2.default.equals(rowA, rowB);
var args = {
rowA: rowA,
rowB: rowB,
width: width,
bufferFunction: buildStringBuffer ? function (str) {
stringBuffer += str + '\n';
} : null,
rowIndex: rowCount,
showRowIndex: true
};
if (rowCount === 0) {
logHeader(args);
} else if (!rowsAreEqual) {
logDiff(args);
diffCount++;
}
rowCount++;
return tuple;
};
return _bluebird2.default.join(fileExists(pathA, 'path-a'), fileExists(pathB, 'path-b')).then(function () {
return new _bluebird2.default(function (resolve, reject) {
var _observableTupleForFi2 = observableTupleForFiles(pathA, pathB);
var observable = _observableTupleForFi2.observable;
var closeStream = _observableTupleForFi2.closeStream;
var handleError = function handleError(err) {
reject(err);
};
var shouldTake = function shouldTake() {
var take = diffCount < rows || rows <= 0;
if (!take) {
closeStream();
}
return take;
};
var handleCompletion = function handleCompletion() {
var summary = {
success: true,
processedRows: rowCount,
differentRows: diffCount,
fileA: pathA,
fileB: pathB,
stringBuffer: stringBuffer
};
logSummary(summary);
resolve(summary);
};
observable.takeWhile(shouldTake).subscribe(handleTuple, handleError, handleCompletion);
});
});
}
function handleConfig(config) {
if (!(0, _config.configIsValid)(config)) return _bluebird2.default.reject(new Error('invalid config'));
return config.pathB ? diff(config) : render(config);
}