-
-
Notifications
You must be signed in to change notification settings - Fork 753
/
Copy pathcommons.js
103 lines (89 loc) · 3.44 KB
/
commons.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
var _ = require('lodash');
// The position of the params parameters for a service method so that we can extend them
// default is 1
var paramsPositions = exports.paramsPositions = {
find: 0,
update: 2,
patch: 2
};
// The default event dispatcher
exports.defaultDispatcher = function (data, params, callback) {
callback(null, data);
};
// Set up event handlers for a given service using the event dispatching mechanism
exports.setupEventHandlers = function setupEventHandlers(info, path, service){
// If the service emits events that we want to listen to (Event mixin)
if (typeof service.on === 'function' && service._serviceEvents) {
var addEvent = function (ev) {
service.on(ev, function (data) {
// Check if there is a method on the service with the same name as the event
var dispatcher = typeof service[ev] === 'function' ?
service[ev] : exports.defaultDispatcher;
var eventName = path + ' ' + ev;
info.clients().forEach(function (socket) {
dispatcher(data, info.params(socket), function (error, dispatchData) {
if (error) {
socket[info.method]('error', error);
} else if (dispatchData) { // Only dispatch if we have data
socket[info.method](eventName, dispatchData);
}
});
});
});
};
_.each(service._serviceEvents, addEvent);
}
};
// Set up all method handlers for a service and socket.
exports.setupMethodHandlers = function setupMethodHandlers(info, socket, path, service) {
this.methods.forEach(function(method) {
if (typeof service[method] === 'function') {
var name = path + '::' + method;
var params = info.params(socket);
var position = typeof paramsPositions[method] !== 'undefined' ?
paramsPositions[method] : 1;
socket.on(name, function () {
var args = _.toArray(arguments);
// If the service is called with no parameter object
// insert an empty object
if(typeof args[position] === 'function') {
args.splice(position, 0, {});
}
args[position] = _.extend({ query: args[position] }, params);
service[method].apply(service, args);
});
}
});
};
// Common setup functionality taking the info object which abstracts websocket access
exports.setup = function(info) {
var app = this;
app._commons = info;
// For a new connection, set up the service method handlers
info.connection().on('connection', function (socket) {
// Process services that were registered at startup.
_.each(app.services, function (service, path) {
exports.setupMethodHandlers.call(app, info, socket, path, service);
});
});
// Set up events and event dispatching
_.each(app.services, function (service, path) {
exports.setupEventHandlers.call(app, info, path, service);
}, this);
};
// Socket mixin when a new service is registered
exports.service = function(path, service) {
var protoService = this._super.apply(this, arguments);
var app = this;
var info = this._commons;
// app._socketInfo will only be available once we are set up
if(service && info) {
// Set up event handlers for this new service
exports.setupEventHandlers.call(app, info, path, protoService);
// For any existing connection add method handlers
info.clients().forEach(function(socket) {
exports.setupMethodHandlers.call(app, info, socket, path, protoService);
});
}
return protoService;
};