Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

absync

Package Overview
Dependencies
Maintainers
1
Versions
61
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

absync - npm Package Compare versions

Comparing version 3.1.0 to 3.2.0

118

dist/development/absync.concat.js

@@ -59,2 +59,4 @@ (function() {

self.__registerLater = [];
// References to all registered event listeners.
self.__listeners = [];

@@ -124,5 +126,36 @@ // The collections that absync provides.

/**
* Detaches absync from the websocket.
* @param {Boolean} [disconnectSocket=false] Should the underlying socket.io connection be disconnected as well?
*/
AbsyncProvider.prototype.disconnect = function AbsyncProvider$disconnect( disconnectSocket ) {
var self = this;
disconnectSocket = disconnectSocket || false;
angular.forEach( self.__listeners, function unregisterListener( listener ) {
listener.unregister();
delete listener.unregister;
self.__registerLater.push( listener );
} );
if( disconnectSocket ) {
self.__ioSocket.disconnect();
self.__ioSocket = null;
}
};
/**
* Register an event listener with socket.io.
* @param {Object} listener
* @private
*/
AbsyncProvider.prototype.__registerListener = function AbsyncProvider$registerListener( listener ) {
var self = this;
self.$get().__handleEntityEvent( listener.eventName, listener.callback );
// Remember this listener.
self.__listeners.push( listener );
// Register the listener and remember the function to use when the listener should be unregistered.
listener.unregister = self.__handleEntityEvent( listener.eventName, listener.callback );
};

@@ -196,36 +229,4 @@

/**
* Register the service factory.
* @returns {AbsyncService}
* @ngInject
*/
AbsyncProvider.prototype.$get = function AbsyncProvider$$get() {
return new AbsyncService( this );
};
/**
* The service that is received when injecting "absync".
* This service is primarily used internally to set up the connection between socket.io and the individual
* caching services.
* @param {AbsyncProvider|Object} parentProvider The AbsyncProvider that provides this service.
* @constructor
*/
function AbsyncService( parentProvider ) {
this.__absyncProvider = parentProvider;
}
/**
* Configure the socket.io connection for absync.
* This configuration of absync should usually be performed through the absyncProvider in the configuration
* phase of a module.
* @param {Object} configuration The configuration for the absync provider.
* Can have a member `socket`, pointing to the socket.io instance or constructor to use.
* Can have a member `debug`, enabling debugging, if set to true.
*/
AbsyncService.prototype.configure = function AbsyncService$configure( configuration ) {
var _absyncProvider = this.__absyncProvider;
_absyncProvider.configure( configuration );
};
/**
* Register an event listener that is called when a specific entity is received on the websocket.

@@ -238,10 +239,9 @@ * @param {String} eventName The event name, usually the name of the entity.

*/
AbsyncService.prototype.on = function AbsyncService$on( eventName, callback ) {
var _absyncProvider = this.__absyncProvider;
var self = this;
AbsyncProvider.prototype.on = function AbsyncProvider$on( eventName, callback ) {
var self = this;
// If we have no configured socket.io connection yet, remember to register it later.
if( !_absyncProvider.__ioSocket ) {
if( !self.__ioSocket ) {
if( _absyncProvider.__registerLater.length > 8192 ) {
if( self.__registerLater.length > 8192 ) {
// Be defensive, something is probably not right here.

@@ -252,3 +252,3 @@ return null;

// TODO: Use promises here, so that we can always return the event listener removal function.
_absyncProvider.__registerLater.push( {
self.__registerLater.push( {
eventName : eventName,

@@ -260,3 +260,6 @@ callback : callback

return self.__handleEntityEvent( eventName, callback );
return self.__registerListener( {
eventName : eventName,
callback : callback
} );
};

@@ -270,11 +273,11 @@

*/
AbsyncService.prototype.__handleEntityEvent = function AbsyncService$handleEntityEvent( eventName, callback ) {
var _absyncProvider = this.__absyncProvider;
AbsyncProvider.prototype.__handleEntityEvent = function AbsyncProvider$handleEntityEvent( eventName, callback ) {
var self = this;
// Register the callback with socket.io.
_absyncProvider.__ioSocket.on( eventName, callback );
self.__ioSocket.on( eventName, callback );
// Return a function that removes the listener.
return function removeListener() {
_absyncProvider.__ioSocket.removeListener( eventName, callback );
self.__ioSocket.removeListener( eventName, callback );
};

@@ -284,3 +287,3 @@ };

/**
* Convenience method to allow the user to emit() from the websocket.
* Convenience method to allow the user to emit() from the socket.io connection.
* This is not utilized in absync internally.

@@ -291,15 +294,24 @@ * @param {String} eventName

*/
AbsyncService.prototype.emit = function AbsyncService$emit( eventName, data, callback ) {
var _absyncProvider = this.__absyncProvider;
AbsyncProvider.prototype.emit = function AbsyncProvider$emit( eventName, data, callback ) {
var self = this;
if( !_absyncProvider.__ioSocket ) {
if( !self.__ioSocket ) {
throw new Error( "socket.io is not initialized." );
}
_absyncProvider.__ioSocket.emit( eventName, data, function afterEmit() {
self.__ioSocket.emit( eventName, data, function afterEmit() {
if( callback ) {
callback.apply( _absyncProvider.__ioSocket, arguments );
callback.apply( self.__ioSocket, arguments );
}
} );
};
/**
* The service is just used as a convenience to access the provider.
* @returns {AbsyncProvider}
* @ngInject
*/
AbsyncProvider.prototype.$get = function AbsyncProvider$$get() {
return this;
};
}());;(function() {

@@ -341,3 +353,3 @@ "use strict";

* @param {angular.IRootScopeService|Object} $rootScope
* @param {AbsyncService} absync
* @param {AbsyncProvider} absync
* @param {Object} absyncNoopLog A log interface that does nothing.

@@ -348,4 +360,4 @@ * @param {Object} absyncUncachedFilter A filter that mutates URLs so they will bypass the browser cache.

*/
CacheService.$inject = ["$http", "$injector", "$log", "$q", "$rootScope", "absync", "absyncNoopLog", "absyncUncachedFilter"];
function CacheService( $http, $injector, $log, $q, $rootScope, absync, absyncNoopLog, absyncUncachedFilter ) {
CacheService.$inject = ["$http", "$injector", "$log", "$q", "$rootScope", "absyncNoopLog", "absync", "absyncUncachedFilter"];
function CacheService( $http, $injector, $log, $q, $rootScope, absyncNoopLog, absync, absyncUncachedFilter ) {
var self = this;

@@ -352,0 +364,0 @@

@@ -54,2 +54,4 @@ (function() {

self.__registerLater = [];
// References to all registered event listeners.
self.__listeners = [];

@@ -119,5 +121,36 @@ // The collections that absync provides.

/**
* Detaches absync from the websocket.
* @param {Boolean} [disconnectSocket=false] Should the underlying socket.io connection be disconnected as well?
*/
AbsyncProvider.prototype.disconnect = function AbsyncProvider$disconnect( disconnectSocket ) {
var self = this;
disconnectSocket = disconnectSocket || false;
angular.forEach( self.__listeners, function unregisterListener( listener ) {
listener.unregister();
delete listener.unregister;
self.__registerLater.push( listener );
} );
if( disconnectSocket ) {
self.__ioSocket.disconnect();
self.__ioSocket = null;
}
};
/**
* Register an event listener with socket.io.
* @param {Object} listener
* @private
*/
AbsyncProvider.prototype.__registerListener = function AbsyncProvider$registerListener( listener ) {
var self = this;
self.$get().__handleEntityEvent( listener.eventName, listener.callback );
// Remember this listener.
self.__listeners.push( listener );
// Register the listener and remember the function to use when the listener should be unregistered.
listener.unregister = self.__handleEntityEvent( listener.eventName, listener.callback );
};

@@ -191,36 +224,4 @@

/**
* Register the service factory.
* @returns {AbsyncService}
* @ngInject
*/
AbsyncProvider.prototype.$get = function AbsyncProvider$$get() {
return new AbsyncService( this );
};
/**
* The service that is received when injecting "absync".
* This service is primarily used internally to set up the connection between socket.io and the individual
* caching services.
* @param {AbsyncProvider|Object} parentProvider The AbsyncProvider that provides this service.
* @constructor
*/
function AbsyncService( parentProvider ) {
this.__absyncProvider = parentProvider;
}
/**
* Configure the socket.io connection for absync.
* This configuration of absync should usually be performed through the absyncProvider in the configuration
* phase of a module.
* @param {Object} configuration The configuration for the absync provider.
* Can have a member `socket`, pointing to the socket.io instance or constructor to use.
* Can have a member `debug`, enabling debugging, if set to true.
*/
AbsyncService.prototype.configure = function AbsyncService$configure( configuration ) {
var _absyncProvider = this.__absyncProvider;
_absyncProvider.configure( configuration );
};
/**
* Register an event listener that is called when a specific entity is received on the websocket.

@@ -233,10 +234,9 @@ * @param {String} eventName The event name, usually the name of the entity.

*/
AbsyncService.prototype.on = function AbsyncService$on( eventName, callback ) {
var _absyncProvider = this.__absyncProvider;
var self = this;
AbsyncProvider.prototype.on = function AbsyncProvider$on( eventName, callback ) {
var self = this;
// If we have no configured socket.io connection yet, remember to register it later.
if( !_absyncProvider.__ioSocket ) {
if( !self.__ioSocket ) {
if( _absyncProvider.__registerLater.length > 8192 ) {
if( self.__registerLater.length > 8192 ) {
// Be defensive, something is probably not right here.

@@ -247,3 +247,3 @@ return null;

// TODO: Use promises here, so that we can always return the event listener removal function.
_absyncProvider.__registerLater.push( {
self.__registerLater.push( {
eventName : eventName,

@@ -255,3 +255,6 @@ callback : callback

return self.__handleEntityEvent( eventName, callback );
return self.__registerListener( {
eventName : eventName,
callback : callback
} );
};

@@ -265,11 +268,11 @@

*/
AbsyncService.prototype.__handleEntityEvent = function AbsyncService$handleEntityEvent( eventName, callback ) {
var _absyncProvider = this.__absyncProvider;
AbsyncProvider.prototype.__handleEntityEvent = function AbsyncProvider$handleEntityEvent( eventName, callback ) {
var self = this;
// Register the callback with socket.io.
_absyncProvider.__ioSocket.on( eventName, callback );
self.__ioSocket.on( eventName, callback );
// Return a function that removes the listener.
return function removeListener() {
_absyncProvider.__ioSocket.removeListener( eventName, callback );
self.__ioSocket.removeListener( eventName, callback );
};

@@ -279,3 +282,3 @@ };

/**
* Convenience method to allow the user to emit() from the websocket.
* Convenience method to allow the user to emit() from the socket.io connection.
* This is not utilized in absync internally.

@@ -286,15 +289,24 @@ * @param {String} eventName

*/
AbsyncService.prototype.emit = function AbsyncService$emit( eventName, data, callback ) {
var _absyncProvider = this.__absyncProvider;
AbsyncProvider.prototype.emit = function AbsyncProvider$emit( eventName, data, callback ) {
var self = this;
if( !_absyncProvider.__ioSocket ) {
if( !self.__ioSocket ) {
throw new Error( "socket.io is not initialized." );
}
_absyncProvider.__ioSocket.emit( eventName, data, function afterEmit() {
self.__ioSocket.emit( eventName, data, function afterEmit() {
if( callback ) {
callback.apply( _absyncProvider.__ioSocket, arguments );
callback.apply( self.__ioSocket, arguments );
}
} );
};
/**
* The service is just used as a convenience to access the provider.
* @returns {AbsyncProvider}
* @ngInject
*/
AbsyncProvider.prototype.$get = function AbsyncProvider$$get() {
return this;
};
}());

@@ -37,3 +37,3 @@ (function() {

* @param {angular.IRootScopeService|Object} $rootScope
* @param {AbsyncService} absync
* @param {AbsyncProvider} absync
* @param {Object} absyncNoopLog A log interface that does nothing.

@@ -44,4 +44,4 @@ * @param {Object} absyncUncachedFilter A filter that mutates URLs so they will bypass the browser cache.

*/
CacheService.$inject = ["$http", "$injector", "$log", "$q", "$rootScope", "absync", "absyncNoopLog", "absyncUncachedFilter"];
function CacheService( $http, $injector, $log, $q, $rootScope, absync, absyncNoopLog, absyncUncachedFilter ) {
CacheService.$inject = ["$http", "$injector", "$log", "$q", "$rootScope", "absyncNoopLog", "absync", "absyncUncachedFilter"];
function CacheService( $http, $injector, $log, $q, $rootScope, absyncNoopLog, absync, absyncUncachedFilter ) {
var self = this;

@@ -48,0 +48,0 @@

@@ -1,2 +0,2 @@

!function(){"use strict";angular.module("absync",[])}(),function(){"use strict";function e(e,n,r){return new t(e,n,r)}function t(e,t,n){var r=this;r.__injector=e,r.__provide=t,r.__absyncCache=n,r.__ioSocket=null,r.__registerLater=[],r.__collections={},r.__entities={},r.debug=void 0}function n(e){this.__absyncProvider=e}e.$inject=["$injector","$provide","absyncCache"],angular.module("absync").provider("absync",e),t.prototype.configure=function(e){var t=this;if("undefined"!=typeof e.socket){var n=e.socket,r="undefined"!=typeof io&&io.Socket&&n instanceof io.Socket;if("function"==typeof n)t.__ioSocket=new n;else{if(!r)throw new Error("configure() expects input to be a function or a socket.io Socket instance.");t.__ioSocket=n}t.__registerLater.length&&(angular.forEach(t.__registerLater,t.__registerListener.bind(t)),t.__registerLater=[])}"undefined"!=typeof e.debug&&(t.debug=e.debug||!1),t.debug&&(angular.forEach(t.__collections,function(e){e.configuration.debug=!0}),angular.forEach(t.__entities,function(e){e.configuration.debug=!0}))},t.prototype.__registerListener=function(e){var t=this;t.$get().__handleEntityEvent(e.eventName,e.callback)},t.prototype.collection=function(e,t){var n=this;if(n.__collections[e])throw new Error("A collection with the name '"+e+"' was already requested. Names for collections must be unique.");if(n.__entities[e])throw new Error("An entity with the name '"+e+"' was already requested. Names for collections must be unique and can't be shared with entities.");t.debug="undefined"==typeof t.debug?n.debug:t.debug,n.__collections[e]={constructor:n.__absyncCache(e,t),configuration:t},n.__provide.service(e,n.__collections[e].constructor)},t.prototype.entity=function(e,t){var n=this;if(n.__entities[e])throw new Error("An entity with the name '"+e+"' was already requested. Names for entities must be unique.");if(n.__collections[e])throw new Error("A collection with the name '"+e+"' was already requested. Names for entities must be unique and can't be shared with collections.");t.debug="undefined"==typeof t.debug?n.debug:t.debug,n.__entities[e]={constructor:n.__absyncCache(e,t),configuration:t},n.__provide.service(e,n.__entities[e].constructor)},t.prototype.$get=function(){return new n(this)},n.prototype.configure=function(e){var t=this.__absyncProvider;t.configure(e)},n.prototype.on=function(e,t){var n=this.__absyncProvider,r=this;return n.__ioSocket?r.__handleEntityEvent(e,t):n.__registerLater.length>8192?null:(n.__registerLater.push({eventName:e,callback:t}),null)},n.prototype.__handleEntityEvent=function(e,t){var n=this.__absyncProvider;return n.__ioSocket.on(e,t),function(){n.__ioSocket.removeListener(e,t)}},n.prototype.emit=function(e,t,n){var r=this.__absyncProvider;if(!r.__ioSocket)throw new Error("socket.io is not initialized.");r.__ioSocket.emit(e,t,function(){n&&n.apply(r.__ioSocket,arguments)})}}(),function(){"use strict";function e(e,n){function r(r,i,o,a,c,s,h,u){var l=this,y=n.injector||i,d=y.has(n.model);if(!d)throw new Error("Unable to construct the '"+e+"' service, because the referenced model '"+n.model+"' is not available for injection.");var f="string"==typeof n.model?y.get(n.model):n.model,_=f.serialize||n.serialize||t,p=f.deserialize||n.deserialize||t;l.name=e,l.configuration=n,l.entityCache=n.collectionName?[]:{},l.__entityCacheRaw=null,l.enableRequestCache=!0,l.__requestCache={},l.allowBrowserCache=(angular.merge||angular.extend)({},{sync:!0,request:!0},n.allowBrowserCache),l.__uncached=u,l.httpInterface=r,l.logInterface=n.debug?o:h,l.scope=c,l.q=a,l.logPrefix="absync:"+e.toLocaleUpperCase()+" ",l.forceEarlyCacheUpdate=!1,l.throwFailures=!0,l.serializer=_,l.deserializer=p,s.on(n.entityName,l.__onEntityOnWebsocket.bind(l)),n.collectionName&&s.on(n.collectionName,l.__onCollectionOnWebsocket.bind(l)),c.$on(n.entityName,l.__onEntityReceived.bind(l)),n.collectionName&&c.$on(n.collectionName,l.__onCollectionReceived.bind(l)),l.logInterface.info(l.logPrefix+"service was instantiated.")}function i(e,t){var r=this;if((e||r.forceEarlyCacheUpdate)&&t.data[n.entityName]){var i=t.data[n.entityName];if(r.forceEarlyCacheUpdate){var o=r.deserializer(i);if(r.__updateCacheWithEntity(o),e)return o}if(e)return i}}function o(e){var t=this;if(t.logInterface.error(t.logPrefix+"Unable to store entity on the server.",e),t.logInterface.error(e),t.scope.$emit("absyncError",e),t.throwFailures)throw e}return r.$inject=["$http","$injector","$log","$q","$rootScope","absync","absyncNoopLog","absyncUncachedFilter"],r.prototype.__onEntityOnWebsocket=function(e){var t=this;t.scope.$broadcast(n.entityName,e[n.entityName])},r.prototype.__onCollectionOnWebsocket=function(e){var t=this;t.scope.$broadcast(n.collectionName,e[n.collectionName])},r.prototype.__onDataAvailable=function(e){function t(e){r.entityCache.push(r.deserializer(e))}var r=this;if(Array.isArray(r.entityCache))angular.forEach(e[n.collectionName],t),r.scope.$broadcast("collectionNew",{service:r,cache:r.entityCache});else{var i=r.deserializer(e[n.entityName]);r.__updateCacheWithEntity(i)}return r.entityCache},r.prototype.__onEntityReceived=function(e,t){var n=this,r=t;return 1===Object.keys(r).length&&r.hasOwnProperty("id")?(n.logInterface.info(n.logPrefix+"Entity was deleted from the server. Updating cache…"),n.__removeEntityFromCache(r.id)):(n.logInterface.debug(n.logPrefix+"Entity was updated on the server. Updating cache…"),n.__updateCacheWithEntity(n.deserializer(r)))},r.prototype.__onCollectionReceived=function(e,t){function n(e){var t=r.deserializer(e);r.__updateCacheWithEntity(t)}var r=this,i=t;r.entityCache.length=0,angular.forEach(i,n)},r.prototype.ensureLoaded=function(e){function t(e){if(!e.data[n.collectionName])throw new Error("The response from the server was not in the expected format. It should have a member named '"+n.collectionName+"'.");return a.__entityCacheRaw=e.data,a.entityCache.splice(0,a.entityCache.length),a.__onDataAvailable(e.data)}function r(e){if(a.logInterface.error(a.logPrefix+"Unable to retrieve the collection from the server.",e),a.__entityCacheRaw=null,a.scope.$emit("absyncError",e),a.throwFailures)throw e}function i(e){if(!e.data[n.entityName])throw new Error("The response from the server was not in the expected format. It should have a member named '"+n.entityName+"'.");a.__entityCacheRaw=e.data,a.__onDataAvailable(e.data)}function o(e){if(a.logInterface.error(a.logPrefix+"Unable to retrieve the entity from the server.",e),a.__entityCacheRaw=null,a.scope.$emit("absyncError",e),a.throwFailures)throw e}var a=this;return e=e===!0,null===a.__entityCacheRaw||e?n.collectionName&&n.collectionUri?(a.logInterface.info(a.logPrefix+"Retrieving '"+n.collectionName+"' collection…"),a.httpInterface.get(a.allowBrowserCache.sync?n.collectionUri:a.__uncached(n.collectionUri)).then(t,r)):n.entityName&&n.entityUri?a.httpInterface.get(a.allowBrowserCache.sync?n.entityUri:a.__uncached(n.entityUri)).then(i,o):a.q.when([]):a.q.when(a.entityCache)},r.prototype.seed=function(e){var t=this;return t.__entityCacheRaw=e,t.__onDataAvailable(t.__entityCacheRaw)},r.prototype.sync=function(){var e=this;return e.__entityCacheRaw=null,e.ensureLoaded(!0)},r.prototype.read=function(e,t){function r(e){if(!e.data[n.entityName])throw new Error("The response from the server was not in the expected format. It should have a member named '"+n.entityName+"'.");var t=o.deserializer(e.data[n.entityName]);return o.__updateCacheWithEntity(t),t}function i(t){if(o.logInterface.error(o.logPrefix+"Unable to retrieve entity with ID '"+e+"' from the server.",t),o.scope.$emit("absyncError",t),o.throwFailures)throw t}var o=this;if(t=t===!0,o.logInterface.debug(o.logPrefix+"Requesting entity '"+e+"' (forceReload:"+t+")…"),!t)for(var a=0,c=o.entityCache[0];a<o.entityCache.length;++a,c=o.entityCache[a])if(c.id===e)return o.logInterface.debug(o.logPrefix+"Requested entity '"+e+"' is served from cache."),o.q.when(c);return o.logInterface.debug(o.logPrefix+"Requested entity '"+e+"' is fetched from backend."),o.__requestEntity(e).then(r,i)},r.prototype.__requestEntity=function(e){function t(e,t){return delete r.__requestCache[e],t}var r=this;if(r.enableRequestCache&&r.__requestCache&&r.__requestCache[e])return r.logInterface.debug(r.logPrefix+"Entity request '"+e+"' served from request cache."),r.__requestCache[e];var i=n.entityUri+(e?"/"+e:""),o=r.httpInterface.get(r.allowBrowserCache.request?i:r.__uncached(i)).then(t.bind(r,e));return r.enableRequestCache&&r.__requestCache&&(r.__requestCache[e]=o),o},r.prototype.update=function(e,t){var r=this;t=t||!1;var a=r.reduceComplex(e),c=r.serializer(a),s={};return s[n.entityName]=c,"undefined"!=typeof e.id?r.httpInterface.put(n.entityUri+"/"+e.id,s).then(i.bind(r,t),o.bind(r)):r.httpInterface.post(n.collectionUri,s).then(i.bind(r,t),o.bind(r))},r.prototype.patch=function(e){var t=this,r=t.reduceComplex(e),a=t.serializer(r),c={};if(c[n.entityName]=a,"undefined"!=typeof e.id)return t.httpInterface.patch(n.entityUri+"/"+e.id,c).then(i.bind(t),o.bind(t));throw new Error("Attempted to patch an entity that was never stored on the server.")},r.prototype.create=r.prototype.update,r.prototype["delete"]=function(e){function t(e){return i.__removeEntityFromCache(o)}function r(e){if(i.logInterface.error(e.data),i.scope.$emit("absyncError",e),i.throwFailures)throw e}var i=this,o=e.id;return i.httpInterface["delete"](n.entityUri+"/"+o).then(t)["catch"](r)},r.prototype.__updateCacheWithEntity=function(e){var t=this;if(t.logInterface.info(t.logPrefix+"Updating entity '"+(e.id||t.name)+"' in cache…",e),!Array.isArray(t.entityCache))return t.scope.$broadcast("beforeEntityUpdated",{service:t,cache:t.entityCache,entity:t.entityCache,updated:e}),"function"==typeof t.entityCache.copyFrom?t.entityCache.copyFrom(e):angular.extend(t.entityCache,e),void t.scope.$broadcast("entityUpdated",{service:t,cache:t.entityCache,entity:t.entityCache});for(var n=!1,r=0,i=t.entityCache[0];r<t.entityCache.length;++r,i=t.entityCache[r])if(i.id==e.id){t.scope.$broadcast("beforeEntityUpdated",{service:t,cache:t.entityCache,entity:t.entityCache[r],updated:e});var o=t.entityCache[r];"function"==typeof o.copyFrom?o.copyFrom(e):angular.extend(o,e),n=!0,t.scope.$broadcast("entityUpdated",{service:t,cache:t.entityCache,entity:t.entityCache[r]});break}n||(t.scope.$broadcast("beforeEntityNew",{service:t,cache:t.entityCache,entity:e}),t.entityCache.push(e),t.scope.$broadcast("entityNew",{service:t,cache:t.entityCache,entity:e}))},r.prototype.__removeEntityFromCache=function(e){for(var t=this,n=0,r=t.entityCache[0];n<t.entityCache.length;++n,r=t.entityCache[n])if(r.id==e){t.scope.$broadcast("beforeEntityRemoved",{service:t,cache:t.entityCache,entity:r}),t.entityCache.splice(n,1),t.scope.$broadcast("entityRemoved",{service:t,cache:t.entityCache,entity:r});break}},r.prototype.lookupTableById=function(){for(var e=this,t=[],n=0;n<e.entityCache.length;++n)t[e.entityCache[n].id]=e.entityCache[n];return t},r.prototype.reduceComplex=function(e,t){var n=this,r=t?[]:{};for(var i in e)e.hasOwnProperty(i)&&(Array.isArray(e[i])?r[i]=n.reduceComplex(e[i],!0):e[i]&&e[i].id?r[i]=e[i].id:r[i]=e[i]);return r},r.prototype.populateComplex=function(e,t,n,r){function i(i,o){function c(n){return e[t][o]=n,e}if("string"!=typeof e[t][o]){if(!r||"object"!=typeof e[t][o]||"string"!=typeof e[t][o].id)return a.q.when(!1);e[t][o]=e[t][o].id}return n.read(e[t][o]).then(c)}function o(n){e[t]=n}var a=this;if(Array.isArray(e[t])){var c=e[t].map(i);return a.q.all(c)}if("string"!=typeof e[t]){if(!r||"object"!=typeof e[t]||"string"!=typeof e[t].id)return a.q.when(!1);e[t]=e[t].id}return n.read(e[t]).then(o)},r.prototype.reset=function(){var e=this;e.entityCache=e.configuration.collectionName?[]:{},e.__entityCacheRaw=null,e.__requestCache={}},r}function t(e){return e}angular.module("absync").constant("absyncCache",e)}(),function(){"use strict";function e(){return t}function t(e,t,n,r,i,o,a,c,s,h){this.model=e,this.collectionUri=t,this.entityUri=n;var u=e.prototype.constructor.name.toLowerCase();this.collectionName=r||u+"s",this.entityName=i||u,this.deserialize=o||void 0,this.serialize=a||void 0,this.injector=c||void 0,this.debug=s||!1,this.allowBrowserCache=angular.merge({},{sync:!0,request:!0},h)}angular.module("absync").service("AbsyncServiceConfiguration",e)}(),function(){"use strict";angular.module("absync").constant("absyncNoopLog",{debug:angular.noop,info:angular.noop,error:angular.noop})}(),function(){"use strict";function e(){function e(e){if(!e)return e;var t=-1<e.indexOf("?")?"&":"?",n=(new Date).getTime();return e+t+"t="+n}return e}angular.module("absync").filter("absyncUncached",e)}();
!function(){"use strict";angular.module("absync",[])}(),function(){"use strict";function e(e,n,r){return new t(e,n,r)}function t(e,t,n){var r=this;r.__injector=e,r.__provide=t,r.__absyncCache=n,r.__ioSocket=null,r.__registerLater=[],r.__listeners=[],r.__collections={},r.__entities={},r.debug=void 0}e.$inject=["$injector","$provide","absyncCache"],angular.module("absync").provider("absync",e),t.prototype.configure=function(e){var t=this;if("undefined"!=typeof e.socket){var n=e.socket,r="undefined"!=typeof io&&io.Socket&&n instanceof io.Socket;if("function"==typeof n)t.__ioSocket=new n;else{if(!r)throw new Error("configure() expects input to be a function or a socket.io Socket instance.");t.__ioSocket=n}t.__registerLater.length&&(angular.forEach(t.__registerLater,t.__registerListener.bind(t)),t.__registerLater=[])}"undefined"!=typeof e.debug&&(t.debug=e.debug||!1),t.debug&&(angular.forEach(t.__collections,function(e){e.configuration.debug=!0}),angular.forEach(t.__entities,function(e){e.configuration.debug=!0}))},t.prototype.disconnect=function(e){var t=this;e=e||!1,angular.forEach(t.__listeners,function(e){e.unregister(),delete e.unregister,t.__registerLater.push(e)}),e&&(t.__ioSocket.disconnect(),t.__ioSocket=null)},t.prototype.__registerListener=function(e){var t=this;t.__listeners.push(e),e.unregister=t.__handleEntityEvent(e.eventName,e.callback)},t.prototype.collection=function(e,t){var n=this;if(n.__collections[e])throw new Error("A collection with the name '"+e+"' was already requested. Names for collections must be unique.");if(n.__entities[e])throw new Error("An entity with the name '"+e+"' was already requested. Names for collections must be unique and can't be shared with entities.");t.debug="undefined"==typeof t.debug?n.debug:t.debug,n.__collections[e]={constructor:n.__absyncCache(e,t),configuration:t},n.__provide.service(e,n.__collections[e].constructor)},t.prototype.entity=function(e,t){var n=this;if(n.__entities[e])throw new Error("An entity with the name '"+e+"' was already requested. Names for entities must be unique.");if(n.__collections[e])throw new Error("A collection with the name '"+e+"' was already requested. Names for entities must be unique and can't be shared with collections.");t.debug="undefined"==typeof t.debug?n.debug:t.debug,n.__entities[e]={constructor:n.__absyncCache(e,t),configuration:t},n.__provide.service(e,n.__entities[e].constructor)},t.prototype.on=function(e,t){var n=this;return n.__ioSocket?n.__registerListener({eventName:e,callback:t}):n.__registerLater.length>8192?null:(n.__registerLater.push({eventName:e,callback:t}),null)},t.prototype.__handleEntityEvent=function(e,t){var n=this;return n.__ioSocket.on(e,t),function(){n.__ioSocket.removeListener(e,t)}},t.prototype.emit=function(e,t,n){var r=this;if(!r.__ioSocket)throw new Error("socket.io is not initialized.");r.__ioSocket.emit(e,t,function(){n&&n.apply(r.__ioSocket,arguments)})},t.prototype.$get=function(){return this}}(),function(){"use strict";function e(e,n){function r(r,i,o,a,c,s,u,h){var l=this,d=n.injector||i,y=d.has(n.model);if(!y)throw new Error("Unable to construct the '"+e+"' service, because the referenced model '"+n.model+"' is not available for injection.");var f="string"==typeof n.model?d.get(n.model):n.model,_=f.serialize||n.serialize||t,p=f.deserialize||n.deserialize||t;l.name=e,l.configuration=n,l.entityCache=n.collectionName?[]:{},l.__entityCacheRaw=null,l.enableRequestCache=!0,l.__requestCache={},l.allowBrowserCache=(angular.merge||angular.extend)({},{sync:!0,request:!0},n.allowBrowserCache),l.__uncached=h,l.httpInterface=r,l.logInterface=n.debug?o:s,l.scope=c,l.q=a,l.logPrefix="absync:"+e.toLocaleUpperCase()+" ",l.forceEarlyCacheUpdate=!1,l.throwFailures=!0,l.serializer=_,l.deserializer=p,u.on(n.entityName,l.__onEntityOnWebsocket.bind(l)),n.collectionName&&u.on(n.collectionName,l.__onCollectionOnWebsocket.bind(l)),c.$on(n.entityName,l.__onEntityReceived.bind(l)),n.collectionName&&c.$on(n.collectionName,l.__onCollectionReceived.bind(l)),l.logInterface.info(l.logPrefix+"service was instantiated.")}function i(e,t){var r=this;if((e||r.forceEarlyCacheUpdate)&&t.data[n.entityName]){var i=t.data[n.entityName];if(r.forceEarlyCacheUpdate){var o=r.deserializer(i);if(r.__updateCacheWithEntity(o),e)return o}if(e)return i}}function o(e){var t=this;if(t.logInterface.error(t.logPrefix+"Unable to store entity on the server.",e),t.logInterface.error(e),t.scope.$emit("absyncError",e),t.throwFailures)throw e}return r.$inject=["$http","$injector","$log","$q","$rootScope","absyncNoopLog","absync","absyncUncachedFilter"],r.prototype.__onEntityOnWebsocket=function(e){var t=this;t.scope.$broadcast(n.entityName,e[n.entityName])},r.prototype.__onCollectionOnWebsocket=function(e){var t=this;t.scope.$broadcast(n.collectionName,e[n.collectionName])},r.prototype.__onDataAvailable=function(e){function t(e){r.entityCache.push(r.deserializer(e))}var r=this;if(Array.isArray(r.entityCache))angular.forEach(e[n.collectionName],t),r.scope.$broadcast("collectionNew",{service:r,cache:r.entityCache});else{var i=r.deserializer(e[n.entityName]);r.__updateCacheWithEntity(i)}return r.entityCache},r.prototype.__onEntityReceived=function(e,t){var n=this,r=t;return 1===Object.keys(r).length&&r.hasOwnProperty("id")?(n.logInterface.info(n.logPrefix+"Entity was deleted from the server. Updating cache…"),n.__removeEntityFromCache(r.id)):(n.logInterface.debug(n.logPrefix+"Entity was updated on the server. Updating cache…"),n.__updateCacheWithEntity(n.deserializer(r)))},r.prototype.__onCollectionReceived=function(e,t){function n(e){var t=r.deserializer(e);r.__updateCacheWithEntity(t)}var r=this,i=t;r.entityCache.length=0,angular.forEach(i,n)},r.prototype.ensureLoaded=function(e){function t(e){if(!e.data[n.collectionName])throw new Error("The response from the server was not in the expected format. It should have a member named '"+n.collectionName+"'.");return a.__entityCacheRaw=e.data,a.entityCache.splice(0,a.entityCache.length),a.__onDataAvailable(e.data)}function r(e){if(a.logInterface.error(a.logPrefix+"Unable to retrieve the collection from the server.",e),a.__entityCacheRaw=null,a.scope.$emit("absyncError",e),a.throwFailures)throw e}function i(e){if(!e.data[n.entityName])throw new Error("The response from the server was not in the expected format. It should have a member named '"+n.entityName+"'.");a.__entityCacheRaw=e.data,a.__onDataAvailable(e.data)}function o(e){if(a.logInterface.error(a.logPrefix+"Unable to retrieve the entity from the server.",e),a.__entityCacheRaw=null,a.scope.$emit("absyncError",e),a.throwFailures)throw e}var a=this;return e=e===!0,null===a.__entityCacheRaw||e?n.collectionName&&n.collectionUri?(a.logInterface.info(a.logPrefix+"Retrieving '"+n.collectionName+"' collection…"),a.httpInterface.get(a.allowBrowserCache.sync?n.collectionUri:a.__uncached(n.collectionUri)).then(t,r)):n.entityName&&n.entityUri?a.httpInterface.get(a.allowBrowserCache.sync?n.entityUri:a.__uncached(n.entityUri)).then(i,o):a.q.when([]):a.q.when(a.entityCache)},r.prototype.seed=function(e){var t=this;return t.__entityCacheRaw=e,t.__onDataAvailable(t.__entityCacheRaw)},r.prototype.sync=function(){var e=this;return e.__entityCacheRaw=null,e.ensureLoaded(!0)},r.prototype.read=function(e,t){function r(e){if(!e.data[n.entityName])throw new Error("The response from the server was not in the expected format. It should have a member named '"+n.entityName+"'.");var t=o.deserializer(e.data[n.entityName]);return o.__updateCacheWithEntity(t),t}function i(t){if(o.logInterface.error(o.logPrefix+"Unable to retrieve entity with ID '"+e+"' from the server.",t),o.scope.$emit("absyncError",t),o.throwFailures)throw t}var o=this;if(t=t===!0,o.logInterface.debug(o.logPrefix+"Requesting entity '"+e+"' (forceReload:"+t+")…"),!t)for(var a=0,c=o.entityCache[0];a<o.entityCache.length;++a,c=o.entityCache[a])if(c.id===e)return o.logInterface.debug(o.logPrefix+"Requested entity '"+e+"' is served from cache."),o.q.when(c);return o.logInterface.debug(o.logPrefix+"Requested entity '"+e+"' is fetched from backend."),o.__requestEntity(e).then(r,i)},r.prototype.__requestEntity=function(e){function t(e,t){return delete r.__requestCache[e],t}var r=this;if(r.enableRequestCache&&r.__requestCache&&r.__requestCache[e])return r.logInterface.debug(r.logPrefix+"Entity request '"+e+"' served from request cache."),r.__requestCache[e];var i=n.entityUri+(e?"/"+e:""),o=r.httpInterface.get(r.allowBrowserCache.request?i:r.__uncached(i)).then(t.bind(r,e));return r.enableRequestCache&&r.__requestCache&&(r.__requestCache[e]=o),o},r.prototype.update=function(e,t){var r=this;t=t||!1;var a=r.reduceComplex(e),c=r.serializer(a),s={};return s[n.entityName]=c,"undefined"!=typeof e.id?r.httpInterface.put(n.entityUri+"/"+e.id,s).then(i.bind(r,t),o.bind(r)):r.httpInterface.post(n.collectionUri,s).then(i.bind(r,t),o.bind(r))},r.prototype.patch=function(e){var t=this,r=t.reduceComplex(e),a=t.serializer(r),c={};if(c[n.entityName]=a,"undefined"!=typeof e.id)return t.httpInterface.patch(n.entityUri+"/"+e.id,c).then(i.bind(t),o.bind(t));throw new Error("Attempted to patch an entity that was never stored on the server.")},r.prototype.create=r.prototype.update,r.prototype["delete"]=function(e){function t(e){return i.__removeEntityFromCache(o)}function r(e){if(i.logInterface.error(e.data),i.scope.$emit("absyncError",e),i.throwFailures)throw e}var i=this,o=e.id;return i.httpInterface["delete"](n.entityUri+"/"+o).then(t)["catch"](r)},r.prototype.__updateCacheWithEntity=function(e){var t=this;if(t.logInterface.info(t.logPrefix+"Updating entity '"+(e.id||t.name)+"' in cache…",e),!Array.isArray(t.entityCache))return t.scope.$broadcast("beforeEntityUpdated",{service:t,cache:t.entityCache,entity:t.entityCache,updated:e}),"function"==typeof t.entityCache.copyFrom?t.entityCache.copyFrom(e):angular.extend(t.entityCache,e),void t.scope.$broadcast("entityUpdated",{service:t,cache:t.entityCache,entity:t.entityCache});for(var n=!1,r=0,i=t.entityCache[0];r<t.entityCache.length;++r,i=t.entityCache[r])if(i.id==e.id){t.scope.$broadcast("beforeEntityUpdated",{service:t,cache:t.entityCache,entity:t.entityCache[r],updated:e});var o=t.entityCache[r];"function"==typeof o.copyFrom?o.copyFrom(e):angular.extend(o,e),n=!0,t.scope.$broadcast("entityUpdated",{service:t,cache:t.entityCache,entity:t.entityCache[r]});break}n||(t.scope.$broadcast("beforeEntityNew",{service:t,cache:t.entityCache,entity:e}),t.entityCache.push(e),t.scope.$broadcast("entityNew",{service:t,cache:t.entityCache,entity:e}))},r.prototype.__removeEntityFromCache=function(e){for(var t=this,n=0,r=t.entityCache[0];n<t.entityCache.length;++n,r=t.entityCache[n])if(r.id==e){t.scope.$broadcast("beforeEntityRemoved",{service:t,cache:t.entityCache,entity:r}),t.entityCache.splice(n,1),t.scope.$broadcast("entityRemoved",{service:t,cache:t.entityCache,entity:r});break}},r.prototype.lookupTableById=function(){for(var e=this,t=[],n=0;n<e.entityCache.length;++n)t[e.entityCache[n].id]=e.entityCache[n];return t},r.prototype.reduceComplex=function(e,t){var n=this,r=t?[]:{};for(var i in e)e.hasOwnProperty(i)&&(Array.isArray(e[i])?r[i]=n.reduceComplex(e[i],!0):e[i]&&e[i].id?r[i]=e[i].id:r[i]=e[i]);return r},r.prototype.populateComplex=function(e,t,n,r){function i(i,o){function c(n){return e[t][o]=n,e}if("string"!=typeof e[t][o]){if(!r||"object"!=typeof e[t][o]||"string"!=typeof e[t][o].id)return a.q.when(!1);e[t][o]=e[t][o].id}return n.read(e[t][o]).then(c)}function o(n){e[t]=n}var a=this;if(Array.isArray(e[t])){var c=e[t].map(i);return a.q.all(c)}if("string"!=typeof e[t]){if(!r||"object"!=typeof e[t]||"string"!=typeof e[t].id)return a.q.when(!1);e[t]=e[t].id}return n.read(e[t]).then(o)},r.prototype.reset=function(){var e=this;e.entityCache=e.configuration.collectionName?[]:{},e.__entityCacheRaw=null,e.__requestCache={}},r}function t(e){return e}angular.module("absync").constant("absyncCache",e)}(),function(){"use strict";function e(){return t}function t(e,t,n,r,i,o,a,c,s,u){this.model=e,this.collectionUri=t,this.entityUri=n;var h=e.prototype.constructor.name.toLowerCase();this.collectionName=r||h+"s",this.entityName=i||h,this.deserialize=o||void 0,this.serialize=a||void 0,this.injector=c||void 0,this.debug=s||!1,this.allowBrowserCache=angular.merge({},{sync:!0,request:!0},u)}angular.module("absync").service("AbsyncServiceConfiguration",e)}(),function(){"use strict";angular.module("absync").constant("absyncNoopLog",{debug:angular.noop,info:angular.noop,error:angular.noop})}(),function(){"use strict";function e(){function e(e){if(!e)return e;var t=-1<e.indexOf("?")?"&":"?",n=(new Date).getTime();return e+t+"t="+n}return e}angular.module("absync").filter("absyncUncached",e)}();
//# sourceMappingURL=maps/absync.concat.min.js.map
{
"name": "absync",
"version": "3.1.0",
"version": "3.2.0",
"description": "absync",

@@ -5,0 +5,0 @@ "main": "dist/development/absync.concat.js",

@@ -51,2 +51,4 @@ /* globals angular, io */

self.__registerLater = [];
// References to all registered event listeners.
self.__listeners = [];

@@ -116,5 +118,36 @@ // The collections that absync provides.

/**
* Detaches absync from the websocket.
* @param {Boolean} [disconnectSocket=false] Should the underlying socket.io connection be disconnected as well?
*/
AbsyncProvider.prototype.disconnect = function AbsyncProvider$disconnect( disconnectSocket ) {
var self = this;
disconnectSocket = disconnectSocket || false;
angular.forEach( self.__listeners, function unregisterListener( listener ) {
listener.unregister();
delete listener.unregister;
self.__registerLater.push( listener );
} );
if( disconnectSocket ) {
self.__ioSocket.disconnect();
self.__ioSocket = null;
}
};
/**
* Register an event listener with socket.io.
* @param {Object} listener
* @private
*/
AbsyncProvider.prototype.__registerListener = function AbsyncProvider$registerListener( listener ) {
var self = this;
self.$get().__handleEntityEvent( listener.eventName, listener.callback );
// Remember this listener.
self.__listeners.push( listener );
// Register the listener and remember the function to use when the listener should be unregistered.
listener.unregister = self.__handleEntityEvent( listener.eventName, listener.callback );
};

@@ -188,36 +221,4 @@

/**
* Register the service factory.
* @returns {AbsyncService}
* @ngInject
*/
AbsyncProvider.prototype.$get = function AbsyncProvider$$get() {
return new AbsyncService( this );
};
/**
* The service that is received when injecting "absync".
* This service is primarily used internally to set up the connection between socket.io and the individual
* caching services.
* @param {AbsyncProvider|Object} parentProvider The AbsyncProvider that provides this service.
* @constructor
*/
function AbsyncService( parentProvider ) {
this.__absyncProvider = parentProvider;
}
/**
* Configure the socket.io connection for absync.
* This configuration of absync should usually be performed through the absyncProvider in the configuration
* phase of a module.
* @param {Object} configuration The configuration for the absync provider.
* Can have a member `socket`, pointing to the socket.io instance or constructor to use.
* Can have a member `debug`, enabling debugging, if set to true.
*/
AbsyncService.prototype.configure = function AbsyncService$configure( configuration ) {
var _absyncProvider = this.__absyncProvider;
_absyncProvider.configure( configuration );
};
/**
* Register an event listener that is called when a specific entity is received on the websocket.

@@ -230,10 +231,9 @@ * @param {String} eventName The event name, usually the name of the entity.

*/
AbsyncService.prototype.on = function AbsyncService$on( eventName, callback ) {
var _absyncProvider = this.__absyncProvider;
var self = this;
AbsyncProvider.prototype.on = function AbsyncProvider$on( eventName, callback ) {
var self = this;
// If we have no configured socket.io connection yet, remember to register it later.
if( !_absyncProvider.__ioSocket ) {
if( !self.__ioSocket ) {
if( _absyncProvider.__registerLater.length > 8192 ) {
if( self.__registerLater.length > 8192 ) {
// Be defensive, something is probably not right here.

@@ -244,3 +244,3 @@ return null;

// TODO: Use promises here, so that we can always return the event listener removal function.
_absyncProvider.__registerLater.push( {
self.__registerLater.push( {
eventName : eventName,

@@ -252,3 +252,6 @@ callback : callback

return self.__handleEntityEvent( eventName, callback );
return self.__registerListener( {
eventName : eventName,
callback : callback
} );
};

@@ -262,11 +265,11 @@

*/
AbsyncService.prototype.__handleEntityEvent = function AbsyncService$handleEntityEvent( eventName, callback ) {
var _absyncProvider = this.__absyncProvider;
AbsyncProvider.prototype.__handleEntityEvent = function AbsyncProvider$handleEntityEvent( eventName, callback ) {
var self = this;
// Register the callback with socket.io.
_absyncProvider.__ioSocket.on( eventName, callback );
self.__ioSocket.on( eventName, callback );
// Return a function that removes the listener.
return function removeListener() {
_absyncProvider.__ioSocket.removeListener( eventName, callback );
self.__ioSocket.removeListener( eventName, callback );
};

@@ -276,3 +279,3 @@ };

/**
* Convenience method to allow the user to emit() from the websocket.
* Convenience method to allow the user to emit() from the socket.io connection.
* This is not utilized in absync internally.

@@ -283,14 +286,23 @@ * @param {String} eventName

*/
AbsyncService.prototype.emit = function AbsyncService$emit( eventName, data, callback ) {
var _absyncProvider = this.__absyncProvider;
AbsyncProvider.prototype.emit = function AbsyncProvider$emit( eventName, data, callback ) {
var self = this;
if( !_absyncProvider.__ioSocket ) {
if( !self.__ioSocket ) {
throw new Error( "socket.io is not initialized." );
}
_absyncProvider.__ioSocket.emit( eventName, data, function afterEmit() {
self.__ioSocket.emit( eventName, data, function afterEmit() {
if( callback ) {
callback.apply( _absyncProvider.__ioSocket, arguments );
callback.apply( self.__ioSocket, arguments );
}
} );
};
/**
* The service is just used as a convenience to access the provider.
* @returns {AbsyncProvider}
* @ngInject
*/
AbsyncProvider.prototype.$get = function AbsyncProvider$$get() {
return this;
};

@@ -35,3 +35,3 @@ /* globals angular */

* @param {angular.IRootScopeService|Object} $rootScope
* @param {AbsyncService} absync
* @param {AbsyncProvider} absync
* @param {Object} absyncNoopLog A log interface that does nothing.

@@ -42,3 +42,3 @@ * @param {Object} absyncUncachedFilter A filter that mutates URLs so they will bypass the browser cache.

*/
function CacheService( $http, $injector, $log, $q, $rootScope, absync, absyncNoopLog, absyncUncachedFilter ) {
function CacheService( $http, $injector, $log, $q, $rootScope, absyncNoopLog, absync, absyncUncachedFilter ) {
var self = this;

@@ -45,0 +45,0 @@

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc