src/server/app/util/sockets/base.server.socket.js
'use strict';
var path = require('path'),
async = require('async'),
q = require('q'),
deps = require(path.resolve('./src/server/dependencies.js')),
logger = deps.logger;
function BaseSocket(config) {
this._socket = config.socket;
if(typeof this._socket.on === 'function') {
this._socket.on('disconnect', this.disconnect.bind(this));
this._socket.on('error', this.error.bind(this));
}
this._userId = null;
this.addListeners();
}
BaseSocket.prototype.name = 'BaseSocket';
/**
* Base function to handle disconnects from the client
*/
BaseSocket.prototype.disconnect = function() {
logger.info('BaseSocket: Disconnected from client.');
};
/**
* Base function to handle errors
*/
BaseSocket.prototype.error = function(err) {
logger.error(err, 'BaseSocket: Client connection error');
};
/**
* Base function to get the socket
*/
BaseSocket.prototype.getSocket = function() {
return this._socket;
};
/**
* Base function to add listeners for the socket events
*/
BaseSocket.prototype.addListeners = function() {
logger.debug('BaseSocket: Calling addListeners');
};
BaseSocket.prototype.getUserId = function() {
if (null == this._userId) {
var s = this.getSocket();
if (null != s && null != s.request && null != s.request.user) {
// Store this for the next request, since it won't change for this socket.
this._userId = s.request.user.id;
}
}
return this._userId;
};
/**
* Gets a placeholder request object for the open socket.
*
* @returns {Object} An object that looks like an HTTP request. It will contain the user object from the
* actually socket request.
*/
BaseSocket.prototype.getRequest = function() {
var self = this;
var data = {};
data.user = self.getSocket().request.user;
data.isAuthenticated = function() {
return self.getSocket().request.isAuthenticated();
};
data.isUnauthenticated = function() {
return self.getSocket().request.isUnauthenticated();
};
return data;
};
/**
* Gets a placeholder response object that can be used for middleware. It stubs out the status() and send()
* methods, and if there is an error, forwards it to the next handler.
*
* @param {Function} next A callback for the async handler. It will be called with an error if the middleware
* callback function passes any message to the UI.
*
* @returns {{status: status, send: send}}
*/
BaseSocket.prototype.getResponse = function(next) {
function send(data) {
var err = null;
if (null != data && null != data.message) {
err = new Error(data.message);
}
else {
err = new Error('Unauthorized');
}
return next(err);
}
function status(data) {
return {
send: send,
json: send
};
}
return {
status: status,
send: send,
json: send
};
};
/**
* Applies a set of callbacks in series. Each function should accept a request and response object and
* a callback function, in the same format as the Express.js middleware.
*
* @param {Array{Function}} callbacks An array of middleware callbacks to execute.
* @param {Function=} done Optionally, a function that will be called when all middleware has processed, either
* with an error or without.
*
* @returns {Promise} A promise that will be resolved when all the middleware has run. You can either
* listen for this or pass in a callback.
*/
BaseSocket.prototype.applyMiddleware = function(callbacks, done) {
var self = this;
var defer = q.defer();
// Use the same request for all callbacks
var req = self.getRequest();
var tasks = callbacks.map(function(callback) {
return function(next) {
// Create a new response for each next() callback
var res = self.getResponse(next);
// Invoke the callback
callback(req, res, next);
};
});
async.series(tasks, function(err, results) {
// Get the result from the last task
var result = results[tasks.length - 1];
// Invoke the callback if there is one
if (null != done) {
done(err, result);
}
// Resolve the promise
defer.makeNodeResolver()(err, result);
});
// Return the promise.
return defer.promise;
};
module.exports = BaseSocket;