@@ -52,7 +52,10 @@ var DEFAULT_API_OPTIONS = {
5252 prefixes : { default : '/' } ,
5353 printNetworkRequests : false ,
5454 disableCache : false ,
55- cacheExpiration : 5 * 60 * 1000
55+ cacheExpiration : 5 * 60 * 1000 ,
56+ cachePrefix : 'offlineApiCache' ,
57+ capServices : false ,
58+ capLimit : 50
5659} ;
5760var DEFAULT_SERVICE_OPTIONS = {
5861 method : 'GET' ,
@@ -61,7 +64,6 @@ var DEFAULT_SERVICE_OPTIONS = {
6164 disableCache : false
6265} ;
6366var DEFAULT_CACHE_DRIVER = react_native_1 . AsyncStorage ;
64- var CACHE_PREFIX = 'offlineApiCache:' ;
6567var OfflineFirstAPI = ( function ( ) {
6668 function OfflineFirstAPI ( options , services , driver ) {
6769 this . _APIServices = { } ;
@@ -133,7 +135,7 @@ var OfflineFirstAPI = (function () {
133135 case 7 :
134136 // Cache if it hasn't been disabled and if the network request has been successful
135137 if ( res . data . ok && shouldUseCache ) {
136- this . _cache ( service , requestId , parsedResponseData , expiration ) ;
138+ this . _cache ( serviceDefinition , service , requestId , parsedResponseData , expiration ) ;
137139 }
138140 this . _log ( 'parsed network response' , parsedResponseData ) ;
139141 return [ 2 /*return*/ , parsedResponseData ] ;
@@ -268,28 +270,49 @@ var OfflineFirstAPI = (function () {
268270 * @returns {(Promise<void|boolean>) }
269271 * @memberof OfflineFirstAPI
270272 */
271- OfflineFirstAPI . prototype . _cache = function ( service , requestId , response , expiration ) {
273+ OfflineFirstAPI . prototype . _cache = function ( serviceDefinition , service , requestId , response , expiration ) {
272274 return __awaiter ( this , void 0 , void 0 , function ( ) {
273- var err_5 ;
275+ var shouldCap , capLimit , serviceDictionaryKey , dictionary , cachedItemsCount , key , err_5 ;
274276 return __generator ( this , function ( _a ) {
275277 switch ( _a . label ) {
276278 case 0 :
277- this . _log ( "Caching " + requestId + " ..." ) ;
279+ shouldCap = typeof serviceDefinition . capService !== 'undefined' ?
280+ serviceDefinition . capService :
281+ this . _APIOptions . capServices ;
278282 _a . label = 1 ;
279283 case 1 :
280- _a . trys . push ( [ 1 , 4 , , 5 ] ) ;
284+ _a . trys . push ( [ 1 , 7 , , 8 ] ) ;
285+ this . _log ( "Caching " + requestId + " ..." ) ;
281286 return [ 4 /*yield*/ , this . _addKeyToServiceDictionary ( service , requestId , expiration ) ] ;
282287 case 2 :
283288 _a . sent ( ) ;
284289 return [ 4 /*yield*/ , this . _APIDriver . setItem ( this . _getCacheObjectKey ( requestId ) , JSON . stringify ( response ) ) ] ;
285290 case 3 :
286291 _a . sent ( ) ;
287292 this . _log ( "Updated cache for request " + requestId ) ;
288- return [ 2 /*return*/ , true ] ;
293+ if ( ! shouldCap ) return [ 3 /*break*/ , 6 ] ;
294+ capLimit = serviceDefinition . capLimit || this . _APIOptions . capLimit ;
295+ serviceDictionaryKey = this . _getServiceDictionaryKey ( service ) ;
296+ return [ 4 /*yield*/ , this . _APIDriver . getItem ( serviceDictionaryKey ) ] ;
289297 case 4 :
298+ dictionary = _a . sent ( ) ;
299+ if ( ! dictionary ) return [ 3 /*break*/ , 6 ] ;
300+ dictionary = JSON . parse ( dictionary ) ;
301+ cachedItemsCount = Object . keys ( dictionary ) . length ;
302+ if ( ! ( cachedItemsCount > capLimit ) ) return [ 3 /*break*/ , 6 ] ;
303+ this . _log ( "service " + service + " cap reached (" + cachedItemsCount + " / " + capLimit + "), removing the oldest cached item..." ) ;
304+ key = this . _getOldestCachedItem ( dictionary ) . key ;
305+ delete dictionary [ key ] ;
306+ return [ 4 /*yield*/ , this . _APIDriver . removeItem ( key ) ] ;
307+ case 5 :
308+ _a . sent ( ) ;
309+ this . _APIDriver . setItem ( serviceDictionaryKey , JSON . stringify ( dictionary ) ) ;
310+ _a . label = 6 ;
311+ case 6 : return [ 2 /*return*/ , true ] ;
312+ case 7 :
290313 err_5 = _a . sent ( ) ;
291314 throw new Error ( "Error while caching API response for " + requestId ) ;
292- case 5 : return [ 2 /*return*/ ] ;
315+ case 8 : return [ 2 /*return*/ ] ;
293316 }
294317 } ) ;
295318 } ) ;
@@ -402,6 +425,28 @@ var OfflineFirstAPI = (function () {
402425 } ) ;
403426 } ) ;
404427 } ;
428+ /**
429+ * Returns the key and the expiration date of the oldest cached item of a cache dictionary
430+ * @private
431+ * @param {ICacheDictionary } dictionary
432+ * @returns {* }
433+ * @memberof OfflineFirstAPI
434+ */
435+ OfflineFirstAPI . prototype . _getOldestCachedItem = function ( dictionary ) {
436+ var oldest ;
437+ for ( var key in dictionary ) {
438+ var keyExpiration = dictionary [ key ] ;
439+ if ( oldest ) {
440+ if ( keyExpiration < oldest . expiration ) {
441+ oldest = { key : key , expiration : keyExpiration } ;
442+ }
443+ }
444+ else {
445+ oldest = { key : key , expiration : keyExpiration } ;
446+ }
447+ }
448+ return oldest ;
449+ } ;
405450 /**
406451 * Promise that resolves every cache key associated to a service : the service dictionary's name, and all requestId
407452 * stored. This is useful to clear the cache without affecting the user's stored data not related to this API.
@@ -412,6 +457,7 @@ var OfflineFirstAPI = (function () {
412457 */
413458 OfflineFirstAPI . prototype . _getAllKeysForService = function ( service ) {
414459 return __awaiter ( this , void 0 , void 0 , function ( ) {
460+ var _this = this ;
415461 var keys , serviceDictionaryKey , dictionary , dictionaryKeys , err_8 ;
416462 return __generator ( this , function ( _a ) {
417463 switch ( _a . label ) {
@@ -425,7 +471,7 @@ var OfflineFirstAPI = (function () {
425471 dictionary = _a . sent ( ) ;
426472 if ( dictionary ) {
427473 dictionary = JSON . parse ( dictionary ) ;
428- dictionaryKeys = Object . keys ( dictionary ) . map ( function ( key ) { return CACHE_PREFIX + ":" + key ; } ) ;
474+ dictionaryKeys = Object . keys ( dictionary ) . map ( function ( key ) { return _this . _APIOptions . cachePrefix + ":" + key ; } ) ;
429475 keys = keys . concat ( dictionaryKeys ) ;
430476 }
431477 return [ 2 /*return*/ , keys ] ;
@@ -445,7 +491,7 @@ var OfflineFirstAPI = (function () {
445491 * @memberof OfflineFirstAP
446492 */
447493 OfflineFirstAPI . prototype . _getServiceDictionaryKey = function ( service ) {
448- return CACHE_PREFIX + ":dictionary:" + service ;
494+ return this . _APIOptions . cachePrefix + ":dictionary:" + service ;
449495 } ;
450496 /**
451497 * Simple helper getting a request's cache key.
@@ -455,7 +501,7 @@ var OfflineFirstAPI = (function () {
455501 * @memberof OfflineFirstAP
456502 */
457503 OfflineFirstAPI . prototype . _getCacheObjectKey = function ( requestId ) {
458- return CACHE_PREFIX + ":" + requestId ;
504+ return this . _APIOptions . cachePrefix + ":" + requestId ;
459505 } ;
460506 /**
461507 * Resolve each middleware provided and merge them into a single object that will be passed to
0 commit comments