Skip to content

Commit

Permalink
Add wrapStaticMethods and wrapInstanceMethods, as well as methodNames…
Browse files Browse the repository at this point in the history
… param
  • Loading branch information
danielstjules committed Sep 15, 2015
1 parent b432e7d commit 3dceb65
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 22 deletions.
37 changes: 24 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,19 +49,7 @@ FakeDataStore.prototype.setAsync = Promise.coroutine(function*(key, value) {
};
```
That's where this library comes in. It offers a helpful little wrap function:
``` javascript
/**
* Wraps all static and instance methods whose name ends with Async. Any
* GeneratorFunction is wrapped with bluebird.coroutine(), and others with
* bluebird.method().
*
* @param {function} klass The class to wrap
*/
```
Using it is simple:
That's where this library comes in. Using it is simple:
``` javascript
'use strict';
Expand All @@ -82,3 +70,26 @@ wrap(FakeDataStore);
```
Clean ES6 classes and async methods!
## API
#### async-class.wrap(klass [, methodNames])
Wraps all static and instance methods whose name ends with Async. Any
GeneratorFunction is wrapped with bluebird.coroutine(), and others with
bluebird.method(). Accepts an optional array of method names, wrapping
only those found in the array, and disabling the Async suffix check.
#### async-class.wrapStaticMethods(klass [, methodNames])
Wraps all static methods whose name ends with Async. Any GeneratorFunction
is wrapped with bluebird.coroutine(), and others with bluebird.method().
Accepts an optional array of method names, wrapping only those found in the
array, and disabling the Async suffix check.
#### async-class.wrapInstanceMethods(klass [, methodNames])
Wraps all instance methods whose name ends with Async. Any GeneratorFunction
is wrapped with bluebird.coroutine(), and others with bluebird.method().
Accepts an optional array of method names, wrapping only those found in the
array, and disabling the Async suffix check.
74 changes: 65 additions & 9 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,71 @@ let Promise = require('bluebird');
/**
* Wraps all static and instance methods whose name ends with Async. Any
* GeneratorFunction is wrapped with bluebird.coroutine(), and others with
* bluebird.method().
* bluebird.method(). Accepts an optional array of method names, wrapping
* only those found in the array, and disabling the Async suffix check.
*
* @param {function} klass The class to wrap
* @param {function} klass The class to wrap
* @param {string[]} [methodNames] Optional array of method names
* @throws {Error} If methodNames is provided, but is not an array
*/
function wrap(klass) {
[klass, klass.prototype].forEach(wrapFunctions);
function wrap(klass, methodNames) {
validateMethodNames(methodNames);

wrapStaticMethods(klass, methodNames);
wrapInstanceMethods(klass, methodNames);
}

module.exports = {
wrap
};
/**
* Wraps all static methods whose name ends with Async. Any GeneratorFunction
* is wrapped with bluebird.coroutine(), and others with bluebird.method().
* Accepts an optional array of method names, wrapping only those found in the
* array, and disabling the Async suffix check.
*
* @param {function} klass The class to wrap
* @param {string[]} [methodNames] Optional array of method names
* @throws {Error} If methodNames is provided, but is not an array
*/
function wrapStaticMethods(klass, methodNames) {
validateMethodNames(methodNames);
wrapFunctions(klass, methodNames);
}

/**
* Wraps all instance methods whose name ends with Async. Any GeneratorFunction
* is wrapped with bluebird.coroutine(), and others with bluebird.method().
* Accepts an optional array of method names, wrapping only those found in the
* array, and disabling the Async suffix check.
*
* @param {function} klass The class to wrap
* @param {string[]} [methodNames] Optional array of method names
* @throws {Error} If methodNames is provided, but is not an array
*/
function wrapInstanceMethods(klass, methodNames) {
validateMethodNames(methodNames);
wrapFunctions(klass.prototype, methodNames);
}

/**
* Helper function that validates the methodNames parameter.
*
* @param {string[]} [methodNames] Optional array of method names
* @throws {Error} If methodNames is provided, but is not an array
*/
function validateMethodNames(methodNames) {
if (methodNames && !(methodNames instanceof Array)) {
throw new Error('Optional methodNames should be an array if provided');
}
}

function wrapFunctions(target) {
function wrapFunctions(target, methodNames) {
Object.getOwnPropertyNames(target).forEach(function(key) {
if (!key.endsWith('Async') || typeof target[key] !== 'function') return;
if (methodNames) {
if (methodNames.indexOf(key) === -1) return;
} else if (!key.endsWith('Async')) {
return;
}

if (typeof target[key] !== 'function') return;

if (target[key].constructor.name === 'GeneratorFunction') {
target[key] = Promise.coroutine(target[key]);
Expand All @@ -27,3 +77,9 @@ function wrapFunctions(target) {
}
});
}

module.exports = {
wrap,
wrapStaticMethods,
wrapInstanceMethods
};
4 changes: 4 additions & 0 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ describe('async-class', function() {
});

describe('wrap', function() {
it('only modifies properties that are functions', function() {
expect(dataStore.store).to.be.instanceOf(Map)
});

it('does not wrap instance methods that do not end with Async', function() {
dataStore.store.set('foo', 'bar');
let keys = dataStore.keys();
Expand Down

0 comments on commit 3dceb65

Please sign in to comment.