angular-persistence
Version:
A library to handle persistence for Angular 2 applications.
1,114 lines (1,095 loc) • 36.3 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('rxjs')) :
typeof define === 'function' && define.amd ? define(['exports', '@angular/core', 'rxjs'], factory) :
(factory((global.ng = global.ng || {}, global.ng.AngularPersistence = global.ng.AngularPersistence || {}),global.ng.core,global.rxjs));
}(this, (function (exports,_angular_core,rxjs) { 'use strict';
var StorageType = {};
StorageType.MEMORY = 0;
StorageType.IMMUTABLE_MEMORY = 1;
StorageType.SESSION = 2;
StorageType.LOCAL = 3;
StorageType[StorageType.MEMORY] = "MEMORY";
StorageType[StorageType.IMMUTABLE_MEMORY] = "IMMUTABLE_MEMORY";
StorageType[StorageType.SESSION] = "SESSION";
StorageType[StorageType.LOCAL] = "LOCAL";
/**
* Internal class which is an implementation of the ICache interface. This is
* intended to be a private class for framework use only and will not be
* exported by the libraries modules.
*
* @export
* \@class CacheImpl
* @template T the type of value being cached
*
* @author Scott O'Bryan
* \@since 1.0
*/
var CacheImpl = (function () {
/**
* Creates an instance of CacheImpl.
* @param {?} key
* @param {?} _loader
* @param {?} service
* @param {?=} config
*/
function CacheImpl(key, _loader, service, config) {
var _this = this;
if (config === void 0) { config = {}; }
this._loader = _loader;
var type = config.type || StorageType.MEMORY;
// For safety sake, ensure that oneUse is not present in configuration
service.defineProperty(this, "_value", key, config);
this._changes = service.changes({ key: key, type: type })
.map(function (def) { return _this._value; })
.publishBehavior(this._value)
.refCount();
}
/**
* Returns an observable to a cached value if one is loaded or
* to the value specified by the loader that was supplied when
* this cache was created if it is not.
*
* single value when it's available before marking the stream
* as complete.
* @return {?}
*/
CacheImpl.prototype.get = function () {
var _this = this;
var /** @type {?} */ result = this._value;
if (result === undefined) {
/*
* smo - if we do not have a result, then we might still have an observable from
* a previous call loaded in memory cache.
*/
var /** @type {?} */ observable = this._cachedObservable;
if (observable === undefined) {
var /** @type {?} */ loaded = this._loader();
if (loaded && loaded instanceof rxjs.Observable) {
var /** @type {?} */ newObservable = ((loaded))
.publishLast()
.refCount()
.do(function (value) { return _this._value = value; })
.do(function (value) { return _this._cachedObservable = undefined; });
// cache the observable before publishing
this._cachedObservable = newObservable;
return newObservable;
}
else {
// static values simply get assigned immedietly
result = (loaded);
this._value = result;
}
}
else {
return observable;
}
}
// We have a real value so we need to make an observable that returns said value
return rxjs.Observable.of(result);
};
/**
* A hot observable returning changes over time.
*
* @return {?}
*/
CacheImpl.prototype.changes = function () {
return this._changes;
};
/**
* Clears the cached value forcing a reload.
* @return {?}
*/
CacheImpl.prototype.clear = function () {
this._value = undefined;
};
return CacheImpl;
}());
var INFO_KEY = '__INFO';
/**
* An internal object used to track items saved by a storage object within the persistence
* framework.
*
* @export
* \@class ContainerInfo
*
* @author Scott O'Bryan
* \@since 1.0
*/
var ContainerInfo = (function () {
/**
* @param {?} _namespace
* @param {?} _container
*/
function ContainerInfo(_namespace, _container) {
this._namespace = _namespace;
this._container = _container;
var infoObj = _container.get(this._namespace);
// If we have an existing object, check its type
if (infoObj) {
if (typeof infoObj !== 'object' || !infoObj[INFO_KEY]) {
throw new Error('Potential attribute conflict detected');
}
}
}
/**
* Adds a key to this info object.
*
* @param {?} key
* @return {?}
*/
ContainerInfo.prototype.addAttribute = function (key) {
var /** @type {?} */ item = this._getInfo();
item[key] = true;
this._setInfo(item);
};
/**
* Removes a key from this info object.
*
* @param {?} key
* @return {?}
*/
ContainerInfo.prototype.removeAttribute = function (key) {
var /** @type {?} */ info = this._getInfo();
delete info[key];
this._setInfo(info);
};
/**
* Returns a list of keys that have been added to this
* info object.
*
* @return {?}
*/
ContainerInfo.prototype.getAttributes = function () {
return Object.keys(this._getInfo())
.filter(function (key) { return key !== INFO_KEY; });
};
/**
* Checks to see if the value stored in the _namespace
* is an info object or if it is empty. If it is NOT
* an info object, then false is returned.
*
* @return {?}
*/
ContainerInfo.prototype.available = function () {
var /** @type {?} */ infoObj = this._container.get(this._namespace);
return !infoObj || (typeof infoObj === 'object' && infoObj[INFO_KEY]);
};
/**
* @return {?}
*/
ContainerInfo.prototype._getInfo = function () {
var /** @type {?} */ obj = this._container.get(this._namespace);
if (!obj) {
obj = {};
obj[INFO_KEY] = true;
}
return obj;
};
/**
* @param {?} info
* @return {?}
*/
ContainerInfo.prototype._setInfo = function (info) {
// this is 1 because the info identifier will be there.
if (Object.keys(info).length <= 1) {
this._container.remove(this._namespace);
}
else {
this._container.set(this._namespace, info);
}
};
return ContainerInfo;
}());
/**
* This is an internal implementation of a storage container. It takes a PersistenceContainer
* (which has a subset of the functionality) and straps on an info object to keep track of
* items that are added to the container. This class can be used for creating storage
* containers within other storage containers.
*
* @export
* \@class PersistenceContainerImpl
*
* @author Scott O'Bryan
* \@since 1.0
*/
var SubStorage = (function () {
/**
* Creates an instance of SubStorage.
* @param {?} _namespace
* @param {?} _root
* @param {?=} _available
*/
function SubStorage(_namespace, _root, _available) {
if (_available === void 0) { _available = true; }
this._namespace = _namespace;
this._root = _root;
this._available = _available;
this._info = new ContainerInfo(_namespace, _root);
}
/**
* Sets a value
*
* @param {?} key
* @param {?} value
* @return {?}
*/
SubStorage.prototype.set = function (key, value) {
if (!this._available) {
return false;
}
var /** @type {?} */ val = this._root.set(this._getNamespacedKey(key), value);
this._info.addAttribute(key);
return val;
};
/**
* Returns a value for a given key
*
* @param {?} key
* @return {?}
*/
SubStorage.prototype.get = function (key) {
if (!this._available) {
return undefined;
}
var /** @type {?} */ val = this._root.get(this._getNamespacedKey(key));
if (val === undefined) {
this._info.removeAttribute(key);
}
return val;
};
/**
* Removes a value for a given key
*
* @param {?} key
* @return {?}
*/
SubStorage.prototype.remove = function (key) {
if (!this._available) {
return undefined;
}
this._info.removeAttribute(key);
return this._root.remove(this._getNamespacedKey(key));
};
/**
* Removes any values which have been stored using this subStorage
* container.
* @return {?}
*/
SubStorage.prototype.removeAll = function () {
var _this = this;
this._info.getAttributes().forEach(function (element) { _this.remove(element); });
};
/**
* Returns true if the parent storage object is available and if the
* available flag was set durring instantiation
*
* @return {?}
*/
SubStorage.prototype.available = function () {
return this._available && this._info.available();
};
/**
* Returns true if the value is not undefined
*
* @param {?} key
* @return {?}
*/
SubStorage.prototype.exists = function (key) {
// This will also make sure the info object is up to date.
return this.get(key) !== undefined;
};
/**
* Returns a list of un-namespaced keys that have been returned by this object.
*
* @return {?}
*/
SubStorage.prototype.keys = function () {
var _this = this;
// The exists will update the underlying storage object because
// it invokes a get. Still, we have an attributes object that is
// not tied to the object in storage, hopefully.
return this._info.getAttributes().filter(function (key) {
return _this.exists(key);
});
};
/**
* @param {?} key
* @return {?}
*/
SubStorage.prototype._getNamespacedKey = function (key) {
return this._namespace + '::' + key;
};
return SubStorage;
}());
var NULL_VALUE = '_____NULL_VALUE_____';
/**
* This is a container that wraps a browser storage object.
*
* @export
* \@class BrowserContainer
*
* @author Scott O'Bryan
* \@since 1.0
*/
var BrowserContainer = (function () {
/**
* Creates an instance of BrowserContainer.
* @param {?} _storage
*/
function BrowserContainer(_storage) {
this._storage = _storage;
}
/**
* Sets a value on the browser storage
*
* @param {?} key
* @param {?} value
* @return {?}
*/
BrowserContainer.prototype.set = function (key, value) {
try {
if (value === null) {
value = NULL_VALUE;
}
if (value === undefined) {
this._storage.removeItem(key);
}
else {
this._storage.setItem(key, JSON.stringify(value));
}
}
catch (error) {
return false;
}
return true;
};
/**
* Gets a value from browser storage
*
* @param {?} key
* @return {?}
*/
BrowserContainer.prototype.get = function (key) {
var /** @type {?} */ strval = this._storage.getItem(key);
if (strval === null) {
return undefined;
}
var /** @type {?} */ value = JSON.parse(strval);
if (value === NULL_VALUE) {
return null;
}
return value;
};
/**
* Removes a value from browser storage
*
* @param {?} key
* @return {?}
*/
BrowserContainer.prototype.remove = function (key) {
var /** @type {?} */ curVal = this.get(key);
if (curVal !== undefined) {
this._storage.removeItem(key);
}
return curVal;
};
/**
* Removes all values from browser storage
* @return {?}
*/
BrowserContainer.prototype.removeAll = function () {
this._storage.clear();
};
return BrowserContainer;
}());
var __extends$1 = (undefined && undefined.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var PREFIX = 'ANGULAR_PERSISTENCE_STORAGE';
/**
* An insternal class which implements the IStorage interface using the SubStorage implementation
* object and it's implementation of the info object.
*
* @export
* @abstract
* \@class AbstractBrowserStorage
*
* @author Scott O'Bryan
* \@since 1.0
* @abstract
*/
var AbstractBrowserStorage = (function (_super) {
__extends$1(AbstractBrowserStorage, _super);
/**
* @param {?} storage
*/
function AbstractBrowserStorage(storage) {
_super.call(this, PREFIX, new BrowserContainer(storage), (storage) ? true : false);
}
return AbstractBrowserStorage;
}(SubStorage));
var __extends = (undefined && undefined.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
/**
* Storage object which saves information to the browser session storage.
*
* @export
* \@class SessionStorage
*
* @author Scott O'Bryan
* \@since 1.0
*/
var SessionStorage = (function (_super) {
__extends(SessionStorage, _super);
function SessionStorage() {
_super.call(this, sessionStorage);
}
return SessionStorage;
}(AbstractBrowserStorage));
var __extends$2 = (undefined && undefined.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
/**
* A storage object using local storage for persistence
*
* @export
* \@class LocalStorage
*
* @author Scott O'Bryan
* \@since 1.0
*/
var LocalStorage = (function (_super) {
__extends$2(LocalStorage, _super);
/**
* Creates an instance of LocalStorage.
*/
function LocalStorage() {
_super.call(this, localStorage);
}
return LocalStorage;
}(AbstractBrowserStorage));
/**
* A storage type which stored values in memory. They are assumed to be mutable, but
* any object will work in this storage type.
*
* @export
* \@class MemoryStorage
*
* @author Scott O'Bryan
* \@since 1.0
*/
var MemoryStorage = (function () {
function MemoryStorage() {
this._data = {};
}
/**
* Always returns true
*
* @return {?}
*/
MemoryStorage.prototype.available = function () {
return true;
};
/**
* Sets a value in this object for the specified key
*
* @param {?} key
* @param {?} value
* @return {?}
*/
MemoryStorage.prototype.set = function (key, value) {
if (value === undefined) {
delete this._data[key];
}
else {
this._data[key] = value;
}
return true;
};
/**
* Returns the value of the specified key
*
* @param {?} key
* @return {?}
*/
MemoryStorage.prototype.get = function (key) {
return this._data[key];
};
/**
* Returns false if the value for the key is undefined.
*
* @param {?} key
* @return {?}
*/
MemoryStorage.prototype.exists = function (key) {
return this._data[key] !== undefined;
};
/**
* Removes a value from this object
*
* @param {?} key
* @return {?}
*/
MemoryStorage.prototype.remove = function (key) {
delete this._data[key];
};
/**
* Removes all values in this storage type.
*
* @return {?}
*/
MemoryStorage.prototype.removeAll = function () {
var /** @type {?} */ keys = Object.keys(this._data);
this._data = {};
return keys;
};
/**
* Returns a list of all keys that are stored
*
* @return {?}
*/
MemoryStorage.prototype.keys = function () {
return Object.keys(this._data);
};
return MemoryStorage;
}());
var __extends$3 = (undefined && undefined.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
/**
* Storage type for immutable memory
*
* @export
* \@class ImmutableMemoryStorage
*
* @author Scott O'Bryan
* \@since 1.0
*/
var ImmutableMemoryStorage = (function (_super) {
__extends$3(ImmutableMemoryStorage, _super);
function ImmutableMemoryStorage() {
_super.apply(this, arguments);
}
/**
* Sets a value in memory storage after stringifying the object. This
* add some overhead but ensures each copy of the object is immutable.
*
* @param {?} key
* @param {?} value
* @return {?}
*/
ImmutableMemoryStorage.prototype.set = function (key, value) {
if (value !== undefined) {
value = JSON.stringify(value);
}
return _super.prototype.set.call(this, key, value);
};
/**
* Returns an immutable value for the specified key.
*
* @param {?} key
* @return {?}
*/
ImmutableMemoryStorage.prototype.get = function (key) {
var /** @type {?} */ value = _super.prototype.get.call(this, key);
if (value !== undefined) {
return JSON.parse(value);
}
return undefined;
};
return ImmutableMemoryStorage;
}(MemoryStorage));
/**
* A factory used to retrieve Storage objects
*
* @export
* \@class StorageFactory
*
* @author Scott O'Bryan
* \@since 1.0
*/
var StorageFactory = (function () {
function StorageFactory() {
this._storages = [];
}
/**
* Returns a new instance of the storage factory.
*
* \@static
* @return {?}
*/
StorageFactory.getStorage = function () {
return new StorageFactory();
};
/**
* Returns a singleton object of a specified type. Storage
* types are initialized lazily.
*
* @param {?} type
* @return {?}
*/
StorageFactory.prototype.of = function (type) {
var /** @type {?} */ storage = this._storages[type];
if (!storage) {
switch (type) {
case StorageType.MEMORY:
storage = new MemoryStorage();
this._storages[type] = storage;
break;
case StorageType.IMMUTABLE_MEMORY:
storage = new ImmutableMemoryStorage();
break;
case StorageType.LOCAL:
storage = new LocalStorage();
break;
case StorageType.SESSION:
storage = new SessionStorage();
break;
default:
}
if (!storage || !storage.available()) {
throw new Error('Storage type not available');
}
this._storages[type] = storage;
}
return storage;
};
return StorageFactory;
}());
/**
* Service used to persist application wide storage. Iterms may be obtained from the Service
* itself or used through proxies. This framework also supports an immutable flag which will
* instruct the service that the objects stored within should not have any side-effects when
* objects on the outside are changed.
*
* Note on immutability: Only clonable objects will be saved when the immutable flag is
* set. This framework will do a deep clone of the objects in question, but items such
* as functions will not be preserved. Also, immutability is slower. If you have objects
* that are well controlled with a single component, it is suggested that you don't save your
* item as immutable.
*
* @export
* \@class PersistenceService
*
* @author Scott O'Bryan
* \@since 1.0
*/
var PersistenceService = (function () {
function PersistenceService() {
this._emitter = new _angular_core.EventEmitter();
this._storage = StorageFactory.getStorage();
}
/**
* Returns a hot observable that can be used to monitor changes to this framework over
* time. Subscribing to this observable has the potential of causing memory leaks,
* so each subscriber is expected to unsubscribe when notifications are no longer
* needed.
*
* results. If not provided, all changes will be
* returned.
*
* to this framework over time.
* @param {?=} config
* @return {?}
*/
PersistenceService.prototype.changes = function (config) {
if (config === void 0) { config = {}; }
var /** @type {?} */ observable = this._emitter.asObservable();
// apply the key filter
if (config.key) {
observable = observable.filter(function (val) { return val.key === config.key; });
}
// apply the type filter
if (config.type) {
observable = observable.filter(function (val) { return val.type === config.type; });
}
return observable;
};
/**
* Returns an object from storage. If the object was stored with the immutable flag
* set, then the object returned will not have any side-effects into the stored model
* until it is set again.
*
* @param {?} key
* @param {?=} type
* @return {?}
*/
PersistenceService.prototype.get = function (key, type) {
if (type === void 0) { type = StorageType.MEMORY; }
var /** @type {?} */ storage = this._getStorage(type);
var /** @type {?} */ value = storage.get(key);
// the value here will actually be an object with some metadata attached. This
// is done to handle immutable and some other things.
if (value) {
var /** @type {?} */ currDate = Date.now();
// if we have a value, we need to check to see if its expired.
if (value.expireAfter && value.created + value.expireAfter < currDate) {
storage.remove(key);
this._emitter.emit({ key: key, type: type });
return undefined;
}
// handle the oneUse configuration
if (value.oneUse) {
storage.remove(key);
this._emitter.emit({ key: key, type: type });
return value.data;
}
// if maxAge then we need to update the expires tag
if (value.timeout) {
if (value.lastAccessed + value.timeout < currDate) {
storage.remove(key);
this._emitter.emit({ key: key, type: type });
return undefined;
}
else {
value.lastAccessed = currDate;
storage.set(key, value);
}
}
return value.data;
}
return undefined;
};
/**
* Puts an object into storage, replacing any item that may be in there. By default,
* the object is stored as-is, which means that when other areas of code get the
* object, they can mutate it.
*
* As immutable storage is slower, and the reconstituted logic may be
* missing functions or metadata, it is recommended to use this only
* if you need to ensure the integrity of the stored object on each set
* as might be the case if you make use of the "change" emitter.
*
* @param {?} key
* @param {?} value
* @param {?=} config
* @return {?}
*/
PersistenceService.prototype.set = function (key, value, config) {
if (config === void 0) { config = {}; }
if (!config.type) {
config.type = StorageType.MEMORY;
}
if (!value === undefined) {
this.remove(key);
this._emitter.emit({ key: key, type: config.type });
return true;
}
var /** @type {?} */ storage = this._getStorage(config.type);
var /** @type {?} */ currDate = Date.now();
var /** @type {?} */ success = storage.set(key, {
data: value,
expireAfter: config.expireAfter,
timeout: config.timeout,
oneUse: config.oneUse ? true : false,
created: currDate,
lastAccessed: currDate
});
// happens if the info object or storage object cannot be saved.
// Ensure we have cleaned up.
if (success) {
// this seems kind of wierd, but if we are using an immutable
// storage type, we want the emitter
this._emitter.emit({ key: key, type: config.type });
}
else {
storage.remove(key);
}
return success;
};
/**
* Clears a value stored in the service for the given type.
*
* @param {?} key
* @param {?=} type
* @return {?}
*/
PersistenceService.prototype.remove = function (key, type) {
if (type === void 0) { type = StorageType.MEMORY; }
var /** @type {?} */ storage = this._getStorage(type);
var /** @type {?} */ currentItem = this.get(key, type);
if (currentItem !== undefined) {
storage.remove(key);
this._emitter.emit({ key: key, type: type });
}
return currentItem;
};
/**
* Clears all stored items for a particular storage type.
*
* @param {?=} type
* @return {?}
*/
PersistenceService.prototype.removeAll = function (type) {
var _this = this;
if (type === void 0) { type = StorageType.MEMORY; }
var /** @type {?} */ keys = this._getStorage(type).keys();
this._getStorage(type).removeAll();
keys.forEach(function (key) { return _this._emitter.emit({ key: key, type: type }); });
};
/**
* Cleans up any expired objects in the cache.
*
* @param {?=} type
* @return {?}
*/
PersistenceService.prototype.clean = function (type) {
if (type === void 0) { type = StorageType.MEMORY; }
var /** @type {?} */ storage = this._getStorage(type);
var /** @type {?} */ keys = storage.keys();
var /** @type {?} */ currDate = Date.now();
for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) {
var key = keys_1[_i];
var /** @type {?} */ item = storage.get(key);
// if we have a value, we need to check to see if its expired.
if (item &&
((item.expireAfter && item.created + item.expireAfter < currDate ||
item.timeout && item.lastAccessed + item.timeout < currDate))) {
this.remove(key);
}
}
};
/**
* Create a property on the object that is bound to this stored value. This method
* requires ES5 compatibility and the property will have special rules associated
* with it. The name of the property will be "key", and the value stored in the
* configured storage will be prefix + key.
*
* @template T the type of property
* @param {?} obj
* @param {?} propName
* @param {?} key
* @param {?=} config
* @return {?}
*/
PersistenceService.prototype.defineProperty = function (obj, propName, key, config) {
var _this = this;
if (config === void 0) { config = {}; }
var /** @type {?} */ type = config.type || StorageType.MEMORY;
Object.defineProperty(obj, propName, {
enumerable: true,
configurable: true,
get: function () { return _this.get(key, type); },
set: function (val) { _this.set(key, val, config); }
});
};
/**
* Returns a facade that makes things a bit easier when interacting with the service.
* The facade will use the prefix in order to isolate they keystore. If no prefix is
* defined, the keystore will be mapped as usual with the keys working as-is in the
* storage.
*
* @param {?} namespace
* @param {?=} config the config for the facade
* @return {?} a PersistenceFacade object representing this store
*/
PersistenceService.prototype.createContainer = function (namespace, config) {
if (config === void 0) { config = {}; }
var /** @type {?} */ thisService = this;
var /** @type {?} */ myConfig = {
oneUse: config.oneUse,
expireAfter: config.expireAfter,
timeout: config.timeout,
type: config.type || StorageType.MEMORY
};
// Return a substorage of the service so the full config can be used.
return new SubStorage(namespace, {
get: function (key) {
return thisService.get(key, myConfig.type);
},
set: function (key, value) {
return thisService.set(key, value, myConfig);
},
remove: function (key) {
return thisService.remove(key, myConfig.type);
},
removeAll: function () {
return thisService.removeAll();
}
}, true);
};
/**
* Returns a cache proxy that makes interacting with this service a little bit easier. The
* proxy returned will have a set key, a generic loader, and a consistent set of config
* parameters. Please note that the "expires" property of the config might have unforseen
* side-effects to the cache in that if the expires setting is already passed, the cache will
* no longer cache values until a new proxy is created.
*
* @param {?} key they key for the item in the persistence layer
* @param {?} loader the function to load the intiial value. Must return either a value or
* an Observable of that value. If an observable is returned, it will be
* converted into a single by this method and returned to the subscriber.
* @param {?=} config optional config object used to "set" the value if it has not already
* been loaded. If a "type" is not specified, memory storage will be
* used.
*
* @return {?} a CacheProxy that can be used to interact with this cache.
*/
PersistenceService.prototype.createCache = function (key, loader, config) {
if (config === void 0) { config = {}; }
// for safety ensure that oneUse is not present. It shouldn't be, but sometimes
// typescript doesn't always catch errors
var /** @type {?} */ myConfig = {
type: config.type || StorageType.MEMORY,
expireAfter: config.expireAfter,
timeout: config.timeout
};
return new CacheImpl(key, loader, this, myConfig);
};
/**
* @param {?} type
* @return {?}
*/
PersistenceService.prototype._getStorage = function (type) {
return this._storage.of(type);
};
/**
* @param {?} maxAge
* @return {?}
*/
PersistenceService.prototype._calculateExpires = function (maxAge) {
return maxAge ? Date.now() + maxAge : undefined;
};
PersistenceService.decorators = [
{ type: _angular_core.Injectable },
];
/** @nocollapse */
PersistenceService.ctorParameters = function () { return []; };
return PersistenceService;
}());
/**
* This is a cache that also implements the <code>CanActivate</code> and <code>Resolve<T></code>
* interfaces in angular so that it can be used as both a provider and a set of guards for Angular
* routing. By implementing the abstract <code>getCache<T></code> method using a cache object,
* this abstract class can form the foundation for a service based off of the persistence framework.
*
* @export
* @abstract
* \@class AbstraceCachedService
* @template T - the type of value returned by this service.
*
* @author Scott O'Bryan
* \@since 1.0
* @abstract
*/
var AbstractCachedService = (function () {
function AbstractCachedService() {
}
/**
* Returns an {Observable<T>} which will monitor changes to the
* cache over a period of time. This is a hot, multi-value
* observable which will emit the cached value, if one exists,
* when the Observable is first subscribed to. The observer will
* then emit a new event each time the cache changes.
*
* As this is a multi-value observer which is not expected to
* complete, it is the responsiblity of the subscriber to
* unsubscribe in order to prevent potential memory leaks.
*
* the value in the cache changes
* @return {?}
*/
AbstractCachedService.prototype.changes = function () {
return this.getCache().changes();
};
/**
* Returns an {Observable<T>} to a cached value if one is loaded
* or to the value specified by the loader that was supplied when
* this cache was created if it is not.
*
* This Observable is guarenteed to be a single observable which
* means it returns a single value before it completes. As such
* you do not have to unsubscribe from this Observable.
*
* value.
* @return {?}
*/
AbstractCachedService.prototype.get = function () {
return this.getCache().get();
};
/**
* Manually clears the value in the cache forcing a reload.
*
* @abstract
* @return {?}
*/
AbstractCachedService.prototype.clear = function () {
return this.getCache().clear();
};
/**
* Returns the observable to the current cached service for use in the angular Router.
* This is equivalent to the get method but implements the resolve interface for the
* Angular Router.
*
* @param {?} route
* @param {?} state
* @return {?}
*/
AbstractCachedService.prototype.resolve = function (route, state) {
return this.get();
};
/**
* Returns true if the value of the cached observable is "truthy" and false if it is not.
*
*
* \@memberOf AbstraceCachedService
* @param {?} route
* @param {?} state
* @return {?}
*/
AbstractCachedService.prototype.canActivate = function (route, state) {
return this.get().map(function (val) { return val ? true : false; });
};
/**
* Returns a cache that this service will use to return values. The Cache may be obtained
* from the PersistenceService or it may be a custom implementation should one be needed.
*
* @protected
* @abstract
* @template T
* @abstract
* @return {?}
*/
AbstractCachedService.prototype.getCache = function () { };
return AbstractCachedService;
}());
/**
* The module for the persistence framework. This will register the PersistenceService
* as a provider and export it.
*
* @export
* \@class AngularPersistenceModule
*
* @author Scott O'Bryan
* \@since 1.0
*/
var PersistenceModule = (function () {
function PersistenceModule() {
}
PersistenceModule.decorators = [
{ type: _angular_core.NgModule, args: [{
providers: [PersistenceService]
},] },
];
/** @nocollapse */
PersistenceModule.ctorParameters = function () { return []; };
return PersistenceModule;
}());
/**
* Entry point for all public APIs of the package.
*/
exports.PersistenceService = PersistenceService;
exports.AbstractCachedService = AbstractCachedService;
exports.StorageType = StorageType;
exports.PersistenceModule = PersistenceModule;
Object.defineProperty(exports, '__esModule', { value: true });
})));