diff --git a/lib/model/SeedData.js b/lib/model/SeedData.js index 1df3658..3d518ce 100644 --- a/lib/model/SeedData.js +++ b/lib/model/SeedData.js @@ -3,6 +3,7 @@ var log = require("../util/log"); var apiJson = require("../util/api-json"); var apiStream = require("../util/api-stream"); +var csv = require("../util/csv"); /** * @class SeedData @@ -50,7 +51,7 @@ SeedData.prototype.readSeedData = function(token, id, callback) { * @param {StreamReader} outStream - a {@link StreamReader} that will consume the opened HTTP connection * sending the SeedData down to the client * @param {function} callback - - * [Called after the API request was finalized]{@link SeedData~appendSeedDataStream(callback)} + * [Called after the API request was finalized]{@link SeedData~readSeedDataStream(callback)} */ SeedData.prototype.readSeedDataStream = function(token, id, outStream, callback) { log.debug("readSeedData(token=" + token + ", id=" + id + ")"); @@ -59,7 +60,7 @@ SeedData.prototype.readSeedDataStream = function(token, id, outStream, callback) apiStream(token, seedDataURL, "GET", null, outStream, callback); }; /** - * @callback SeedData~appendSeedDataStream(callback) callback + * @callback SeedData~readSeedDataStream(callback) callback * * @param {?(APIError|Error)} err - {@link null} or an objecrt describing an exception that occured during execution */ @@ -69,7 +70,7 @@ SeedData.prototype.readSeedDataStream = function(token, id, outStream, callback) * * @param {string} token - API-Auth token retrieved with {@link Tokens} * @param {string} id - ID of the Repository Object - * @param {string} content - Content to be appended to the SeedData object, in CSV form + * @param {(string|string[])} content - Content to be appended to the SeedData object, in CSV form or array of strings * @param {function} callback - * [Called after the API request was finalized]{@link SeedData~appendSeedData(callback)} */ @@ -77,7 +78,14 @@ SeedData.prototype.appendSeedData = function(token, id, content, callback) { log.debug("appendSeedData(token=" + token + ", id=" + id + ", content=" + content + ")"); var seedDataURL = this.getSeedDataURL(id); - apiJson(token, seedDataURL, "POST", content, callback); + csv.toCSV(content, function(err, data) { + if (err) { + callback(err); + return; + } + + apiJson(token, seedDataURL, "POST", data, callback); + }); }; /** * @callback SeedData~appendSeedData(callback) callback diff --git a/lib/util/api-json.js b/lib/util/api-json.js index d99b118..d7dbd4d 100644 --- a/lib/util/api-json.js +++ b/lib/util/api-json.js @@ -63,7 +63,19 @@ function api(token, endpoint, method, requestBody, callback) { if (responseBody.trim().length === 0) { responseBody = null; } else { - responseBody = JSON.parse(responseBody); + try { + responseBody = JSON.parse(responseBody); + } + catch(exception) { + if (exception instanceof SyntaxError) { + // if it isn't a SyntaxError because the response was CSV (SeedData) + // do the callback with the Exception. Otherwise move on and handle response + if (!exception.message.match(/^Unexpected token ,$/).hasOwnProperty("length")) { + callback(exception, null); + return; + } + } + } } // Consider anything in the 200-299 range to be success. diff --git a/lib/util/csv.js b/lib/util/csv.js new file mode 100644 index 0000000..78c8574 --- /dev/null +++ b/lib/util/csv.js @@ -0,0 +1,73 @@ +"use strict"; + +var csvStringify = require("csv-stringify"); + +/** + * @module CSV + * @memberof Util + * @desc + * Utility funcitons handling CSV data and Arrays + */ + +/** + * @function isArray + * + * @desc + * Test if the passed in argument is an array or not + * + * @param {} object - Argument tested for being an Array or not + * + * @returns {boolean} - true if the argument to the function is an Array + */ +exports.isArray = function(object) { + return Object.prototype.toString.call(object) === "[object Array]"; +}; + +/** + * @namespace csv + * @function is2D + * + * @desc + * Test if the elements in an already identified array are also an arrays + * + * _NOTE:_ This will also fail if only one element is also an array but the rest are singular values! + * + * @param {Object[]} array - An array to test for being a two dimensional array + * + * @returns {boolean} - true if the array is two dimensional + */ +exports.is2D = function(array) { + return array.filter(function(element) { return !exports.isArray(element) }).length === 0; +}; + +/** + * @namespace csv + * @function toCSV + * + * @desc + * Turn content into CSV formatted string + * Uses {@link csv~is2D} and {@link csv~isArray} to test if the first argument is in the proper format + * otherwise will simply return the content of the first argument, trusting that it is CSV + * + * @param {} content - Any type of object or array that can be turned into a 2D array for processing + * @param {function} callback - + * [Called once stringify has happend or it was determined not to be an array]{@link csv~toCSV(callback)} + */ +exports.toCSV = function(content, callback) { + if(exports.isArray(content)) { + if (!exports.is2D(content)) { + content = [content]; + } + csvStringify(content, function(err, csv) { + callback(err, csv); + }); + } else { + callback(null, content); + } +} +/** + * @callback csv~toCSV(callback) callback + * + * @param {?Error} error - {@link null} or an Error object describing the error that occured + * @param {?string} csvString - {@link null} in Error case or CSV formatted string of data + */ diff --git a/package.json b/package.json index 92a25b0..ed22101 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "homepage": "https://github.com/SOASTA/repository.js#readme", "dependencies": { "commander": "^2.8.1", + "csv-stringify": "0.0.8", "grunt-jsdoc": "^0.6.7", "lodash": "^3.10.1", "winston": "^1.0.1"