import { Injectable , Optional } from '@angular/core' ; import { CacheOptionsInterface } from '../interfaces/cache-options.interface' ; import { CacheStoragesEnum } from '../enums/cache-storages.enum' ; import { CacheStorageAbstract } from './storage/cache-storage-abstract.service' ; import { CacheSessionStorage } from './storage/session-storage/cache-session-storage.service' ; import { CacheLocalStorage } from './storage/local-storage/cache-local-storage.service' ; import { CacheMemoryStorage } from './storage/memory/cache-memory.service' ; import { StorageValueInterface } from '../interfaces/storage-value.interface' ; const CACHE_PREFIX = 'CacheService' ; const DEFAULT_STORAGE = CacheStoragesEnum . SESSION_STORAGE ; const DEFAULT_ENABLED_STORAGE = CacheStoragesEnum . MEMORY ; @ Injectable ( ) export class CacheService { /**
     * Default cache options
     */ private _defaultOptions : CacheOptionsInterface = { expires : Number . MAX_VALUE , maxAge : Number . MAX_VALUE } ; /**
     * Cache prefix
     */ private _prefix : string = CACHE_PREFIX ; public constructor ( @ Optional ( ) private _storage ) { this . _validateStorage ( ) ; } param key param value param options public set ( key , value , options ? ) { let storageKey = this . _toStorageKey ( key ) ; options = options ? options : this . _defaultOptions ; if ( this . _storage . setItem ( storageKey , this . _toStorageValue ( value , options ) ) ) { if ( ! this . _isSystemKey ( key ) && options . tag ) { this . _saveTag ( options . tag , storageKey ) ; } return true ; } return false ; } param key returns public get ( key ) { let storageValue = this . _storage . getItem ( this . _toStorageKey ( key ) ) , value = null ; if ( storageValue ) { if ( this . _validateStorageValue ( storageValue ) ) { value = storageValue . value ; } else { this . remove ( key ) ; } } return value ; } param key returns public exists ( key ) { return ! ! this . get ( key ) ; } param key public remove ( key ) { this . _storage . removeItem ( this . _toStorageKey ( key ) ) ; this . _removeFromTag ( this . _toStorageKey ( key ) ) ; } /**
     * Remove all from cache
     */ public removeAll ( ) { this . _storage . clear ( ) ; } param tag returns public getTagData ( tag ) { let tags = this . get ( this . _tagsStorageKey ( ) ) || { } , result = { } ; if ( tags [ tag ] ) { tags [ tag ] . forEach ( ( key ) => { let data = this . get ( this . _fromStorageKey ( key ) ) ; if ( data ) { result [ this . _fromStorageKey ( key ) ] = data ; } } ) ; } return result ; } param type public useStorage ( type ) { let service = new CacheService ( this . _initStorage ( type ) ) ; service . setGlobalPrefix ( this . _getCachePrefix ( ) ) ; return service ; } param tag public removeTag ( tag ) { let tags = this . get ( this . _tagsStorageKey ( ) ) || { } ; if ( tags [ tag ] ) { tags [ tag ] . forEach ( ( key ) => { this . _storage . removeItem ( key ) ; } ) ; delete tags [ tag ] ; this . set ( this . _tagsStorageKey ( ) , tags ) ; } } param prefix public setGlobalPrefix ( prefix ) { this . _prefix = prefix ; } /**
     * Validate cache storage
     */ private _validateStorage ( ) { if ( ! this . _storage ) { this . _storage = this . _initStorage ( DEFAULT_STORAGE ) ; } if ( ! this . _storage . isEnabled ( ) ) { this . _storage = this . _initStorage ( DEFAULT_ENABLED_STORAGE ) ; } } param key private _removeFromTag ( key ) { let tags = this . get ( this . _tagsStorageKey ( ) ) || { } , index ; for ( let tag in tags ) { index = tags [ tag ] . indexOf ( key ) ; if ( index !== - 1 ) { tags [ tag ] . splice ( index , 1 ) ; this . set ( this . _tagsStorageKey ( ) , tags ) ; break ; } } } param type returns private _initStorage ( type ) { let storage ; switch ( type ) { case CacheStoragesEnum . SESSION_STORAGE : storage = new CacheSessionStorage ( ) ; break ; case CacheStoragesEnum . LOCAL_STORAGE : storage = new CacheLocalStorage ( ) ; break ; default : storage = new CacheMemoryStorage ( ) ; } return storage ; } private _toStorageKey ( key ) { return this . _getCachePrefix ( ) + key ; } private _fromStorageKey ( key ) { return key . replace ( this . _getCachePrefix ( ) , '' ) ; } param value param options private _toStorageValue ( value , options ) { return { value : value , options : this . _toStorageOptions ( options ) } ; } param options returns private _toStorageOptions ( options ) { var storageOptions = { } ; storageOptions . expires = options . expires ? options . expires : ( options . maxAge ? Date . now ( ) + ( options . maxAge * 1000 ) : this . _defaultOptions . expires ) ; storageOptions . maxAge = options . maxAge ? options . maxAge : this . _defaultOptions . maxAge ; return storageOptions ; } param value returns private _validateStorageValue ( value ) { return ! ! value . options . expires && value . options . expires > Date . now ( ) ; } param key private _isSystemKey ( key ) { return [ this . _tagsStorageKey ( ) ] . indexOf ( key ) !== - 1 ; } param tag param key private _saveTag ( tag , key ) { let tags = this . get ( this . _tagsStorageKey ( ) ) || { } ; if ( ! tags [ tag ] ) { tags [ tag ] = [ key ] ; } else { tags [ tag ] . push ( key ) ; } this . set ( this . _tagsStorageKey ( ) , tags ) ; } /**
     * Get global cache prefix
     * returns {string}
     * private
     */ private _getCachePrefix ( ) { return this . _prefix ; } private _tagsStorageKey ( ) { return 'CacheService_tags' ; } }