diff --git a/elasticio.js b/elasticio.js index 7795a9e..7e3149e 100644 --- a/elasticio.js +++ b/elasticio.js @@ -1,2 +1,6 @@ -exports.HttpComponent = require("./lib/httpComponent.js").HttpComponent; -exports.messages = require("./lib/messages.js"); \ No newline at end of file +exports.HttpComponent = require("./lib/httpComponent").HttpComponent; +exports.messages = require("./lib/messages"); +exports.crypt = require("./lib/crypt"); +exports.formats = require("./lib/formats"); +exports.HeartBeatStream = require("./lib/heartbeat-stream"); +exports.ObjectUtilities = require("./lib/ObjectUtilities"); \ No newline at end of file diff --git a/lib/ObjectUtilities.js b/lib/ObjectUtilities.js new file mode 100644 index 0000000..785e174 --- /dev/null +++ b/lib/ObjectUtilities.js @@ -0,0 +1,92 @@ +module.exports = { + flatten: makeObjectFlatten, + unflatten: makeObjectUnflatten, + getRefWithPath: getRefWithPath, + removeEmptyValues: removeEmptyValues +}; + +/** + * Remove all null, empty string (''), empty object ({}), empty array ([]) properties from an object + */ +function removeEmptyValues(obj){ + + for (var key in obj) { + if (obj[key] === null || obj[key] === '') { + delete obj[key]; + } + if (typeof obj[key] === 'object') { + // recursive clean of child object + obj[key] = removeEmptyValues(obj[key]); + // delete child object if empty + if (Object.keys(obj[key]).length === 0) { + delete obj[key]; + } + } + } + return obj; +} + +/** + * Return value of field with given path in given object + * If path couldn't be resolved return null + * @param {Object} obj + * @param {String} path + * @returns {Object|null} + */ +function getRefWithPath(obj, path) { + var keys = path.split("."); + var curr = obj; + for (var i = 0; i < keys.length; i++) { + if (!curr[keys[i]]) { + return null; + } else { + curr = curr[keys[i]]; + } + } + return curr; +} + +function makeObjectFlatten(data) { + var result = {}; + function recurse (cur, prop) { + if (Object(cur) !== cur) { + result[prop] = cur; + } else if (Array.isArray(cur)) { + for (var i=0, l=cur.length; i 0 && lastPoint > 0) { + // if we have both, then the last wins + if (lastComma > lastPoint) { + decimal = ',' + } else { + decimal = '.' + } + } else { + if (lastComma >= 0 && expr.test(string.substr(lastComma + 1))) { + decimal = ','; + } else if (lastPoint >= 0 && expr.test(string.substr(lastPoint + 1))) { + decimal = '.' + } else if (lastPoint >= 0 && expr2.test(string.substr(lastPoint + 1))) { + decimal = ','; + } + } + } + return accounting.unformat(string, decimal); +}; \ No newline at end of file diff --git a/lib/heartbeat-stream.js b/lib/heartbeat-stream.js new file mode 100644 index 0000000..2f7d875 --- /dev/null +++ b/lib/heartbeat-stream.js @@ -0,0 +1,45 @@ +var events = require("events"); +var StreamCounter = require('stream-counter'); +var util = require("util"); + +var HEARTBEAT_PERIOD = 10 * 1000; // 10 secs + +var HeartBeatStream = function(heartBeatEmitter) { + if (heartBeatEmitter instanceof events.EventEmitter) { + this.emitter = heartBeatEmitter; + } + events.EventEmitter.call(this); +}; + +util.inherits(HeartBeatStream, events.EventEmitter); + +HeartBeatStream.prototype.start = function start(stream) { + + var lastHeartbeatTime = 0; + + var that = this; + + var counter = new StreamCounter(); + + counter.on('progress', function() { + + var now = new Date().getTime(); + + if ((now - lastHeartbeatTime) > HEARTBEAT_PERIOD) { + console.log(counter.bytes + " bytes read so far"); + + lastHeartbeatTime = now; + + if (that.emitter) { + that.emitter.emit('heartbeat') + } + + that.emit('heartbeat'); + } + + }); + + stream.pipe(counter); +}; + +exports.HeartBeatStream = HeartBeatStream; \ No newline at end of file diff --git a/package.json b/package.json index 07a686f..48f0b47 100644 --- a/package.json +++ b/package.json @@ -1,43 +1,47 @@ { - "name": "elasticio-node", - "description": "Node.js API for the elastic.io integration platform", - "version": "0.0.6", - "author": { - "name": "elastic.io GmbH", - "email": "info@elastic.io" - }, - "keywords": [ - "elasticio", - "integration", - "restful", - "webservice", - "http" - ], - "main": "./elasticio.js", - "repository": { - "type": "git", - "url": "git://github.com/elasticio/nodejs-api" - }, - "bugs": { - "url": "https://github.com/elasticio/nodejs-api/issues" - }, - "homepage": "http://www.elastic.io", - "dependencies": { - "request": "2.9.x", - "node-uuid": "1.3.3", - "q": "1.0.0", - "underscore":"1.5.1" - }, - "devDependencies": { - "nock": "0.27.2", - "grunt": "~0.4.5", - "grunt-cli": "~0.1.9", - "grunt-contrib-clean": "~0.5.0", - "grunt-jasmine-node": "0.2.1", - "grunt-istanbul": "0.3.0", - "grunt-env": "~0.4.1", - "grunt-coveralls": "0.3.0", - "grunt-contrib-jshint": "~0.7.2", - "grunt-contrib-copy": "~0.5.0" - } + "name": "elasticio-node", + "description": "Node.js API for the elastic.io integration platform", + "version": "0.0.7", + "author": { + "name": "elastic.io GmbH", + "email": "info@elastic.io" + }, + "keywords": [ + "elasticio", + "integration", + "restful", + "webservice", + "http" + ], + "main": "./elasticio.js", + "repository": { + "type": "git", + "url": "git://github.com/elasticio/nodejs-api" + }, + "bugs": { + "url": "https://github.com/elasticio/nodejs-api/issues" + }, + "homepage": "http://www.elastic.io", + "dependencies": { + "accounting": "0.4.1", + "crc": "3.3.0", + "moment": "2.10.6", + "node-uuid": "1.3.3", + "q": "1.0.0", + "request": "2.9.x", + "stream-counter": "1.0.0", + "underscore": "1.5.1" + }, + "devDependencies": { + "nock": "0.27.2", + "grunt": "~0.4.5", + "grunt-cli": "~0.1.9", + "grunt-contrib-clean": "~0.5.0", + "grunt-jasmine-node": "0.2.1", + "grunt-istanbul": "0.3.0", + "grunt-env": "~0.4.1", + "grunt-coveralls": "0.3.0", + "grunt-contrib-jshint": "~0.7.2", + "grunt-contrib-copy": "~0.5.0" + } } diff --git a/spec/ObjectUtilities.spec.js b/spec/ObjectUtilities.spec.js new file mode 100644 index 0000000..a73e498 --- /dev/null +++ b/spec/ObjectUtilities.spec.js @@ -0,0 +1,126 @@ +describe('ObjectUtilities', function () { + + var objectUtilities = require('../lib/ObjectUtilities.js'); + + var obj = { + "field1": "value1", // string + "field2": 123456, // number + "field2-1": null, // null + "field2-2": undefined, // undefined + "field2-3": 5.6, // float + "field3": { // object + "field4": "value2", + "field5": 654321, + "field6": { + "field7": "value3", + "field8": 987654, // array + "field9": [{ + "id": 1, + "name": "Jim", // array in array + "books": [ + {"title": "Adventures of James Bond"}, + {"title": "Adventures of Huckleberry Finn"}, + null, 0, false] // null, 0, false in array + },{ + "id": 2, + "name": "Bim", + "books": [ + undefined, // undefined in array + {"title": "Adventures of James Bond"}, + {"title": "Adventures of Huckleberry Finn"} + ] + }] + } + } + }; + + var flattened = { + "field1": "value1", + "field2": 123456, + "field2-1": null, + "field2-2": undefined, + "field2-3": 5.6, + + "field3.field4": "value2", + "field3.field5": 654321, + "field3.field6.field7": "value3", + "field3.field6.field8": 987654, + + "field3.field6.field9[0].id": 1, + "field3.field6.field9[0].name": "Jim", + + "field3.field6.field9[0].books[0].title": "Adventures of James Bond", + "field3.field6.field9[0].books[1].title": "Adventures of Huckleberry Finn", + "field3.field6.field9[0].books[2]": null, + "field3.field6.field9[0].books[3]": 0, + "field3.field6.field9[0].books[4]": false, + + "field3.field6.field9[1].id": 2, + "field3.field6.field9[1].name": "Bim", + + "field3.field6.field9[1].books[0]": undefined, + "field3.field6.field9[1].books[1].title": "Adventures of James Bond", + "field3.field6.field9[1].books[2].title": "Adventures of Huckleberry Finn" + }; + + describe('getPath', function () { + it('should not create object if it not exists and return reference', function () { + var obj = {}; + var result = objectUtilities.getRefWithPath(obj, 'test.path.ref'); + expect(obj.test).toBeUndefined(); + expect(result).toEqual(null); + }); + + it('should return reference if it exists', function () { + var obj = { + test: { + path: { + ref: { + some: 1 + } + } + } + }; + var result = objectUtilities.getRefWithPath(obj, 'test.path.ref'); + expect(result.some).toEqual(1); + }); + }); + + it('Flatten', function () { + var result = objectUtilities.flatten(obj); + expect(result).toEqual(flattened); + }); + + it('Unflatten', function () { + var result = objectUtilities.unflatten(flattened); + expect(result).toEqual(obj); + }); + + describe('removeEmptyValues', function () { + + it('remove empty string value', function () { + var input = {"param1": '', "param2": 2}; + var output = {"param2": 2}; + + var result = objectUtilities.removeEmptyValues(input); + expect(result).toEqual(output); + }); + + it('remove null value', function () { + var input = {"param1": null, "param2": 2}; + var output = {"param2": 2}; + + var result = objectUtilities.removeEmptyValues(input); + expect(result).toEqual(output); + }); + + it('remove object in which empty string', function () { + var input = {"param1": {"param3" : ''}, "param2": 2}; + var output = {"param2": 2}; + + var result = objectUtilities.removeEmptyValues(input); + expect(result).toEqual(output); + }); + + }); +}); \ No newline at end of file diff --git a/spec/formats.spec.js b/spec/formats.spec.js new file mode 100644 index 0000000..80705fa --- /dev/null +++ b/spec/formats.spec.js @@ -0,0 +1,34 @@ +var parse = require('../lib/formats').moneyToNumber; +describe('formats.js', function () { + var assertions = { + '100' : 100, + '12345' : 12345, + '$12345' : 12345, + '$ 12345' : 12345, + '12345 €' : 12345, + '12345, €' : 12345, + '12345. €' : 12345, + '12,3 €' : 12.3, // Germans are using commas as decimal separator + '12,34 €' : 12.34, // Germans are using commas as decimal separator + '1.234 €' : 1234, // Germans are using points as group separator + '12.345, €' : 12345, + '1.234,5 €' : 1234.5, + '1.234,56 €' : 1234.56, + '234,56 €' : 234.56, + '$ 12.34' : 12.34, + '$ 1,234' : 1234, + '$ 1,234.5' : 1234.5, + '$ 1,234.56' : 1234.56, + '$ 234.56' : 234.56 + }; + Object.keys(assertions).forEach(function(str) { + it('should be able to parse ' + str + ' correctly', function() { + expect(parse(str)).toEqual(assertions[str]); + }); + }); + + it('should work with numbers too', function() { + expect(parse(200)).toEqual(200); + }); + +}); \ No newline at end of file diff --git a/spec/heartbeat-stream.spec.js b/spec/heartbeat-stream.spec.js new file mode 100644 index 0000000..f797323 --- /dev/null +++ b/spec/heartbeat-stream.spec.js @@ -0,0 +1,29 @@ +var HeartBeatStream = require('../lib/heartbeat-stream.js').HeartBeatStream; +var Stream = require('stream'); +var events = require('events'); + +describe('HeartbeatStream', function () { + it('Emit heartbeat on progress', function () { + var stream = new Stream(); + var eventEmitter = new events.EventEmitter(); + var hb1 = jasmine.createSpy('hb1'); + var hb2 = jasmine.createSpy('hb2'); + + eventEmitter.on('heartbeat', hb1); + + runs(function () { + new HeartBeatStream(eventEmitter).on('heartbeat', hb2).start(stream); + stream.emit('data', "A DATA"); + stream.emit('end'); + }); + + waitsFor(function () { + return hb1.calls.length; + }); + + runs(function () { + expect(hb1).toHaveBeenCalled(); + expect(hb2).toHaveBeenCalled(); + }); + }); +}); \ No newline at end of file