Skip to content
This repository has been archived by the owner on May 13, 2019. It is now read-only.

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
yvele committed Jun 3, 2015
1 parent 08e9481 commit 7c4ab06
Show file tree
Hide file tree
Showing 9 changed files with 391 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
node_modules
coverage
npm-debug.log
sandbox.js
6 changes: 6 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
language: node_js
node_js:
- "0.12"
sudo: false
script: "make test-travis"
after_script: "npm install coveralls@2 && cat ./coverage/lcov.info | coveralls"
31 changes: 31 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
REQUIRED = --require should

TESTS = test/wrapperBuilder/index.js

test:
@NODE_ENV=test node \
./node_modules/.bin/mocha \
$(REQUIRED) \
$(TESTS) \
--bail

test-cov:
@NODE_ENV=test node \
./node_modules/.bin/istanbul cover \
./node_modules/.bin/_mocha \
-- -u exports \
$(REQUIRED) \
$(TESTS) \
--bail

test-travis:
@NODE_ENV=test node \
./node_modules/.bin/istanbul cover \
./node_modules/.bin/_mocha \
--report lcovonly \
-- -u exports \
$(REQUIRED) \
$(TESTS) \
--bail

.PHONY: test
68 changes: 68 additions & 0 deletions lib/WrapperBuilder.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
'use strict';

var functionWrapper = require('./functionWrapper');


/** @const */
var INNER_FIELD = '_inner';


/**
* @constructor
*/
function WrapperBuilder() {
this.Wrapper = function(inner) {
this[INNER_FIELD] = inner;
}
}


/**
*
* @param {(Array<string>|string)} methods
* @param {Object=} options
* @return {Wrapper} Provides chainability.
*/
WrapperBuilder.prototype.add = function(methods, options) {
functionWrapper.addPrototypes(
this.Wrapper,
methods,
options);

return this;
};


/**
*
* @param {(Array<string>|string)} methods
* @return {Wrapper} Provides chainability.
*/
WrapperBuilder.prototype.addPassThrough = function(methods) {
var self = this;

if(!Array.isArray(methods)) {
methods = [methods];
}

methods.forEach(function(method) {
self.Wrapper.prototype[method] = function() {
var inner = this[INNER_FIELD];

return inner[method].apply(inner, arguments);
}
});

return self;
};


/**
*
* @return {function} The wrapper constructor.
*/
WrapperBuilder.prototype.getWrapper = function() {
return this.Wrapper;
};

exports.WrapperBuilder = WrapperBuilder;
79 changes: 79 additions & 0 deletions lib/functionWrapper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
'use strict';


/** @const */
var INNER_FIELD = '_inner';


/*
* @param {!function} Wrapper The wrapper on which the new prototype will be defined.
* @param {!string} fnName Fonction name to be wrapped in a new prototype.
* @param {!Object} options
**/
function addPrototype(Wrapper, fnName, options) {
Wrapper.prototype[fnName] = function() {

// Bluebird Optimization (http://bit.ly/1cwovPq)
var args = new Array(arguments.length);
for(var i = 0; i < args.length; ++i) {
args[i] = arguments[i];
}

var inner = this[INNER_FIELD];

return function(done) {

if(options.transformations) {
args.push(wrapDoneWithTransformations(done, options.transformations));
} else {
args.push(done);
}

inner[fnName].apply(inner, args);
}
}
};


/*
* @param {!function} done A done function to be wrapped.
* @param {!Array<Object<number, function>>} transformations
* @return {function} A wrapped done function with transformations.
**/
function wrapDoneWithTransformations(done, transformations) {
return function() {
var args = new Array(arguments.length);
for(var i = 0; i < args.length; ++i) {

var transformation = transformations[i];
if(transformation) {
args[i] = transformation(arguments[i]);
} else {
args[i] = arguments[i];
}
}

done.apply(null, args);
}
}


/*
* @param {function} Wrapper Wrapper The wrapper on which the new prototypes will be defined.
* @param {(Array<string>|string)} fnNames Fonction names to be wrapped in a new prototype.
* @param {Object=} options
**/
exports.addPrototypes = function(Wrapper, fnNames, options) {
if(!Array.isArray(fnNames)) {
fnNames = [fnNames];
}

if(!options) {
// Default value
options = {};
}

fnNames.forEach(function(fnName) {
addPrototype(Wrapper, fnName, options);
});
};
3 changes: 3 additions & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
'use strict';

exports.WrapperBuilder = require('./WrapperBuilder').WrapperBuilder;
31 changes: 31 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"name": "thunkify-object",
"version": "0.0.1",
"description": "Wrap an object with callbacks functions into a wrapper with thunk returning functions",
"main": "lib/index.js",
"scripts": {
"test": "make test"
},
"repository": "yvele/node-thunkify-object",
"keywords": [
"thunk",
"thunkify",
"object",
"co",
"generator",
"generators",
"promise",
"yield",
"wrapper"
],
"license": "MIT",
"author": "Yves Merlicco",
"dependencies": {

},
"devDependencies": {
"mocha": "*",
"should": "*",
"istanbul": "*"
}
}
44 changes: 44 additions & 0 deletions test/wrapperBuilder/Dummy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@

function Dummy(cp) {
this._cp = cp;
}

Dummy.prototype.doNoParams = function(callback) {
var self = this;

setTimeout(function() {
var res = self._cp;
callback(null, res);
}, 1);
}

Dummy.prototype.doWithMultipleResults = function(callback) {
var self = this;

setTimeout(function() {
callback(null, 'RES1', 'RES2');
}, 1);
}

Dummy.prototype.doWithParams = function(p1, p2, callback) {
var self = this;

setTimeout(function() {
var res = p1 + ' ' + p2 + ' ' + self._cp;
callback(null, res);
}, 1);
}

Dummy.prototype.doNoCallback = function(p1) {
var self = this;

return self._cp + ' ' + p1;
}

Dummy.prototype.doNoCallbackNoParams = function() {
var self = this;

return self._cp;
}

exports.Dummy = Dummy;
125 changes: 125 additions & 0 deletions test/wrapperBuilder/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
var assert = require('assert');

var WrapperBuilder = require('../../lib').WrapperBuilder;
var Dummy = require('./Dummy').Dummy;


describe('WrapperBuilder', function() {


it('add() should work with no transformations', function(done) {

var wp = new WrapperBuilder();
wp.add('doNoParams');

var DummyWrapper = wp.getWrapper();
var dummy = new DummyWrapper(new Dummy('CP'));

dummy.doNoParams()(function(err, res) {
assert(!err);
assert.equal(res, 'CP');
done();
});
});

it('add() should work with an array of methods', function(done) {

var wp = new WrapperBuilder();
wp.add(['doNoParams', 'doWithParams']);

var DummyWrapper = wp.getWrapper();
var dummy = new DummyWrapper(new Dummy('CP'));

dummy.doNoParams()(function(err, res) {
assert(!err);
assert.equal(res, 'CP');

dummy.doWithParams('P1', 'P2')(function(err, res) {
assert(!err);
assert.equal(res, 'P1 P2 CP');

done();
});
});
});


it('add() should work with transformations', function(done) {

var wp = new WrapperBuilder();
wp.add('doNoParams', {
transformations: {
1: function(res) { return res + ' TRANS'; }
}
});

var DummyWrapper = wp.getWrapper();
var dummy = new DummyWrapper(new Dummy('CP'));

dummy.doNoParams()(function(err, res) {
assert(!err);
assert.equal(res, 'CP TRANS');
done();
});
});

it('add() should work with multiple results', function(done) {

var wp = new WrapperBuilder();
wp.add('doWithMultipleResults');

var DummyWrapper = wp.getWrapper();
var dummy = new DummyWrapper(new Dummy());

dummy.doWithMultipleResults()(function(err, res1, res2) {
assert(!err);
assert.equal(res1, 'RES1');
assert.equal(res2, 'RES2');
done();
});
});

it('add() should be chainable', function() {
var wp = new WrapperBuilder();
var res = wp.add('doNoParams');

assert.strictEqual(res, wp);
});


it('addPassThrough() should work', function() {

var wp = new WrapperBuilder();
wp.addPassThrough('doNoCallback');

var DummyWrapper = wp.getWrapper();
var dummy = new DummyWrapper(new Dummy('CP'));

var res = dummy.doNoCallback('P1');
assert.equal(res, 'CP P1');
});


it('addPassThrough() should work with an array of methods', function() {

var wp = new WrapperBuilder();
wp.addPassThrough(['doNoCallback', 'doNoCallbackNoParams']);

var DummyWrapper = wp.getWrapper();
var dummy = new DummyWrapper(new Dummy('CP'));

var res = dummy.doNoCallback('P1');
assert.equal(res, 'CP P1');

res = dummy.doNoCallbackNoParams();
assert.equal(res, 'CP');
});

it('addPassThrough() should be chainable', function() {
var wp = new WrapperBuilder();
var res = wp.addPassThrough('doNoParams');

assert.strictEqual(res, wp);
});

});

0 comments on commit 7c4ab06

Please sign in to comment.