angular-sails
Advanced tools
Comparing version 1.1.4 to 2.0.0-beta.4
{ | ||
"name": "angular-sails", | ||
"version": "1.1.4", | ||
"version": "2.0.0-beta.4", | ||
"authors": [ | ||
@@ -20,8 +20,8 @@ "Jan-Oliver Pantel <jan.pantel@gmail.com>", | ||
"license": "MIT", | ||
"homepage": "https://github.com/kyjan/angular-sails", | ||
"homepage": "https://github.com/janpantel/angular-sails", | ||
"dependencies": { | ||
"angular": ">=1.2.*", | ||
"sails.io.js": "*" | ||
"socket.io-client": ">=1.3.0" | ||
}, | ||
"devDependencies":{ | ||
"devDependencies": { | ||
"angular-mocks": ">=1.2.*" | ||
@@ -28,0 +28,0 @@ }, |
@@ -1,313 +0,742 @@ | ||
(function (angular, io) { | ||
'use strict'/*global angular */ | ||
angular.module('ngSails', ['ng']); | ||
/*! | ||
* angular-sails | ||
* An angular provider for using the sails socket.io api | ||
* @version v2.0.0-beta.4 | ||
* @link https://github.com/janpantel/angular-sails | ||
* @license MIT License, http://www.opensource.org/licenses/MIT | ||
*/ | ||
(function(window, angular, undefined){'use strict'; | ||
/*global angular, io */ | ||
(function(angular, io) { | ||
'use strict'; | ||
if(io.sails){ | ||
io.sails.autoConnect = false; | ||
angular.module('ngSails', ['ngSails.$sails']); | ||
'use strict'; | ||
function parseHeaders(headers) { | ||
var parsed = {}, | ||
key, val, i; | ||
if (!headers) return parsed; | ||
angular.forEach(headers.split('\n'), function(line) { | ||
i = line.indexOf(':'); | ||
key = angular.lowercase(trim(line.substr(0, i))); | ||
val = trim(line.substr(i + 1)); | ||
if (key) { | ||
parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val; | ||
} | ||
}); | ||
// copied from angular | ||
function parseHeaders(headers) { | ||
var parsed = {}, | ||
key, val, i; | ||
if (!headers) return parsed; | ||
angular.forEach(headers.split('\n'), function(line) { | ||
i = line.indexOf(':'); | ||
key = lowercase(trim(line.substr(0, i))); | ||
val = trim(line.substr(i + 1)); | ||
if (key) { | ||
parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val; | ||
} | ||
}); | ||
return parsed; | ||
} | ||
return parsed; | ||
function executeHeaderFns(headers, config) { | ||
var headerContent, processedHeaders = {}; | ||
angular.forEach(headers, function(headerFn, header) { | ||
if (angular.isFunction(headerFn)) { | ||
headerContent = headerFn(config); | ||
if (headerContent != null) { | ||
processedHeaders[header] = headerContent; | ||
} | ||
} else { | ||
processedHeaders[header] = headerFn; | ||
} | ||
}); | ||
function trim(value) { | ||
return angular.isString(value) ? value.trim() : value; | ||
return processedHeaders; | ||
} | ||
function mergeHeaders(config, defHeaders) { | ||
var reqHeaders = angular.extend({}, config.headers), | ||
defHeaderName, lowercaseDefHeaderName, reqHeaderName; | ||
defHeaders = angular.extend({}, defHeaders.common, defHeaders[angular.lowercase(config.method)]); | ||
// using for-in instead of forEach to avoid unecessary iteration after header has been found | ||
defaultHeadersIteration: | ||
for (defHeaderName in defHeaders) { | ||
lowercaseDefHeaderName = angular.lowercase(defHeaderName); | ||
for (reqHeaderName in reqHeaders) { | ||
if (angular.lowercase(reqHeaderName) === lowercaseDefHeaderName) { | ||
continue defaultHeadersIteration; | ||
} | ||
} | ||
function isPromiseLike (obj){ | ||
return obj && angular.isFunction(obj.then); | ||
reqHeaders[defHeaderName] = defHeaders[defHeaderName]; | ||
} | ||
// execute if header value is a function for merged headers | ||
return executeHeaderFns(reqHeaders, shallowCopy(config)); | ||
} | ||
function shallowCopy(src, dst) { | ||
if (angular.isArray(src)) { | ||
dst = dst || []; | ||
for (var i = 0, ii = src.length; i < ii; i++) { | ||
dst[i] = src[i]; | ||
} | ||
} else if (angular.isObject(src)) { | ||
dst = dst || {}; | ||
// copied from angular | ||
function headersGetter(headers) { | ||
var headersObj = angular.isObject(headers) ? headers : undefined; | ||
return function(name) { | ||
if (!headersObj) headersObj = parseHeaders(headers); | ||
if (name) { | ||
var value = headersObj[lowercase(name)]; | ||
if (value === void 0) { | ||
value = null; | ||
} | ||
return value; | ||
} | ||
return headersObj; | ||
for (var key in src) { | ||
if (!(key.charAt(0) === '$' && key.charAt(1) === '$')) { | ||
dst[key] = src[key]; | ||
} | ||
} | ||
} | ||
return dst || src; | ||
} | ||
function trim(value) { | ||
return angular.isString(value) ? value.trim() : value; | ||
} | ||
function isPromiseLike(obj) { | ||
return obj && angular.isFunction(obj.then); | ||
} | ||
// copied from angular | ||
function headersGetter(headers) { | ||
var headersObj = angular.isObject(headers) ? headers : undefined; | ||
return function(name) { | ||
if (!headersObj) headersObj = parseHeaders(headers); | ||
if (name) { | ||
var value = headersObj[angular.lowercase(name)]; | ||
if (value === void 0) { | ||
value = null; | ||
} | ||
return value; | ||
} | ||
return headersObj; | ||
}; | ||
} | ||
function arrIndexOf(arr, val) { | ||
if (!angular.isArray(arr)) { | ||
throw new TypeError('Expected type "array" by got type "' + (Object.prototype.toString.call(arr)) + '".'); | ||
} | ||
if (Array.prototype.indexOf) { | ||
return arr.indexOf(val); | ||
} else { | ||
var i = 0; | ||
var len = arr.length; | ||
if (len === 0) { | ||
return -1; | ||
} | ||
while (i < len) { | ||
if (i in arr && arr[i] === val) { | ||
return i; | ||
} | ||
i++; | ||
} | ||
return -1; | ||
} | ||
} | ||
function buildUrl(url, params) { | ||
if (!params) return url; | ||
var parts = []; | ||
forEachSorted(params, function(value, key) { | ||
if (value === null || angular.isUndefined(value)) return; | ||
if (!angular.isArray(value)) value = [value]; | ||
angular.forEach(value, function(v) { | ||
if (angular.isObject(v)) { | ||
if (angular.isDate(v)) { | ||
v = v.toISOString(); | ||
} else { | ||
v = angular.toJson(v); | ||
} | ||
} | ||
parts.push(encodeUriQuery(key) + '=' + | ||
encodeUriQuery(v)); | ||
}); | ||
}); | ||
if (parts.length > 0) { | ||
url += ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&'); | ||
} | ||
return url; | ||
} | ||
function forEachSorted(obj, iterator, context) { | ||
var keys = sortedKeys(obj); | ||
for (var i = 0; i < keys.length; i++) { | ||
iterator.call(context, obj[keys[i]], keys[i]); | ||
} | ||
return keys; | ||
} | ||
function sortedKeys(obj) { | ||
var keys = []; | ||
for (var key in obj) { | ||
if (obj.hasOwnProperty(key)) { | ||
keys.push(key); | ||
} | ||
} | ||
return keys.sort(); | ||
} | ||
function encodeUriQuery(val, pctEncodeSpaces) { | ||
return encodeURIComponent(val). | ||
replace(/%40/gi, '@'). | ||
replace(/%3A/gi, ':'). | ||
replace(/%24/g, '$'). | ||
replace(/%2C/gi, ','). | ||
replace(/%20/g, (pctEncodeSpaces ? '%20' : '+')); | ||
} | ||
function isFile(obj) { | ||
return Object.prototype.toString.call(obj) === '[object File]'; | ||
} | ||
function isBlob(obj) { | ||
return Object.prototype.toString.call(obj) === '[object Blob]'; | ||
} | ||
var statusText = { | ||
100: "100 Continue", | ||
101: "101 Switching Protocols", | ||
102: "102 Processing", | ||
200: "200 OK", | ||
201: "201 Created", | ||
202: "202 Accepted", | ||
203: "203 Non-Authoritative Information", | ||
204: "204 No Content", | ||
205: "205 Reset Content", | ||
206: "206 Partial Content", | ||
207: "207 Multi-Status", | ||
208: "208 Already Reported", | ||
226: "226 IM Used", | ||
300: "300 Multiple Choices", | ||
301: "301 Moved Permanently", | ||
302: "302 Found", | ||
303: "303 See Other", | ||
304: "304 Not Modified", | ||
305: "305 Use Proxy", | ||
306: "306 (Unused)", | ||
307: "307 Temporary Redirect", | ||
308: "308 Permanent Redirect", | ||
400: "400 Bad Request", | ||
401: "401 Unauthorized", | ||
402: "402 Payment Required", | ||
403: "403 Forbidden", | ||
404: "404 Not Found", | ||
405: "405 Method Not Allowed", | ||
406: "406 Not Acceptable", | ||
407: "407 Proxy Authentication Required", | ||
408: "408 Request Timeout", | ||
409: "409 Conflict", | ||
410: "410 Gone", | ||
411: "411 Length Required", | ||
412: "412 Precondition Failed", | ||
413: "413 Payload Too Large", | ||
414: "414 URI Too Long", | ||
415: "415 Unsupported Media Type", | ||
416: "416 Range Not Satisfiable", | ||
417: "417 Expectation Failed", | ||
422: "422 Unprocessable Entity", | ||
423: "423 Locked", | ||
424: "424 Failed Dependency", | ||
426: "426 Upgrade Required", | ||
428: "428 Precondition Required", | ||
429: "429 Too Many Requests", | ||
431: "431 Request Header Fields Too Large", | ||
500: "500 Internal Server Error", | ||
501: "501 Not Implemented", | ||
502: "502 Bad Gateway", | ||
503: "503 Service Unavailable", | ||
504: "504 Gateway Timeout", | ||
505: "505 HTTP Version Not Supported", | ||
506: "506 Variant Also Negotiates", | ||
507: "507 Insufficient Storage", | ||
508: "508 Loop Detected", | ||
510: "510 Not Extended", | ||
511: "511 Network Authentication Required" | ||
}; | ||
'use strict'; | ||
/* jshint newcap: false */ | ||
/* global headersGetter: true, | ||
mergeHeaders: true, | ||
arrIndexOf: true, | ||
isFile: true, | ||
isBlob: true | ||
*/ | ||
angular.module('ngSails.$sails', ['ngSails.$sailsIo', 'ngSails.$sailsInterceptor']) | ||
.provider('$sails', $sails); | ||
function $sails($sailsInterceptorProvider, $sailsIoProvider) { | ||
var provider = this; | ||
var httpVerbsWithData = ['post', 'put', 'patch']; | ||
provider.httpVerbs = $sailsIoProvider.httpVerbs = ['get', 'post', 'put', 'patch', 'delete', 'head']; | ||
provider.eventNames = $sailsIoProvider.eventNames = ['on', 'off', 'once']; | ||
provider.config = { | ||
transports: ['websocket', 'polling'] | ||
}; | ||
provider.debug = $sailsInterceptorProvider.debug = $sailsIoProvider.debug = false; | ||
provider.debugger = function(val) { | ||
provider.debug = $sailsInterceptorProvider.debug = $sailsIoProvider.debug = val; | ||
}; | ||
provider.defaults = { | ||
transformResponse: [], | ||
transformRequest: [], | ||
headers: {} // TODO: what should the default default headers | ||
}; | ||
provider.interceptors = $sailsInterceptorProvider.interceptors = [ | ||
/*function($injectables) { | ||
return { | ||
request: function(config) {}, | ||
response: function(response) {}, | ||
requestError: function(rejection) {}, | ||
responseError: function(rejection) {} | ||
}; | ||
}*/ | ||
]; | ||
this.$get = ["$rootScope", "$q", "$log", "$timeout", "$sailsIo", "$sailsInterceptor", function($rootScope, $q, $log, $timeout, $sailsIo, $sailsInterceptor) { | ||
var socket = new $sailsIo(provider.socket || provider.url, provider.config); | ||
var socketFunctions = ['connect', 'disconnect', 'isConnected']; | ||
function $sails(config) { | ||
return $sails[config.method](config.url, config); | ||
} | ||
angular.module('ngSails').provider('$sails', function() { | ||
var provider = this; | ||
$sails._socket = socket; | ||
this.httpVerbs = ['get', 'post', 'put', 'delete']; | ||
function exposeSocketFunction(fnName) { | ||
$sails[fnName] = socket[fnName].bind(socket); | ||
} | ||
this.eventNames = ['on', 'off']; | ||
function exposeVerbEndpoints(methodName) { | ||
this.url = undefined; | ||
$sails[methodName] = function(url, data, requestConfig) { | ||
var config = { | ||
method: methodName, | ||
transformRequest: provider.defaults.transformRequest, | ||
transformResponse: provider.defaults.transformResponse | ||
}; | ||
this.urlPrefix = ''; | ||
requestConfig = requestConfig || {}; | ||
this.config = { | ||
transports: ['websocket', 'polling'], | ||
useCORSRouteToGetCookie: false | ||
// more compatible with $http method arguments | ||
if (arrIndexOf(httpVerbsWithData, methodName) === -1) { | ||
requestConfig = data || requestConfig; | ||
delete requestConfig.data; | ||
} else { | ||
requestConfig.data = data; | ||
} | ||
config = angular.extend({}, config, requestConfig); | ||
config.method = angular.uppercase(config.method || methodName); | ||
config.headers = mergeHeaders(config, provider.defaults.headers); | ||
config.url = (provider.urlPrefix || '') + (url || config.url); | ||
if (angular.isUndefined(config.withCredentials) && !angular.isUndefined(provider.defaults.withCredentials)) { | ||
config.withCredentials = provider.defaults.withCredentials; | ||
} | ||
var promise = $sailsInterceptor(socket[methodName].bind(socket), config); | ||
promise.success = function(fn) { | ||
promise.then(function(res) { | ||
fn(res.data, res.status, headersGetter(res.headers), res.config); | ||
}); | ||
return promise; | ||
}; | ||
this.debug = false; | ||
promise.error = function(fn) { | ||
promise.then(null, function(res) { | ||
fn(res.data, res.status, headersGetter(res.headers), res.config); | ||
}); | ||
return promise; | ||
}; | ||
// like https://docs.angularjs.org/api/ng/service/$http#interceptors | ||
// but with sails.io arguments | ||
var interceptorFactories = this.interceptors = [ | ||
/*function($injectables) { | ||
return { | ||
request: function(config) {}, | ||
response: function(response) {}, | ||
requestError: function(rejection) {}, | ||
responseError: function(rejection) {} | ||
}; | ||
}*/ | ||
]; | ||
return promise; | ||
/*@ngInject*/ | ||
this.$get = ["$q", "$injector", "$rootScope", "$log", "$timeout", function($q, $injector, $rootScope, $log, $timeout) { | ||
var socket = (io.sails && io.sails.connect || io.connect)(provider.url, provider.config); | ||
}; | ||
} | ||
socket.connect = function(opts){ | ||
if(!socket.isConnected()){ | ||
var _opts = opts||{}; | ||
_opts = angular.extend({},provider.config,opts); | ||
function exposeEventsEndpoitns(eventName) { | ||
$sails[eventName] = socket[eventName].bind(socket); | ||
} | ||
// These are the options sails.io.js actually sets when making the connection. | ||
socket.useCORSRouteToGetCookie = _opts.useCORSRouteToGetCookie; | ||
socket.url = _opts.url || provider.url; | ||
socket.multiplex = _opts.multiplex; | ||
angular.forEach(provider.httpVerbs, exposeVerbEndpoints, this); | ||
angular.forEach(provider.eventNames, exposeEventsEndpoitns, this); | ||
angular.forEach(socketFunctions, exposeSocketFunction, this); | ||
socket._connect(); | ||
} | ||
return socket; | ||
}; | ||
/** | ||
* Update a model on sails pushes | ||
* @param {String} name Sails model name | ||
* @param {Array} models Array with model objects | ||
* @returns {Function} Function to remove the model updater instance | ||
*/ | ||
$sails.$modelUpdater = function(name, models) { | ||
// TODO: separate out interceptors into its own file (and provider?). | ||
// build interceptor chain | ||
var reversedInterceptors = []; | ||
angular.forEach(interceptorFactories, function(interceptorFactory) { | ||
reversedInterceptors.unshift( | ||
angular.isString(interceptorFactory) ? | ||
$injector.get(interceptorFactory) : $injector.invoke(interceptorFactory) | ||
); | ||
}); | ||
var update = function(message) { | ||
// Send the request using the socket | ||
function serverRequest(config) { | ||
var defer = $q.defer(); | ||
if (provider.debug) $log.info('$sails ' + config.method + ' ' + config.url, config.data || ''); | ||
$rootScope.$evalAsync(function() { | ||
var i; | ||
if (config.timeout > 0) { | ||
$timeout(timeoutRequest, config.timeout); | ||
} else if (isPromiseLike(config.timeout)) { | ||
config.timeout.then(timeoutRequest); | ||
} | ||
switch (message.verb) { | ||
socket['legacy_' + config.method.toLowerCase()](config.url, config.data, serverResponse); | ||
case "created": | ||
// create new model item | ||
models.push(message.data); | ||
break; | ||
function timeoutRequest(){ | ||
serverResponse(null); | ||
case "updated": | ||
var obj; | ||
for (i = 0; i < models.length; i++) { | ||
if (models[i].id === message.id) { | ||
obj = models[i]; | ||
break; | ||
} | ||
} | ||
function serverResponse(result, jwr) { | ||
// cant update if the angular-model does not have the item and the | ||
// sails message does not give us the previous record | ||
if (!obj && !message.previous) return; | ||
if (!jwr) { | ||
jwr = { | ||
body: result, | ||
headers: result.headers || {}, | ||
statusCode: result.statusCode || result.status || 0, | ||
error: (function() { | ||
if (this.statusCode < 200 || this.statusCode >= 400) { | ||
return this.body || this.statusCode; | ||
} | ||
})() | ||
}; | ||
} | ||
if (!obj) { | ||
// sails has given us the previous record, create it in our model | ||
obj = message.previous; | ||
models.push(obj); | ||
} | ||
jwr.data = jwr.body; // $http compat | ||
jwr.status = jwr.statusCode; // $http compat | ||
jwr.socket = socket; | ||
jwr.url = config.url; | ||
jwr.method = config.method; | ||
jwr.config = config.config; | ||
if (jwr.error) { | ||
if (provider.debug) $log.warn('$sails response ' + jwr.statusCode + ' ' + config.url, jwr); | ||
defer.reject(jwr); | ||
} else { | ||
if (provider.debug) $log.info('$sails response ' + config.url, jwr); | ||
defer.resolve(jwr); | ||
} | ||
// update the model item | ||
angular.extend(obj, message.data); | ||
break; | ||
case "destroyed": | ||
for (i = 0; i < models.length; i++) { | ||
if (models[i].id === message.id) { | ||
models.splice(i, 1); | ||
break; | ||
} | ||
} | ||
break; | ||
} | ||
}); | ||
}; | ||
return defer.promise; | ||
} | ||
socket._socket.on(name, update); | ||
function promisify(methodName) { | ||
socket['legacy_' + methodName] = socket[methodName]; | ||
return function() { | ||
socket._socket.off(name, update); | ||
}; | ||
}; | ||
socket[methodName] = function(url, data, config) { | ||
$sails.defaults = this.defaults; | ||
var chain = [serverRequest, undefined]; | ||
return $sails; | ||
}]; | ||
} | ||
$sails.$inject = ["$sailsInterceptorProvider", "$sailsIoProvider"]; | ||
//TODO: more compatible with $http methods and config | ||
'use strict'; | ||
var promise = $q.when({ | ||
url: provider.urlPrefix + url, | ||
data: data, | ||
socket: socket, | ||
config: config || {}, | ||
method: methodName.toUpperCase() | ||
}); | ||
/* global isPromiseLike: true, | ||
headersGetter: true | ||
*/ | ||
// apply interceptors | ||
angular.forEach(reversedInterceptors, function(interceptor) { | ||
if (interceptor.request || interceptor.requestError) { | ||
chain.unshift(interceptor.request, interceptor.requestError); | ||
} | ||
if (interceptor.response || interceptor.responseError) { | ||
chain.push(interceptor.response, interceptor.responseError); | ||
} | ||
}); | ||
angular.module('ngSails.$sailsInterceptor', []) | ||
.provider('$sailsInterceptor', $sailsInterceptor); | ||
while (chain.length) { | ||
var thenFn = chain.shift(); | ||
var rejectFn = chain.shift(); | ||
function $sailsInterceptor() { | ||
var provider = this; | ||
provider.interceptors = []; | ||
promise = promise.then(thenFn, rejectFn); | ||
} | ||
this.$get = ["$injector", "$q", function($injector, $q) { | ||
// be $http compatible | ||
promise.success = function(fn) { | ||
promise.then(function(jwr) { | ||
fn(jwr.body, jwr.statusCode, headersGetter(jwr.headers), jwr); | ||
}); | ||
return promise; | ||
}; | ||
promise.error = function(fn) { | ||
promise.then(null, function(jwr) { | ||
fn(jwr.body, jwr.statusCode, headersGetter(jwr.headers), jwr); | ||
}); | ||
return promise; | ||
}; | ||
var reversedInterceptors = []; | ||
return promise; | ||
}; | ||
} | ||
angular.forEach(provider.interceptors, function(interceptorFactory) { | ||
reversedInterceptors.unshift(angular.isString(interceptorFactory) ? $injector.get(interceptorFactory) : $injector.invoke(interceptorFactory)); | ||
}); | ||
function wrapEvent(eventName) { | ||
if(socket[eventName] || socket._raw && socket._raw[eventName]) { | ||
socket['legacy_' + eventName] = socket[eventName] || socket._raw[eventName]; | ||
socket[eventName] = function(event, cb) { | ||
var wrapEventFn = null; | ||
if (eventName == 'off') { | ||
return socket['legacy_' + eventName](event, cb); | ||
}else if (cb !== null && angular.isFunction(cb)) { | ||
socket['legacy_' + eventName](event, wrapEventFn = function(result) { | ||
$rootScope.$evalAsync(cb.bind(socket, result)); | ||
}); | ||
} | ||
return wrapEventFn; | ||
}; | ||
} | ||
} | ||
var intercept = function(sendRequest, config) { | ||
var _sendRequest = sendRequest; | ||
// sails.io.js doesn't have `once`, need to access it through `._raw` | ||
socket.once = function(event, cb){ | ||
if (cb !== null && angular.isFunction(cb)) { | ||
if(socket._raw){ | ||
socket._raw.once(event, function(result) { | ||
$rootScope.$evalAsync(cb.bind(socket, result)); | ||
}); | ||
} | ||
} | ||
}; | ||
if (isPromiseLike(sendRequest)) { | ||
_sendRequest = function() { | ||
return sendRequest; | ||
}; | ||
} | ||
angular.forEach(provider.httpVerbs, promisify); | ||
angular.forEach(provider.eventNames, wrapEvent); | ||
var chain = [transformRequest, undefined, _sendRequest, undefined, transformResponse, transformResponse]; | ||
var promise = $q.when(config); | ||
angular.forEach(reversedInterceptors, function(interceptor) { | ||
if (interceptor.request || interceptor.requestError) { | ||
chain.unshift(interceptor.request, interceptor.requestError); | ||
} | ||
if (interceptor.response || interceptor.responseError) { | ||
chain.push(interceptor.response, interceptor.responseError); | ||
} | ||
}); | ||
/** | ||
* Update a model on sails pushes | ||
* @param {String} name Sails model name | ||
* @param {Array} models Array with model objects | ||
*/ | ||
socket.$modelUpdater = function(name, models) { | ||
while (chain.length) { | ||
var thenFn = chain.shift(); | ||
var rejectFn = chain.shift(); | ||
var update = function(message) { | ||
promise = promise.then(thenFn, rejectFn); | ||
} | ||
$rootScope.$evalAsync(function(){ | ||
var i; | ||
return promise; | ||
}; | ||
switch (message.verb) { | ||
function transformRequest(config) { | ||
return angular.extend({}, config, { | ||
data: transformData(config.data, headersGetter(config.headers), config.transformRequest || []) | ||
}); | ||
} | ||
case "created": | ||
// create new model item | ||
models.push(message.data); | ||
break; | ||
function transformResponse(response) { | ||
var resp = angular.extend({}, response, { | ||
data: transformData(response.data, response.headers, response.config && response.config.transformResponse || []) | ||
}); | ||
return (200 <= response.status && response.status < 300) ? resp : $q.reject(resp); | ||
} | ||
case "updated": | ||
var obj; | ||
for (i = 0; i < models.length; i++) { | ||
if (models[i].id === message.id) { | ||
obj = models[i]; | ||
break; | ||
} | ||
} | ||
function transformData(data, headers, fns) { | ||
if (angular.isFunction(fns)){ | ||
return fns(data, headers); | ||
} | ||
// cant update if the angular-model does not have the item and the | ||
// sails message does not give us the previous record | ||
if (!obj && !message.previous) return; | ||
angular.forEach(fns, function(fn) { | ||
data = fn(data, headers); | ||
}); | ||
if (!obj) { | ||
// sails has given us the previous record, create it in our model | ||
obj = message.previous; | ||
models.push(obj); | ||
} | ||
return data; | ||
} | ||
// update the model item | ||
angular.extend(obj, message.data); | ||
break; | ||
return intercept; | ||
}]; | ||
} | ||
case "destroyed": | ||
for (i = 0; i < models.length; i++) { | ||
if (models[i].id === message.id) { | ||
models.splice(i, 1); | ||
break; | ||
} | ||
} | ||
break; | ||
} | ||
}); | ||
}; | ||
'use strict'; | ||
socket.legacy_on(name, update); | ||
/* global statusText: true, | ||
buildUrl: true | ||
*/ | ||
return function(){ | ||
socket.legacy_off(name, update); | ||
}; | ||
}; | ||
angular.module('ngSails.$sailsIo', ['ngSails.sailsSdk', 'ngSails.socketIo']) | ||
.provider('$sailsIo', $sailsIo); | ||
return socket; | ||
}]; | ||
this.$get.$inject = ["$q", "$injector", "$rootScope", "$log", "$timeout"]; | ||
function $sailsIo() { | ||
var provider = this; | ||
provider.httpVerbs = ['get', 'post', 'put', 'delete']; | ||
provider.eventNames = ['on', 'off', 'once']; | ||
this.$get = ["$rootScope", "$q", "$log", "socketIo", "sailsSdk", function($rootScope, $q, $log, socketIo, sailsSdk) { | ||
var io = socketIo; | ||
function SailsIo(url, config) { | ||
return this.connect(url, config); | ||
} | ||
SailsIo.prototype.connect = function(url, config) { | ||
var self = this; | ||
config = config || {}; | ||
if(self._socket && self._socket.connected){ | ||
throw new Error('Socket is already connected.'); | ||
} | ||
if(!self.connectDefer){ | ||
self.connectDefer = $q.defer(); | ||
} | ||
if (angular.isObject(url) && angular.isFunction(url.on) && angular.isFunction(url.emit)){ | ||
// user passed in a socket, lets use it. | ||
self._socket = url; | ||
self.connectDefer.resolve(); | ||
}else{ | ||
if(!angular.isString(config.query)){ | ||
config.query = sailsSdk.versionString(); | ||
}else{ | ||
config.query += '&'+sailsSdk.versionString(); | ||
} | ||
if (!self._socket || !self._socket.connected) { | ||
self._socket = io(url || config.url, config); | ||
self.connectDefer.resolve(); | ||
} | ||
} | ||
if (provider.debug) { | ||
self.on('connect', $log.info.bind(self, '$sails connected.')); | ||
self.on('disconnect', $log.info.bind(self, '$sails disconnected.')); | ||
self.on('reconnecting', function(attemps) { | ||
$log.warn.bind(self, '$sails is attemping to reconnect. (#' + attemps + ')'); | ||
}); | ||
self.on('reconnect', function(transport, attemps) { | ||
$log.info.bind(self, '$sails successfully reconnected after ' + attemps + ' attemps.'); | ||
}); | ||
self.on('error', function(err) { | ||
$log.error('$sails could not connect:', err); | ||
}); | ||
} | ||
return self; | ||
}; | ||
SailsIo.prototype.disconnect = function() { | ||
var self = this; | ||
if (self._socket) { | ||
self._socket.disconnect(); | ||
} | ||
if(self.connectDefer){ | ||
self.connectDefer.reject('disconnect'); | ||
} | ||
self.connectDefer = $q.defer(); | ||
}; | ||
SailsIo.prototype.isConnected = function() { | ||
if (!this._socket) { | ||
return false; | ||
} | ||
return this._socket.connected; | ||
}; | ||
SailsIo.prototype._send = function(req, res) { | ||
var self = this; | ||
var sailsEndpoint = angular.lowercase(req.method); | ||
self.connectDefer.promise.then(function sendRequest() { | ||
if (provider.debug) { | ||
$log.info('$sails ' + req.method + ' ' + req.url, req.data || ''); | ||
} | ||
self._socket.emit(sailsEndpoint, {data: req.data, headers: req.headers, url: req.url}, function requestResponse(response) { | ||
if (provider.debug) { | ||
$log.info('$sails' + req.method + ' ' + req.url + ' response received', response); | ||
} | ||
response = response || {}; | ||
var serverResponse = { | ||
data: response.body || response, | ||
status: response.statusCode || response.status || response.Status || 200, | ||
headers: response.headers || {}, | ||
config: req | ||
}; | ||
serverResponse.statusText = statusText[serverResponse.status]; | ||
if (200 <= serverResponse.status && serverResponse.status < 300) { | ||
res.reject(serverResponse); | ||
} else { | ||
res.resolve(serverResponse); | ||
} | ||
}); | ||
}, function voidRequest() { | ||
if (provider.debug) { | ||
$log.warn('$sails' + req.method + ' ' + req.url + ' request terminated', req); | ||
} | ||
res.reject({ | ||
data: null, | ||
status: 0, | ||
headers: {}, | ||
config: req, | ||
statusText: null | ||
}); | ||
}); | ||
}; | ||
SailsIo.prototype._req = function(req) { | ||
var self = this; | ||
var res = $q.defer(); | ||
req.url = req.url.replace(/^(.+)\/*\s*$/, '$1'); | ||
req.headers = req.headers || {}; | ||
req.data = req.params || req.data || {}; | ||
req.method = angular.uppercase(req.method); | ||
if (typeof req.url !== 'string') { | ||
throw new Error('Invalid or missing URL!'); | ||
} | ||
self._send(req, res); | ||
return res.promise; | ||
}; | ||
angular.forEach(provider.httpVerbs, function(method) { | ||
SailsIo.prototype[method] = function(req){ | ||
req.method = req.method || method; | ||
return SailsIo.prototype._req.apply(this, [req]); | ||
}; | ||
}); | ||
}(angular, io)); | ||
}(angular, io)); | ||
angular.forEach(provider.eventNames, function(ev) { | ||
SailsIo.prototype[ev] = function(evt, cb) { | ||
var self = this; | ||
if (cb !== null && angular.isFunction(cb)) { | ||
self._socket[ev](evt, function(result) { | ||
$rootScope.$evalAsync(cb.bind(self, result)); | ||
}); | ||
} | ||
}; | ||
}, this); | ||
return SailsIo; | ||
}]; | ||
} | ||
'use strict'; | ||
// Sailsjs expects this information in the request... | ||
angular.module('ngSails.sailsSdk', []) | ||
.constant('sailsSdk', { | ||
info: { | ||
version: { | ||
key: '__sails_io_sdk_version', | ||
value: '0.11.0' | ||
}, | ||
platform: { | ||
key: '__sails_io_sdk_platform', | ||
value: typeof module === 'undefined' ? 'browser' : 'node' | ||
}, | ||
language: { | ||
key: '__sails_io_sdk_language', | ||
value: 'javascript' | ||
} | ||
}, | ||
versionString: function() { | ||
var self = this; | ||
return (function(){ | ||
var tmp = []; | ||
angular.forEach(self.info, function(data){ | ||
tmp.push(data.key+'='+data.value); | ||
}); | ||
return tmp.join('&'); | ||
}()); | ||
} | ||
}); | ||
'use strict'; | ||
angular.module('ngSails.socketIo', []) | ||
.factory('socketIo', socketIo); | ||
function socketIo($window) { | ||
if (!$window.io) { | ||
throw new Error('Socket.io-client not found. Ensure socket.io-client is loaded before this script'); | ||
} | ||
return $window.io; | ||
} | ||
socketIo.$inject = ["$window"]; | ||
})(window, window.angular); |
@@ -1,1 +0,8 @@ | ||
!function(e,t){"use strict";e.module("ngSails",["ng"]),function(e,t){function n(t){var n,r,s,i={};return t?(e.forEach(t.split("\n"),function(e){s=e.indexOf(":"),n=lowercase(o(e.substr(0,s))),r=o(e.substr(s+1)),n&&(i[n]=i[n]?i[n]+", "+r:r)}),i):i}function o(t){return e.isString(t)?t.trim():t}function r(t){return t&&e.isFunction(t.then)}function s(t){var o=e.isObject(t)?t:void 0;return function(e){if(o||(o=n(t)),e){var r=o[lowercase(e)];return void 0===r&&(r=null),r}return o}}t.sails&&(t.sails.autoConnect=!1),e.module("ngSails").provider("$sails",function(){var n=this;this.httpVerbs=["get","post","put","delete"],this.eventNames=["on","off"],this.url=void 0,this.urlPrefix="",this.config={transports:["websocket","polling"],useCORSRouteToGetCookie:!1},this.debug=!1;var o=this.interceptors=[];this.$get=["$q","$injector","$rootScope","$log","$timeout",function(i,u,a,c,f){function l(e){function t(){o(null)}function o(t,o){o||(o={body:t,headers:t.headers||{},statusCode:t.statusCode||t.status||0,error:function(){return this.statusCode<200||this.statusCode>=400?this.body||this.statusCode:void 0}()}),o.data=o.body,o.status=o.statusCode,o.socket=g,o.url=e.url,o.method=e.method,o.config=e.config,o.error?(n.debug&&c.warn("$sails response "+o.statusCode+" "+e.url,o),s.reject(o)):(n.debug&&c.info("$sails response "+e.url,o),s.resolve(o))}var s=i.defer();return n.debug&&c.info("$sails "+e.method+" "+e.url,e.data||""),e.timeout>0?f(t,e.timeout):r(e.timeout)&&e.timeout.then(t),g["legacy_"+e.method.toLowerCase()](e.url,e.data,o),s.promise}function d(t){g["legacy_"+t]=g[t],g[t]=function(o,r,u){var a=[l,void 0],c=i.when({url:n.urlPrefix+o,data:r,socket:g,config:u||{},method:t.toUpperCase()});for(e.forEach(v,function(e){(e.request||e.requestError)&&a.unshift(e.request,e.requestError),(e.response||e.responseError)&&a.push(e.response,e.responseError)});a.length;){var f=a.shift(),d=a.shift();c=c.then(f,d)}return c.success=function(e){return c.then(function(t){e(t.body,t.statusCode,s(t.headers),t)}),c},c.error=function(e){return c.then(null,function(t){e(t.body,t.statusCode,s(t.headers),t)}),c},c}}function h(t){(g[t]||g._raw&&g._raw[t])&&(g["legacy_"+t]=g[t]||g._raw[t],g[t]=function(n,o){var r=null;return"off"==t?g["legacy_"+t](n,o):(null!==o&&e.isFunction(o)&&g["legacy_"+t](n,r=function(e){a.$evalAsync(o.bind(g,e))}),r)})}var g=(t.sails&&t.sails.connect||t.connect)(n.url,n.config);g.connect=function(t){if(!g.isConnected()){var o=t||{};o=e.extend({},n.config,t),g.useCORSRouteToGetCookie=o.useCORSRouteToGetCookie,g.url=o.url||n.url,g.multiplex=o.multiplex,g._connect()}return g};var v=[];return e.forEach(o,function(t){v.unshift(e.isString(t)?u.get(t):u.invoke(t))}),g.once=function(t,n){null!==n&&e.isFunction(n)&&g._raw&&g._raw.once(t,function(e){a.$evalAsync(n.bind(g,e))})},e.forEach(n.httpVerbs,d),e.forEach(n.eventNames,h),g.$modelUpdater=function(t,n){var o=function(t){a.$evalAsync(function(){var o;switch(t.verb){case"created":n.push(t.data);break;case"updated":var r;for(o=0;o<n.length;o++)if(n[o].id===t.id){r=n[o];break}if(!r&&!t.previous)return;r||(r=t.previous,n.push(r)),e.extend(r,t.data);break;case"destroyed":for(o=0;o<n.length;o++)if(n[o].id===t.id){n.splice(o,1);break}}})};return g.legacy_on(t,o),function(){g.legacy_off(t,o)}},g}],this.$get.$inject=["$q","$injector","$rootScope","$log","$timeout"]})}(e,t)}(angular,io); | ||
/*! | ||
* angular-sails | ||
* An angular provider for using the sails socket.io api | ||
* @version v2.0.0-beta.4 | ||
* @link https://github.com/janpantel/angular-sails | ||
* @license MIT License, http://www.opensource.org/licenses/MIT | ||
*/ | ||
!function(e,t,n){"use strict";function r(e){var n,r,o,s={};return e?(t.forEach(e.split("\n"),function(e){o=e.indexOf(":"),n=t.lowercase(a(e.substr(0,o))),r=a(e.substr(o+1)),n&&(s[n]=s[n]?s[n]+", "+r:r)}),s):s}function o(e,n){var r,o={};return t.forEach(e,function(e,s){t.isFunction(e)?(r=e(n),null!=r&&(o[s]=r)):o[s]=e}),o}function s(e,n){var r,s,a,c=t.extend({},e.headers);n=t.extend({},n.common,n[t.lowercase(e.method)]);e:for(r in n){s=t.lowercase(r);for(a in c)if(t.lowercase(a)===s)continue e;c[r]=n[r]}return o(c,i(e))}function i(e,n){if(t.isArray(e)){n=n||[];for(var r=0,o=e.length;o>r;r++)n[r]=e[r]}else if(t.isObject(e)){n=n||{};for(var s in e)("$"!==s.charAt(0)||"$"!==s.charAt(1))&&(n[s]=e[s])}return n||e}function a(e){return t.isString(e)?e.trim():e}function c(e){return e&&t.isFunction(e.then)}function u(e){var o=t.isObject(e)?e:n;return function(n){if(o||(o=r(e)),n){var s=o[t.lowercase(n)];return void 0===s&&(s=null),s}return o}}function d(e,n){if(!t.isArray(e))throw new TypeError('Expected type "array" by got type "'+Object.prototype.toString.call(e)+'".');if(Array.prototype.indexOf)return e.indexOf(n);var r=0,o=e.length;if(0===o)return-1;for(;o>r;){if(r in e&&e[r]===n)return r;r++}return-1}function f(e,n){var r=this,o=["post","put","patch"];r.httpVerbs=n.httpVerbs=["get","post","put","patch","delete","head"],r.eventNames=n.eventNames=["on","off","once"],r.config={transports:["websocket","polling"]},r.debug=e.debug=n.debug=!1,r["debugger"]=function(t){r.debug=e.debug=n.debug=t},r.defaults={transformResponse:[],transformRequest:[],headers:{}},r.interceptors=e.interceptors=[],this.$get=["$rootScope","$q","$log","$timeout","$sailsIo","$sailsInterceptor",function(e,n,i,a,c,f){function l(e){return l[e.method](e.url,e)}function h(e){l[e]=v[e].bind(v)}function p(e){l[e]=function(n,i,a){var c={method:e,transformRequest:r.defaults.transformRequest,transformResponse:r.defaults.transformResponse};a=a||{},-1===d(o,e)?(a=i||a,delete a.data):a.data=i,c=t.extend({},c,a),c.method=t.uppercase(c.method||e),c.headers=s(c,r.defaults.headers),c.url=(r.urlPrefix||"")+(n||c.url),t.isUndefined(c.withCredentials)&&!t.isUndefined(r.defaults.withCredentials)&&(c.withCredentials=r.defaults.withCredentials);var l=f(v[e].bind(v),c);return l.success=function(e){return l.then(function(t){e(t.data,t.status,u(t.headers),t.config)}),l},l.error=function(e){return l.then(null,function(t){e(t.data,t.status,u(t.headers),t.config)}),l},l}}function g(e){l[e]=v[e].bind(v)}var v=new c(r.socket||r.url,r.config),m=["connect","disconnect","isConnected"];return l._socket=v,t.forEach(r.httpVerbs,p,this),t.forEach(r.eventNames,g,this),t.forEach(m,h,this),l.$modelUpdater=function(n,r){var o=function(n){e.$evalAsync(function(){var e;switch(n.verb){case"created":r.push(n.data);break;case"updated":var o;for(e=0;e<r.length;e++)if(r[e].id===n.id){o=r[e];break}if(!o&&!n.previous)return;o||(o=n.previous,r.push(o)),t.extend(o,n.data);break;case"destroyed":for(e=0;e<r.length;e++)if(r[e].id===n.id){r.splice(e,1);break}}})};return v._socket.on(n,o),function(){v._socket.off(n,o)}},l.defaults=this.defaults,l}]}function l(){var e=this;e.interceptors=[],this.$get=["$injector","$q",function(r,o){function s(e){return t.extend({},e,{data:a(e.data,u(e.headers),e.transformRequest||[])})}function i(e){var n=t.extend({},e,{data:a(e.data,e.headers,e.config&&e.config.transformResponse||[])});return 200<=e.status&&e.status<300?n:o.reject(n)}function a(e,n,r){return t.isFunction(r)?r(e,n):(t.forEach(r,function(t){e=t(e,n)}),e)}var d=[];t.forEach(e.interceptors,function(e){d.unshift(t.isString(e)?r.get(e):r.invoke(e))});var f=function(e,r){var a=e;c(e)&&(a=function(){return e});var u=[s,n,a,n,i,i],f=o.when(r);for(t.forEach(d,function(e){(e.request||e.requestError)&&u.unshift(e.request,e.requestError),(e.response||e.responseError)&&u.push(e.response,e.responseError)});u.length;){var l=u.shift(),h=u.shift();f=f.then(l,h)}return f};return f}]}function h(){var e=this;e.httpVerbs=["get","post","put","delete"],e.eventNames=["on","off","once"],this.$get=["$rootScope","$q","$log","socketIo","sailsSdk",function(n,r,o,s,i){function a(e,t){return this.connect(e,t)}var c=s;return a.prototype.connect=function(n,s){var a=this;if(s=s||{},a._socket&&a._socket.connected)throw new Error("Socket is already connected.");return a.connectDefer||(a.connectDefer=r.defer()),t.isObject(n)&&t.isFunction(n.on)&&t.isFunction(n.emit)?(a._socket=n,a.connectDefer.resolve()):(t.isString(s.query)?s.query+="&"+i.versionString():s.query=i.versionString(),a._socket&&a._socket.connected||(a._socket=c(n||s.url,s),a.connectDefer.resolve())),e.debug&&(a.on("connect",o.info.bind(a,"$sails connected.")),a.on("disconnect",o.info.bind(a,"$sails disconnected.")),a.on("reconnecting",function(e){o.warn.bind(a,"$sails is attemping to reconnect. (#"+e+")")}),a.on("reconnect",function(e,t){o.info.bind(a,"$sails successfully reconnected after "+t+" attemps.")}),a.on("error",function(e){o.error("$sails could not connect:",e)})),a},a.prototype.disconnect=function(){var e=this;e._socket&&e._socket.disconnect(),e.connectDefer&&e.connectDefer.reject("disconnect"),e.connectDefer=r.defer()},a.prototype.isConnected=function(){return this._socket?this._socket.connected:!1},a.prototype._send=function(n,r){var s=this,i=t.lowercase(n.method);s.connectDefer.promise.then(function(){e.debug&&o.info("$sails "+n.method+" "+n.url,n.data||""),s._socket.emit(i,{data:n.data,headers:n.headers,url:n.url},function(t){e.debug&&o.info("$sails"+n.method+" "+n.url+" response received",t),t=t||{};var s={data:t.body||t,status:t.statusCode||t.status||t.Status||200,headers:t.headers||{},config:n};s.statusText=g[s.status],200<=s.status&&s.status<300?r.reject(s):r.resolve(s)})},function(){e.debug&&o.warn("$sails"+n.method+" "+n.url+" request terminated",n),r.reject({data:null,status:0,headers:{},config:n,statusText:null})})},a.prototype._req=function(e){var n=this,o=r.defer();if(e.url=e.url.replace(/^(.+)\/*\s*$/,"$1"),e.headers=e.headers||{},e.data=e.params||e.data||{},e.method=t.uppercase(e.method),"string"!=typeof e.url)throw new Error("Invalid or missing URL!");return n._send(e,o),o.promise},t.forEach(e.httpVerbs,function(e){a.prototype[e]=function(t){return t.method=t.method||e,a.prototype._req.apply(this,[t])}}),t.forEach(e.eventNames,function(e){a.prototype[e]=function(r,o){var s=this;null!==o&&t.isFunction(o)&&s._socket[e](r,function(e){n.$evalAsync(o.bind(s,e))})}},this),a}]}function p(e){if(!e.io)throw new Error("Socket.io-client not found. Ensure socket.io-client is loaded before this script");return e.io}t.module("ngSails",["ngSails.$sails"]);var g={100:"100 Continue",101:"101 Switching Protocols",102:"102 Processing",200:"200 OK",201:"201 Created",202:"202 Accepted",203:"203 Non-Authoritative Information",204:"204 No Content",205:"205 Reset Content",206:"206 Partial Content",207:"207 Multi-Status",208:"208 Already Reported",226:"226 IM Used",300:"300 Multiple Choices",301:"301 Moved Permanently",302:"302 Found",303:"303 See Other",304:"304 Not Modified",305:"305 Use Proxy",306:"306 (Unused)",307:"307 Temporary Redirect",308:"308 Permanent Redirect",400:"400 Bad Request",401:"401 Unauthorized",402:"402 Payment Required",403:"403 Forbidden",404:"404 Not Found",405:"405 Method Not Allowed",406:"406 Not Acceptable",407:"407 Proxy Authentication Required",408:"408 Request Timeout",409:"409 Conflict",410:"410 Gone",411:"411 Length Required",412:"412 Precondition Failed",413:"413 Payload Too Large",414:"414 URI Too Long",415:"415 Unsupported Media Type",416:"416 Range Not Satisfiable",417:"417 Expectation Failed",422:"422 Unprocessable Entity",423:"423 Locked",424:"424 Failed Dependency",426:"426 Upgrade Required",428:"428 Precondition Required",429:"429 Too Many Requests",431:"431 Request Header Fields Too Large",500:"500 Internal Server Error",501:"501 Not Implemented",502:"502 Bad Gateway",503:"503 Service Unavailable",504:"504 Gateway Timeout",505:"505 HTTP Version Not Supported",506:"506 Variant Also Negotiates",507:"507 Insufficient Storage",508:"508 Loop Detected",510:"510 Not Extended",511:"511 Network Authentication Required"};t.module("ngSails.$sails",["ngSails.$sailsIo","ngSails.$sailsInterceptor"]).provider("$sails",f),f.$inject=["$sailsInterceptorProvider","$sailsIoProvider"],t.module("ngSails.$sailsInterceptor",[]).provider("$sailsInterceptor",l),t.module("ngSails.$sailsIo",["ngSails.sailsSdk","ngSails.socketIo"]).provider("$sailsIo",h),t.module("ngSails.sailsSdk",[]).constant("sailsSdk",{info:{version:{key:"__sails_io_sdk_version",value:"0.11.0"},platform:{key:"__sails_io_sdk_platform",value:"undefined"==typeof module?"browser":"node"},language:{key:"__sails_io_sdk_language",value:"javascript"}},versionString:function(){var e=this;return function(){var n=[];return t.forEach(e.info,function(e){n.push(e.key+"="+e.value)}),n.join("&")}()}}),t.module("ngSails.socketIo",[]).factory("socketIo",p),p.$inject=["$window"]}(window,window.angular); |
@@ -0,1 +1,3 @@ | ||
'use strict'; | ||
var pkg = require('./package.json'); | ||
@@ -10,4 +12,3 @@ | ||
'bower_components/angular-mocks/angular-mocks.js', | ||
'mock/socket-io.js', | ||
'bower_components/sails.io.js/sails.io.js' | ||
'mock/socket-io.js' | ||
], | ||
@@ -33,3 +34,3 @@ 'karma-build': [ | ||
src: [ | ||
'src/**/*.js', | ||
'src/**/*.js' | ||
] | ||
@@ -36,0 +37,0 @@ }; |
104
gulpfile.js
'use strict'; | ||
var gulp = require('gulp'), | ||
concat = require('gulp-concat'), | ||
uglify = require('gulp-uglify'), | ||
header = require('gulp-header'), | ||
footer = require('gulp-footer'), | ||
ngAnnotate = require('gulp-ng-annotate'), | ||
gulpKarma = require('gulp-karma'), | ||
pkg = require('./package.json'), | ||
files = require('./files'); | ||
var gulp = require('gulp'); | ||
var jshint = require('gulp-jshint'); | ||
var ngAnnotate = require('gulp-ng-annotate'); | ||
var uglify = require('gulp-uglifyjs'); | ||
var concat = require('gulp-concat'); | ||
var wrap = require('gulp-wrap'); | ||
var header = require('gulp-header'); | ||
var bump = require('gulp-bump'); | ||
var gulpKarma = require('gulp-karma'); | ||
var gulpSequence = require('gulp-sequence').use(gulp); | ||
var pkg = require('./package.json'); | ||
var files = require('./files'); | ||
var karmaTestConfig = gulpKarma({configFile: 'karma.conf.js', action: 'run'}); | ||
var karmaTestConfig = gulpKarma({ | ||
configFile: 'karma.conf.js', | ||
action: 'run' | ||
}); | ||
var banner = '/*!\n' + | ||
' * <%= pkg.name %>\n' + | ||
' * <%= pkg.description %>\n' + | ||
' * @version v<%= pkg.version %>\n' + | ||
' * @link <%= pkg.homepage %>\n' + | ||
' * @license MIT License, http://www.opensource.org/licenses/MIT\n' + | ||
' */\n'; | ||
gulp.task('build-js', function () { | ||
return gulp.src(files.mergeFilesFor('src')) | ||
.pipe(ngAnnotate()) | ||
.pipe(concat(pkg.name+'.js')) | ||
.pipe(header('(function (angular, io) {\n\'use strict\'')) | ||
.pipe(footer('}(angular, io));')) | ||
.pipe(gulp.dest('./build/')) | ||
.pipe(concat(pkg.name+'.min.js')) | ||
.pipe(uglify()) | ||
.pipe(gulp.dest('./build/')); | ||
gulp.task('bump', function() { | ||
return gulp.src('./*.json') | ||
.pipe(bump({ | ||
type: 'minor' | ||
})) | ||
.pipe(gulp.dest('./')); | ||
}); | ||
gulp.task('dist-js', ['build-js'], function () { | ||
return gulp.src('./build/*.js') | ||
gulp.task('updatePkg', function(){ | ||
pkg = require('./package.json'); | ||
}); | ||
gulp.task('buildDev', function() { | ||
return gulp.src(files.mergeFilesFor('src')) | ||
.pipe(jshint()) | ||
.pipe(jshint.reporter('default')) | ||
.pipe(jshint.reporter('fail')) | ||
.pipe(concat(pkg.name + '.js')) | ||
.pipe(ngAnnotate()) | ||
.pipe(wrap('(function(window, angular, undefined){<%= contents %>})(window, window.angular);')) | ||
.pipe(header(banner, { | ||
pkg: pkg | ||
})) | ||
.pipe(gulp.dest('./build/')); | ||
}); | ||
gulp.task('minBuild', function() { | ||
return gulp.src('./build/' + pkg.name + '.js') | ||
.pipe(uglify(pkg.name + '.min.js', { | ||
outSourceMap: false, | ||
mangle: true, | ||
preserveComments: 'some' | ||
})) | ||
.pipe(header(banner, { | ||
pkg: pkg | ||
})) | ||
.pipe(gulp.dest('./build/')); | ||
}); | ||
gulp.task('copyBuild', function() { | ||
return gulp.src('./build/*.js') | ||
.pipe(gulp.dest('./dist/')); | ||
}); | ||
gulp.task('test', function () { | ||
return gulp.src(files.mergeFilesFor('karma-src')).pipe(karmaTestConfig); | ||
gulp.task('default', function() { | ||
return gulp.watch(files.mergeFilesFor('src'), ['test']); | ||
}); | ||
gulp.task('test-build', ['build-js'], function () { | ||
return gulp.src(files.mergeFilesFor('karma-build')).pipe(karmaTestConfig); | ||
gulp.task('test', function() { | ||
return gulp.src(files.mergeFilesFor('karma-src')).pipe(karmaTestConfig); | ||
}); | ||
gulp.task('test-min', ['build-js'], function () { | ||
return gulp.src(files.mergeFilesFor('karma-min')).pipe(karmaTestConfig); | ||
gulp.task('testBuild', function() { | ||
return gulp.src(files.mergeFilesFor('karma-build')).pipe(karmaTestConfig); | ||
}); | ||
gulp.task('watch', function () { | ||
return gulp.watch('src/**/*.js', ['build-js']); | ||
gulp.task('testMin', function() { | ||
return gulp.src(files.mergeFilesFor('karma-min')).pipe(karmaTestConfig); | ||
}); | ||
gulp.task('default', ['build-js', 'watch']); | ||
gulp.task('build', gulpSequence('buildDev', 'minBuild', ['testBuild', 'testMin'])); | ||
gulp.task('release', gulpSequence('bump', 'updatePkg', 'build', 'copyBuild')); |
// Karma configuration | ||
// Generated on Thu Jan 09 2014 13:59:16 GMT-0500 (EST) | ||
'use strict'; | ||
module.exports = function (config) { | ||
@@ -5,0 +5,0 @@ config.set({ |
@@ -0,28 +1,29 @@ | ||
'use strict'; | ||
// fix for phantomjs < 2.0 | ||
if (!Function.prototype.bind) { | ||
Function.prototype.bind = function(oThis) { | ||
if (typeof this !== 'function') { | ||
// closest thing possible to the ECMAScript 5 | ||
// internal IsCallable function | ||
throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable'); | ||
} | ||
Function.prototype.bind = function(oThis) { | ||
if (typeof this !== 'function') { | ||
// closest thing possible to the ECMAScript 5 | ||
// internal IsCallable function | ||
throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable'); | ||
} | ||
var aArgs = Array.prototype.slice.call(arguments, 1), | ||
fToBind = this, | ||
fNOP = function() {}, | ||
fBound = function() { | ||
return fToBind.apply(this instanceof fNOP && oThis ? this : oThis, | ||
aArgs.concat(Array.prototype.slice.call(arguments))); | ||
}; | ||
var aArgs = Array.prototype.slice.call(arguments, 1), | ||
fToBind = this, | ||
FNOP = function() {}, | ||
fBound = function() { | ||
return fToBind.apply(this instanceof FNOP && oThis ? this : oThis, | ||
aArgs.concat(Array.prototype.slice.call(arguments))); | ||
}; | ||
fNOP.prototype = this.prototype; | ||
fBound.prototype = new fNOP(); | ||
FNOP.prototype = this.prototype; | ||
fBound.prototype = new FNOP(); | ||
return fBound; | ||
}; | ||
return fBound; | ||
}; | ||
} | ||
function io() { | ||
var mockSocketObject = createMockSocketObject(); | ||
return mockSocketObject.connect(); | ||
var mockSocketObject = createMockSocketObject(); | ||
return mockSocketObject.connect(); | ||
} | ||
@@ -32,61 +33,61 @@ | ||
var socket = { | ||
on: function(ev, fn) { | ||
(this._listeners[ev] = this._listeners[ev] || []).push(fn); | ||
}, | ||
once: function(ev, fn) { | ||
(this._listeners[ev] = this._listeners[ev] || []).push(fn); | ||
fn._once = true; | ||
}, | ||
emit: function(ev, data) { | ||
if (this._listeners[ev]) { | ||
var args = arguments; | ||
this._listeners[ev].forEach(function(listener) { | ||
if (listener._once) { | ||
this.removeListener(ev, listener); | ||
} | ||
listener.apply(null, Array.prototype.slice.call(args, 1)); | ||
}.bind(this)); | ||
var socket = { | ||
on: function(ev, fn) { | ||
(this._listeners[ev] = this._listeners[ev] || []).push(fn); | ||
}, | ||
once: function(ev, fn) { | ||
(this._listeners[ev] = this._listeners[ev] || []).push(fn); | ||
fn._once = true; | ||
}, | ||
emit: function(ev, data) { | ||
if (this._listeners[ev]) { | ||
var args = arguments; | ||
this._listeners[ev].forEach(function(listener) { | ||
if (listener._once) { | ||
this.removeListener(ev, listener); | ||
} | ||
listener.apply(null, Array.prototype.slice.call(args, 1)); | ||
}.bind(this)); | ||
} | ||
}, | ||
_listeners: {}, | ||
removeListener: function(ev, fn) { | ||
if (fn) { | ||
var index = this._listeners[ev].indexOf(fn); | ||
if (index > -1) { | ||
this._listeners[ev].splice(index, 1); | ||
} | ||
} else { | ||
delete this._listeners[ev]; | ||
} | ||
}, | ||
off: function(ev, fn) { | ||
if (fn) { | ||
var index = this._listeners[ev].indexOf(fn); | ||
if (index > -1) { | ||
this._listeners[ev].splice(index, 1); | ||
} | ||
}, | ||
_listeners: {}, | ||
removeListener: function(ev, fn) { | ||
if (fn) { | ||
var index = this._listeners[ev].indexOf(fn); | ||
if (index > -1) { | ||
this._listeners[ev].splice(index, 1); | ||
} | ||
} else { | ||
delete this._listeners[ev]; | ||
} | ||
}, | ||
off: function(ev, fn) { | ||
if (fn) { | ||
var index = this._listeners[ev].indexOf(fn); | ||
if (index > -1) { | ||
this._listeners[ev].splice(index, 1); | ||
} | ||
} else { | ||
delete this._listeners[ev]; | ||
} | ||
}, | ||
removeAllListeners: function(ev) { | ||
if (ev) { | ||
delete this._listeners[ev]; | ||
} else { | ||
this._listeners = {}; | ||
} | ||
}, | ||
disconnect: function() { | ||
this.connected = false; | ||
this.emit('disconnect'); | ||
}, | ||
connect: function() { | ||
this.connected = true; | ||
this.emit('connect'); | ||
return this; | ||
} else { | ||
delete this._listeners[ev]; | ||
} | ||
}; | ||
}, | ||
removeAllListeners: function(ev) { | ||
if (ev) { | ||
delete this._listeners[ev]; | ||
} else { | ||
this._listeners = {}; | ||
} | ||
}, | ||
disconnect: function() { | ||
this.connected = false; | ||
this.emit('disconnect'); | ||
}, | ||
connect: function() { | ||
this.connected = true; | ||
this.emit('connect'); | ||
return this; | ||
} | ||
}; | ||
return socket; | ||
return socket; | ||
} |
{ | ||
"name": "angular-sails", | ||
"version": "1.1.4", | ||
"version": "2.0.0-beta.4", | ||
"description": "An angular provider for using the sails socket.io api", | ||
"scripts": { | ||
"build": "gulp build-js", | ||
"build": "gulp build", | ||
"test": "gulp test" | ||
}, | ||
"main": "index.js", | ||
"main": "dist/angular-sails.js", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/janpantel/angular-sails.git" | ||
"url": "https://github.com/kyjan/angular-sails.git" | ||
}, | ||
"author": "Jan-Oliver Pantel <info@janpantel.de>", | ||
"author": "Jan-Oliver Pantel <jan.pantel@gmail.com>", | ||
"contributors": [ | ||
"Jan-Oliver Pantel <jan.pantel@gmail.com>", | ||
"Evan Sharp <dumbdrum@gmail.com>" | ||
], | ||
"license": "MIT", | ||
"bugs": { | ||
"url": "https://github.com/kyjan/angular-sails/issues" | ||
"url": "https://github.com/janpantel/angular-sails/issues" | ||
}, | ||
"homepage": "https://github.com/kyjan/angular-sails", | ||
"dependencies": { | ||
"angular": "^1.3.0", | ||
"sails.io.js": "^0.11.0" | ||
}, | ||
"homepage": "https://github.com/janpantel/angular-sails", | ||
"devDependencies": { | ||
"chai": "^1.10.0", | ||
"gulp": "^3.5.6", | ||
"gulp-bump": "^0.1.13", | ||
"gulp-concat": "^2.2.0", | ||
"gulp-footer": "^1.0.4", | ||
"gulp-header": "^1.0.2", | ||
"gulp-jshint": "^1.9.2", | ||
"gulp-karma": "0.0.4", | ||
"gulp-ng-annotate": "^0.3.3", | ||
"gulp-uglify": "^0.2.1", | ||
"gulp-sequence": "^0.3.2", | ||
"gulp-uglifyjs": "^0.6.0", | ||
"gulp-wrap": "^0.11.0", | ||
"karma": "^0.12.21", | ||
@@ -34,0 +37,0 @@ "karma-chai-sinon": "^0.1.4", |
@@ -1,2 +0,2 @@ | ||
[![Build Status](https://travis-ci.org/janpantel/angular-sails.svg?branch=master)](https://travis-ci.org/janpantel/angular-sails) | ||
[![Build Status](https://travis-ci.org/janpantel/angular-sails.svg?branch=2.0)](https://travis-ci.org/janpantel/angular-sails) | ||
@@ -6,3 +6,3 @@ Angular Sails | ||
This small module allows you to use Sails.JS's awesome socket.io api with AngularJS. | ||
This module allows you to use Sails.JS's awesome socket.io api with AngularJS. | ||
@@ -16,9 +16,12 @@ Just add a dependency to your module and controllers and get it going! | ||
``` | ||
You must also include [sails.io.js](https://github.com/balderdashy/sails.io.js) in order to use this. | ||
You must also include [sails.io-client](https://github.com/automattic/socket.io-client) in order to use this. | ||
Switching from angular's `$http`? | ||
--------------------------------- | ||
Angular Sails is a drop-in replacement for Angular's `$http` service. If you are currently using `$http` with sailsjs then switching to sockets is a snap, just replace `$http` with `$sails`! | ||
Usage | ||
----- | ||
For a more complex example, have a look at the [tutorial by Maarten](https://github.com/maartendb/angular-sails-scrum-tutorial). | ||
A small example: | ||
@@ -40,6 +43,6 @@ | ||
$sails.get("/bars") | ||
.success(function (data, status, headers, jwr) { | ||
.success(function (data, status, headers, config) { | ||
$scope.bars = data; | ||
}) | ||
.error(function (data, status, headers, jwr) { | ||
.error(function (data, status, headers, config) { | ||
alert('Houston, we got a problem!'); | ||
@@ -57,3 +60,3 @@ }); | ||
// Watching for updates | ||
var barsHandler = $sails.on("bars", function (message) { | ||
$sails.on("bars", function (message) { | ||
if (message.verb === "created") { | ||
@@ -63,8 +66,2 @@ $scope.bars.push(message.data); | ||
}); | ||
// Stop watching for updates | ||
$scope.$on('$destroy', function() { | ||
$sails.off('bars', barsHandler); | ||
}); | ||
}()); | ||
@@ -78,5 +75,4 @@ }); | ||
### Sails.JS REST ### | ||
Angular Sails wraps the native sails.js REST functions. For further information check out [the sails docs](http://sailsjs.org/#!documentation/sockets) and [Mike's Screencast](http://www.youtube.com/watch?v=GK-tFvpIR7c) | ||
### Native socket functions ### | ||
The sails service is nothing more like the native socket.io object! | ||
Angular Sails mimics Angular's `$http` service to provide a drop-in socket replacement for http. | ||
For more information check out [angular's `$http` docs](https://docs.angularjs.org/api/ng/service/$http#usage)<br /> | ||
<small>Note: Angular Sails does not have a `jsonp` method as jsonp is a specific implementation of HTTP</small> |
@@ -1,2 +0,3 @@ | ||
/*global angular */ | ||
angular.module('ngSails', ['ng']); | ||
'use strict'; | ||
angular.module('ngSails', ['ngSails.$sails']); |
@@ -0,1 +1,3 @@ | ||
'use strict'; | ||
describe('Agnular Sails provider', function() { | ||
@@ -7,3 +9,4 @@ | ||
requestErrorSpy, | ||
responseErrorSpy; | ||
responseErrorSpy, | ||
socketRequestSpy, | ||
methods = ['get', 'post', 'put', 'delete'], | ||
@@ -23,7 +26,7 @@ response = { | ||
spy = sinon.spy(); | ||
requestSpy = sinon.spy(); | ||
responseSpy = sinon.spy(); | ||
requestErrorSpy = sinon.spy(); | ||
responseErrorSpy = sinon.spy(); | ||
socketRequestSpy = sinon.spy(); | ||
requestSpy = sinon.spy().named('requestSpy'); | ||
responseSpy = sinon.spy().named('responseSpy'); | ||
requestErrorSpy = sinon.spy().named('requestErrorSpy'); | ||
responseErrorSpy = sinon.spy().named('responseErrorSpy'); | ||
socketRequestSpy = sinon.spy().named('socketRequestSpy'); | ||
}); | ||
@@ -43,2 +46,5 @@ | ||
mockIoSocket = io(); | ||
$sailsProvider.socket = mockIoSocket; | ||
$sailsProvider.interceptors.push(function($q){ | ||
@@ -69,3 +75,2 @@ return { | ||
$sails = _$sails_; | ||
mockIoSocket = $sails._raw; | ||
@@ -119,3 +124,3 @@ mockIoSocket.on('get', function(ctx, cb){ | ||
request: function(config){ | ||
return $q.reject('rejected'); | ||
return $q.reject(config); | ||
} | ||
@@ -127,3 +132,3 @@ }; | ||
inject(function($rootScope, $sails) { | ||
$sails._raw.on('get', function(ctx, cb){ | ||
$sails._socket._socket.on('get', function(ctx, cb){ | ||
socketRequestSpy(); | ||
@@ -147,3 +152,3 @@ cb(response[ctx.url]); | ||
response: function(config){ | ||
return $q.reject('rejected'); | ||
return $q.reject(config); | ||
} | ||
@@ -156,3 +161,3 @@ }; | ||
var errorSpy = sinon.spy(); | ||
$sails._raw.on('get', function(ctx, cb){ | ||
$sails._socket._socket.on('get', function(ctx, cb){ | ||
socketRequestSpy(); | ||
@@ -179,3 +184,3 @@ cb(response[ctx.url]); | ||
expect(config.method).to.equal('POST'); | ||
expect(config.data).to.deep.equal({value: true}) | ||
expect(config.data).to.deep.equal({value: true}); | ||
spy(); | ||
@@ -190,3 +195,3 @@ return config; | ||
var errorSpy = sinon.spy(); | ||
$sails._raw.on('post', function(ctx, cb){ | ||
$sails._socket._socket.on('post', function(ctx, cb){ | ||
socketRequestSpy(); | ||
@@ -196,3 +201,3 @@ cb(response[ctx.url]); | ||
$sails.post('success',{value: true}); | ||
$sails.post('success', {value: true}); | ||
$rootScope.$digest(); | ||
@@ -222,4 +227,3 @@ | ||
var errorSpy = sinon.spy(); | ||
$sails._raw.on('post', function(ctx, cb){ | ||
expect(ctx.method).to.equal('post'); | ||
$sails._socket._socket.on('post', function(ctx, cb){ | ||
expect(ctx.url).to.equal('success'); | ||
@@ -231,3 +235,3 @@ expect(ctx.data).to.deep.equal({value: true}); | ||
$sails.get('error', {value: false}); | ||
$sails.get('error'); | ||
$rootScope.$digest(); | ||
@@ -277,3 +281,3 @@ | ||
inject(function($rootScope, $sails) { | ||
$sails._raw.on('get', function(ctx, cb){ | ||
$sails._socket._socket.on('get', function(ctx, cb){ | ||
cb(response.success); | ||
@@ -283,6 +287,6 @@ }); | ||
$sails.get('success').then(function(res){ | ||
expect(res.method).to.equal('GET'); | ||
expect(res.url).to.equal('successOuterInner'); | ||
expect(res.config.method).to.equal('GET'); | ||
expect(res.config.url).to.equal('successOuterInner'); | ||
expect(res.data).to.equal('{{Success!} inner} outer'); | ||
spy() | ||
spy(); | ||
}); | ||
@@ -289,0 +293,0 @@ $rootScope.$digest(); |
@@ -0,1 +1,3 @@ | ||
'use strict'; | ||
describe('Agnular Sails service', function() { | ||
@@ -24,3 +26,3 @@ | ||
$sails = _$sails_; | ||
mockIoSocket = $sails._raw; | ||
mockIoSocket = $sails._socket._socket; | ||
spy = sinon.spy(); | ||
@@ -54,6 +56,6 @@ })); | ||
it('should queue up requests', function () { | ||
var getSpy = sinon.spy(), | ||
postSpy = sinon.spy(), | ||
getCbSpy = sinon.spy(), | ||
postCbSpy = sinon.spy(); | ||
var getSpy = sinon.spy().named('getSpy'), | ||
postSpy = sinon.spy().named('postSpy'), | ||
getCbSpy = sinon.spy().named('getCbSpy'), | ||
postCbSpy = sinon.spy().named('postCbSpy'); | ||
@@ -83,25 +85,19 @@ $sails.disconnect(); | ||
/* TODO: Someone determine how to test this | ||
Because `$sails.connect()` automatically runs the queued calls on the new socket, | ||
We cannot grab the other end of the new socket to watch for the calls and respond | ||
to the calls.... This makes this really hard to test. In fact, from what I can | ||
tell impossible to test. | ||
*/ | ||
// mockIoSocket = $sails._raw; | ||
// | ||
// mockIoSocket.on('get', function(ctx, cb){ | ||
// getSpy(); | ||
// cb(response[ctx.url]); | ||
// }); | ||
// mockIoSocket.on('post', function(ctx, cb){ | ||
// postSpy(); | ||
// cb(response[ctx.url]); | ||
// }); | ||
// | ||
// $scope.$digest(); | ||
// | ||
// expect(getSpy).to.have.been.calledOnce; | ||
// expect(postSpy).to.have.been.calledOnce; | ||
// expect(getCbSpy).to.have.been.calledOnce; | ||
// expect(postCbSpy).to.have.been.calledOnce; | ||
mockIoSocket = $sails._socket._socket; | ||
mockIoSocket.on('get', function(ctx, cb){ | ||
getSpy(); | ||
cb(response[ctx.url]); | ||
}); | ||
mockIoSocket.on('post', function(ctx, cb){ | ||
postSpy(); | ||
cb(response[ctx.url]); | ||
}); | ||
$scope.$digest(); | ||
expect(getSpy).to.have.been.calledOnce; | ||
expect(postSpy).to.have.been.calledOnce; | ||
expect(getCbSpy).to.have.been.calledOnce; | ||
expect(postCbSpy).to.have.been.calledOnce; | ||
}); | ||
@@ -123,94 +119,5 @@ | ||
}); | ||
it('should allow multiple listeners for the same event', function () { | ||
var eventSpy = sinon.spy() | ||
$sails.on('event', spy); | ||
$sails.on('event', eventSpy); | ||
mockIoSocket.emit('event'); | ||
$scope.$digest(); | ||
expect(spy).to.have.been.calledOnce; | ||
expect(eventSpy).to.have.been.calledOnce; | ||
}); | ||
it('should call the correct lisener', function () { | ||
var eventSpy = sinon.spy() | ||
$sails.on('event', spy); | ||
$sails.on('anotherEvent', eventSpy); | ||
mockIoSocket.emit('event'); | ||
$scope.$digest(); | ||
expect(spy).to.have.been.calledOnce; | ||
expect(eventSpy).to.have.not.been.called; | ||
}); | ||
}); | ||
describe('off', function() { | ||
describe('by event name only', function(){ | ||
it('should remove all event listener by the given name', function () { | ||
var eventSpy = sinon.spy() | ||
$sails.on('event', spy); | ||
$sails.on('event', eventSpy); | ||
$sails.off('event'); | ||
mockIoSocket.emit('event'); | ||
$scope.$digest(); | ||
expect(spy).to.have.not.been.called; | ||
expect(eventSpy).to.have.not.been.called; | ||
}); | ||
it('should only the listeners that match the given event name', function () { | ||
var eventSpy = sinon.spy() | ||
var anotherEventSpy = sinon.spy() | ||
$sails.on('event', spy); | ||
$sails.on('event', eventSpy); | ||
$sails.on('anotherEvent', anotherEventSpy); | ||
$sails.off('event'); | ||
mockIoSocket.emit('event'); | ||
mockIoSocket.emit('anotherEvent'); | ||
$scope.$digest(); | ||
expect(spy).to.have.not.been.called; | ||
expect(eventSpy).to.have.not.been.called; | ||
expect(anotherEventSpy).to.have.been.calledOnce; | ||
}); | ||
}); | ||
describe('by event name and function', function(){ | ||
it('should remove the listener with that function', function () { | ||
var listener = $sails.on('event', spy); | ||
$sails.off('event', listener); | ||
mockIoSocket.emit('event'); | ||
$scope.$digest(); | ||
expect(spy).to.have.not.been.called; | ||
}); | ||
it('should only remove the listener with the function', function () { | ||
var eventSpy = sinon.spy() | ||
var anotherEventSpy = sinon.spy() | ||
$sails.on('event', spy); | ||
var listner = $sails.on('event', eventSpy); | ||
$sails.on('anotherEvent', anotherEventSpy); | ||
$sails.off('event', listner); | ||
mockIoSocket.emit('event'); | ||
mockIoSocket.emit('anotherEvent'); | ||
$scope.$digest(); | ||
expect(eventSpy).to.have.not.been.called; | ||
expect(spy).to.have.been.calledOnce; | ||
expect(anotherEventSpy).to.have.been.calledOnce; | ||
}); | ||
}); | ||
}); | ||
describe('once', function () { | ||
@@ -284,3 +191,3 @@ | ||
}); | ||
errorSpy = sinon.spy(); | ||
errorSpy = sinon.spy().named('errorSpy'); | ||
}); | ||
@@ -287,0 +194,0 @@ |
Sorry, the diff of this file is not supported yet
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
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
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
83754
0
25
1976
20
1
73
1
- Removedangular@^1.3.0
- Removedsails.io.js@^0.11.0
- Removedangular@1.8.3(transitive)
- Removedasn1@0.1.11(transitive)
- Removedassert-plus@0.1.5(transitive)
- Removedasync@0.9.2(transitive)
- Removedaws-sign2@0.5.0(transitive)
- Removedboom@0.4.2(transitive)
- Removedcombined-stream@0.0.7(transitive)
- Removedcryptiles@0.2.2(transitive)
- Removedctype@0.5.3(transitive)
- Removeddelayed-stream@0.0.5(transitive)
- Removedforever-agent@0.5.2(transitive)
- Removedform-data@0.1.4(transitive)
- Removedhawk@1.0.0(transitive)
- Removedhoek@0.9.1(transitive)
- Removedhttp-signature@0.10.1(transitive)
- Removedjson-stringify-safe@5.0.1(transitive)
- Removedmime@1.2.11(transitive)
- Removednode-uuid@1.4.8(transitive)
- Removedoauth-sign@0.3.0(transitive)
- Removedqs@0.6.6(transitive)
- Removedrequest@2.34.0(transitive)
- Removedsails.io.js@0.11.7(transitive)
- Removedsntp@0.2.4(transitive)
- Removedtldts@6.1.58(transitive)
- Removedtldts-core@6.1.58(transitive)
- Removedtough-cookie@5.0.0(transitive)
- Removedtunnel-agent@0.3.0(transitive)