node-barefoot
Advanced tools
Comparing version 0.0.4 to 0.0.5
/** Mixin: Barefoot.APIAdapter.Server | ||
* The server mixin for the <APIAdapter> takes the specified apiRoutes and does | ||
* two things: | ||
* * Create Express.JS routes for the client part | ||
* * Map server-side API calls to the correct callback | ||
* * Create RESTful API routes with Express.JS, callable via HTTP | ||
* * Map server-side API calls to the correct local callback | ||
* | ||
* The creation of the Express.JS routes is done on initalization. The mapping | ||
* of server-side API calls is executed during runtime. | ||
* | ||
* Function Mapping: | ||
* The following matrix describes which function of <APIAdapter.Server> is | ||
* related to which task: | ||
* | ||
* > + REST API + Local API + | ||
* > +------------------------+----------+-----------+ | ||
* > processCallbacks | X | X | | ||
* > createExpressJsCallback | X | | | ||
* > createExpressJsRoute | X | | | ||
* > urlRegexp | | X | | ||
* > matchRoute | | X | | ||
* > addRoute | X | X | | ||
* > createRouteFactories | X | X | | ||
* > dispatchLocalApiCall | | X | | ||
* > sync | | X | | ||
* > +------------------------+----------+-----------+ | ||
*/ | ||
@@ -20,5 +37,82 @@ var _ = require('underscore') | ||
/** PrivateFunction: processCallbacks | ||
* This function is used to run a callback function or an array of stacked | ||
* callback functions which are registered for an API route. | ||
* | ||
* Parameters: | ||
* (Object) namedRouteParameters - If a route contains named parameters | ||
* (stuff like ":id", ":name"), this object | ||
* should contain these values. They are | ||
* passed as arguments to each callback | ||
* function. | ||
* (Object) data - The data argument contains any larger data amount. Stuff | ||
* like the body of a POST request in example. | ||
* (Object) req - ExpressJS request object is needed for creating scope | ||
* objects for callback execution | ||
* (Object) res - ExpressJS response object is needed for creating the scope | ||
* object for calling the handler functions. | ||
* (Function) successHandler - A function which is injected as the first | ||
* argument when executing the callback | ||
* (Function) errorHandler - A function which is injected as the second | ||
* argument when executing the callback | ||
* (Function)/(Array) callbacks - An API function which should be executed. | ||
* If you pass an array with functions, each | ||
* function gets executed as it is stacked | ||
* upon the array. Calling success will | ||
* proceed, error will stop execution. | ||
* Make sure you call one of them or your | ||
* code will go nuts. | ||
*/ | ||
function processCallbacks(namedRouteParameters, data, req, res, successHandler | ||
, errorHandler, callbacks) { | ||
var callbackScope = { | ||
app: req.app | ||
, req: req | ||
} | ||
, handlerScope = { | ||
app: req.app | ||
, req: req | ||
, res: res | ||
} | ||
, callbackArguments = _.union( | ||
successHandler.bind(handlerScope) | ||
, errorHandler.bind(handlerScope) | ||
, namedRouteParameters | ||
, data | ||
) | ||
, index = -1 | ||
, executeCallback = function executeCallback(callback) { | ||
callback.apply(callbackScope, callbackArguments); | ||
} | ||
, runner; | ||
if(!_.isArray(callbacks)) { | ||
runner = function() { executeCallback(callbacks); }; | ||
} else { | ||
var finalSuccessHandler = callbackArguments[0] | ||
, stackedSuccessHandler = function stackedSuccessHandler() { | ||
index += 1; | ||
if(index < callbacks.length) { | ||
executeCallback(callbacks[index]); | ||
} else { | ||
finalSuccessHandler.apply(handlerScope, arguments); | ||
} | ||
}; | ||
callbackArguments[0] = stackedSuccessHandler; | ||
runner = stackedSuccessHandler; | ||
} | ||
try { | ||
runner(); | ||
} catch(err) { | ||
errorHandler.call(handlerScope, err); | ||
} | ||
} | ||
/** Function: createExpressJsCallback | ||
* Encapsulates given callback function and prepares it so it can be registered | ||
* as an express js route. | ||
* Encapsulates given callback function or an array with stacked callback | ||
* functions and prepares it so it can be registered as an express js route. | ||
* | ||
@@ -33,32 +127,23 @@ * The two functions successHandler and errorHandler are passed to the callback | ||
* argument when executing the callback | ||
* (Function) callback - The actual callback function you want to execute | ||
* for an express js route. | ||
* (Function)/(Array) callbacks - An API function which should be executed. | ||
* If you pass an array with functions, each | ||
* function gets executed as it is stacked | ||
* upon the array. | ||
* | ||
* Returns: | ||
* (Function) to be registered with express js. | ||
* | ||
* See also: | ||
* * <processCallbacks> | ||
*/ | ||
function createExpressJsCallback(successHandler, errorHandler, callback) { | ||
function createExpressJsCallback(successHandler, errorHandler, callbacks) { | ||
return function handler(req, res) { | ||
var callbackScope = { | ||
app: req.app | ||
, req: req | ||
} | ||
, handlerScope = { | ||
app:req.app | ||
, req:req | ||
, res:res | ||
} | ||
, args = _.union( | ||
successHandler.bind(handlerScope) | ||
, errorHandler.bind(handlerScope) | ||
, _.values(req.params) | ||
, req.body | ||
, req.query | ||
); | ||
try { | ||
callback.apply(callbackScope, args); | ||
} catch(err) { | ||
errorHandler.call(handlerScope, err); | ||
} | ||
processCallbacks( | ||
_.values(req.params) | ||
, req.body | ||
, req | ||
, res | ||
, successHandler | ||
, errorHandler | ||
, callbacks); | ||
}; | ||
@@ -92,8 +177,8 @@ } | ||
* | ||
* Scope: | ||
* <createExpressJsRoute> creates each a special scope object which provides | ||
* access to the express.js app and the current request object. | ||
* | ||
* Parameters: | ||
* (Object) routes - Routes to bind | ||
* (Object) url - URL route to bind | ||
* (Function)/(Array) callbacks - An API function which should be executed. | ||
* If you pass an array with functions, each | ||
* function gets executed as it is stacked | ||
* upon the array. | ||
* (Function) expressJsMethod - A function of Express.JS like app.get etc. | ||
@@ -105,3 +190,3 @@ * (Object) app - The Express.JS app | ||
*/ | ||
function createExpressJsRoute(url, callback, expressJsMethod, app) { | ||
function createExpressJsRoute(url, callbacks, expressJsMethod, app) { | ||
var expressJsHandler = createExpressJsCallback( | ||
@@ -119,3 +204,3 @@ function success(apiResult, httpStatusCode) { | ||
} | ||
, callback | ||
, callbacks | ||
, app); | ||
@@ -236,5 +321,8 @@ | ||
* (String) url - The URL for this route. Gets prepared with <prepareAPIUrl> | ||
* (Function) callback - The handler for this route | ||
* (Function)/(Array) callbacks - An API function which should be executed. | ||
* If you pass an array with functions, each | ||
* function gets executed as it is stacked | ||
* upon the array. | ||
*/ | ||
function addRoute(method, url, callback) { | ||
function addRoute(method, url, callbacks) { | ||
var urlParamKeys = [] | ||
@@ -247,7 +335,7 @@ , regexp = urlRegexp(url, urlParamKeys, true, true); | ||
createExpressJsRoute.call( | ||
this, url, callback, this.app[method], this.app | ||
this, url, callbacks, this.app[method], this.app | ||
); | ||
this.apiRoutes[method][url] = { | ||
callback: callback | ||
callback: callbacks | ||
, regexp: regexp | ||
@@ -266,2 +354,7 @@ , keys: urlParamKeys | ||
* These functions then can be used to create an APIAdapter route. | ||
* | ||
* Example: | ||
* > apiAdapter.get('/myroute', function myCallback(success) { success(); }); | ||
* > apiAdapter.post('/myroute', function myCallback(success) { success(); }); | ||
* > // any HTTP verb :) | ||
*/ | ||
@@ -283,3 +376,4 @@ function createRouteFactories() { | ||
* It tries to match the given url with a registered route for the given | ||
* httpMethod. If found, the route callback is invoked. | ||
* httpMethod. If found, the route callback(s) is/are invoked using | ||
* <processCallbacks>. | ||
* | ||
@@ -314,19 +408,17 @@ * If the data argument contains any information, that stuf gets passed to the | ||
var success = function success(apiResult) { | ||
var successHandler = function successHandler(apiResult) { | ||
if(_.has(options, 'success')) { options.success(apiResult); } | ||
} | ||
, error = function error(err) { | ||
, errorHandler = function errorHandler(err) { | ||
if(_.has(options, 'error')) { options.error(err); } | ||
} | ||
, args = _.union( | ||
success | ||
, error | ||
, _.values(params) | ||
, data | ||
); | ||
try { | ||
matchedRoute.callback.apply(this, args); | ||
} catch(err) { | ||
error(err); | ||
} | ||
}; | ||
processCallbacks( | ||
_.values(params) | ||
, data | ||
, this.req | ||
, {} | ||
, successHandler | ||
, errorHandler | ||
, matchedRoute.callback); | ||
} | ||
@@ -333,0 +425,0 @@ |
{ | ||
"name": "node-barefoot" | ||
, "version": "0.0.4" | ||
, "version": "0.0.5" | ||
, "description": "Barefoot makes code sharing between browser and server reality. Write your application once and run it on both ends of the wire." | ||
@@ -5,0 +5,0 @@ , "keywords": [ |
@@ -6,2 +6,3 @@ describe('APIAdapter.Server', function() { | ||
, app | ||
, req | ||
, getRoute = '/testGet' | ||
@@ -12,2 +13,3 @@ , postRoute = '/testPost'; | ||
app = require('../mocks/expressjs/app'); | ||
req = require('../mocks/expressjs/req'); | ||
@@ -17,2 +19,3 @@ apiAdapter = new Barefoot.APIAdapter({ | ||
}); | ||
apiAdapter.req = req; | ||
}) | ||
@@ -63,5 +66,38 @@ | ||
apiAdapter.dispatchLocalApiCall('post', postRoute, expectedData); | ||
}) | ||
}) | ||
it('should execute a single callback', function(done) { | ||
apiAdapter.get(getRoute, function(success) { success(); }); | ||
apiAdapter.dispatchLocalApiCall('get', getRoute, {}, { | ||
success: done | ||
}); | ||
}) | ||
it('should execute all callbacks if more than one is stacked upon a route', function(done) { | ||
var callbacks = [ | ||
function callback1(success) { success(); } | ||
, function callback2(success) { success(); } | ||
, function callback3(success) { success(); } | ||
]; | ||
apiAdapter.get(getRoute, callbacks); | ||
apiAdapter.dispatchLocalApiCall('get', getRoute, {}, { | ||
success: done | ||
}); | ||
}) | ||
it('should stop execution of stacked callbacks as soon as error callback is called', function(done) { | ||
var callbacks = [ | ||
function callback1(success) { success(); } | ||
, function callback2(success) { error(); } | ||
]; | ||
apiAdapter.get(getRoute, callbacks); | ||
apiAdapter.dispatchLocalApiCall('get', getRoute, {}, { | ||
success: function() {} | ||
, error: function() { done(); } | ||
}); | ||
}) | ||
}) | ||
}) |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
102849
52
2352