Skip to content

Commit 951bd0d

Browse files
committed
Merge pull request #50 from TheSharpieOne/master
Chore(release): Bump Release 1.1.0
2 parents 59cb59c + 2a536da commit 951bd0d

File tree

4 files changed

+269
-83
lines changed

4 files changed

+269
-83
lines changed

bower.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "angular-sails",
3-
"version": "1.0.5",
3+
"version": "1.1.0",
44
"authors": [
55
"Jan-Oliver Pantel <[email protected]>"
66
],

dist/angular-sails.js

Lines changed: 266 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -2,100 +2,286 @@
22
'use strict'/*global angular */
33
angular.module('ngSails', ['ng']);
44

5-
/*jslint sloppy:true*/
65
/*global angular, io */
7-
angular.module('ngSails').provider('$sails', function () {
8-
var provider = this,
9-
httpVerbs = ['get', 'post', 'put', 'delete'],
10-
eventNames = ['on', 'once'];
11-
12-
this.url = undefined;
13-
this.interceptors = [];
14-
this.responseHandler = undefined;
15-
16-
this.$get = ['$q', '$timeout', function ($q, $timeout) {
17-
var socket = io.connect(provider.url),
18-
defer = function () {
19-
var deferred = $q.defer(),
20-
promise = deferred.promise;
21-
22-
promise.success = function (fn) {
23-
promise.then(function(response) {
24-
fn(response.data, response.status, response.headers);
25-
});
26-
return promise;
27-
};
6+
(function(angular, io) {
7+
'use strict';
8+
io.sails.autoConnect = false;
289

29-
promise.error = function (fn) {
30-
promise.then(null, function(response) {
31-
fn(response.data, response.status, response.headers);
32-
});
33-
return promise;
10+
// copied from angular
11+
function parseHeaders(headers) {
12+
var parsed = {},
13+
key, val, i;
14+
if (!headers) return parsed;
15+
angular.forEach(headers.split('\n'), function(line) {
16+
i = line.indexOf(':');
17+
key = lowercase(trim(line.substr(0, i)));
18+
val = trim(line.substr(i + 1));
19+
if (key) {
20+
parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val;
21+
}
22+
});
23+
24+
return parsed;
25+
}
26+
27+
function trim(value) {
28+
return angular.isString(value) ? value.trim() : value;
29+
}
30+
31+
function isPromiseLike (obj){
32+
return obj && angular.isFunction(obj.then);
33+
}
34+
35+
// copied from angular
36+
function headersGetter(headers) {
37+
var headersObj = angular.isObject(headers) ? headers : undefined;
38+
return function(name) {
39+
if (!headersObj) headersObj = parseHeaders(headers);
40+
if (name) {
41+
var value = headersObj[lowercase(name)];
42+
if (value === void 0) {
43+
value = null;
44+
}
45+
return value;
46+
}
47+
return headersObj;
48+
};
49+
}
50+
51+
angular.module('ngSails').provider('$sails', function() {
52+
var provider = this;
53+
54+
this.httpVerbs = ['get', 'post', 'put', 'delete'];
55+
56+
this.eventNames = ['on', 'off', 'once'];
57+
58+
this.url = undefined;
59+
60+
this.urlPrefix = '';
61+
62+
this.config = {
63+
transports: ['websocket', 'polling'],
64+
useCORSRouteToGetCookie: false
65+
};
66+
67+
this.debug = false;
68+
69+
// like https://docs.angularjs.org/api/ng/service/$http#interceptors
70+
// but with sails.io arguments
71+
var interceptorFactories = this.interceptors = [
72+
/*function($injectables) {
73+
return {
74+
request: function(config) {},
75+
response: function(response) {},
76+
requestError: function(rejection) {},
77+
responseError: function(rejection) {}
3478
};
79+
}*/
80+
];
3581

36-
return deferred;
37-
},
38-
resolveOrReject = this.responseHandler || function (deferred, response) {
39-
var jwr = response;
40-
41-
// backward compatibility with older sails.io (no JWR)
42-
if(!(response instanceof Object && response.constructor.name === "JWR")){
43-
jwr = {
44-
body: response,
45-
headers: response.headers || {},
46-
statusCode: response.statusCode || response.status
47-
};
82+
/*@ngInject*/
83+
this.$get = ["$q", "$injector", "$rootScope", "$log", "$timeout", function($q, $injector, $rootScope, $log, $timeout) {
84+
var socket = (io.sails && io.sails.connect || io.connect)(provider.url, provider.config);
85+
86+
socket.connect = function(opts){
87+
if(!socket.isConnected()){
88+
var _opts = opts||{};
89+
_opts = angular.extend({},provider.config,opts);
90+
91+
// These are the options sails.io.js actually sets when making the connection.
92+
socket.useCORSRouteToGetCookie = _opts.useCORSRouteToGetCookie;
93+
socket.url = _opts.url || provider.url;
94+
socket.multiplex = _opts.multiplex;
95+
96+
socket._connect();
4897
}
98+
return socket;
99+
}
49100

50-
// angular $http returns the 'body' as 'data'.
51-
jwr.data = jwr.body;
101+
// TODO: separate out interceptors into its own file (and provider?).
102+
// build interceptor chain
103+
var reversedInterceptors = [];
104+
angular.forEach(interceptorFactories, function(interceptorFactory) {
105+
reversedInterceptors.unshift(
106+
angular.isString(interceptorFactory) ?
107+
$injector.get(interceptorFactory) : $injector.invoke(interceptorFactory)
108+
);
109+
});
52110

53-
// angular $http returns the 'statusCode' as 'status'.
54-
jwr.status = jwr.statusCode;
111+
// Send the request using the socket
112+
function serverRequest(config) {
113+
var defer = $q.defer();
114+
if (provider.debug) $log.info('$sails ' + config.method + ' ' + config.url, config.data || '');
55115

56-
// TODO: map 'status'/'statusCode' to a 'statusText' to mimic angular $http
116+
if (config.timeout > 0) {
117+
$timeout(timeoutRequest, config.timeout);
118+
} else if (isPromiseLike(config.timeout)) {
119+
config.timeout.then(timeoutRequest);
120+
}
121+
122+
socket['legacy_' + config.method.toLowerCase()](config.url, config.data, serverResponse);
57123

58-
if (jwr.error) {
59-
deferred.reject(jwr);
60-
} else {
61-
deferred.resolve(jwr);
124+
function timeoutRequest(){
125+
serverResponse(null);
62126
}
63-
},
64-
angularify = function (cb, data) {
65-
$timeout(function () {
66-
cb(data);
67-
});
68-
},
69-
promisify = function (methodName) {
70-
socket['legacy_' + methodName] = socket[methodName];
71-
socket[methodName] = function (url, data, cb) {
72-
var deferred = defer();
73-
if (cb === undefined && angular.isFunction(data)) {
74-
cb = data;
75-
data = null;
127+
128+
function serverResponse(result, jwr) {
129+
130+
if (!jwr) {
131+
jwr = {
132+
body: result,
133+
headers: result.headers || {},
134+
statusCode: result.statusCode || result.status || 0,
135+
error: (function() {
136+
if (this.statusCode < 200 || this.statusCode >= 400) {
137+
return this.body || this.statusCode;
138+
}
139+
})()
140+
};
141+
}
142+
143+
jwr.data = jwr.body; // $http compat
144+
jwr.status = jwr.statusCode; // $http compat
145+
jwr.socket = socket;
146+
jwr.url = config.url;
147+
jwr.method = config.method;
148+
jwr.config = config.config;
149+
if (jwr.error) {
150+
if (provider.debug) $log.warn('$sails response ' + jwr.statusCode + ' ' + config.url, jwr);
151+
defer.reject(jwr);
152+
} else {
153+
if (provider.debug) $log.info('$sails response ' + config.url, jwr);
154+
defer.resolve(jwr);
76155
}
77-
deferred.promise.then(cb);
78-
socket['legacy_' + methodName](url, data, function (emulatedHTTPBody, jsonWebSocketResponse) {
79-
resolveOrReject(deferred, jsonWebSocketResponse || emulatedHTTPBody);
156+
}
157+
158+
return defer.promise;
159+
}
160+
161+
function promisify(methodName) {
162+
socket['legacy_' + methodName] = socket[methodName];
163+
164+
socket[methodName] = function(url, data, config) {
165+
166+
var chain = [serverRequest, undefined];
167+
168+
//TODO: more compatible with $http methods and config
169+
170+
var promise = $q.when({
171+
url: provider.urlPrefix + url,
172+
data: data,
173+
socket: socket,
174+
config: config || {},
175+
method: methodName.toUpperCase()
80176
});
81-
return deferred.promise;
82-
};
83-
},
84-
wrapEvent = function (eventName) {
85-
socket['legacy_' + eventName] = socket[eventName];
86-
socket[eventName] = function (event, cb) {
87-
if (cb !== null && angular.isFunction(cb)) {
88-
socket['legacy_' + eventName](event, function (result) {
89-
angularify(cb, result);
90-
});
177+
178+
// apply interceptors
179+
angular.forEach(reversedInterceptors, function(interceptor) {
180+
if (interceptor.request || interceptor.requestError) {
181+
chain.unshift(interceptor.request, interceptor.requestError);
182+
}
183+
if (interceptor.response || interceptor.responseError) {
184+
chain.push(interceptor.response, interceptor.responseError);
185+
}
186+
});
187+
188+
while (chain.length) {
189+
var thenFn = chain.shift();
190+
var rejectFn = chain.shift();
191+
192+
promise = promise.then(thenFn, rejectFn);
91193
}
194+
195+
// be $http compatible
196+
promise.success = function(fn) {
197+
promise.then(function(jwr) {
198+
fn(jwr.body, jwr.statusCode, headersGetter(jwr.headers), jwr);
199+
});
200+
return promise;
201+
};
202+
promise.error = function(fn) {
203+
promise.then(null, function(jwr) {
204+
fn(jwr.body, jwr.statusCode, headersGetter(jwr.headers), jwr);
205+
});
206+
return promise;
207+
};
208+
209+
return promise;
92210
};
93-
};
211+
}
212+
213+
function wrapEvent(eventName) {
214+
if(socket[eventName] || socket._raw[eventName]){
215+
socket['legacy_' + eventName] = socket[eventName] || socket._raw[eventName];
216+
socket[eventName] = function(event, cb) {
217+
if (cb !== null && angular.isFunction(cb)) {
218+
socket['legacy_' + eventName](event, function(result) {
219+
$rootScope.$evalAsync(cb.bind(socket, result));
220+
});
221+
}
222+
};
223+
}
224+
}
225+
226+
angular.forEach(provider.httpVerbs, promisify);
227+
angular.forEach(provider.eventNames, wrapEvent);
228+
229+
230+
/**
231+
* Update a model on sails pushes
232+
* @param {String} name Sails model name
233+
* @param {Array} models Array with model objects
234+
*/
235+
socket.$modelUpdater = function(name, models) {
236+
237+
socket.on(name, function(message) {
238+
var i;
239+
240+
switch (message.verb) {
94241

95-
angular.forEach(httpVerbs, promisify);
96-
angular.forEach(eventNames, wrapEvent);
242+
case "created":
243+
// create new model item
244+
models.push(message.data);
245+
break;
246+
247+
case "updated":
248+
var obj;
249+
for (i = 0; i < models.length; i++) {
250+
if (models[i].id === message.id) {
251+
obj = models[i];
252+
break;
253+
}
254+
}
255+
256+
// cant update if the angular-model does not have the item and the
257+
// sails message does not give us the previous record
258+
if (!obj && !message.previous) return;
259+
260+
if (!obj) {
261+
// sails has given us the previous record, create it in our model
262+
obj = message.previous;
263+
models.push(obj);
264+
}
265+
266+
// update the model item
267+
angular.extend(obj, message.data);
268+
break;
269+
270+
case "destroyed":
271+
for (i = 0; i < models.length; i++) {
272+
if (models[i].id === message.id) {
273+
models.splice(i, 1);
274+
break;
275+
}
276+
}
277+
break;
278+
}
279+
});
280+
};
97281

98-
return socket;
99-
}];
100-
});
282+
return socket;
283+
}];
284+
this.$get.$inject = ["$q", "$injector", "$rootScope", "$log", "$timeout"];
285+
});
286+
}(angular, io));
101287
}(angular, io));

dist/angular-sails.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "angular-sails",
33
"private": true,
4-
"version": "1.0.5",
4+
"version": "1.1.0",
55
"description": "An angular provider for using the sails socket.io api",
66
"scripts": {
77
"build": "gulp build-js",

0 commit comments

Comments
 (0)