Socket
Socket
Sign inDemoInstall

angular-async-local-storage

Package Overview
Dependencies
6
Maintainers
1
Versions
20
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 4.0.0 to 5.0.0

src/service/validation/json-schema.d.ts

3

angular-async-local-storage.d.ts

@@ -5,3 +5,2 @@ /**

export * from './index';
export { asyncLocalStorageFactory as ɵa } from './src/module';
export { AsyncLocalDatabase as ɵb } from './src/service/databases/async-local-database';
export { databaseFactory as ɵa } from './src/module';
import { Injectable, NgModule, PLATFORM_ID } from '@angular/core';
import { ReplaySubject } from 'rxjs/ReplaySubject';
import { first, map, mergeMap } from 'rxjs/operators';
import { fromEvent } from 'rxjs/observable/fromEvent';
import { of } from 'rxjs/observable/of';
import { _throw } from 'rxjs/observable/throw';
import { race } from 'rxjs/observable/race';
import { isPlatformBrowser } from '@angular/common';
import { Observable } from 'rxjs/Observable';
import { ReplaySubject } from 'rxjs/ReplaySubject';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/mergeMap';
import 'rxjs/add/operator/pluck';
import 'rxjs/add/operator/first';
import 'rxjs/add/observable/fromEvent';
import 'rxjs/add/observable/merge';
import 'rxjs/add/observable/throw';
import 'rxjs/add/observable/of';
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* @abstract

@@ -20,83 +20,5 @@ */

}
/**
* @abstract
* @template T
* @param {?} key
* @return {?}
*/
AsyncLocalDatabase.prototype.getItem = function (key) { };
/**
* @abstract
* @param {?} key
* @param {?} data
* @return {?}
*/
AsyncLocalDatabase.prototype.setItem = function (key, data) { };
/**
* @abstract
* @param {?} key
* @return {?}
*/
AsyncLocalDatabase.prototype.removeItem = function (key) { };
/**
* @abstract
* @return {?}
*/
AsyncLocalDatabase.prototype.clear = function () { };
return AsyncLocalDatabase;
}());
var AsyncLocalStorage = (function () {
/**
* Injects a local database
* @param {?} database
*/
function AsyncLocalStorage(database) {
this.database = database;
}
/**
* Gets an item value in local storage
* @template T
* @param {?} key The item's key
* @return {?} The item's value if the key exists, null otherwise, wrapped in an RxJS Observable
*/
AsyncLocalStorage.prototype.getItem = function (key) {
return this.database.getItem(key);
};
/**
* Sets an item in local storage
* @param {?} key The item's key
* @param {?} data The item's value, must NOT be null or undefined
* @return {?} An RxJS Observable to wait the end of the operation
*/
AsyncLocalStorage.prototype.setItem = function (key, data) {
return this.database.setItem(key, data);
};
/**
* Deletes an item in local storage
* @param {?} key The item's key
* @return {?} An RxJS Observable to wait the end of the operation
*/
AsyncLocalStorage.prototype.removeItem = function (key) {
return this.database.removeItem(key);
};
/**
* Deletes all items from local storage
* @return {?} An RxJS Observable to wait the end of the operation
*/
AsyncLocalStorage.prototype.clear = function () {
return this.database.clear();
};
return AsyncLocalStorage;
}());
AsyncLocalStorage.decorators = [
{ type: Injectable },
];
/**
* @nocollapse
*/
AsyncLocalStorage.ctorParameters = function () { return [
{ type: AsyncLocalDatabase, },
]; };
var __extends = (undefined && undefined.__extends) || (function () {

@@ -112,2 +34,6 @@ var extendStatics = Object.setPrototypeOf ||

})();
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var IndexedDBDatabase = (function (_super) {

@@ -137,4 +63,6 @@ __extends(IndexedDBDatabase, _super);

/* Creating the RxJS ReplaySubject */
/* Creating the RxJS ReplaySubject */
_this.database = new ReplaySubject();
/* Connecting to IndexedDB */
/* Connecting to IndexedDB */
_this.connect();

@@ -145,2 +73,7 @@ return _this;

* Gets an item value in local storage
* @param key The item's key
* @returns The item's value if the key exists, null otherwise, wrapped in an RxJS Observable
*/
/**
* Gets an item value in local storage
* @template T

@@ -150,16 +83,27 @@ * @param {?} key The item's key

*/
IndexedDBDatabase.prototype.getItem = function (key) {
IndexedDBDatabase.prototype.getItem = /**
* Gets an item value in local storage
* @template T
* @param {?} key The item's key
* @return {?} The item's value if the key exists, null otherwise, wrapped in an RxJS Observable
*/
function (key) {
var _this = this;
/* Opening a trasaction and requesting the item in local storage */
return this.transaction().map(function (transaction) { return transaction.get(key); }).mergeMap(function (request) {
return this.transaction().pipe(map(function (transaction) { return transaction.get(key); }), mergeMap(function (request) {
/* Listening to the success event, and passing the item value if found, null otherwise */
var /** @type {?} */ success = Observable.fromEvent(request, 'success')
.pluck('target', 'result')
.map(function (result) { return result ? result[_this.dataPath] : null; });
var /** @type {?} */ success = (/** @type {?} */ (fromEvent(request, 'success'))).pipe(map(function (event) { return (/** @type {?} */ (event.target)).result; }), map(function (result) { return result && (_this.dataPath in result) ? (/** @type {?} */ (result[_this.dataPath])) : null; }));
/* Merging success and errors events and autoclosing the observable */
return Observable.merge(success, _this.toErrorObservable(request, "getter")).first();
}).first();
return (/** @type {?} */ (race(success, _this.toErrorObservable(request, "getter"))))
.pipe(first());
}), first());
};
/**
* Sets an item in local storage
* @param key The item's key
* @param data The item's value, must NOT be null or undefined
* @returns An RxJS Observable to wait the end of the operation
*/
/**
* Sets an item in local storage
* @param {?} key The item's key

@@ -169,12 +113,18 @@ * @param {?} data The item's value, must NOT be null or undefined

*/
IndexedDBDatabase.prototype.setItem = function (key, data) {
IndexedDBDatabase.prototype.setItem = /**
* Sets an item in local storage
* @param {?} key The item's key
* @param {?} data The item's value, must NOT be null or undefined
* @return {?} An RxJS Observable to wait the end of the operation
*/
function (key, data) {
var _this = this;
/* Storing null is not correctly supported by IndexedDB and unnecessary here */
if (data == null) {
return Observable.of(true).first();
return of(true);
}
/* Opening a transaction and checking if the item already exists in local storage */
return this.getItem(key).map(function (existingData) { return (existingData == null) ? 'add' : 'put'; }).mergeMap(function (method) {
return this.getItem(key).pipe(map(function (existingData) { return (existingData == null) ? 'add' : 'put'; }), mergeMap(function (method) {
/* Opening a transaction */
return _this.transaction('readwrite').mergeMap(function (transaction) {
return _this.transaction('readwrite').pipe(mergeMap(function (transaction) {
var /** @type {?} */ request;

@@ -192,49 +142,77 @@ /* Adding or updating local storage, based on previous checking */

/* Merging success (passing true) and error events and autoclosing the observable */
return Observable.merge(_this.toSuccessObservable(request), _this.toErrorObservable(request, "setter")).first();
return (/** @type {?} */ (race(_this.toSuccessObservable(request), _this.toErrorObservable(request, "setter"))))
.pipe(first());
var _a, _b;
});
}).first();
}));
}), first());
};
/**
* Deletes an item in local storage
* @param key The item's key
* @returns An RxJS Observable to wait the end of the operation
*/
/**
* Deletes an item in local storage
* @param {?} key The item's key
* @return {?} An RxJS Observable to wait the end of the operation
*/
IndexedDBDatabase.prototype.removeItem = function (key) {
IndexedDBDatabase.prototype.removeItem = /**
* Deletes an item in local storage
* @param {?} key The item's key
* @return {?} An RxJS Observable to wait the end of the operation
*/
function (key) {
var _this = this;
/* Opening a transaction and checking if the item exists in local storage */
return this.getItem(key).mergeMap(function (data) {
return this.getItem(key).pipe(mergeMap(function (data) {
/* If the item exists in local storage */
if (data != null) {
/* Opening a transaction */
return _this.transaction('readwrite').mergeMap(function (transaction) {
return _this.transaction('readwrite').pipe(mergeMap(function (transaction) {
/* Deleting the item in local storage */
var /** @type {?} */ request = transaction.delete(key);
/* Merging success (passing true) and error events and autoclosing the observable */
return Observable.merge(_this.toSuccessObservable(request), _this.toErrorObservable(request, "remover")).first();
});
return (/** @type {?} */ (race(_this.toSuccessObservable(request), _this.toErrorObservable(request, "remover"))))
.pipe(first());
}));
}
/* Passing true if the item does not exist in local storage */
return Observable.of(true).first();
}).first();
return of(true);
}), first());
};
/**
* Deletes all items from local storage
* @returns An RxJS Observable to wait the end of the operation
*/
/**
* Deletes all items from local storage
* @return {?} An RxJS Observable to wait the end of the operation
*/
IndexedDBDatabase.prototype.clear = function () {
IndexedDBDatabase.prototype.clear = /**
* Deletes all items from local storage
* @return {?} An RxJS Observable to wait the end of the operation
*/
function () {
var _this = this;
/* Opening a transaction */
return this.transaction('readwrite').mergeMap(function (transaction) {
return this.transaction('readwrite').pipe(mergeMap(function (transaction) {
/* Deleting all items from local storage */
var /** @type {?} */ request = transaction.clear();
/* Merging success (passing true) and error events and autoclosing the observable */
return Observable.merge(_this.toSuccessObservable(request), _this.toErrorObservable(request, "clearer")).first();
}).first();
return (/** @type {?} */ (race(_this.toSuccessObservable(request), _this.toErrorObservable(request, "clearer"))))
.pipe(first());
}), first());
};
/**
* Connects to IndexedDB and creates the object store on first time
*/
/**
* Connects to IndexedDB and creates the object store on first time
* @return {?}
*/
IndexedDBDatabase.prototype.connect = function () {
IndexedDBDatabase.prototype.connect = /**
* Connects to IndexedDB and creates the object store on first time
* @return {?}
*/
function () {
var _this = this;

@@ -244,5 +222,7 @@ /* Connecting to IndexedDB */

/* Listening the event fired on first connection, creating the object store for local storage */
Observable.fromEvent(request, 'upgradeneeded').first().subscribe(function (event) {
(/** @type {?} */ (fromEvent(request, 'upgradeneeded')))
.pipe(first())
.subscribe(function (event) {
/* Getting the database connection */
var /** @type {?} */ database = (((event.target)).result);
var /** @type {?} */ database = /** @type {?} */ ((/** @type {?} */ (event.target)).result);
/* Checking if the object store already exists, to avoid error */

@@ -255,7 +235,10 @@ if (!database.objectStoreNames.contains(_this.objectStoreName)) {

/* Listening the success event and converting to an RxJS Observable */
var /** @type {?} */ success = Observable.fromEvent(request, 'success');
var /** @type {?} */ success = /** @type {?} */ (fromEvent(request, 'success'));
/* Merging success and errors events */
Observable.merge(success, this.toErrorObservable(request, "connection")).first().subscribe(function (event) {
(/** @type {?} */ (race(success, this.toErrorObservable(request, "connection"))))
.pipe(first())
.subscribe(function (event) {
/* Storing the database connection for further access */
_this.database.next(/** @type {?} */ (((event.target)).result));
/* Storing the database connection for further access */
_this.database.next(/** @type {?} */ ((/** @type {?} */ (event.target)).result));
}, function (error) {

@@ -267,22 +250,50 @@ _this.database.error(/** @type {?} */ (error));

* Opens an IndexedDB transaction and gets the local storage object store
* @param mode Default to 'readonly' for read operations, or 'readwrite' for write operations
* @returns An IndexedDB transaction object store, wrapped in an RxJS Observable
*/
/**
* Opens an IndexedDB transaction and gets the local storage object store
* @param {?=} mode Default to 'readonly' for read operations, or 'readwrite' for write operations
* @return {?} An IndexedDB transaction object store, wrapped in an RxJS Observable
*/
IndexedDBDatabase.prototype.transaction = function (mode) {
IndexedDBDatabase.prototype.transaction = /**
* Opens an IndexedDB transaction and gets the local storage object store
* @param {?=} mode Default to 'readonly' for read operations, or 'readwrite' for write operations
* @return {?} An IndexedDB transaction object store, wrapped in an RxJS Observable
*/
function (mode) {
var _this = this;
if (mode === void 0) { mode = 'readonly'; }
/* From the IndexedDB connection, opening a transaction and getting the local storage objet store */
return this.database.map(function (database) { return database.transaction([_this.objectStoreName], mode).objectStore(_this.objectStoreName); });
return this.database
.pipe(map(function (database) { return database.transaction([_this.objectStoreName], mode).objectStore(_this.objectStoreName); }));
};
/**
* Transforms a IndexedDB success event in an RxJS Observable
* @param request The request to listen
* @returns A RxJS Observable with true value
*/
/**
* Transforms a IndexedDB success event in an RxJS Observable
* @param {?} request The request to listen
* @return {?} A RxJS Observable with true value
*/
IndexedDBDatabase.prototype.toSuccessObservable = function (request) {
IndexedDBDatabase.prototype.toSuccessObservable = /**
* Transforms a IndexedDB success event in an RxJS Observable
* @param {?} request The request to listen
* @return {?} A RxJS Observable with true value
*/
function (request) {
/* Transforming a IndexedDB success event in an RxJS Observable with true value */
return Observable.fromEvent(request, 'success').map(function () { return true; });
return (/** @type {?} */ (fromEvent(request, 'success')))
.pipe(map(function () { return true; }));
};
/**
* Transforms a IndexedDB error event in an RxJS ErrorObservable
* @param request The request to listen
* @param error Optionnal details about the error's origin
* @returns A RxJS ErrorObservable
*/
/**
* Transforms a IndexedDB error event in an RxJS ErrorObservable
* @param {?} request The request to listen

@@ -292,16 +303,21 @@ * @param {?=} error Optionnal details about the error's origin

*/
IndexedDBDatabase.prototype.toErrorObservable = function (request, error) {
IndexedDBDatabase.prototype.toErrorObservable = /**
* Transforms a IndexedDB error event in an RxJS ErrorObservable
* @param {?} request The request to listen
* @param {?=} error Optionnal details about the error's origin
* @return {?} A RxJS ErrorObservable
*/
function (request, error) {
if (error === void 0) { error = ""; }
/* Transforming a IndexedDB error event in an RxJS ErrorObservable */
return Observable.fromEvent(request, 'error').mergeMap(function () { return Observable.throw(new Error("IndexedDB " + error + " issue.")); });
return (/** @type {?} */ (fromEvent(request, 'error')))
.pipe(mergeMap(function (event) { return _throw(new Error("IndexedDB " + error + " issue : " + request.error.message + ".")); }));
};
IndexedDBDatabase.decorators = [
{ type: Injectable },
];
/** @nocollapse */
IndexedDBDatabase.ctorParameters = function () { return []; };
return IndexedDBDatabase;
}(AsyncLocalDatabase));
IndexedDBDatabase.decorators = [
{ type: Injectable },
];
/**
* @nocollapse
*/
IndexedDBDatabase.ctorParameters = function () { return []; };

@@ -318,2 +334,6 @@ var __extends$1 = (undefined && undefined.__extends) || (function () {

})();
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var LocalStorageDatabase = (function (_super) {

@@ -329,2 +349,7 @@ __extends$1(LocalStorageDatabase, _super);

* Gets an item value in local storage
* @param key The item's key
* @returns The item's value if the key exists, null otherwise, wrapped in an RxJS Observable
*/
/**
* Gets an item value in local storage
* @template T

@@ -334,16 +359,29 @@ * @param {?} key The item's key

*/
LocalStorageDatabase.prototype.getItem = function (key) {
var /** @type {?} */ data = this.localStorage.getItem(key);
if (data != null) {
LocalStorageDatabase.prototype.getItem = /**
* Gets an item value in local storage
* @template T
* @param {?} key The item's key
* @return {?} The item's value if the key exists, null otherwise, wrapped in an RxJS Observable
*/
function (key) {
var /** @type {?} */ unparsedData = this.localStorage.getItem(key);
var /** @type {?} */ parsedData = null;
if (unparsedData != null) {
try {
data = JSON.parse(data);
parsedData = JSON.parse(unparsedData);
}
catch (error) {
return Observable.throw(new Error("Invalid data in localStorage."));
catch (/** @type {?} */ error) {
return _throw(new Error("Invalid data in localStorage."));
}
}
return Observable.of(data);
return of(parsedData);
};
/**
* Sets an item in local storage
* @param key The item's key
* @param data The item's value, must NOT be null or undefined
* @returns An RxJS Observable to wait the end of the operation
*/
/**
* Sets an item in local storage
* @param {?} key The item's key

@@ -353,32 +391,54 @@ * @param {?} data The item's value, must NOT be null or undefined

*/
LocalStorageDatabase.prototype.setItem = function (key, data) {
LocalStorageDatabase.prototype.setItem = /**
* Sets an item in local storage
* @param {?} key The item's key
* @param {?} data The item's value, must NOT be null or undefined
* @return {?} An RxJS Observable to wait the end of the operation
*/
function (key, data) {
this.localStorage.setItem(key, JSON.stringify(data));
return Observable.of(true);
return of(true);
};
/**
* Deletes an item in local storage
* @param key The item's key
* @returns An RxJS Observable to wait the end of the operation
*/
/**
* Deletes an item in local storage
* @param {?} key The item's key
* @return {?} An RxJS Observable to wait the end of the operation
*/
LocalStorageDatabase.prototype.removeItem = function (key) {
LocalStorageDatabase.prototype.removeItem = /**
* Deletes an item in local storage
* @param {?} key The item's key
* @return {?} An RxJS Observable to wait the end of the operation
*/
function (key) {
this.localStorage.removeItem(key);
return Observable.of(true);
return of(true);
};
/**
* Deletes all items from local storage
* @returns An RxJS Observable to wait the end of the operation
*/
/**
* Deletes all items from local storage
* @return {?} An RxJS Observable to wait the end of the operation
*/
LocalStorageDatabase.prototype.clear = function () {
LocalStorageDatabase.prototype.clear = /**
* Deletes all items from local storage
* @return {?} An RxJS Observable to wait the end of the operation
*/
function () {
this.localStorage.clear();
return Observable.of(true);
return of(true);
};
LocalStorageDatabase.decorators = [
{ type: Injectable },
];
/** @nocollapse */
LocalStorageDatabase.ctorParameters = function () { return []; };
return LocalStorageDatabase;
}(AsyncLocalDatabase));
LocalStorageDatabase.decorators = [
{ type: Injectable },
];
/**
* @nocollapse
*/
LocalStorageDatabase.ctorParameters = function () { return []; };

@@ -395,2 +455,6 @@ var __extends$2 = (undefined && undefined.__extends) || (function () {

})();
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var MockLocalDatabase = (function (_super) {

@@ -405,2 +469,7 @@ __extends$2(MockLocalDatabase, _super);

* Gets an item value in local storage
* @param key The item's key
* @returns The item's value if the key exists, null otherwise, wrapped in an RxJS Observable
*/
/**
* Gets an item value in local storage
* @template T

@@ -410,8 +479,20 @@ * @param {?} key The item's key

*/
MockLocalDatabase.prototype.getItem = function (key) {
var /** @type {?} */ data = this.localStorage.get(key);
return Observable.of((data !== undefined) ? data : null);
MockLocalDatabase.prototype.getItem = /**
* Gets an item value in local storage
* @template T
* @param {?} key The item's key
* @return {?} The item's value if the key exists, null otherwise, wrapped in an RxJS Observable
*/
function (key) {
var /** @type {?} */ rawData = this.localStorage.get(key);
return of((rawData !== undefined) ? rawData : null);
};
/**
* Sets an item in local storage
* @param key The item's key
* @param data The item's value, must NOT be null or undefined
* @returns An RxJS Observable to wait the end of the operation
*/
/**
* Sets an item in local storage
* @param {?} key The item's key

@@ -421,80 +502,463 @@ * @param {?} data The item's value, must NOT be null or undefined

*/
MockLocalDatabase.prototype.setItem = function (key, data) {
MockLocalDatabase.prototype.setItem = /**
* Sets an item in local storage
* @param {?} key The item's key
* @param {?} data The item's value, must NOT be null or undefined
* @return {?} An RxJS Observable to wait the end of the operation
*/
function (key, data) {
this.localStorage.set(key, data);
return Observable.of(true);
return of(true);
};
/**
* Deletes an item in local storage
* @param key The item's key
* @returns An RxJS Observable to wait the end of the operation
*/
/**
* Deletes an item in local storage
* @param {?} key The item's key
* @return {?} An RxJS Observable to wait the end of the operation
*/
MockLocalDatabase.prototype.removeItem = function (key) {
MockLocalDatabase.prototype.removeItem = /**
* Deletes an item in local storage
* @param {?} key The item's key
* @return {?} An RxJS Observable to wait the end of the operation
*/
function (key) {
this.localStorage.delete(key);
return Observable.of(true);
return of(true);
};
/**
* Deletes all items from local storage
* @returns An RxJS Observable to wait the end of the operation
*/
/**
* Deletes all items from local storage
* @return {?} An RxJS Observable to wait the end of the operation
*/
MockLocalDatabase.prototype.clear = function () {
MockLocalDatabase.prototype.clear = /**
* Deletes all items from local storage
* @return {?} An RxJS Observable to wait the end of the operation
*/
function () {
this.localStorage.clear();
return Observable.of(true);
return of(true);
};
MockLocalDatabase.decorators = [
{ type: Injectable },
];
/** @nocollapse */
MockLocalDatabase.ctorParameters = function () { return []; };
return MockLocalDatabase;
}(AsyncLocalDatabase));
MockLocalDatabase.decorators = [
{ type: Injectable },
];
/**
* @nocollapse
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
MockLocalDatabase.ctorParameters = function () { return []; };
/**
* \@todo Add other JSON Schema validation features
*/
var JSONValidator = (function () {
function JSONValidator() {
this.simpleTypes = ['string', 'number', 'boolean', 'object'];
}
/**
* @param {?} value
* @return {?}
*/
JSONValidator.prototype.isObjectNotNull = /**
* @param {?} value
* @return {?}
*/
function (value) {
return (value !== null) && (typeof value === 'object');
};
/**
* Validate a JSON data against a JSON Schema
* @param data JSON data to validate
* @param schema Subset of JSON Schema
* @returns If data is valid : true, if it is invalid : false, and throws if the schema is invalid
*/
/**
* Validate a JSON data against a JSON Schema
* @param {?} data JSON data to validate
* @param {?} schema Subset of JSON Schema
* @return {?} If data is valid : true, if it is invalid : false, and throws if the schema is invalid
*/
JSONValidator.prototype.validate = /**
* Validate a JSON data against a JSON Schema
* @param {?} data JSON data to validate
* @param {?} schema Subset of JSON Schema
* @return {?} If data is valid : true, if it is invalid : false, and throws if the schema is invalid
*/
function (data, schema) {
if (!this.isObjectNotNull(schema)) {
throw new Error("A schema must be an object (unlike spec, booleans are not supported to enforce strict types).");
}
if ((!schema.hasOwnProperty('type') || schema.type === 'array' || schema.type === 'object')
&& !schema.hasOwnProperty('properties') && !schema.hasOwnProperty('items')) {
throw new Error("Each value must have a 'type' or 'properties' or 'items', to enforce strict types.");
}
if (schema.hasOwnProperty('type') && !this.validateType(data, schema)) {
return false;
}
if (schema.hasOwnProperty('items') && !this.validateItems(data, schema)) {
return false;
}
if (schema.hasOwnProperty('properties')) {
if (schema.hasOwnProperty('required') && !this.validateRequired(data, schema)) {
return false;
}
if (!this.validateProperties(data, schema)) {
return false;
}
}
return true;
};
/**
* @param {?} data
* @param {?} schema
* @return {?}
*/
JSONValidator.prototype.validateProperties = /**
* @param {?} data
* @param {?} schema
* @return {?}
*/
function (data, schema) {
if (!this.isObjectNotNull(data)) {
return false;
}
if (!schema.properties || !this.isObjectNotNull(schema.properties)) {
throw new Error("'properties' must be a schema object.");
}
/**
* Check if the object doesn't have more properties than expected
* Equivalent of additionalProperties: false
*/
if (Object.keys(schema.properties).length !== Object.keys(data).length) {
return false;
}
/* Recursively validate all properties */
for (var /** @type {?} */ property in schema.properties) {
if (schema.properties.hasOwnProperty(property) && data.hasOwnProperty(property)) {
if (!this.validate(data[property], schema.properties[property])) {
return false;
}
}
}
return true;
};
/**
* @param {?} data
* @param {?} schema
* @return {?}
*/
JSONValidator.prototype.validateRequired = /**
* @param {?} data
* @param {?} schema
* @return {?}
*/
function (data, schema) {
if (!this.isObjectNotNull(data)) {
return false;
}
if (!Array.isArray(schema.required)) {
throw new Error("'required' field must be an array. Note that since JSON Schema draft 6, booleans are not supported anymore.");
}
for (var _i = 0, _a = schema.required; _i < _a.length; _i++) {
var requiredProp = _a[_i];
if (typeof requiredProp !== 'string') {
throw new Error("'required' array must contain strings only.");
}
/* Checks if the property is present in the schema 'properties' */
if (!schema.properties || !schema.properties.hasOwnProperty(requiredProp)) {
throw new Error("'required' properties must be described in 'properties' too.");
}
/* Checks if the property is present in the data */
if (!data.hasOwnProperty(requiredProp)) {
return false;
}
}
return true;
};
/**
* @param {?} data
* @param {?} schema
* @return {?}
*/
JSONValidator.prototype.validateType = /**
* @param {?} data
* @param {?} schema
* @return {?}
*/
function (data, schema) {
if (Array.isArray(schema.type)) {
return this.validateTypeList(data, schema);
}
if (typeof schema.type !== 'string') {
throw new Error("'type' must be a string (arrays of types are not supported yet).");
}
if ((schema.type === 'null') && (data !== null)) {
return false;
}
if ((this.simpleTypes.indexOf(schema.type) !== -1) && (typeof data !== schema.type)) {
return false;
}
if ((schema.type === 'integer') && ((typeof data !== 'number') || !Number.isInteger(data))) {
return false;
}
return true;
};
/**
* @param {?} data
* @param {?} schema
* @return {?}
*/
JSONValidator.prototype.validateTypeList = /**
* @param {?} data
* @param {?} schema
* @return {?}
*/
function (data, schema) {
var /** @type {?} */ types = /** @type {?} */ (schema.type);
var /** @type {?} */ typesTests = [];
for (var _i = 0, types_1 = types; _i < types_1.length; _i++) {
var type = types_1[_i];
typesTests.push(this.validateType(data, { type: type }));
}
return (typesTests.indexOf(true) !== -1);
};
/**
* @param {?} data
* @param {?} schema
* @return {?}
*/
JSONValidator.prototype.validateItems = /**
* @param {?} data
* @param {?} schema
* @return {?}
*/
function (data, schema) {
if (!Array.isArray(data)) {
return false;
}
if (Array.isArray(schema.items)) {
return this.validateItemsList(data, schema);
}
if (!schema.items || !this.isObjectNotNull(schema.items)) {
throw new Error("'items' must be a schema object.");
}
for (var _i = 0, data_1 = data; _i < data_1.length; _i++) {
var value = data_1[_i];
if (!this.validate(value, schema.items)) {
return false;
}
}
return true;
};
/**
* @param {?} data
* @param {?} schema
* @return {?}
*/
JSONValidator.prototype.validateItemsList = /**
* @param {?} data
* @param {?} schema
* @return {?}
*/
function (data, schema) {
var /** @type {?} */ items = /** @type {?} */ (schema.items);
if (data.length !== items.length) {
return false;
}
for (var /** @type {?} */ i = 0; i < items.length; i += 1) {
if (!this.validate(data[i], items[i])) {
return false;
}
}
return true;
};
return JSONValidator;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* @record
*/
var AsyncLocalStorage = (function () {
function AsyncLocalStorage(database, jsonValidator) {
this.database = database;
this.jsonValidator = jsonValidator;
this.getItemOptionsDefault = {
schema: null
};
}
/**
* Gets an item value in local storage
* @param key The item's key
* @returns The item's value if the key exists, null otherwise, wrapped in an RxJS Observable
*/
/**
* Gets an item value in local storage
* @template T
* @param {?} key The item's key
* @param {?=} options
* @return {?} The item's value if the key exists, null otherwise, wrapped in an RxJS Observable
*/
AsyncLocalStorage.prototype.getItem = /**
* Gets an item value in local storage
* @template T
* @param {?} key The item's key
* @param {?=} options
* @return {?} The item's value if the key exists, null otherwise, wrapped in an RxJS Observable
*/
function (key, options) {
var _this = this;
if (options === void 0) { options = this.getItemOptionsDefault; }
return this.database.getItem(key).pipe(/* Validate data upon a json schema if requested */
mergeMap(function (data) {
if (options.schema && data !== null) {
var /** @type {?} */ validation = true;
try {
validation = _this.jsonValidator.validate(data, options.schema);
}
catch (/** @type {?} */ error) {
return _throw(error);
}
if (!validation) {
return _throw(new Error("JSON invalid"));
}
}
return of(data);
}));
};
/**
* Sets an item in local storage
* @param key The item's key
* @param data The item's value, must NOT be null or undefined
* @returns An RxJS Observable to wait the end of the operation
*/
/**
* Sets an item in local storage
* @param {?} key The item's key
* @param {?} data The item's value, must NOT be null or undefined
* @return {?} An RxJS Observable to wait the end of the operation
*/
AsyncLocalStorage.prototype.setItem = /**
* Sets an item in local storage
* @param {?} key The item's key
* @param {?} data The item's value, must NOT be null or undefined
* @return {?} An RxJS Observable to wait the end of the operation
*/
function (key, data) {
return this.database.setItem(key, data);
};
/**
* Deletes an item in local storage
* @param key The item's key
* @returns An RxJS Observable to wait the end of the operation
*/
/**
* Deletes an item in local storage
* @param {?} key The item's key
* @return {?} An RxJS Observable to wait the end of the operation
*/
AsyncLocalStorage.prototype.removeItem = /**
* Deletes an item in local storage
* @param {?} key The item's key
* @return {?} An RxJS Observable to wait the end of the operation
*/
function (key) {
return this.database.removeItem(key);
};
/**
* Deletes all items from local storage
* @returns An RxJS Observable to wait the end of the operation
*/
/**
* Deletes all items from local storage
* @return {?} An RxJS Observable to wait the end of the operation
*/
AsyncLocalStorage.prototype.clear = /**
* Deletes all items from local storage
* @return {?} An RxJS Observable to wait the end of the operation
*/
function () {
return this.database.clear();
};
AsyncLocalStorage.decorators = [
{ type: Injectable },
];
/** @nocollapse */
AsyncLocalStorage.ctorParameters = function () { return [
{ type: AsyncLocalDatabase, },
{ type: JSONValidator, },
]; };
return AsyncLocalStorage;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* @param {?} platformId
* @return {?}
*/
function asyncLocalStorageFactory(platformId) {
var /** @type {?} */ database;
function databaseFactory(platformId) {
if (isPlatformBrowser(platformId) && ('indexedDB' in window) && (indexedDB !== undefined) && (indexedDB !== null)) {
/* Try with IndexedDB in modern browsers */
database = new IndexedDBDatabase();
return new IndexedDBDatabase();
}
else if (isPlatformBrowser(platformId) && ('localStorage' in window) && (localStorage !== undefined) && (localStorage !== null)) {
/* Try with localStorage in old browsers (IE9) */
database = new LocalStorageDatabase();
return new LocalStorageDatabase();
}
else {
/* Fake database for server-side rendering (Universal) */
database = new MockLocalDatabase();
return new MockLocalDatabase();
}
return new AsyncLocalStorage(database);
}
var AsyncLocalStorageModule = (function () {
function AsyncLocalStorageModule() {
}
AsyncLocalStorageModule.decorators = [
{ type: NgModule, args: [{
providers: [
JSONValidator,
{
provide: AsyncLocalDatabase,
useFactory: databaseFactory,
deps: [PLATFORM_ID]
},
AsyncLocalStorage,
]
},] },
];
/** @nocollapse */
AsyncLocalStorageModule.ctorParameters = function () { return []; };
return AsyncLocalStorageModule;
}());
AsyncLocalStorageModule.decorators = [
{ type: NgModule, args: [{
providers: [
{
provide: AsyncLocalStorage,
useFactory: asyncLocalStorageFactory,
deps: [PLATFORM_ID]
}
]
},] },
];
/**
* @nocollapse
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
AsyncLocalStorageModule.ctorParameters = function () { return []; };
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* Generated bundle index. Do not edit.
*/
export { AsyncLocalStorage, AsyncLocalStorageModule, asyncLocalStorageFactory as ɵa, AsyncLocalDatabase as ɵb };
export { AsyncLocalDatabase, IndexedDBDatabase, LocalStorageDatabase, MockLocalDatabase, JSONValidator, AsyncLocalStorage, AsyncLocalStorageModule, databaseFactory as ɵa };
//# sourceMappingURL=angular-async-local-storage.es5.js.map
import { Injectable, NgModule, PLATFORM_ID } from '@angular/core';
import { ReplaySubject } from 'rxjs/ReplaySubject';
import { first, map, mergeMap } from 'rxjs/operators';
import { fromEvent } from 'rxjs/observable/fromEvent';
import { of } from 'rxjs/observable/of';
import { _throw } from 'rxjs/observable/throw';
import { race } from 'rxjs/observable/race';
import { isPlatformBrowser } from '@angular/common';
import { Observable } from 'rxjs/Observable';
import { ReplaySubject } from 'rxjs/ReplaySubject';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/mergeMap';
import 'rxjs/add/operator/pluck';
import 'rxjs/add/operator/first';
import 'rxjs/add/observable/fromEvent';
import 'rxjs/add/observable/merge';
import 'rxjs/add/observable/throw';
import 'rxjs/add/observable/of';
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* @abstract
*/
class AsyncLocalDatabase {
/**
* @abstract
* @template T
* @param {?} key
* @return {?}
*/
getItem(key) { }
/**
* @abstract
* @param {?} key
* @param {?} data
* @return {?}
*/
setItem(key, data) { }
/**
* @abstract
* @param {?} key
* @return {?}
*/
removeItem(key) { }
/**
* @abstract
* @return {?}
*/
clear() { }
}
class AsyncLocalStorage {
/**
* Injects a local database
* @param {?} database
*/
constructor(database) {
this.database = database;
}
/**
* Gets an item value in local storage
* @template T
* @param {?} key The item's key
* @return {?} The item's value if the key exists, null otherwise, wrapped in an RxJS Observable
*/
getItem(key) {
return this.database.getItem(key);
}
/**
* Sets an item in local storage
* @param {?} key The item's key
* @param {?} data The item's value, must NOT be null or undefined
* @return {?} An RxJS Observable to wait the end of the operation
*/
setItem(key, data) {
return this.database.setItem(key, data);
}
/**
* Deletes an item in local storage
* @param {?} key The item's key
* @return {?} An RxJS Observable to wait the end of the operation
*/
removeItem(key) {
return this.database.removeItem(key);
}
/**
* Deletes all items from local storage
* @return {?} An RxJS Observable to wait the end of the operation
*/
clear() {
return this.database.clear();
}
}
AsyncLocalStorage.decorators = [
{ type: Injectable },
];
/**
* @nocollapse
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
AsyncLocalStorage.ctorParameters = () => [
{ type: AsyncLocalDatabase, },
];
class IndexedDBDatabase extends AsyncLocalDatabase {

@@ -132,10 +59,9 @@ /**

/* Opening a trasaction and requesting the item in local storage */
return this.transaction().map((transaction) => transaction.get(key)).mergeMap((request) => {
return this.transaction().pipe(map((transaction) => transaction.get(key)), mergeMap((request) => {
/* Listening to the success event, and passing the item value if found, null otherwise */
let /** @type {?} */ success = Observable.fromEvent(request, 'success')
.pluck('target', 'result')
.map((result) => result ? result[this.dataPath] : null);
const /** @type {?} */ success = (/** @type {?} */ (fromEvent(request, 'success'))).pipe(map((event) => (/** @type {?} */ (event.target)).result), map((result) => result && (this.dataPath in result) ? (/** @type {?} */ (result[this.dataPath])) : null));
/* Merging success and errors events and autoclosing the observable */
return Observable.merge(success, this.toErrorObservable(request, `getter`)).first();
}).first();
return (/** @type {?} */ (race(success, this.toErrorObservable(request, `getter`))))
.pipe(first());
}), first());
}

@@ -151,8 +77,8 @@ /**

if (data == null) {
return Observable.of(true).first();
return of(true);
}
/* Opening a transaction and checking if the item already exists in local storage */
return this.getItem(key).map((existingData) => (existingData == null) ? 'add' : 'put').mergeMap((method) => {
return this.getItem(key).pipe(map((existingData) => (existingData == null) ? 'add' : 'put'), mergeMap((method) => {
/* Opening a transaction */
return this.transaction('readwrite').mergeMap((transaction) => {
return this.transaction('readwrite').pipe(mergeMap((transaction) => {
let /** @type {?} */ request;

@@ -170,5 +96,6 @@ /* Adding or updating local storage, based on previous checking */

/* Merging success (passing true) and error events and autoclosing the observable */
return Observable.merge(this.toSuccessObservable(request), this.toErrorObservable(request, `setter`)).first();
});
}).first();
return (/** @type {?} */ (race(this.toSuccessObservable(request), this.toErrorObservable(request, `setter`))))
.pipe(first());
}));
}), first());
}

@@ -182,16 +109,17 @@ /**

/* Opening a transaction and checking if the item exists in local storage */
return this.getItem(key).mergeMap((data) => {
return this.getItem(key).pipe(mergeMap((data) => {
/* If the item exists in local storage */
if (data != null) {
/* Opening a transaction */
return this.transaction('readwrite').mergeMap((transaction) => {
return this.transaction('readwrite').pipe(mergeMap((transaction) => {
/* Deleting the item in local storage */
let /** @type {?} */ request = transaction.delete(key);
const /** @type {?} */ request = transaction.delete(key);
/* Merging success (passing true) and error events and autoclosing the observable */
return Observable.merge(this.toSuccessObservable(request), this.toErrorObservable(request, `remover`)).first();
});
return (/** @type {?} */ (race(this.toSuccessObservable(request), this.toErrorObservable(request, `remover`))))
.pipe(first());
}));
}
/* Passing true if the item does not exist in local storage */
return Observable.of(true).first();
}).first();
return of(true);
}), first());
}

@@ -204,8 +132,9 @@ /**

/* Opening a transaction */
return this.transaction('readwrite').mergeMap((transaction) => {
return this.transaction('readwrite').pipe(mergeMap((transaction) => {
/* Deleting all items from local storage */
let /** @type {?} */ request = transaction.clear();
const /** @type {?} */ request = transaction.clear();
/* Merging success (passing true) and error events and autoclosing the observable */
return Observable.merge(this.toSuccessObservable(request), this.toErrorObservable(request, `clearer`)).first();
}).first();
return (/** @type {?} */ (race(this.toSuccessObservable(request), this.toErrorObservable(request, `clearer`))))
.pipe(first());
}), first());
}

@@ -218,7 +147,9 @@ /**

/* Connecting to IndexedDB */
let /** @type {?} */ request = indexedDB.open(this.dbName);
const /** @type {?} */ request = indexedDB.open(this.dbName);
/* Listening the event fired on first connection, creating the object store for local storage */
Observable.fromEvent(request, 'upgradeneeded').first().subscribe((event) => {
(/** @type {?} */ (fromEvent(request, 'upgradeneeded')))
.pipe(first())
.subscribe((event) => {
/* Getting the database connection */
let /** @type {?} */ database = (((event.target)).result);
const /** @type {?} */ database = /** @type {?} */ ((/** @type {?} */ (event.target)).result);
/* Checking if the object store already exists, to avoid error */

@@ -231,7 +162,9 @@ if (!database.objectStoreNames.contains(this.objectStoreName)) {

/* Listening the success event and converting to an RxJS Observable */
let /** @type {?} */ success = Observable.fromEvent(request, 'success');
const /** @type {?} */ success = /** @type {?} */ (fromEvent(request, 'success'));
/* Merging success and errors events */
Observable.merge(success, this.toErrorObservable(request, `connection`)).first().subscribe((event) => {
(/** @type {?} */ (race(success, this.toErrorObservable(request, `connection`))))
.pipe(first())
.subscribe((event) => {
/* Storing the database connection for further access */
this.database.next(/** @type {?} */ (((event.target)).result));
this.database.next(/** @type {?} */ ((/** @type {?} */ (event.target)).result));
}, (error) => {

@@ -248,3 +181,4 @@ this.database.error(/** @type {?} */ (error));

/* From the IndexedDB connection, opening a transaction and getting the local storage objet store */
return this.database.map((database) => database.transaction([this.objectStoreName], mode).objectStore(this.objectStoreName));
return this.database
.pipe(map((database) => database.transaction([this.objectStoreName], mode).objectStore(this.objectStoreName)));
}

@@ -258,3 +192,4 @@ /**

/* Transforming a IndexedDB success event in an RxJS Observable with true value */
return Observable.fromEvent(request, 'success').map(() => true);
return (/** @type {?} */ (fromEvent(request, 'success')))
.pipe(map(() => true));
}

@@ -269,3 +204,4 @@ /**

/* Transforming a IndexedDB error event in an RxJS ErrorObservable */
return Observable.fromEvent(request, 'error').mergeMap(() => Observable.throw(new Error(`IndexedDB ${error} issue.`)));
return (/** @type {?} */ (fromEvent(request, 'error')))
.pipe(mergeMap((event) => _throw(new Error(`IndexedDB ${error} issue : ${request.error.message}.`))));
}

@@ -276,7 +212,9 @@ }

];
/** @nocollapse */
IndexedDBDatabase.ctorParameters = () => [];
/**
* @nocollapse
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
IndexedDBDatabase.ctorParameters = () => [];
class LocalStorageDatabase extends AsyncLocalDatabase {

@@ -295,12 +233,13 @@ constructor() {

getItem(key) {
let /** @type {?} */ data = this.localStorage.getItem(key);
if (data != null) {
const /** @type {?} */ unparsedData = this.localStorage.getItem(key);
let /** @type {?} */ parsedData = null;
if (unparsedData != null) {
try {
data = JSON.parse(data);
parsedData = JSON.parse(unparsedData);
}
catch (error) {
return Observable.throw(new Error(`Invalid data in localStorage.`));
catch (/** @type {?} */ error) {
return _throw(new Error(`Invalid data in localStorage.`));
}
}
return Observable.of(data);
return of(parsedData);
}

@@ -315,3 +254,3 @@ /**

this.localStorage.setItem(key, JSON.stringify(data));
return Observable.of(true);
return of(true);
}

@@ -325,3 +264,3 @@ /**

this.localStorage.removeItem(key);
return Observable.of(true);
return of(true);
}

@@ -334,3 +273,3 @@ /**

this.localStorage.clear();
return Observable.of(true);
return of(true);
}

@@ -341,7 +280,9 @@ }

];
/** @nocollapse */
LocalStorageDatabase.ctorParameters = () => [];
/**
* @nocollapse
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
LocalStorageDatabase.ctorParameters = () => [];
class MockLocalDatabase extends AsyncLocalDatabase {

@@ -359,4 +300,4 @@ constructor() {

getItem(key) {
let /** @type {?} */ data = this.localStorage.get(key);
return Observable.of((data !== undefined) ? data : null);
const /** @type {?} */ rawData = this.localStorage.get(key);
return of((rawData !== undefined) ? rawData : null);
}

@@ -371,3 +312,3 @@ /**

this.localStorage.set(key, data);
return Observable.of(true);
return of(true);
}

@@ -381,3 +322,3 @@ /**

this.localStorage.delete(key);
return Observable.of(true);
return of(true);
}

@@ -390,3 +331,3 @@ /**

this.localStorage.clear();
return Observable.of(true);
return of(true);
}

@@ -397,28 +338,287 @@ }

];
/** @nocollapse */
MockLocalDatabase.ctorParameters = () => [];
/**
* @nocollapse
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
MockLocalDatabase.ctorParameters = () => [];
/**
* \@todo Add other JSON Schema validation features
*/
class JSONValidator {
constructor() {
this.simpleTypes = ['string', 'number', 'boolean', 'object'];
}
/**
* @param {?} value
* @return {?}
*/
isObjectNotNull(value) {
return (value !== null) && (typeof value === 'object');
}
/**
* Validate a JSON data against a JSON Schema
* @param {?} data JSON data to validate
* @param {?} schema Subset of JSON Schema
* @return {?} If data is valid : true, if it is invalid : false, and throws if the schema is invalid
*/
validate(data, schema) {
if (!this.isObjectNotNull(schema)) {
throw new Error(`A schema must be an object (unlike spec, booleans are not supported to enforce strict types).`);
}
if ((!schema.hasOwnProperty('type') || schema.type === 'array' || schema.type === 'object')
&& !schema.hasOwnProperty('properties') && !schema.hasOwnProperty('items')) {
throw new Error(`Each value must have a 'type' or 'properties' or 'items', to enforce strict types.`);
}
if (schema.hasOwnProperty('type') && !this.validateType(data, schema)) {
return false;
}
if (schema.hasOwnProperty('items') && !this.validateItems(data, schema)) {
return false;
}
if (schema.hasOwnProperty('properties')) {
if (schema.hasOwnProperty('required') && !this.validateRequired(data, schema)) {
return false;
}
if (!this.validateProperties(data, schema)) {
return false;
}
}
return true;
}
/**
* @param {?} data
* @param {?} schema
* @return {?}
*/
validateProperties(data, schema) {
if (!this.isObjectNotNull(data)) {
return false;
}
if (!schema.properties || !this.isObjectNotNull(schema.properties)) {
throw new Error(`'properties' must be a schema object.`);
}
/**
* Check if the object doesn't have more properties than expected
* Equivalent of additionalProperties: false
*/
if (Object.keys(schema.properties).length !== Object.keys(data).length) {
return false;
}
/* Recursively validate all properties */
for (let /** @type {?} */ property in schema.properties) {
if (schema.properties.hasOwnProperty(property) && data.hasOwnProperty(property)) {
if (!this.validate(data[property], schema.properties[property])) {
return false;
}
}
}
return true;
}
/**
* @param {?} data
* @param {?} schema
* @return {?}
*/
validateRequired(data, schema) {
if (!this.isObjectNotNull(data)) {
return false;
}
if (!Array.isArray(schema.required)) {
throw new Error(`'required' field must be an array. Note that since JSON Schema draft 6, booleans are not supported anymore.`);
}
for (let /** @type {?} */ requiredProp of schema.required) {
if (typeof requiredProp !== 'string') {
throw new Error(`'required' array must contain strings only.`);
}
/* Checks if the property is present in the schema 'properties' */
if (!schema.properties || !schema.properties.hasOwnProperty(requiredProp)) {
throw new Error(`'required' properties must be described in 'properties' too.`);
}
/* Checks if the property is present in the data */
if (!data.hasOwnProperty(requiredProp)) {
return false;
}
}
return true;
}
/**
* @param {?} data
* @param {?} schema
* @return {?}
*/
validateType(data, schema) {
if (Array.isArray(schema.type)) {
return this.validateTypeList(data, schema);
}
if (typeof schema.type !== 'string') {
throw new Error(`'type' must be a string (arrays of types are not supported yet).`);
}
if ((schema.type === 'null') && (data !== null)) {
return false;
}
if ((this.simpleTypes.indexOf(schema.type) !== -1) && (typeof data !== schema.type)) {
return false;
}
if ((schema.type === 'integer') && ((typeof data !== 'number') || !Number.isInteger(data))) {
return false;
}
return true;
}
/**
* @param {?} data
* @param {?} schema
* @return {?}
*/
validateTypeList(data, schema) {
const /** @type {?} */ types = /** @type {?} */ (schema.type);
const /** @type {?} */ typesTests = [];
for (let /** @type {?} */ type of types) {
typesTests.push(this.validateType(data, { type }));
}
return (typesTests.indexOf(true) !== -1);
}
/**
* @param {?} data
* @param {?} schema
* @return {?}
*/
validateItems(data, schema) {
if (!Array.isArray(data)) {
return false;
}
if (Array.isArray(schema.items)) {
return this.validateItemsList(data, schema);
}
if (!schema.items || !this.isObjectNotNull(schema.items)) {
throw new Error(`'items' must be a schema object.`);
}
for (let /** @type {?} */ value of data) {
if (!this.validate(value, schema.items)) {
return false;
}
}
return true;
}
/**
* @param {?} data
* @param {?} schema
* @return {?}
*/
validateItemsList(data, schema) {
const /** @type {?} */ items = /** @type {?} */ (schema.items);
if (data.length !== items.length) {
return false;
}
for (let /** @type {?} */ i = 0; i < items.length; i += 1) {
if (!this.validate(data[i], items[i])) {
return false;
}
}
return true;
}
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* @record
*/
class AsyncLocalStorage {
/**
* @param {?} database
* @param {?} jsonValidator
*/
constructor(database, jsonValidator) {
this.database = database;
this.jsonValidator = jsonValidator;
this.getItemOptionsDefault = {
schema: null
};
}
/**
* Gets an item value in local storage
* @template T
* @param {?} key The item's key
* @param {?=} options
* @return {?} The item's value if the key exists, null otherwise, wrapped in an RxJS Observable
*/
getItem(key, options = this.getItemOptionsDefault) {
return this.database.getItem(key).pipe(/* Validate data upon a json schema if requested */
mergeMap((data) => {
if (options.schema && data !== null) {
let /** @type {?} */ validation = true;
try {
validation = this.jsonValidator.validate(data, options.schema);
}
catch (/** @type {?} */ error) {
return _throw(error);
}
if (!validation) {
return _throw(new Error(`JSON invalid`));
}
}
return of(data);
}));
}
/**
* Sets an item in local storage
* @param {?} key The item's key
* @param {?} data The item's value, must NOT be null or undefined
* @return {?} An RxJS Observable to wait the end of the operation
*/
setItem(key, data) {
return this.database.setItem(key, data);
}
/**
* Deletes an item in local storage
* @param {?} key The item's key
* @return {?} An RxJS Observable to wait the end of the operation
*/
removeItem(key) {
return this.database.removeItem(key);
}
/**
* Deletes all items from local storage
* @return {?} An RxJS Observable to wait the end of the operation
*/
clear() {
return this.database.clear();
}
}
AsyncLocalStorage.decorators = [
{ type: Injectable },
];
/** @nocollapse */
AsyncLocalStorage.ctorParameters = () => [
{ type: AsyncLocalDatabase, },
{ type: JSONValidator, },
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* @param {?} platformId
* @return {?}
*/
function asyncLocalStorageFactory(platformId) {
let /** @type {?} */ database;
function databaseFactory(platformId) {
if (isPlatformBrowser(platformId) && ('indexedDB' in window) && (indexedDB !== undefined) && (indexedDB !== null)) {
/* Try with IndexedDB in modern browsers */
database = new IndexedDBDatabase();
return new IndexedDBDatabase();
}
else if (isPlatformBrowser(platformId) && ('localStorage' in window) && (localStorage !== undefined) && (localStorage !== null)) {
/* Try with localStorage in old browsers (IE9) */
database = new LocalStorageDatabase();
return new LocalStorageDatabase();
}
else {
/* Fake database for server-side rendering (Universal) */
database = new MockLocalDatabase();
return new MockLocalDatabase();
}
return new AsyncLocalStorage(database);
}
class AsyncLocalStorageModule {

@@ -429,20 +629,29 @@ }

providers: [
JSONValidator,
{
provide: AsyncLocalStorage,
useFactory: asyncLocalStorageFactory,
provide: AsyncLocalDatabase,
useFactory: databaseFactory,
deps: [PLATFORM_ID]
}
},
AsyncLocalStorage,
]
},] },
];
/** @nocollapse */
AsyncLocalStorageModule.ctorParameters = () => [];
/**
* @nocollapse
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
AsyncLocalStorageModule.ctorParameters = () => [];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* Generated bundle index. Do not edit.
*/
export { AsyncLocalStorage, AsyncLocalStorageModule, asyncLocalStorageFactory as ɵa, AsyncLocalDatabase as ɵb };
export { AsyncLocalDatabase, IndexedDBDatabase, LocalStorageDatabase, MockLocalDatabase, JSONValidator, AsyncLocalStorage, AsyncLocalStorageModule, databaseFactory as ɵa };
//# sourceMappingURL=angular-async-local-storage.js.map

@@ -1,1 +0,1 @@

{"__symbolic":"module","version":3,"metadata":{"AsyncLocalStorage":{"__symbolic":"class","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Injectable"}}],"members":{"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"reference","name":"ɵb"}]}],"getItem":[{"__symbolic":"method"}],"setItem":[{"__symbolic":"method"}],"removeItem":[{"__symbolic":"method"}],"clear":[{"__symbolic":"method"}]}},"ɵa":{"__symbolic":"function"},"AsyncLocalStorageModule":{"__symbolic":"class","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"NgModule"},"arguments":[{"providers":[{"provide":{"__symbolic":"reference","name":"AsyncLocalStorage"},"useFactory":{"__symbolic":"reference","name":"ɵa"},"deps":[{"__symbolic":"reference","module":"@angular/core","name":"PLATFORM_ID"}]}]}]}],"members":{}},"ɵb":{"__symbolic":"class","members":{"getItem":[{"__symbolic":"method"}],"setItem":[{"__symbolic":"method"}],"removeItem":[{"__symbolic":"method"}],"clear":[{"__symbolic":"method"}]}}},"origins":{"AsyncLocalStorage":"./src/service/lib.service","ɵa":"./src/module","AsyncLocalStorageModule":"./src/module","ɵb":"./src/service/databases/async-local-database"},"importAs":"angular-async-local-storage"}
{"__symbolic":"module","version":4,"metadata":{"JSONSchema":{"__symbolic":"interface"},"JSONSchemaType":{"__symbolic":"interface"},"AsyncLocalDatabase":{"__symbolic":"class","members":{"getItem":[{"__symbolic":"method"}],"setItem":[{"__symbolic":"method"}],"removeItem":[{"__symbolic":"method"}],"clear":[{"__symbolic":"method"}]}},"IndexedDBDatabase":{"__symbolic":"class","extends":{"__symbolic":"reference","name":"AsyncLocalDatabase"},"decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Injectable","line":12,"character":1}}],"members":{"__ctor__":[{"__symbolic":"constructor"}],"getItem":[{"__symbolic":"method"}],"setItem":[{"__symbolic":"method"}],"removeItem":[{"__symbolic":"method"}],"clear":[{"__symbolic":"method"}],"connect":[{"__symbolic":"method"}],"transaction":[{"__symbolic":"method"}],"toSuccessObservable":[{"__symbolic":"method"}],"toErrorObservable":[{"__symbolic":"method"}]}},"LocalStorageDatabase":{"__symbolic":"class","extends":{"__symbolic":"reference","name":"AsyncLocalDatabase"},"decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Injectable","line":8,"character":1}}],"members":{"getItem":[{"__symbolic":"method"}],"setItem":[{"__symbolic":"method"}],"removeItem":[{"__symbolic":"method"}],"clear":[{"__symbolic":"method"}]}},"MockLocalDatabase":{"__symbolic":"class","extends":{"__symbolic":"reference","name":"AsyncLocalDatabase"},"decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Injectable","line":7,"character":1}}],"members":{"getItem":[{"__symbolic":"method"}],"setItem":[{"__symbolic":"method"}],"removeItem":[{"__symbolic":"method"}],"clear":[{"__symbolic":"method"}]}},"JSONValidator":{"__symbolic":"class","members":{"isObjectNotNull":[{"__symbolic":"method"}],"validate":[{"__symbolic":"method"}],"validateProperties":[{"__symbolic":"method"}],"validateRequired":[{"__symbolic":"method"}],"validateType":[{"__symbolic":"method"}],"validateTypeList":[{"__symbolic":"method"}],"validateItems":[{"__symbolic":"method"}],"validateItemsList":[{"__symbolic":"method"}]}},"ALSGetItemOptions":{"__symbolic":"interface"},"AsyncLocalStorage":{"__symbolic":"class","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Injectable","line":14,"character":1}}],"members":{"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"reference","name":"AsyncLocalDatabase"},{"__symbolic":"reference","name":"JSONValidator"}]}],"getItem":[{"__symbolic":"method"}],"setItem":[{"__symbolic":"method"}],"removeItem":[{"__symbolic":"method"}],"clear":[{"__symbolic":"method"}]}},"ɵa":{"__symbolic":"function"},"AsyncLocalStorageModule":{"__symbolic":"class","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"NgModule","line":31,"character":1},"arguments":[{"providers":[{"__symbolic":"reference","name":"JSONValidator"},{"provide":{"__symbolic":"reference","name":"AsyncLocalDatabase"},"useFactory":{"__symbolic":"reference","name":"ɵa"},"deps":[{"__symbolic":"reference","module":"@angular/core","name":"PLATFORM_ID","line":37,"character":13}]},{"__symbolic":"reference","name":"AsyncLocalStorage"}]}]}],"members":{}}},"origins":{"JSONSchema":"./src/service/validation/json-schema","JSONSchemaType":"./src/service/validation/json-schema","AsyncLocalDatabase":"./src/service/databases/async-local-database","IndexedDBDatabase":"./src/service/databases/indexeddb-database","LocalStorageDatabase":"./src/service/databases/localstorage-database","MockLocalDatabase":"./src/service/databases/mock-local-database","JSONValidator":"./src/service/validation/json-validator","ALSGetItemOptions":"./src/service/lib.service","AsyncLocalStorage":"./src/service/lib.service","ɵa":"./src/module","AsyncLocalStorageModule":"./src/module"},"importAs":"angular-async-local-storage"}
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('@angular/common'), require('rxjs/Observable'), require('rxjs/ReplaySubject'), require('rxjs/add/operator/map'), require('rxjs/add/operator/mergeMap'), require('rxjs/add/operator/pluck'), require('rxjs/add/operator/first'), require('rxjs/add/observable/fromEvent'), require('rxjs/add/observable/merge'), require('rxjs/add/observable/throw'), require('rxjs/add/observable/of')) :
typeof define === 'function' && define.amd ? define(['exports', '@angular/core', '@angular/common', 'rxjs/Observable', 'rxjs/ReplaySubject', 'rxjs/add/operator/map', 'rxjs/add/operator/mergeMap', 'rxjs/add/operator/pluck', 'rxjs/add/operator/first', 'rxjs/add/observable/fromEvent', 'rxjs/add/observable/merge', 'rxjs/add/observable/throw', 'rxjs/add/observable/of'], factory) :
(factory((global.angularAsyncLocalStorage = global.angularAsyncLocalStorage || {}),global.ng.core,global.ng.common,global.Rx,global.Rx));
}(this, (function (exports,_angular_core,_angular_common,rxjs_Observable,rxjs_ReplaySubject) { 'use strict';
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('rxjs/ReplaySubject'), require('rxjs/operators'), require('rxjs/observable/fromEvent'), require('rxjs/observable/of'), require('rxjs/observable/throw'), require('rxjs/observable/race'), require('@angular/common')) :
typeof define === 'function' && define.amd ? define(['exports', '@angular/core', 'rxjs/ReplaySubject', 'rxjs/operators', 'rxjs/observable/fromEvent', 'rxjs/observable/of', 'rxjs/observable/throw', 'rxjs/observable/race', '@angular/common'], factory) :
(factory((global.angularAsyncLocalStorage = global.angularAsyncLocalStorage || {}),global.ng.core,global.Rx,global.Rx.operators,global.Rx.Observable,global.Rx.Observable,global.Rx.Observable,global.Rx.Observable,global.ng.common));
}(this, (function (exports,_angular_core,rxjs_ReplaySubject,rxjs_operators,rxjs_observable_fromEvent,rxjs_observable_of,rxjs_observable_throw,rxjs_observable_race,_angular_common) { 'use strict';
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* @abstract

@@ -13,83 +17,5 @@ */

}
/**
* @abstract
* @template T
* @param {?} key
* @return {?}
*/
AsyncLocalDatabase.prototype.getItem = function (key) { };
/**
* @abstract
* @param {?} key
* @param {?} data
* @return {?}
*/
AsyncLocalDatabase.prototype.setItem = function (key, data) { };
/**
* @abstract
* @param {?} key
* @return {?}
*/
AsyncLocalDatabase.prototype.removeItem = function (key) { };
/**
* @abstract
* @return {?}
*/
AsyncLocalDatabase.prototype.clear = function () { };
return AsyncLocalDatabase;
}());
var AsyncLocalStorage = (function () {
/**
* Injects a local database
* @param {?} database
*/
function AsyncLocalStorage(database) {
this.database = database;
}
/**
* Gets an item value in local storage
* @template T
* @param {?} key The item's key
* @return {?} The item's value if the key exists, null otherwise, wrapped in an RxJS Observable
*/
AsyncLocalStorage.prototype.getItem = function (key) {
return this.database.getItem(key);
};
/**
* Sets an item in local storage
* @param {?} key The item's key
* @param {?} data The item's value, must NOT be null or undefined
* @return {?} An RxJS Observable to wait the end of the operation
*/
AsyncLocalStorage.prototype.setItem = function (key, data) {
return this.database.setItem(key, data);
};
/**
* Deletes an item in local storage
* @param {?} key The item's key
* @return {?} An RxJS Observable to wait the end of the operation
*/
AsyncLocalStorage.prototype.removeItem = function (key) {
return this.database.removeItem(key);
};
/**
* Deletes all items from local storage
* @return {?} An RxJS Observable to wait the end of the operation
*/
AsyncLocalStorage.prototype.clear = function () {
return this.database.clear();
};
return AsyncLocalStorage;
}());
AsyncLocalStorage.decorators = [
{ type: _angular_core.Injectable },
];
/**
* @nocollapse
*/
AsyncLocalStorage.ctorParameters = function () { return [
{ type: AsyncLocalDatabase, },
]; };
var __extends = (undefined && undefined.__extends) || (function () {

@@ -105,2 +31,6 @@ var extendStatics = Object.setPrototypeOf ||

})();
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var IndexedDBDatabase = (function (_super) {

@@ -130,4 +60,6 @@ __extends(IndexedDBDatabase, _super);

/* Creating the RxJS ReplaySubject */
/* Creating the RxJS ReplaySubject */
_this.database = new rxjs_ReplaySubject.ReplaySubject();
/* Connecting to IndexedDB */
/* Connecting to IndexedDB */
_this.connect();

@@ -138,2 +70,7 @@ return _this;

* Gets an item value in local storage
* @param key The item's key
* @returns The item's value if the key exists, null otherwise, wrapped in an RxJS Observable
*/
/**
* Gets an item value in local storage
* @template T

@@ -143,16 +80,27 @@ * @param {?} key The item's key

*/
IndexedDBDatabase.prototype.getItem = function (key) {
IndexedDBDatabase.prototype.getItem = /**
* Gets an item value in local storage
* @template T
* @param {?} key The item's key
* @return {?} The item's value if the key exists, null otherwise, wrapped in an RxJS Observable
*/
function (key) {
var _this = this;
/* Opening a trasaction and requesting the item in local storage */
return this.transaction().map(function (transaction) { return transaction.get(key); }).mergeMap(function (request) {
return this.transaction().pipe(rxjs_operators.map(function (transaction) { return transaction.get(key); }), rxjs_operators.mergeMap(function (request) {
/* Listening to the success event, and passing the item value if found, null otherwise */
var /** @type {?} */ success = rxjs_Observable.Observable.fromEvent(request, 'success')
.pluck('target', 'result')
.map(function (result) { return result ? result[_this.dataPath] : null; });
var /** @type {?} */ success = (/** @type {?} */ (rxjs_observable_fromEvent.fromEvent(request, 'success'))).pipe(rxjs_operators.map(function (event) { return (/** @type {?} */ (event.target)).result; }), rxjs_operators.map(function (result) { return result && (_this.dataPath in result) ? (/** @type {?} */ (result[_this.dataPath])) : null; }));
/* Merging success and errors events and autoclosing the observable */
return rxjs_Observable.Observable.merge(success, _this.toErrorObservable(request, "getter")).first();
}).first();
return (/** @type {?} */ (rxjs_observable_race.race(success, _this.toErrorObservable(request, "getter"))))
.pipe(rxjs_operators.first());
}), rxjs_operators.first());
};
/**
* Sets an item in local storage
* @param key The item's key
* @param data The item's value, must NOT be null or undefined
* @returns An RxJS Observable to wait the end of the operation
*/
/**
* Sets an item in local storage
* @param {?} key The item's key

@@ -162,12 +110,18 @@ * @param {?} data The item's value, must NOT be null or undefined

*/
IndexedDBDatabase.prototype.setItem = function (key, data) {
IndexedDBDatabase.prototype.setItem = /**
* Sets an item in local storage
* @param {?} key The item's key
* @param {?} data The item's value, must NOT be null or undefined
* @return {?} An RxJS Observable to wait the end of the operation
*/
function (key, data) {
var _this = this;
/* Storing null is not correctly supported by IndexedDB and unnecessary here */
if (data == null) {
return rxjs_Observable.Observable.of(true).first();
return rxjs_observable_of.of(true);
}
/* Opening a transaction and checking if the item already exists in local storage */
return this.getItem(key).map(function (existingData) { return (existingData == null) ? 'add' : 'put'; }).mergeMap(function (method) {
return this.getItem(key).pipe(rxjs_operators.map(function (existingData) { return (existingData == null) ? 'add' : 'put'; }), rxjs_operators.mergeMap(function (method) {
/* Opening a transaction */
return _this.transaction('readwrite').mergeMap(function (transaction) {
return _this.transaction('readwrite').pipe(rxjs_operators.mergeMap(function (transaction) {
var /** @type {?} */ request;

@@ -185,49 +139,77 @@ /* Adding or updating local storage, based on previous checking */

/* Merging success (passing true) and error events and autoclosing the observable */
return rxjs_Observable.Observable.merge(_this.toSuccessObservable(request), _this.toErrorObservable(request, "setter")).first();
return (/** @type {?} */ (rxjs_observable_race.race(_this.toSuccessObservable(request), _this.toErrorObservable(request, "setter"))))
.pipe(rxjs_operators.first());
var _a, _b;
});
}).first();
}));
}), rxjs_operators.first());
};
/**
* Deletes an item in local storage
* @param key The item's key
* @returns An RxJS Observable to wait the end of the operation
*/
/**
* Deletes an item in local storage
* @param {?} key The item's key
* @return {?} An RxJS Observable to wait the end of the operation
*/
IndexedDBDatabase.prototype.removeItem = function (key) {
IndexedDBDatabase.prototype.removeItem = /**
* Deletes an item in local storage
* @param {?} key The item's key
* @return {?} An RxJS Observable to wait the end of the operation
*/
function (key) {
var _this = this;
/* Opening a transaction and checking if the item exists in local storage */
return this.getItem(key).mergeMap(function (data) {
return this.getItem(key).pipe(rxjs_operators.mergeMap(function (data) {
/* If the item exists in local storage */
if (data != null) {
/* Opening a transaction */
return _this.transaction('readwrite').mergeMap(function (transaction) {
return _this.transaction('readwrite').pipe(rxjs_operators.mergeMap(function (transaction) {
/* Deleting the item in local storage */
var /** @type {?} */ request = transaction.delete(key);
/* Merging success (passing true) and error events and autoclosing the observable */
return rxjs_Observable.Observable.merge(_this.toSuccessObservable(request), _this.toErrorObservable(request, "remover")).first();
});
return (/** @type {?} */ (rxjs_observable_race.race(_this.toSuccessObservable(request), _this.toErrorObservable(request, "remover"))))
.pipe(rxjs_operators.first());
}));
}
/* Passing true if the item does not exist in local storage */
return rxjs_Observable.Observable.of(true).first();
}).first();
return rxjs_observable_of.of(true);
}), rxjs_operators.first());
};
/**
* Deletes all items from local storage
* @returns An RxJS Observable to wait the end of the operation
*/
/**
* Deletes all items from local storage
* @return {?} An RxJS Observable to wait the end of the operation
*/
IndexedDBDatabase.prototype.clear = function () {
IndexedDBDatabase.prototype.clear = /**
* Deletes all items from local storage
* @return {?} An RxJS Observable to wait the end of the operation
*/
function () {
var _this = this;
/* Opening a transaction */
return this.transaction('readwrite').mergeMap(function (transaction) {
return this.transaction('readwrite').pipe(rxjs_operators.mergeMap(function (transaction) {
/* Deleting all items from local storage */
var /** @type {?} */ request = transaction.clear();
/* Merging success (passing true) and error events and autoclosing the observable */
return rxjs_Observable.Observable.merge(_this.toSuccessObservable(request), _this.toErrorObservable(request, "clearer")).first();
}).first();
return (/** @type {?} */ (rxjs_observable_race.race(_this.toSuccessObservable(request), _this.toErrorObservable(request, "clearer"))))
.pipe(rxjs_operators.first());
}), rxjs_operators.first());
};
/**
* Connects to IndexedDB and creates the object store on first time
*/
/**
* Connects to IndexedDB and creates the object store on first time
* @return {?}
*/
IndexedDBDatabase.prototype.connect = function () {
IndexedDBDatabase.prototype.connect = /**
* Connects to IndexedDB and creates the object store on first time
* @return {?}
*/
function () {
var _this = this;

@@ -237,5 +219,7 @@ /* Connecting to IndexedDB */

/* Listening the event fired on first connection, creating the object store for local storage */
rxjs_Observable.Observable.fromEvent(request, 'upgradeneeded').first().subscribe(function (event) {
(/** @type {?} */ (rxjs_observable_fromEvent.fromEvent(request, 'upgradeneeded')))
.pipe(rxjs_operators.first())
.subscribe(function (event) {
/* Getting the database connection */
var /** @type {?} */ database = (((event.target)).result);
var /** @type {?} */ database = /** @type {?} */ ((/** @type {?} */ (event.target)).result);
/* Checking if the object store already exists, to avoid error */

@@ -248,7 +232,10 @@ if (!database.objectStoreNames.contains(_this.objectStoreName)) {

/* Listening the success event and converting to an RxJS Observable */
var /** @type {?} */ success = rxjs_Observable.Observable.fromEvent(request, 'success');
var /** @type {?} */ success = /** @type {?} */ (rxjs_observable_fromEvent.fromEvent(request, 'success'));
/* Merging success and errors events */
rxjs_Observable.Observable.merge(success, this.toErrorObservable(request, "connection")).first().subscribe(function (event) {
(/** @type {?} */ (rxjs_observable_race.race(success, this.toErrorObservable(request, "connection"))))
.pipe(rxjs_operators.first())
.subscribe(function (event) {
/* Storing the database connection for further access */
_this.database.next(/** @type {?} */ (((event.target)).result));
/* Storing the database connection for further access */
_this.database.next(/** @type {?} */ ((/** @type {?} */ (event.target)).result));
}, function (error) {

@@ -260,22 +247,50 @@ _this.database.error(/** @type {?} */ (error));

* Opens an IndexedDB transaction and gets the local storage object store
* @param mode Default to 'readonly' for read operations, or 'readwrite' for write operations
* @returns An IndexedDB transaction object store, wrapped in an RxJS Observable
*/
/**
* Opens an IndexedDB transaction and gets the local storage object store
* @param {?=} mode Default to 'readonly' for read operations, or 'readwrite' for write operations
* @return {?} An IndexedDB transaction object store, wrapped in an RxJS Observable
*/
IndexedDBDatabase.prototype.transaction = function (mode) {
IndexedDBDatabase.prototype.transaction = /**
* Opens an IndexedDB transaction and gets the local storage object store
* @param {?=} mode Default to 'readonly' for read operations, or 'readwrite' for write operations
* @return {?} An IndexedDB transaction object store, wrapped in an RxJS Observable
*/
function (mode) {
var _this = this;
if (mode === void 0) { mode = 'readonly'; }
/* From the IndexedDB connection, opening a transaction and getting the local storage objet store */
return this.database.map(function (database) { return database.transaction([_this.objectStoreName], mode).objectStore(_this.objectStoreName); });
return this.database
.pipe(rxjs_operators.map(function (database) { return database.transaction([_this.objectStoreName], mode).objectStore(_this.objectStoreName); }));
};
/**
* Transforms a IndexedDB success event in an RxJS Observable
* @param request The request to listen
* @returns A RxJS Observable with true value
*/
/**
* Transforms a IndexedDB success event in an RxJS Observable
* @param {?} request The request to listen
* @return {?} A RxJS Observable with true value
*/
IndexedDBDatabase.prototype.toSuccessObservable = function (request) {
IndexedDBDatabase.prototype.toSuccessObservable = /**
* Transforms a IndexedDB success event in an RxJS Observable
* @param {?} request The request to listen
* @return {?} A RxJS Observable with true value
*/
function (request) {
/* Transforming a IndexedDB success event in an RxJS Observable with true value */
return rxjs_Observable.Observable.fromEvent(request, 'success').map(function () { return true; });
return (/** @type {?} */ (rxjs_observable_fromEvent.fromEvent(request, 'success')))
.pipe(rxjs_operators.map(function () { return true; }));
};
/**
* Transforms a IndexedDB error event in an RxJS ErrorObservable
* @param request The request to listen
* @param error Optionnal details about the error's origin
* @returns A RxJS ErrorObservable
*/
/**
* Transforms a IndexedDB error event in an RxJS ErrorObservable
* @param {?} request The request to listen

@@ -285,16 +300,21 @@ * @param {?=} error Optionnal details about the error's origin

*/
IndexedDBDatabase.prototype.toErrorObservable = function (request, error) {
IndexedDBDatabase.prototype.toErrorObservable = /**
* Transforms a IndexedDB error event in an RxJS ErrorObservable
* @param {?} request The request to listen
* @param {?=} error Optionnal details about the error's origin
* @return {?} A RxJS ErrorObservable
*/
function (request, error) {
if (error === void 0) { error = ""; }
/* Transforming a IndexedDB error event in an RxJS ErrorObservable */
return rxjs_Observable.Observable.fromEvent(request, 'error').mergeMap(function () { return rxjs_Observable.Observable.throw(new Error("IndexedDB " + error + " issue.")); });
return (/** @type {?} */ (rxjs_observable_fromEvent.fromEvent(request, 'error')))
.pipe(rxjs_operators.mergeMap(function (event) { return rxjs_observable_throw._throw(new Error("IndexedDB " + error + " issue : " + request.error.message + ".")); }));
};
IndexedDBDatabase.decorators = [
{ type: _angular_core.Injectable },
];
/** @nocollapse */
IndexedDBDatabase.ctorParameters = function () { return []; };
return IndexedDBDatabase;
}(AsyncLocalDatabase));
IndexedDBDatabase.decorators = [
{ type: _angular_core.Injectable },
];
/**
* @nocollapse
*/
IndexedDBDatabase.ctorParameters = function () { return []; };

@@ -311,2 +331,6 @@ var __extends$1 = (undefined && undefined.__extends) || (function () {

})();
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var LocalStorageDatabase = (function (_super) {

@@ -322,2 +346,7 @@ __extends$1(LocalStorageDatabase, _super);

* Gets an item value in local storage
* @param key The item's key
* @returns The item's value if the key exists, null otherwise, wrapped in an RxJS Observable
*/
/**
* Gets an item value in local storage
* @template T

@@ -327,16 +356,29 @@ * @param {?} key The item's key

*/
LocalStorageDatabase.prototype.getItem = function (key) {
var /** @type {?} */ data = this.localStorage.getItem(key);
if (data != null) {
LocalStorageDatabase.prototype.getItem = /**
* Gets an item value in local storage
* @template T
* @param {?} key The item's key
* @return {?} The item's value if the key exists, null otherwise, wrapped in an RxJS Observable
*/
function (key) {
var /** @type {?} */ unparsedData = this.localStorage.getItem(key);
var /** @type {?} */ parsedData = null;
if (unparsedData != null) {
try {
data = JSON.parse(data);
parsedData = JSON.parse(unparsedData);
}
catch (error) {
return rxjs_Observable.Observable.throw(new Error("Invalid data in localStorage."));
catch (/** @type {?} */ error) {
return rxjs_observable_throw._throw(new Error("Invalid data in localStorage."));
}
}
return rxjs_Observable.Observable.of(data);
return rxjs_observable_of.of(parsedData);
};
/**
* Sets an item in local storage
* @param key The item's key
* @param data The item's value, must NOT be null or undefined
* @returns An RxJS Observable to wait the end of the operation
*/
/**
* Sets an item in local storage
* @param {?} key The item's key

@@ -346,32 +388,54 @@ * @param {?} data The item's value, must NOT be null or undefined

*/
LocalStorageDatabase.prototype.setItem = function (key, data) {
LocalStorageDatabase.prototype.setItem = /**
* Sets an item in local storage
* @param {?} key The item's key
* @param {?} data The item's value, must NOT be null or undefined
* @return {?} An RxJS Observable to wait the end of the operation
*/
function (key, data) {
this.localStorage.setItem(key, JSON.stringify(data));
return rxjs_Observable.Observable.of(true);
return rxjs_observable_of.of(true);
};
/**
* Deletes an item in local storage
* @param key The item's key
* @returns An RxJS Observable to wait the end of the operation
*/
/**
* Deletes an item in local storage
* @param {?} key The item's key
* @return {?} An RxJS Observable to wait the end of the operation
*/
LocalStorageDatabase.prototype.removeItem = function (key) {
LocalStorageDatabase.prototype.removeItem = /**
* Deletes an item in local storage
* @param {?} key The item's key
* @return {?} An RxJS Observable to wait the end of the operation
*/
function (key) {
this.localStorage.removeItem(key);
return rxjs_Observable.Observable.of(true);
return rxjs_observable_of.of(true);
};
/**
* Deletes all items from local storage
* @returns An RxJS Observable to wait the end of the operation
*/
/**
* Deletes all items from local storage
* @return {?} An RxJS Observable to wait the end of the operation
*/
LocalStorageDatabase.prototype.clear = function () {
LocalStorageDatabase.prototype.clear = /**
* Deletes all items from local storage
* @return {?} An RxJS Observable to wait the end of the operation
*/
function () {
this.localStorage.clear();
return rxjs_Observable.Observable.of(true);
return rxjs_observable_of.of(true);
};
LocalStorageDatabase.decorators = [
{ type: _angular_core.Injectable },
];
/** @nocollapse */
LocalStorageDatabase.ctorParameters = function () { return []; };
return LocalStorageDatabase;
}(AsyncLocalDatabase));
LocalStorageDatabase.decorators = [
{ type: _angular_core.Injectable },
];
/**
* @nocollapse
*/
LocalStorageDatabase.ctorParameters = function () { return []; };

@@ -388,2 +452,6 @@ var __extends$2 = (undefined && undefined.__extends) || (function () {

})();
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var MockLocalDatabase = (function (_super) {

@@ -398,2 +466,7 @@ __extends$2(MockLocalDatabase, _super);

* Gets an item value in local storage
* @param key The item's key
* @returns The item's value if the key exists, null otherwise, wrapped in an RxJS Observable
*/
/**
* Gets an item value in local storage
* @template T

@@ -403,8 +476,20 @@ * @param {?} key The item's key

*/
MockLocalDatabase.prototype.getItem = function (key) {
var /** @type {?} */ data = this.localStorage.get(key);
return rxjs_Observable.Observable.of((data !== undefined) ? data : null);
MockLocalDatabase.prototype.getItem = /**
* Gets an item value in local storage
* @template T
* @param {?} key The item's key
* @return {?} The item's value if the key exists, null otherwise, wrapped in an RxJS Observable
*/
function (key) {
var /** @type {?} */ rawData = this.localStorage.get(key);
return rxjs_observable_of.of((rawData !== undefined) ? rawData : null);
};
/**
* Sets an item in local storage
* @param key The item's key
* @param data The item's value, must NOT be null or undefined
* @returns An RxJS Observable to wait the end of the operation
*/
/**
* Sets an item in local storage
* @param {?} key The item's key

@@ -414,83 +499,470 @@ * @param {?} data The item's value, must NOT be null or undefined

*/
MockLocalDatabase.prototype.setItem = function (key, data) {
MockLocalDatabase.prototype.setItem = /**
* Sets an item in local storage
* @param {?} key The item's key
* @param {?} data The item's value, must NOT be null or undefined
* @return {?} An RxJS Observable to wait the end of the operation
*/
function (key, data) {
this.localStorage.set(key, data);
return rxjs_Observable.Observable.of(true);
return rxjs_observable_of.of(true);
};
/**
* Deletes an item in local storage
* @param key The item's key
* @returns An RxJS Observable to wait the end of the operation
*/
/**
* Deletes an item in local storage
* @param {?} key The item's key
* @return {?} An RxJS Observable to wait the end of the operation
*/
MockLocalDatabase.prototype.removeItem = function (key) {
MockLocalDatabase.prototype.removeItem = /**
* Deletes an item in local storage
* @param {?} key The item's key
* @return {?} An RxJS Observable to wait the end of the operation
*/
function (key) {
this.localStorage.delete(key);
return rxjs_Observable.Observable.of(true);
return rxjs_observable_of.of(true);
};
/**
* Deletes all items from local storage
* @returns An RxJS Observable to wait the end of the operation
*/
/**
* Deletes all items from local storage
* @return {?} An RxJS Observable to wait the end of the operation
*/
MockLocalDatabase.prototype.clear = function () {
MockLocalDatabase.prototype.clear = /**
* Deletes all items from local storage
* @return {?} An RxJS Observable to wait the end of the operation
*/
function () {
this.localStorage.clear();
return rxjs_Observable.Observable.of(true);
return rxjs_observable_of.of(true);
};
MockLocalDatabase.decorators = [
{ type: _angular_core.Injectable },
];
/** @nocollapse */
MockLocalDatabase.ctorParameters = function () { return []; };
return MockLocalDatabase;
}(AsyncLocalDatabase));
MockLocalDatabase.decorators = [
{ type: _angular_core.Injectable },
];
/**
* @nocollapse
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
MockLocalDatabase.ctorParameters = function () { return []; };
/**
* \@todo Add other JSON Schema validation features
*/
var JSONValidator = (function () {
function JSONValidator() {
this.simpleTypes = ['string', 'number', 'boolean', 'object'];
}
/**
* @param {?} value
* @return {?}
*/
JSONValidator.prototype.isObjectNotNull = /**
* @param {?} value
* @return {?}
*/
function (value) {
return (value !== null) && (typeof value === 'object');
};
/**
* Validate a JSON data against a JSON Schema
* @param data JSON data to validate
* @param schema Subset of JSON Schema
* @returns If data is valid : true, if it is invalid : false, and throws if the schema is invalid
*/
/**
* Validate a JSON data against a JSON Schema
* @param {?} data JSON data to validate
* @param {?} schema Subset of JSON Schema
* @return {?} If data is valid : true, if it is invalid : false, and throws if the schema is invalid
*/
JSONValidator.prototype.validate = /**
* Validate a JSON data against a JSON Schema
* @param {?} data JSON data to validate
* @param {?} schema Subset of JSON Schema
* @return {?} If data is valid : true, if it is invalid : false, and throws if the schema is invalid
*/
function (data, schema) {
if (!this.isObjectNotNull(schema)) {
throw new Error("A schema must be an object (unlike spec, booleans are not supported to enforce strict types).");
}
if ((!schema.hasOwnProperty('type') || schema.type === 'array' || schema.type === 'object')
&& !schema.hasOwnProperty('properties') && !schema.hasOwnProperty('items')) {
throw new Error("Each value must have a 'type' or 'properties' or 'items', to enforce strict types.");
}
if (schema.hasOwnProperty('type') && !this.validateType(data, schema)) {
return false;
}
if (schema.hasOwnProperty('items') && !this.validateItems(data, schema)) {
return false;
}
if (schema.hasOwnProperty('properties')) {
if (schema.hasOwnProperty('required') && !this.validateRequired(data, schema)) {
return false;
}
if (!this.validateProperties(data, schema)) {
return false;
}
}
return true;
};
/**
* @param {?} data
* @param {?} schema
* @return {?}
*/
JSONValidator.prototype.validateProperties = /**
* @param {?} data
* @param {?} schema
* @return {?}
*/
function (data, schema) {
if (!this.isObjectNotNull(data)) {
return false;
}
if (!schema.properties || !this.isObjectNotNull(schema.properties)) {
throw new Error("'properties' must be a schema object.");
}
/**
* Check if the object doesn't have more properties than expected
* Equivalent of additionalProperties: false
*/
if (Object.keys(schema.properties).length !== Object.keys(data).length) {
return false;
}
/* Recursively validate all properties */
for (var /** @type {?} */ property in schema.properties) {
if (schema.properties.hasOwnProperty(property) && data.hasOwnProperty(property)) {
if (!this.validate(data[property], schema.properties[property])) {
return false;
}
}
}
return true;
};
/**
* @param {?} data
* @param {?} schema
* @return {?}
*/
JSONValidator.prototype.validateRequired = /**
* @param {?} data
* @param {?} schema
* @return {?}
*/
function (data, schema) {
if (!this.isObjectNotNull(data)) {
return false;
}
if (!Array.isArray(schema.required)) {
throw new Error("'required' field must be an array. Note that since JSON Schema draft 6, booleans are not supported anymore.");
}
for (var _i = 0, _a = schema.required; _i < _a.length; _i++) {
var requiredProp = _a[_i];
if (typeof requiredProp !== 'string') {
throw new Error("'required' array must contain strings only.");
}
/* Checks if the property is present in the schema 'properties' */
if (!schema.properties || !schema.properties.hasOwnProperty(requiredProp)) {
throw new Error("'required' properties must be described in 'properties' too.");
}
/* Checks if the property is present in the data */
if (!data.hasOwnProperty(requiredProp)) {
return false;
}
}
return true;
};
/**
* @param {?} data
* @param {?} schema
* @return {?}
*/
JSONValidator.prototype.validateType = /**
* @param {?} data
* @param {?} schema
* @return {?}
*/
function (data, schema) {
if (Array.isArray(schema.type)) {
return this.validateTypeList(data, schema);
}
if (typeof schema.type !== 'string') {
throw new Error("'type' must be a string (arrays of types are not supported yet).");
}
if ((schema.type === 'null') && (data !== null)) {
return false;
}
if ((this.simpleTypes.indexOf(schema.type) !== -1) && (typeof data !== schema.type)) {
return false;
}
if ((schema.type === 'integer') && ((typeof data !== 'number') || !Number.isInteger(data))) {
return false;
}
return true;
};
/**
* @param {?} data
* @param {?} schema
* @return {?}
*/
JSONValidator.prototype.validateTypeList = /**
* @param {?} data
* @param {?} schema
* @return {?}
*/
function (data, schema) {
var /** @type {?} */ types = /** @type {?} */ (schema.type);
var /** @type {?} */ typesTests = [];
for (var _i = 0, types_1 = types; _i < types_1.length; _i++) {
var type = types_1[_i];
typesTests.push(this.validateType(data, { type: type }));
}
return (typesTests.indexOf(true) !== -1);
};
/**
* @param {?} data
* @param {?} schema
* @return {?}
*/
JSONValidator.prototype.validateItems = /**
* @param {?} data
* @param {?} schema
* @return {?}
*/
function (data, schema) {
if (!Array.isArray(data)) {
return false;
}
if (Array.isArray(schema.items)) {
return this.validateItemsList(data, schema);
}
if (!schema.items || !this.isObjectNotNull(schema.items)) {
throw new Error("'items' must be a schema object.");
}
for (var _i = 0, data_1 = data; _i < data_1.length; _i++) {
var value = data_1[_i];
if (!this.validate(value, schema.items)) {
return false;
}
}
return true;
};
/**
* @param {?} data
* @param {?} schema
* @return {?}
*/
JSONValidator.prototype.validateItemsList = /**
* @param {?} data
* @param {?} schema
* @return {?}
*/
function (data, schema) {
var /** @type {?} */ items = /** @type {?} */ (schema.items);
if (data.length !== items.length) {
return false;
}
for (var /** @type {?} */ i = 0; i < items.length; i += 1) {
if (!this.validate(data[i], items[i])) {
return false;
}
}
return true;
};
return JSONValidator;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* @record
*/
var AsyncLocalStorage = (function () {
function AsyncLocalStorage(database, jsonValidator) {
this.database = database;
this.jsonValidator = jsonValidator;
this.getItemOptionsDefault = {
schema: null
};
}
/**
* Gets an item value in local storage
* @param key The item's key
* @returns The item's value if the key exists, null otherwise, wrapped in an RxJS Observable
*/
/**
* Gets an item value in local storage
* @template T
* @param {?} key The item's key
* @param {?=} options
* @return {?} The item's value if the key exists, null otherwise, wrapped in an RxJS Observable
*/
AsyncLocalStorage.prototype.getItem = /**
* Gets an item value in local storage
* @template T
* @param {?} key The item's key
* @param {?=} options
* @return {?} The item's value if the key exists, null otherwise, wrapped in an RxJS Observable
*/
function (key, options) {
var _this = this;
if (options === void 0) { options = this.getItemOptionsDefault; }
return this.database.getItem(key).pipe(/* Validate data upon a json schema if requested */
rxjs_operators.mergeMap(function (data) {
if (options.schema && data !== null) {
var /** @type {?} */ validation = true;
try {
validation = _this.jsonValidator.validate(data, options.schema);
}
catch (/** @type {?} */ error) {
return rxjs_observable_throw._throw(error);
}
if (!validation) {
return rxjs_observable_throw._throw(new Error("JSON invalid"));
}
}
return rxjs_observable_of.of(data);
}));
};
/**
* Sets an item in local storage
* @param key The item's key
* @param data The item's value, must NOT be null or undefined
* @returns An RxJS Observable to wait the end of the operation
*/
/**
* Sets an item in local storage
* @param {?} key The item's key
* @param {?} data The item's value, must NOT be null or undefined
* @return {?} An RxJS Observable to wait the end of the operation
*/
AsyncLocalStorage.prototype.setItem = /**
* Sets an item in local storage
* @param {?} key The item's key
* @param {?} data The item's value, must NOT be null or undefined
* @return {?} An RxJS Observable to wait the end of the operation
*/
function (key, data) {
return this.database.setItem(key, data);
};
/**
* Deletes an item in local storage
* @param key The item's key
* @returns An RxJS Observable to wait the end of the operation
*/
/**
* Deletes an item in local storage
* @param {?} key The item's key
* @return {?} An RxJS Observable to wait the end of the operation
*/
AsyncLocalStorage.prototype.removeItem = /**
* Deletes an item in local storage
* @param {?} key The item's key
* @return {?} An RxJS Observable to wait the end of the operation
*/
function (key) {
return this.database.removeItem(key);
};
/**
* Deletes all items from local storage
* @returns An RxJS Observable to wait the end of the operation
*/
/**
* Deletes all items from local storage
* @return {?} An RxJS Observable to wait the end of the operation
*/
AsyncLocalStorage.prototype.clear = /**
* Deletes all items from local storage
* @return {?} An RxJS Observable to wait the end of the operation
*/
function () {
return this.database.clear();
};
AsyncLocalStorage.decorators = [
{ type: _angular_core.Injectable },
];
/** @nocollapse */
AsyncLocalStorage.ctorParameters = function () { return [
{ type: AsyncLocalDatabase, },
{ type: JSONValidator, },
]; };
return AsyncLocalStorage;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* @param {?} platformId
* @return {?}
*/
function asyncLocalStorageFactory(platformId) {
var /** @type {?} */ database;
function databaseFactory(platformId) {
if (_angular_common.isPlatformBrowser(platformId) && ('indexedDB' in window) && (indexedDB !== undefined) && (indexedDB !== null)) {
/* Try with IndexedDB in modern browsers */
database = new IndexedDBDatabase();
return new IndexedDBDatabase();
}
else if (_angular_common.isPlatformBrowser(platformId) && ('localStorage' in window) && (localStorage !== undefined) && (localStorage !== null)) {
/* Try with localStorage in old browsers (IE9) */
database = new LocalStorageDatabase();
return new LocalStorageDatabase();
}
else {
/* Fake database for server-side rendering (Universal) */
database = new MockLocalDatabase();
return new MockLocalDatabase();
}
return new AsyncLocalStorage(database);
}
var AsyncLocalStorageModule = (function () {
function AsyncLocalStorageModule() {
}
AsyncLocalStorageModule.decorators = [
{ type: _angular_core.NgModule, args: [{
providers: [
JSONValidator,
{
provide: AsyncLocalDatabase,
useFactory: databaseFactory,
deps: [_angular_core.PLATFORM_ID]
},
AsyncLocalStorage,
]
},] },
];
/** @nocollapse */
AsyncLocalStorageModule.ctorParameters = function () { return []; };
return AsyncLocalStorageModule;
}());
AsyncLocalStorageModule.decorators = [
{ type: _angular_core.NgModule, args: [{
providers: [
{
provide: AsyncLocalStorage,
useFactory: asyncLocalStorageFactory,
deps: [_angular_core.PLATFORM_ID]
}
]
},] },
];
/**
* @nocollapse
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
AsyncLocalStorageModule.ctorParameters = function () { return []; };
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* Generated bundle index. Do not edit.
*/
exports.AsyncLocalDatabase = AsyncLocalDatabase;
exports.IndexedDBDatabase = IndexedDBDatabase;
exports.LocalStorageDatabase = LocalStorageDatabase;
exports.MockLocalDatabase = MockLocalDatabase;
exports.JSONValidator = JSONValidator;
exports.AsyncLocalStorage = AsyncLocalStorage;
exports.AsyncLocalStorageModule = AsyncLocalStorageModule;
exports.ɵa = asyncLocalStorageFactory;
exports.ɵb = AsyncLocalDatabase;
exports.ɵa = databaseFactory;

@@ -497,0 +969,0 @@ Object.defineProperty(exports, '__esModule', { value: true });

@@ -1,2 +0,2 @@

!function(e,r){"object"==typeof exports&&"undefined"!=typeof module?r(exports,require("@angular/core"),require("@angular/common"),require("rxjs/Observable"),require("rxjs/ReplaySubject"),require("rxjs/add/operator/map"),require("rxjs/add/operator/mergeMap"),require("rxjs/add/operator/pluck"),require("rxjs/add/operator/first"),require("rxjs/add/observable/fromEvent"),require("rxjs/add/observable/merge"),require("rxjs/add/observable/throw"),require("rxjs/add/observable/of")):"function"==typeof define&&define.amd?define(["exports","@angular/core","@angular/common","rxjs/Observable","rxjs/ReplaySubject","rxjs/add/operator/map","rxjs/add/operator/mergeMap","rxjs/add/operator/pluck","rxjs/add/operator/first","rxjs/add/observable/fromEvent","rxjs/add/observable/merge","rxjs/add/observable/throw","rxjs/add/observable/of"],r):r(e.angularAsyncLocalStorage=e.angularAsyncLocalStorage||{},e.ng.core,e.ng.common,e.Rx,e.Rx)}(this,function(e,r,t,o,n){"use strict";function a(e){var r;return r=t.isPlatformBrowser(e)&&"indexedDB"in window&&void 0!==indexedDB&&null!==indexedDB?new i:t.isPlatformBrowser(e)&&"localStorage"in window&&void 0!==localStorage&&null!==localStorage?new p:new b,new c(r)}var s=function(){function e(){}return e.prototype.getItem=function(e){},e.prototype.setItem=function(e,r){},e.prototype.removeItem=function(e){},e.prototype.clear=function(){},e}(),c=function(){function e(e){this.database=e}return e.prototype.getItem=function(e){return this.database.getItem(e)},e.prototype.setItem=function(e,r){return this.database.setItem(e,r)},e.prototype.removeItem=function(e){return this.database.removeItem(e)},e.prototype.clear=function(){return this.database.clear()},e}();c.decorators=[{type:r.Injectable}],c.ctorParameters=function(){return[{type:s}]};var u=function(){var e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,r){e.__proto__=r}||function(e,r){for(var t in r)r.hasOwnProperty(t)&&(e[t]=r[t])};return function(r,t){function o(){this.constructor=r}e(r,t),r.prototype=null===t?Object.create(t):(o.prototype=t.prototype,new o)}}(),i=function(e){function r(){var r=e.call(this)||this;return r.dbName="ngStorage",r.objectStoreName="localStorage",r.keyPath="key",r.dataPath="value",r.database=new n.ReplaySubject,r.connect(),r}return u(r,e),r.prototype.getItem=function(e){var r=this;return this.transaction().map(function(r){return r.get(e)}).mergeMap(function(e){var t=o.Observable.fromEvent(e,"success").pluck("target","result").map(function(e){return e?e[r.dataPath]:null});return o.Observable.merge(t,r.toErrorObservable(e,"getter")).first()}).first()},r.prototype.setItem=function(e,r){var t=this;return null==r?o.Observable.of(!0).first():this.getItem(e).map(function(e){return null==e?"add":"put"}).mergeMap(function(n){return t.transaction("readwrite").mergeMap(function(a){var s;switch(n){case"add":s=a.add((c={},c[t.dataPath]=r,c),e);break;case"put":default:s=a.put((u={},u[t.dataPath]=r,u),e)}return o.Observable.merge(t.toSuccessObservable(s),t.toErrorObservable(s,"setter")).first();var c,u})}).first()},r.prototype.removeItem=function(e){var r=this;return this.getItem(e).mergeMap(function(t){return null!=t?r.transaction("readwrite").mergeMap(function(t){var n=t.delete(e);return o.Observable.merge(r.toSuccessObservable(n),r.toErrorObservable(n,"remover")).first()}):o.Observable.of(!0).first()}).first()},r.prototype.clear=function(){var e=this;return this.transaction("readwrite").mergeMap(function(r){var t=r.clear();return o.Observable.merge(e.toSuccessObservable(t),e.toErrorObservable(t,"clearer")).first()}).first()},r.prototype.connect=function(){var e=this,r=indexedDB.open(this.dbName);o.Observable.fromEvent(r,"upgradeneeded").first().subscribe(function(r){var t=r.target.result;t.objectStoreNames.contains(e.objectStoreName)||t.createObjectStore(e.objectStoreName)});var t=o.Observable.fromEvent(r,"success");o.Observable.merge(t,this.toErrorObservable(r,"connection")).first().subscribe(function(r){e.database.next(r.target.result)},function(r){e.database.error(r)})},r.prototype.transaction=function(e){var r=this;return void 0===e&&(e="readonly"),this.database.map(function(t){return t.transaction([r.objectStoreName],e).objectStore(r.objectStoreName)})},r.prototype.toSuccessObservable=function(e){return o.Observable.fromEvent(e,"success").map(function(){return!0})},r.prototype.toErrorObservable=function(e,r){return void 0===r&&(r=""),o.Observable.fromEvent(e,"error").mergeMap(function(){return o.Observable.throw(new Error("IndexedDB "+r+" issue."))})},r}(s);i.decorators=[{type:r.Injectable}],i.ctorParameters=function(){return[]};var l=function(){var e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,r){e.__proto__=r}||function(e,r){for(var t in r)r.hasOwnProperty(t)&&(e[t]=r[t])};return function(r,t){function o(){this.constructor=r}e(r,t),r.prototype=null===t?Object.create(t):(o.prototype=t.prototype,new o)}}(),p=function(e){function r(){var r=null!==e&&e.apply(this,arguments)||this;return r.localStorage=localStorage,r}return l(r,e),r.prototype.getItem=function(e){var r=this.localStorage.getItem(e);if(null!=r)try{r=JSON.parse(r)}catch(e){return o.Observable.throw(new Error("Invalid data in localStorage."))}return o.Observable.of(r)},r.prototype.setItem=function(e,r){return this.localStorage.setItem(e,JSON.stringify(r)),o.Observable.of(!0)},r.prototype.removeItem=function(e){return this.localStorage.removeItem(e),o.Observable.of(!0)},r.prototype.clear=function(){return this.localStorage.clear(),o.Observable.of(!0)},r}(s);p.decorators=[{type:r.Injectable}],p.ctorParameters=function(){return[]};var f=function(){var e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,r){e.__proto__=r}||function(e,r){for(var t in r)r.hasOwnProperty(t)&&(e[t]=r[t])};return function(r,t){function o(){this.constructor=r}e(r,t),r.prototype=null===t?Object.create(t):(o.prototype=t.prototype,new o)}}(),b=function(e){function r(){var r=null!==e&&e.apply(this,arguments)||this;return r.localStorage=new Map,r}return f(r,e),r.prototype.getItem=function(e){var r=this.localStorage.get(e);return o.Observable.of(void 0!==r?r:null)},r.prototype.setItem=function(e,r){return this.localStorage.set(e,r),o.Observable.of(!0)},r.prototype.removeItem=function(e){return this.localStorage.delete(e),o.Observable.of(!0)},r.prototype.clear=function(){return this.localStorage.clear(),o.Observable.of(!0)},r}(s);b.decorators=[{type:r.Injectable}],b.ctorParameters=function(){return[]};var d=function(){return function(){}}();d.decorators=[{type:r.NgModule,args:[{providers:[{provide:c,useFactory:a,deps:[r.PLATFORM_ID]}]}]}],d.ctorParameters=function(){return[]},e.AsyncLocalStorage=c,e.AsyncLocalStorageModule=d,e.ɵa=a,e.ɵb=s,Object.defineProperty(e,"__esModule",{value:!0})});
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("@angular/core"),require("rxjs/ReplaySubject"),require("rxjs/operators"),require("rxjs/observable/fromEvent"),require("rxjs/observable/of"),require("rxjs/observable/throw"),require("rxjs/observable/race"),require("@angular/common")):"function"==typeof define&&define.amd?define(["exports","@angular/core","rxjs/ReplaySubject","rxjs/operators","rxjs/observable/fromEvent","rxjs/observable/of","rxjs/observable/throw","rxjs/observable/race","@angular/common"],t):t(e.angularAsyncLocalStorage=e.angularAsyncLocalStorage||{},e.ng.core,e.Rx,e.Rx.operators,e.Rx.Observable,e.Rx.Observable,e.Rx.Observable,e.Rx.Observable,e.ng.common)}(this,function(e,t,r,o,n,a,i,s,u){"use strict";function p(e){return u.isPlatformBrowser(e)&&"indexedDB"in window&&void 0!==indexedDB&&null!==indexedDB?new f:u.isPlatformBrowser(e)&&"localStorage"in window&&void 0!==localStorage&&null!==localStorage?new b:new d}var c=function(){return function(){}}(),l=function(){var e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])};return function(t,r){function o(){this.constructor=t}e(t,r),t.prototype=null===r?Object.create(r):(o.prototype=r.prototype,new o)}}(),f=function(e){function u(){var t=e.call(this)||this;return t.dbName="ngStorage",t.objectStoreName="localStorage",t.keyPath="key",t.dataPath="value",t.database=new r.ReplaySubject,t.connect(),t}return l(u,e),u.prototype.getItem=function(e){var t=this;return this.transaction().pipe(o.map(function(t){return t.get(e)}),o.mergeMap(function(e){var r=n.fromEvent(e,"success").pipe(o.map(function(e){return e.target.result}),o.map(function(e){return e&&t.dataPath in e?e[t.dataPath]:null}));return s.race(r,t.toErrorObservable(e,"getter")).pipe(o.first())}),o.first())},u.prototype.setItem=function(e,t){var r=this;return null==t?a.of(!0):this.getItem(e).pipe(o.map(function(e){return null==e?"add":"put"}),o.mergeMap(function(n){return r.transaction("readwrite").pipe(o.mergeMap(function(a){var i;switch(n){case"add":i=a.add((u={},u[r.dataPath]=t,u),e);break;case"put":default:i=a.put((p={},p[r.dataPath]=t,p),e)}return s.race(r.toSuccessObservable(i),r.toErrorObservable(i,"setter")).pipe(o.first());var u,p}))}),o.first())},u.prototype.removeItem=function(e){var t=this;return this.getItem(e).pipe(o.mergeMap(function(r){return null!=r?t.transaction("readwrite").pipe(o.mergeMap(function(r){var n=r.delete(e);return s.race(t.toSuccessObservable(n),t.toErrorObservable(n,"remover")).pipe(o.first())})):a.of(!0)}),o.first())},u.prototype.clear=function(){var e=this;return this.transaction("readwrite").pipe(o.mergeMap(function(t){var r=t.clear();return s.race(e.toSuccessObservable(r),e.toErrorObservable(r,"clearer")).pipe(o.first())}),o.first())},u.prototype.connect=function(){var e=this,t=indexedDB.open(this.dbName);n.fromEvent(t,"upgradeneeded").pipe(o.first()).subscribe(function(t){var r=t.target.result;r.objectStoreNames.contains(e.objectStoreName)||r.createObjectStore(e.objectStoreName)});var r=n.fromEvent(t,"success");s.race(r,this.toErrorObservable(t,"connection")).pipe(o.first()).subscribe(function(t){e.database.next(t.target.result)},function(t){e.database.error(t)})},u.prototype.transaction=function(e){var t=this;return void 0===e&&(e="readonly"),this.database.pipe(o.map(function(r){return r.transaction([t.objectStoreName],e).objectStore(t.objectStoreName)}))},u.prototype.toSuccessObservable=function(e){return n.fromEvent(e,"success").pipe(o.map(function(){return!0}))},u.prototype.toErrorObservable=function(e,t){return void 0===t&&(t=""),n.fromEvent(e,"error").pipe(o.mergeMap(function(r){return i._throw(new Error("IndexedDB "+t+" issue : "+e.error.message+"."))}))},u.decorators=[{type:t.Injectable}],u.ctorParameters=function(){return[]},u}(c),y=function(){var e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])};return function(t,r){function o(){this.constructor=t}e(t,r),t.prototype=null===r?Object.create(r):(o.prototype=r.prototype,new o)}}(),b=function(e){function r(){var t=null!==e&&e.apply(this,arguments)||this;return t.localStorage=localStorage,t}return y(r,e),r.prototype.getItem=function(e){var t=this.localStorage.getItem(e),r=null;if(null!=t)try{r=JSON.parse(t)}catch(e){return i._throw(new Error("Invalid data in localStorage."))}return a.of(r)},r.prototype.setItem=function(e,t){return this.localStorage.setItem(e,JSON.stringify(t)),a.of(!0)},r.prototype.removeItem=function(e){return this.localStorage.removeItem(e),a.of(!0)},r.prototype.clear=function(){return this.localStorage.clear(),a.of(!0)},r.decorators=[{type:t.Injectable}],r.ctorParameters=function(){return[]},r}(c),h=function(){var e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])};return function(t,r){function o(){this.constructor=t}e(t,r),t.prototype=null===r?Object.create(r):(o.prototype=r.prototype,new o)}}(),d=function(e){function r(){var t=null!==e&&e.apply(this,arguments)||this;return t.localStorage=new Map,t}return h(r,e),r.prototype.getItem=function(e){var t=this.localStorage.get(e);return a.of(void 0!==t?t:null)},r.prototype.setItem=function(e,t){return this.localStorage.set(e,t),a.of(!0)},r.prototype.removeItem=function(e){return this.localStorage.delete(e),a.of(!0)},r.prototype.clear=function(){return this.localStorage.clear(),a.of(!0)},r.decorators=[{type:t.Injectable}],r.ctorParameters=function(){return[]},r}(c),m=function(){function e(){this.simpleTypes=["string","number","boolean","object"]}return e.prototype.isObjectNotNull=function(e){return null!==e&&"object"==typeof e},e.prototype.validate=function(e,t){if(!this.isObjectNotNull(t))throw new Error("A schema must be an object (unlike spec, booleans are not supported to enforce strict types).");if(!(t.hasOwnProperty("type")&&"array"!==t.type&&"object"!==t.type||t.hasOwnProperty("properties")||t.hasOwnProperty("items")))throw new Error("Each value must have a 'type' or 'properties' or 'items', to enforce strict types.");if(t.hasOwnProperty("type")&&!this.validateType(e,t))return!1;if(t.hasOwnProperty("items")&&!this.validateItems(e,t))return!1;if(t.hasOwnProperty("properties")){if(t.hasOwnProperty("required")&&!this.validateRequired(e,t))return!1;if(!this.validateProperties(e,t))return!1}return!0},e.prototype.validateProperties=function(e,t){if(!this.isObjectNotNull(e))return!1;if(!t.properties||!this.isObjectNotNull(t.properties))throw new Error("'properties' must be a schema object.");if(Object.keys(t.properties).length!==Object.keys(e).length)return!1;for(var r in t.properties)if(t.properties.hasOwnProperty(r)&&e.hasOwnProperty(r)&&!this.validate(e[r],t.properties[r]))return!1;return!0},e.prototype.validateRequired=function(e,t){if(!this.isObjectNotNull(e))return!1;if(!Array.isArray(t.required))throw new Error("'required' field must be an array. Note that since JSON Schema draft 6, booleans are not supported anymore.");for(var r=0,o=t.required;r<o.length;r++){var n=o[r];if("string"!=typeof n)throw new Error("'required' array must contain strings only.");if(!t.properties||!t.properties.hasOwnProperty(n))throw new Error("'required' properties must be described in 'properties' too.");if(!e.hasOwnProperty(n))return!1}return!0},e.prototype.validateType=function(e,t){if(Array.isArray(t.type))return this.validateTypeList(e,t);if("string"!=typeof t.type)throw new Error("'type' must be a string (arrays of types are not supported yet).");return("null"!==t.type||null===e)&&((-1===this.simpleTypes.indexOf(t.type)||typeof e===t.type)&&!!("integer"!==t.type||"number"==typeof e&&Number.isInteger(e)))},e.prototype.validateTypeList=function(e,t){for(var r=[],o=0,n=t.type;o<n.length;o++){var a=n[o];r.push(this.validateType(e,{type:a}))}return-1!==r.indexOf(!0)},e.prototype.validateItems=function(e,t){if(!Array.isArray(e))return!1;if(Array.isArray(t.items))return this.validateItemsList(e,t);if(!t.items||!this.isObjectNotNull(t.items))throw new Error("'items' must be a schema object.");for(var r=0,o=e;r<o.length;r++){var n=o[r];if(!this.validate(n,t.items))return!1}return!0},e.prototype.validateItemsList=function(e,t){var r=t.items;if(e.length!==r.length)return!1;for(var o=0;o<r.length;o+=1)if(!this.validate(e[o],r[o]))return!1;return!0},e}(),v=function(){function e(e,t){this.database=e,this.jsonValidator=t,this.getItemOptionsDefault={schema:null}}return e.prototype.getItem=function(e,t){var r=this;return void 0===t&&(t=this.getItemOptionsDefault),this.database.getItem(e).pipe(o.mergeMap(function(e){if(t.schema&&null!==e){var o=!0;try{o=r.jsonValidator.validate(e,t.schema)}catch(e){return i._throw(e)}if(!o)return i._throw(new Error("JSON invalid"))}return a.of(e)}))},e.prototype.setItem=function(e,t){return this.database.setItem(e,t)},e.prototype.removeItem=function(e){return this.database.removeItem(e)},e.prototype.clear=function(){return this.database.clear()},e.decorators=[{type:t.Injectable}],e.ctorParameters=function(){return[{type:c},{type:m}]},e}(),g=function(){function e(){}return e.decorators=[{type:t.NgModule,args:[{providers:[m,{provide:c,useFactory:p,deps:[t.PLATFORM_ID]},v]}]}],e.ctorParameters=function(){return[]},e}();e.AsyncLocalDatabase=c,e.IndexedDBDatabase=f,e.LocalStorageDatabase=b,e.MockLocalDatabase=d,e.JSONValidator=m,e.AsyncLocalStorage=v,e.AsyncLocalStorageModule=g,e.ɵa=p,Object.defineProperty(e,"__esModule",{value:!0})});
//# sourceMappingURL=angular-async-local-storage.umd.min.js.map

@@ -1,2 +0,8 @@

export { AsyncLocalStorage } from './src/service/lib.service';
export { JSONSchema, JSONSchemaType } from './src/service/validation/json-schema';
export { AsyncLocalDatabase } from './src/service/databases/async-local-database';
export { IndexedDBDatabase } from './src/service/databases/indexeddb-database';
export { LocalStorageDatabase } from './src/service/databases/localstorage-database';
export { MockLocalDatabase } from './src/service/databases/mock-local-database';
export { JSONValidator } from './src/service/validation/json-validator';
export { ALSGetItemOptions, AsyncLocalStorage } from './src/service/lib.service';
export { AsyncLocalStorageModule } from './src/module';
{
"name": "angular-async-local-storage",
"version": "4.0.0",
"version": "5.0.0",
"description": "Efficient local storage module for Angular : simple API based on native localStorage API, but internally stored via the asynchronous IndexedDB API for performance, and wrapped in RxJS observables to be homogeneous with other Angular modules.",

@@ -13,4 +13,8 @@ "main": "./bundles/angular-async-local-storage.umd.js",

"angular",
"angular2",
"angular 2",
"angular4",
"angular 4",
"angular5",
"angular 5",
"localstorage",

@@ -54,15 +58,17 @@ "local storage"

"reinstall": "rimraf node_modules && npm install",
"publish": "npm publish dist --tag lts"
"publish": "npm publish dist"
},
"dependencies": {},
"peerDependencies": {
"@angular/core": ">=4.0.0 <5.0.0",
"@angular/common": ">=4.0.0 <5.0.0"
"@angular/core": ">=5.0.0 <6.0.0",
"@angular/common": ">=5.0.0 <6.0.0",
"rxjs": "^5.5.2"
},
"devDependencies": {
"@angular/common": "^4.4.6",
"@angular/compiler": "^4.4.6",
"@angular/compiler-cli": "^4.4.6",
"@angular/core": "^4.4.6",
"@angular/platform-browser": "^4.4.6",
"@angular/platform-browser-dynamic": "^4.4.6",
"@angular/common": "^5.2.9",
"@angular/compiler": "^5.2.9",
"@angular/compiler-cli": "^5.2.9",
"@angular/core": "^5.2.9",
"@angular/platform-browser": "^5.2.9",
"@angular/platform-browser-dynamic": "^5.2.9",
"@types/jasmine": "2.5.36",

@@ -79,4 +85,6 @@ "@types/node": "^6.0.46",

"karma-coverage": "^1.1.1",
"karma-edge-launcher": "^0.4.2",
"karma-firefox-launcher": "^1.0.1",
"karma-html-reporter": "^0.2.7",
"karma-ie-launcher": "^1.0.0",
"karma-jasmine": "^1.1.0",

@@ -93,9 +101,9 @@ "karma-jasmine-html-reporter": "^0.2.2",

"rollup-plugin-uglify": "^2.0.1",
"rxjs": "^5.0.1",
"rxjs": "^5.5.2",
"standard-version": "^4.0.0",
"systemjs": "^0.19.40",
"tslint": "^4.4.2",
"typescript": "~2.3.4",
"typescript": "~2.4.2",
"zone.js": "^0.8.4"
}
}
# Async local storage for Angular
Efficient local storage module for Angular :
- **simple** : based on native `localStorage` API,
- **perfomance** : internally stored via the asynchronous `IndexedDB` API,
- **Angular-like** : wrapped in RxJS `Observables`.
Efficient local storage module for Angular:
- **simplicity**: based on native `localStorage` API and automatic JSON stringify/parse,
- **perfomance**: internally stored via the asynchronous `IndexedDB` API,
- **Angular-like**: wrapped in RxJS `Observables`,
- **security**: validate data with a JSON Schema,
- **extensibility**: add your own storage.
## Why this module ?
## Angular onsite training
The author of this library organizes Angular courses (based in Paris, France, but open to travel). You can find [details here](https://formationjavascript.com/formation-angular/) (in French).
## Why this module?
For now, Angular does not provide a local storage module, and almost every app needs some local storage.
There is 2 native JavaScript APIs available :
There are 2 native JavaScript APIs available:
- [localStorage](https://developer.mozilla.org/en-US/docs/Web/API/Storage/LocalStorage)

@@ -18,3 +24,3 @@ - [IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API)

The `IndexedDB` API is asynchronous and efficient, but it's a mess to use :
The `IndexedDB` API is asynchronous and efficient, but it's a mess to use:
you'll soon be caught by the callback hell, as it does not support Promises yet.

@@ -25,6 +31,6 @@

but internally stored via the asynchronous `IndexedDB` for performance.
But it is written in ES5 and then it's a mess to include into Angular.
But it's built in ES5 old school way and then it's a mess to include into Angular.
This module is based on the same idea as localForage, but in ES6/ES2015
and additionnaly wrapped into [RxJS Observables](http://reactivex.io/rxjs/)
and additionally wrapped into [RxJS Observables](http://reactivex.io/rxjs/)
to be homogeneous with other Angular modules.

@@ -34,9 +40,13 @@

Install via [npm](http://npmjs.com) :
Install the same version as your Angular one via [npm](http://npmjs.com):
```bash
# For Angular 5 (latest):
npm install angular-async-local-storage
# For Angular 4 (and TypeScript >= 2.3):
npm install angular-async-local-storage@4
```
Then include the `AsyncLocalStorage` module in your app root module (just once, do NOT re-import it in your sub modules).
Then include the `AsyncLocalStorage` module in your app root module (just once, do NOT re-import it in your submodules).

@@ -57,3 +67,3 @@ ```typescript

Now you just have to inject the service where you need it :
Now you just have to inject the service where you need it:

@@ -88,3 +98,3 @@ ```typescript

To delete one item :
To delete one item:

@@ -95,3 +105,3 @@ ```typescript

To delete all items :
To delete all items:

@@ -111,7 +121,35 @@ ```typescript

As any data can be stored, you can type your data.
But don't forget it's client-side storage : **always check the data**, as it could have been forged or deleted.
### Checking data
Don't forget it's client-side storage: **always check the data**, as it could have been forged or deleted.
Starting with *version 3.1*, you can use a [JSON Schema](http://json-schema.org/) to validate the data.
```typescript
import { JSONSchema } from 'angular-async-local-storage';
const schema: JSONSchema = {
properties: {
firstName: { type: 'string' },
lastName: { type: 'string' }
},
required: ['firstName', 'lastName']
};
this.localStorage.getItem<User>('user', { schema }).subscribe((user) => {
// Called if data is valid or null
}, (error) => {
// Called if data is invalid
});
```
Note: last draft of JSON Schema is used (draft 7 at this time),
but we don't support all validation features yet. Just follow the interface.
Contributions are welcome to add more features.
Note: as the goal is validation, types are enforced: each value MUST have either `type` or `properties` or `items`.
### Notes
Not finding an item is not an error, it succeeds but returns `null`.
- Not finding an item is not an error, it succeeds but returns `null`.

@@ -124,3 +162,3 @@ ```typescript

Errors are unlikely to happen, but in an app it's better to catch any potential error.
- Errors are unlikely to happen, but in an app, it's better to catch any potential error.

@@ -135,15 +173,22 @@ ```typescript

You *DO* need to subscribe, even if you don't have something specific to do after writing in local storage (because it's how RxJS Observables work).
- You *DO* need to subscribe, even if you don't have something specific to do after writing in local storage (because it's how RxJS Observables work).
You do *NOT* need to unsubscribe : the observable autocompletes (like in the `HttpClient` service).
- You do *NOT* need to unsubscribe: the observable autocompletes (like in the `HttpClient` service).
- When reading data, you'll only get one value: the observable is here for asynchronicity but is not meant to
emit again when the stored data is changed. And it's normal: if app data change, it's the role of your app
to keep track of it, not of this lib. See [#16](https://github.com/cyrilletuzi/angular-async-local-storage/issues/16)
for more context and [#4](https://github.com/cyrilletuzi/angular-async-local-storage/issues/4)
for an example.
## Angular support
The last version of this library requires **Angular 4+** and **TypeScript 2.3+**.
This lib major version is aligned to the major version of Angular. Meaning for Angular 4 you need version 4,
for Angular 5 you need version 5, and so on.
If you need Angular 2 support, stay on version 1 :
```bash
npm install angular-async-local-storage@1
```
We follow [Angular LTS support](https://github.com/angular/angular/blob/master/docs/RELEASE_SCHEDULE.md),
meaning we support Angular 4 minimum, until October 2018.
You can still have Angular 2 support by installing version 1 of this lib, but bug fixes has not been backported.
This module supports [AoT pre-compiling](https://angular.io/guide/aot-compiler).

@@ -157,3 +202,3 @@

[All browsers supporting IndexedDB](http://caniuse.com/#feat=indexeddb), ie. **all current browsers** :
Firefox, Chrome, Opera, Safari, Edge and IE10+.
Firefox, Chrome, Opera, Safari, Edge, and IE10+.

@@ -168,2 +213,45 @@ Local storage is required only for apps, and given that you won't do an app in older browsers,

It also works in tools based on browser engines (like Electron) but not in non-browser tools (like NativeScript, see
[#11](https://github.com/cyrilletuzi/angular-async-local-storage/issues/11)).
### Private mode
Be aware that local storage is limited in browsers when in private / incognito modes. Most browsers will delete the data when the private browsing session ends.
It's not a real issue as local storage is useful for apps, and apps should not be in private mode.
In IE / Edge, `indexedDB` is `null` when in private mode. The lib fallbacks to (synchronous) `localStorage`.
In Firefox, `indexedDB` API is available in code but throwing error on usage. It's a bug in the browser, this lib can't handle it, see
[#26](https://github.com/cyrilletuzi/angular-async-local-storage/issues/26).
## Extensibility
### Add your own storage
Starting with *version 3.1*, you can easily add your own storage:
```typescript
import { AsyncLocalStorageModule, AsyncLocalDatabase } from 'angular-async-local-storage';
export class MyDatabase extends AsyncLocalDatabase {
/* Implement the methods required by the parent class */
}
@NgModule({
provide: [
AsyncLocalStorageModule,
{ provide: AsyncLocalDatabase, useClass: MyDatabase }
]
})
export class AppModule {}
```
Be sure to be compatible with Universal by checking the current platform before using any browser-specific API.
### Extend JSON Validator
You can also extend the JSON validator, but if you do so, please contribute so everyone can enjoy.
## Changelog

@@ -170,0 +258,0 @@

@@ -1,4 +0,6 @@

import { AsyncLocalStorage } from './service/lib.service';
export declare function asyncLocalStorageFactory(platformId: Object): AsyncLocalStorage;
import { IndexedDBDatabase } from './service/databases/indexeddb-database';
import { LocalStorageDatabase } from './service/databases/localstorage-database';
import { MockLocalDatabase } from './service/databases/mock-local-database';
export declare function databaseFactory(platformId: Object): IndexedDBDatabase | LocalStorageDatabase | MockLocalDatabase;
export declare class AsyncLocalStorageModule {
}
import { Observable } from 'rxjs/Observable';
import { ReplaySubject } from 'rxjs/ReplaySubject';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/mergeMap';
import 'rxjs/add/operator/pluck';
import 'rxjs/add/operator/first';
import 'rxjs/add/observable/fromEvent';
import 'rxjs/add/observable/merge';
import 'rxjs/add/observable/throw';
import 'rxjs/add/observable/of';
import { AsyncLocalDatabase } from './async-local-database';

@@ -12,0 +4,0 @@ export declare class IndexedDBDatabase extends AsyncLocalDatabase {

import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';
import 'rxjs/add/observable/throw';
import { AsyncLocalDatabase } from './async-local-database';

@@ -5,0 +3,0 @@ export declare class LocalStorageDatabase extends AsyncLocalDatabase {

import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';
import { AsyncLocalDatabase } from './async-local-database';

@@ -4,0 +3,0 @@ export declare class MockLocalDatabase extends AsyncLocalDatabase {

import { Observable } from 'rxjs/Observable';
import { AsyncLocalDatabase } from './databases/async-local-database';
import { JSONSchema } from './validation/json-schema';
import { JSONValidator } from './validation/json-validator';
export interface ALSGetItemOptions {
schema?: JSONSchema | null;
}
export declare class AsyncLocalStorage {
protected database: AsyncLocalDatabase;
protected jsonValidator: JSONValidator;
protected readonly getItemOptionsDefault: {
schema: null;
};
constructor(database: AsyncLocalDatabase, jsonValidator: JSONValidator);
/**
* Injects a local database
*/
constructor(database: AsyncLocalDatabase);
/**
* Gets an item value in local storage

@@ -14,3 +20,3 @@ * @param key The item's key

*/
getItem<T = any>(key: string): Observable<T | null>;
getItem<T = any>(key: string, options?: ALSGetItemOptions): Observable<any>;
/**

@@ -17,0 +23,0 @@ * Sets an item in local storage

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc