/** * Will return a Stale resource when a given resource cannot be found by the * supplied descriptor. */ fetch(descriptor) { var fragmentCache = this._getFragment(descriptor.partial) , resourceId = descriptor.id , result = null , resource = null , fragments, i, data, entry; result = new RefraxFragmentResult(); if (resourceId) { resource = fragmentCache[resourceId]; if (resource) { result.status = resource.status; result.timestamp = resource.timestamp; result.data = resource.data; } if (!result.data) { // Create a new list of fragments with our global default being last at highest priority. fragments = [].concat(descriptor.fragments, FRAGMENT_DEFAULT); for (i = 0; i < fragments.length; i++) { fragmentCache = this._getFragment(fragments[i])[resourceId]; if (fragmentCache && fragmentCache.data) { result.data = RefraxTools.extend({}, result.data || {}, fragmentCache.data || {}); result.status = STATUS_PARTIAL; } } } } else if (descriptor.basePath) { resource = this.queries[descriptor.basePath]; if (resource) { result.status = resource.status; result.timestamp = resource.timestamp; } if (!resource || !(data = resource.data)) { return result; } if (descriptor.classify === CLASSIFY_COLLECTION) { result.data = RefraxTools.map(data || [], function(id) { var entry = fragmentCache[id]; if (!entry) { throw new TypeError( 'RefraxFragmentCache:fetch - Unexpected error, failure to find collection entry for `' + id + '`.' ); } return RefraxTools.extend({}, entry.data); }); } else if (descriptor.classify === CLASSIFY_ITEM) { entry = fragmentCache[data]; if (!entry) { throw new TypeError( 'RefraxFragmentCache:fetch - Unexpected error, failure to find entry for `' + data + '`.' ); } result.data = RefraxTools.extend({}, entry.data); } else { if (RefraxTools.isArray(data)) { data = [].concat(data); } else if (RefraxTools.isObject(data)) { data = RefraxTools.extend({}, data); } result.data = data; } } // If we are expecting a collection let's ensure we are an array atleast if (!result.data && descriptor.classify === CLASSIFY_COLLECTION) { result.data = []; } return result; }
/** * Update the content for a given resource. */ update(descriptor, data, status) { var self = this , fragmentCache = this._getFragment(descriptor.partial) , queryData , resourcePath = descriptor.basePath , result , touchedIds = [] , dataId = null; // if no data is present (ie a 204 response) our data then becomes stale result = { status: status || STATUS_COMPLETE, timestamp: data ? Date.now() : TIMESTAMP_STALE }; // Fragments if (descriptor.classify === CLASSIFY_COLLECTION && data) { if (!RefraxTools.isArray(data) && !RefraxTools.isPlainObject(data)) { throw new TypeError( 'RefraxFragmentCache:update expected collection compatible type of Array/Object\n\r' + 'basePath: ' + resourcePath + '\n\r' + 'found: `' + typeof(data) + '`' ); } if (RefraxTools.isArray(data)) { dataId = RefraxTools.map(data, function(item) { return self._updateFragmentCache(fragmentCache, descriptor, result, item, touchedIds); }); } else { dataId = this._updateFragmentCache(fragmentCache, descriptor, result, data, touchedIds); } } else if (descriptor.classify === CLASSIFY_ITEM) { dataId = this._updateFragmentCache(fragmentCache, descriptor, result, data, touchedIds); } // Queries if (resourcePath) { queryData = this.queries[resourcePath] && this.queries[resourcePath].data; // from a REST perspective collections are typically modified when creating into them if (descriptor.classify === CLASSIFY_COLLECTION) { if (dataId) { queryData = RefraxTools.concatUnique(queryData, dataId); } // if no data was received creating into a collection we can mark it as stale else { result.status = STATUS_STALE; result.timestamp = TIMESTAMP_STALE; } } else if (descriptor.classify === CLASSIFY_ITEM) { queryData = dataId; } else if (data) { if (descriptor.cacheStrategy === CACHE_STRATEGY_MERGE) { if (RefraxTools.isArray(queryData) || RefraxTools.isArray(data)) { queryData = RefraxTools.concatUnique(queryData, data); } else { queryData = RefraxTools.extend(queryData || {}, data); } } else { queryData = data; } } this.queries[resourcePath] = RefraxTools.extend({}, result, { data: queryData }); } return touchedIds; }