UNPKG

angular-cached-resource

Version:

An AngularJS module to interact with RESTful resources, even when browser is offline

295 lines (280 loc) 11.3 kB
// Generated by CoffeeScript 1.7.1 var CachedResourceManager, DEFAULT_ACTIONS, ResourceCacheArrayEntry, ResourceCacheEntry, app, resourceManagerListener, __slice = [].slice; DEFAULT_ACTIONS = { get: { method: 'GET' }, query: { method: 'GET', isArray: true }, save: { method: 'POST' }, remove: { method: 'DELETE' }, "delete": { method: 'DELETE' } }; ResourceCacheEntry = require('./resource_cache_entry'); ResourceCacheArrayEntry = require('./resource_cache_array_entry'); CachedResourceManager = require('./cached_resource_manager'); resourceManagerListener = null; app = angular.module('ngCachedResource', ['ngResource']); app.factory('$cachedResource', [ '$resource', '$timeout', '$q', '$log', function($resource, $timeout, $q, $log) { var modifyObjectInPlace, processReadArgs, readArrayCache, readCache, resourceManager, writeCache; resourceManager = new CachedResourceManager($timeout); if (resourceManagerListener) { document.removeEventListener('online', resourceManagerListener); } resourceManagerListener = function(event) { return resourceManager.flushQueues(); }; document.addEventListener('online', resourceManagerListener); processReadArgs = function(args) { var deferred, error, params, success; args = Array.prototype.slice.call(args); params = angular.isObject(args[0]) ? args.shift() : {}; success = args[0], error = args[1]; deferred = $q.defer(); if (angular.isFunction(success)) { deferred.promise.then(success); } if (angular.isFunction(error)) { deferred.promise["catch"](error); } return { params: params, deferred: deferred }; }; modifyObjectInPlace = function(oldObject, newObject) { var key, _i, _j, _len, _len1, _ref, _ref1, _results; _ref = Object.keys(oldObject); for (_i = 0, _len = _ref.length; _i < _len; _i++) { key = _ref[_i]; if (key[0] !== '$') { if (newObject[key] == null) { delete oldObject[key]; } } } _ref1 = Object.keys(newObject); _results = []; for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { key = _ref1[_j]; if (key[0] !== '$') { if (angular.isObject(oldObject[key]) && angular.isObject(newObject[key])) { _results.push(modifyObjectInPlace(oldObject[key], newObject[key])); } else if (!angular.equals(oldObject[key], newObject[key])) { _results.push(oldObject[key] = newObject[key]); } else { _results.push(void 0); } } } return _results; }; readArrayCache = function(name, CachedResource) { return function() { var arrayInstance, cacheArrayEntry, cacheDeferred, cacheInstanceEntry, cacheInstanceParams, httpDeferred, params, resource, _i, _len, _ref, _ref1; _ref = processReadArgs(arguments), params = _ref.params, cacheDeferred = _ref.deferred; httpDeferred = $q.defer(); arrayInstance = new Array(); arrayInstance.$promise = cacheDeferred.promise; arrayInstance.$httpPromise = httpDeferred.promise; cacheArrayEntry = new ResourceCacheArrayEntry(CachedResource.$key, params); resource = CachedResource.$resource[name].apply(CachedResource.$resource, arguments); resource.$promise.then(function() { var cachedResourceInstances; cachedResourceInstances = resource.map(function(resourceInstance) { return new CachedResource(resourceInstance); }); arrayInstance.splice.apply(arrayInstance, [0, arrayInstance.length].concat(__slice.call(cachedResourceInstances))); if (!cacheArrayEntry.value) { cacheDeferred.resolve(arrayInstance); } return httpDeferred.resolve(arrayInstance); }); resource.$promise["catch"](function(error) { if (!cacheArrayEntry.value) { cacheDeferred.reject(error); } return httpDeferred.reject(error); }); arrayInstance.$httpPromise.then(function(response) { var cacheArrayReferences, cacheInstanceEntry, cacheInstanceParams, instance, _i, _len; cacheArrayReferences = []; for (_i = 0, _len = response.length; _i < _len; _i++) { instance = response[_i]; cacheInstanceParams = instance.$params(); if (Object.keys(cacheInstanceParams).length === 0) { $log.error("instance " + instance + " doesn't have any boundParams. Please, make sure you specified them in your resource's initialization, f.e. `{id: \"@id\"}`, or it won't be cached."); } else { cacheArrayReferences.push(cacheInstanceParams); cacheInstanceEntry = new ResourceCacheEntry(CachedResource.$key, cacheInstanceParams); cacheInstanceEntry.set(instance, false); } } return cacheArrayEntry.set(cacheArrayReferences); }); if (cacheArrayEntry.value) { _ref1 = cacheArrayEntry.value; for (_i = 0, _len = _ref1.length; _i < _len; _i++) { cacheInstanceParams = _ref1[_i]; cacheInstanceEntry = new ResourceCacheEntry(CachedResource.$key, cacheInstanceParams); arrayInstance.push(new CachedResource(cacheInstanceEntry.value)); } cacheDeferred.resolve(arrayInstance); } return arrayInstance; }; }; readCache = function(name, CachedResource) { return function() { var cacheDeferred, cacheEntry, httpDeferred, instance, params, readHttp, _ref; _ref = processReadArgs(arguments), params = _ref.params, cacheDeferred = _ref.deferred; httpDeferred = $q.defer(); instance = new CachedResource({ $promise: cacheDeferred.promise, $httpPromise: httpDeferred.promise }); cacheEntry = new ResourceCacheEntry(CachedResource.$key, params); readHttp = function() { var resource; resource = CachedResource.$resource[name].call(CachedResource.$resource, params); resource.$promise.then(function(response) { angular.extend(instance, response); if (!cacheEntry.value) { cacheDeferred.resolve(instance); } httpDeferred.resolve(instance); return cacheEntry.set(response, false); }); return resource.$promise["catch"](function(error) { if (!cacheEntry.value) { cacheDeferred.reject(error); } return httpDeferred.reject(error); }); }; if (cacheEntry.dirty) { resourceManager.getQueue(CachedResource).processResource(params, readHttp); } else { readHttp(); } if (cacheEntry.value) { angular.extend(instance, cacheEntry.value); cacheDeferred.resolve(instance); } return instance; }; }; writeCache = function(action, CachedResource) { return function() { var args, cacheEntry, deferred, error, instanceMethod, param, params, queue, queueDeferred, resource, success, value, _ref; instanceMethod = this instanceof CachedResource; args = Array.prototype.slice.call(arguments); params = !instanceMethod && angular.isObject(args[1]) ? args.shift() : instanceMethod && angular.isObject(args[0]) ? args.shift() : {}; resource = instanceMethod ? this : new CachedResource(args.shift()); success = args[0], error = args[1]; resource.$resolved = false; _ref = resource.$params(); for (param in _ref) { value = _ref[param]; params[param] = value; } deferred = $q.defer(); resource.$promise = deferred.promise; if (angular.isFunction(success)) { deferred.promise.then(success); } if (angular.isFunction(error)) { deferred.promise["catch"](error); } cacheEntry = new ResourceCacheEntry(CachedResource.$key, params); if (!angular.equals(cacheEntry.data, resource)) { cacheEntry.set(resource, true); } queueDeferred = $q.defer(); queueDeferred.promise.then(function(httpResource) { modifyObjectInPlace(resource, httpResource); resource.$resolved = true; return deferred.resolve(resource); }); queueDeferred.promise["catch"](deferred.reject); queue = resourceManager.getQueue(CachedResource); queue.enqueue(params, action, queueDeferred); queue.flush(); return resource; }; }; return function() { var $key, CachedResource, Resource, actions, arg, args, boundParams, handler, isPermissibleBoundValue, name, param, paramDefault, paramDefaults, params, url, _ref; args = Array.prototype.slice.call(arguments); $key = args.shift(); url = args.shift(); while (args.length) { arg = args.pop(); if (angular.isObject(arg[Object.keys(arg)[0]])) { actions = arg; } else { paramDefaults = arg; } } actions = angular.extend({}, DEFAULT_ACTIONS, actions); if (paramDefaults == null) { paramDefaults = {}; } boundParams = {}; for (param in paramDefaults) { paramDefault = paramDefaults[param]; if (paramDefault[0] === '@') { boundParams[paramDefault.substr(1)] = param; } } Resource = $resource.call(null, url, paramDefaults, actions); isPermissibleBoundValue = function(value) { return angular.isDate(value) || angular.isNumber(value) || angular.isString(value); }; CachedResource = (function() { CachedResource.prototype.$cache = true; function CachedResource(attrs) { angular.extend(this, attrs); } CachedResource.prototype.$params = function() { var attribute, params; params = {}; for (attribute in boundParams) { param = boundParams[attribute]; if (isPermissibleBoundValue(this[attribute])) { params[param] = this[attribute]; } } return params; }; CachedResource.$resource = Resource; CachedResource.$key = $key; return CachedResource; })(); for (name in actions) { params = actions[name]; handler = params.method === 'GET' && params.isArray ? readArrayCache(name, CachedResource) : params.method === 'GET' ? readCache(name, CachedResource) : (_ref = params.method) === 'POST' || _ref === 'PUT' || _ref === 'DELETE' ? writeCache(name, CachedResource) : void 0; CachedResource[name] = handler; if (params.method !== 'GET') { CachedResource.prototype["$" + name] = handler; } } resourceManager.add(CachedResource); resourceManager.flushQueues(); return CachedResource; }; } ]); if (typeof module !== "undefined" && module !== null) { module.exports = app; }