ngx-indexed-database
Version:
<div align="center"> <img src="https://w3c.github.io/IndexedDB/logo-db.svg" width="120"/> </div> <h1 align="center">ngx-indexed-database</h1>
430 lines (415 loc) • 22.2 kB
JavaScript
import * as i0 from '@angular/core';
import { Injectable, NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { __awaiter } from 'tslib';
class InvalidArgumentsException extends Error {
constructor() {
super('Invalid arguments provided');
}
}
class HelperUtils {
static getDatabaseVersion(dbName) {
return indexedDB.databases().then((databases) => { var _a; return ((_a = databases.find(database => database.name === dbName)) === null || _a === void 0 ? void 0 : _a.version) || 0; });
}
static getIndexedDBStoreSchemaPrimaryKeys(storeSchema) {
return Object.keys(storeSchema).filter(key => storeSchema[key].primary);
}
static promisifyIndexedDBRequest(request, resolveMethod, rejectMethod) {
return new Promise((resolve, reject) => {
request[resolveMethod] = (event) => resolve(event);
if (rejectMethod) {
request[rejectMethod] = (event) => reject(event);
}
});
}
}
class PrimaryKeysCountException extends Error {
constructor() {
super('There must be only one primary key');
}
}
var IndexedDBKeysDataType;
(function (IndexedDBKeysDataType) {
IndexedDBKeysDataType[IndexedDBKeysDataType["STRING"] = 0] = "STRING";
IndexedDBKeysDataType[IndexedDBKeysDataType["INTEGER"] = 1] = "INTEGER";
IndexedDBKeysDataType[IndexedDBKeysDataType["OBJECT"] = 2] = "OBJECT";
IndexedDBKeysDataType[IndexedDBKeysDataType["ARRAY"] = 3] = "ARRAY";
IndexedDBKeysDataType[IndexedDBKeysDataType["BOOLEAN"] = 4] = "BOOLEAN";
IndexedDBKeysDataType[IndexedDBKeysDataType["ANY"] = 5] = "ANY";
})(IndexedDBKeysDataType || (IndexedDBKeysDataType = {}));
const SCHEMA_STORE_NAME = 'indexed_database_schemas';
class NgxIndexedDatabaseStoreSchemaService {
constructor() {
this.primaryKey = 'name';
}
defineSchemasStore(dbName) {
return __awaiter(this, void 0, void 0, function* () {
try {
const indexedDBOpenRequest = indexedDB.open(dbName, 1);
yield HelperUtils.promisifyIndexedDBRequest(indexedDBOpenRequest, 'onupgradeneeded', 'onerror');
const database = indexedDBOpenRequest.result;
yield database.createObjectStore(SCHEMA_STORE_NAME, { keyPath: this.primaryKey });
yield HelperUtils.promisifyIndexedDBRequest(indexedDBOpenRequest, 'onsuccess', 'onerror');
database === null || database === void 0 ? void 0 : database.close();
}
catch (e) { }
return { success: true };
});
}
modifySchemaStore(dbName, storeName, storeSchema) {
return __awaiter(this, void 0, void 0, function* () {
const indexedDBOpenRequest = indexedDB.open(dbName);
const data = {
[this.primaryKey]: storeName,
schema: encodeURIComponent(JSON.stringify(storeSchema))
};
yield HelperUtils.promisifyIndexedDBRequest(indexedDBOpenRequest, 'onsuccess', 'onerror');
const database = indexedDBOpenRequest.result;
const transaction = database.transaction(SCHEMA_STORE_NAME, "readwrite");
const store = transaction.objectStore(SCHEMA_STORE_NAME);
const updateRequest = store.put(data);
yield HelperUtils.promisifyIndexedDBRequest(updateRequest, 'onsuccess', 'onerror');
database === null || database === void 0 ? void 0 : database.close();
return data;
});
}
getStoreSchema(dbName, storeName) {
var _a;
return __awaiter(this, void 0, void 0, function* () {
const indexedDBOpenRequest = indexedDB.open(dbName);
yield HelperUtils.promisifyIndexedDBRequest(indexedDBOpenRequest, 'onsuccess', 'onerror');
const database = indexedDBOpenRequest.result;
const transaction = database.transaction(SCHEMA_STORE_NAME, "readwrite");
const store = transaction.objectStore(SCHEMA_STORE_NAME);
const readRequest = store.get(storeName);
yield HelperUtils.promisifyIndexedDBRequest(readRequest, 'onsuccess', 'onerror');
database === null || database === void 0 ? void 0 : database.close();
return JSON.parse(decodeURIComponent(((_a = readRequest === null || readRequest === void 0 ? void 0 : readRequest.result) === null || _a === void 0 ? void 0 : _a.schema) || null));
});
}
removeStoreSchema(dbName, storeName) {
return __awaiter(this, void 0, void 0, function* () {
const indexedDBOpenRequest = indexedDB.open(dbName);
yield HelperUtils.promisifyIndexedDBRequest(indexedDBOpenRequest, 'onsuccess', 'onerror');
const database = indexedDBOpenRequest.result;
const transaction = database.transaction(SCHEMA_STORE_NAME, "readwrite");
const store = transaction.objectStore(SCHEMA_STORE_NAME);
const deleteRequest = store.delete(storeName);
yield HelperUtils.promisifyIndexedDBRequest(deleteRequest, 'onsuccess', 'onerror');
database === null || database === void 0 ? void 0 : database.close();
return { success: true };
});
}
}
NgxIndexedDatabaseStoreSchemaService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: NgxIndexedDatabaseStoreSchemaService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
NgxIndexedDatabaseStoreSchemaService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: NgxIndexedDatabaseStoreSchemaService });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: NgxIndexedDatabaseStoreSchemaService, decorators: [{
type: Injectable
}], ctorParameters: function () { return []; } });
class InvalidStoreNameException extends Error {
constructor() {
super(`Store name cannot be equal to ${SCHEMA_STORE_NAME}`);
}
}
const areIdentical = (valueA, valueB) => {
if (typeof valueA == "object" && valueA != null && typeof valueB == "object" && valueB != null) {
const count = [0, 0];
for (const key in valueA)
count[0]++;
for (const key in valueB)
count[1]++;
if (count[0] - count[1] != 0) {
return false;
}
for (const key in valueA) {
if (!(key in valueB) || !areIdentical(valueA[key], valueB[key])) {
return false;
}
}
for (const key in valueB) {
if (!(key in valueA) || !areIdentical(valueB[key], valueA[key])) {
return false;
}
}
return true;
}
else {
return Object.is(valueA, valueB);
}
};
class NgxIndexedDatabaseService {
constructor(_ngxIndexedDatabaseStoreSchemaService) {
this._ngxIndexedDatabaseStoreSchemaService = _ngxIndexedDatabaseStoreSchemaService;
}
static getInstance() {
if (!this._instance) {
this._instance = new NgxIndexedDatabaseService(new NgxIndexedDatabaseStoreSchemaService());
}
return this._instance;
}
createStore(dbName, storeName, storeSchema) {
var _a;
return __awaiter(this, void 0, void 0, function* () {
if (!dbName || !storeName) {
throw new InvalidArgumentsException();
}
if (storeName === SCHEMA_STORE_NAME) {
throw new InvalidStoreNameException();
}
const primaryKeys = HelperUtils.getIndexedDBStoreSchemaPrimaryKeys(storeSchema);
if (primaryKeys.length !== 1) {
throw new PrimaryKeysCountException();
}
yield this._ngxIndexedDatabaseStoreSchemaService.defineSchemasStore(dbName);
const alreadyExistingSchema = yield this._ngxIndexedDatabaseStoreSchemaService.getStoreSchema(dbName, storeName);
const ifSchemasIdentical = areIdentical(alreadyExistingSchema, storeSchema);
if (ifSchemasIdentical) {
return { success: true };
}
if (alreadyExistingSchema && !ifSchemasIdentical) {
yield this.deleteStore(dbName, storeName);
}
const version = (yield HelperUtils.getDatabaseVersion(dbName)) + 1;
const indexedDBOpenRequest = indexedDB.open(dbName, version);
yield HelperUtils.promisifyIndexedDBRequest(indexedDBOpenRequest, 'onupgradeneeded');
const database = indexedDBOpenRequest.result;
const store = database.createObjectStore(storeName, { keyPath: primaryKeys[0] });
for (const attribute in storeSchema) {
if ([IndexedDBKeysDataType.STRING, IndexedDBKeysDataType.INTEGER].includes(storeSchema[attribute].datatype)) {
store.createIndex(attribute, attribute, { unique: ((_a = storeSchema[attribute]) === null || _a === void 0 ? void 0 : _a.unique) || false });
}
}
yield HelperUtils.promisifyIndexedDBRequest(indexedDBOpenRequest, 'onsuccess', 'onerror');
database === null || database === void 0 ? void 0 : database.close();
yield this._ngxIndexedDatabaseStoreSchemaService.modifySchemaStore(dbName, storeName, storeSchema);
return { success: true };
});
}
deleteStore(dbName, storeName) {
return __awaiter(this, void 0, void 0, function* () {
if (!dbName || !storeName) {
throw new InvalidArgumentsException();
}
const version = (yield HelperUtils.getDatabaseVersion(dbName)) + 1;
const indexedDBOpenRequest = indexedDB.open(dbName, version);
yield HelperUtils.promisifyIndexedDBRequest(indexedDBOpenRequest, 'onupgradeneeded');
const database = indexedDBOpenRequest.result;
database.deleteObjectStore(storeName);
yield this._ngxIndexedDatabaseStoreSchemaService.removeStoreSchema(dbName, storeName);
database === null || database === void 0 ? void 0 : database.close();
return { success: true };
});
}
}
NgxIndexedDatabaseService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: NgxIndexedDatabaseService, deps: [{ token: NgxIndexedDatabaseStoreSchemaService }], target: i0.ɵɵFactoryTarget.Injectable });
NgxIndexedDatabaseService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: NgxIndexedDatabaseService, providedIn: 'root' });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: NgxIndexedDatabaseService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: function () { return [{ type: NgxIndexedDatabaseStoreSchemaService }]; } });
const isExcludeConfig = (data) => {
return 'exclude' in data;
};
class NgxIndexedDatabaseStoreOperationsService {
constructor() { }
upsert(dbName, storeName, data) {
return __awaiter(this, void 0, void 0, function* () {
if (!dbName || !storeName || !data) {
throw new InvalidArgumentsException();
}
const indexedDBOpenRequest = indexedDB.open(dbName);
yield HelperUtils.promisifyIndexedDBRequest(indexedDBOpenRequest, 'onsuccess', 'onerror');
const database = indexedDBOpenRequest.result;
const transaction = database.transaction(storeName, "readwrite");
const store = transaction.objectStore(storeName);
const updateRequest = store.put(data);
yield HelperUtils.promisifyIndexedDBRequest(updateRequest, 'onsuccess', 'onerror');
database === null || database === void 0 ? void 0 : database.close();
return data;
});
}
delete(dbName, storeName, value) {
return __awaiter(this, void 0, void 0, function* () {
if (!dbName || !storeName || !value) {
throw new InvalidArgumentsException();
}
const indexedDBOpenRequest = indexedDB.open(dbName);
yield HelperUtils.promisifyIndexedDBRequest(indexedDBOpenRequest, 'onsuccess', 'onerror');
const database = indexedDBOpenRequest.result;
const transaction = database.transaction(storeName, "readwrite");
const store = transaction.objectStore(storeName);
const deleteRequest = store.delete(value);
yield HelperUtils.promisifyIndexedDBRequest(deleteRequest, 'onsuccess', 'onerror');
database === null || database === void 0 ? void 0 : database.close();
return { success: true };
});
}
deleteBy(dbName, storeName, key, value) {
var _a;
return __awaiter(this, void 0, void 0, function* () {
if (!dbName || !storeName || !key || !value) {
throw new InvalidArgumentsException();
}
const indexedDBOpenRequest = indexedDB.open(dbName);
yield HelperUtils.promisifyIndexedDBRequest(indexedDBOpenRequest, 'onsuccess', 'onerror');
const database = indexedDBOpenRequest.result;
const transaction = database.transaction(storeName, "readwrite");
const store = transaction.objectStore(storeName);
const primaryKeyIndex = store.index(key);
const cursorOpenRequest = primaryKeyIndex.openCursor(IDBKeyRange.only(value));
yield HelperUtils.promisifyIndexedDBRequest(cursorOpenRequest, 'onsuccess', 'onerror');
const deleteRequest = (_a = cursorOpenRequest.result) === null || _a === void 0 ? void 0 : _a.delete();
yield HelperUtils.promisifyIndexedDBRequest(deleteRequest, 'onsuccess', 'onerror');
database === null || database === void 0 ? void 0 : database.close();
return { success: true };
});
}
clear(dbName, storeName) {
return __awaiter(this, void 0, void 0, function* () {
if (!dbName || !storeName) {
throw new InvalidArgumentsException();
}
const indexedDBOpenRequest = indexedDB.open(dbName);
yield HelperUtils.promisifyIndexedDBRequest(indexedDBOpenRequest, 'onsuccess', 'onerror');
const database = indexedDBOpenRequest.result;
const transaction = database.transaction(storeName, "readwrite");
const store = transaction.objectStore(storeName);
const clearRequest = store.clear();
yield HelperUtils.promisifyIndexedDBRequest(clearRequest, 'onsuccess', 'onerror');
database === null || database === void 0 ? void 0 : database.close();
return { success: true };
});
}
find(dbName, storeName, value) {
return __awaiter(this, void 0, void 0, function* () {
if (!dbName || !storeName || !value) {
throw new InvalidArgumentsException();
}
const indexedDBOpenRequest = indexedDB.open(dbName);
yield HelperUtils.promisifyIndexedDBRequest(indexedDBOpenRequest, 'onsuccess', 'onerror');
const database = indexedDBOpenRequest.result;
const transaction = database.transaction(storeName, "readwrite");
const store = transaction.objectStore(storeName);
const readRequest = store.get(value);
yield HelperUtils.promisifyIndexedDBRequest(readRequest, 'onsuccess', 'onerror');
database === null || database === void 0 ? void 0 : database.close();
return (readRequest === null || readRequest === void 0 ? void 0 : readRequest.result) || null;
});
}
findBy(dbName, storeName, key, value) {
return __awaiter(this, void 0, void 0, function* () {
if (!dbName || !storeName || !key || !value) {
throw new InvalidArgumentsException();
}
const indexedDBOpenRequest = indexedDB.open(dbName);
yield HelperUtils.promisifyIndexedDBRequest(indexedDBOpenRequest, 'onsuccess', 'onerror');
const database = indexedDBOpenRequest.result;
const transaction = database.transaction(storeName, "readwrite");
const store = transaction.objectStore(storeName);
const keyIndex = store.index(key);
const readRequest = keyIndex.get(value);
yield HelperUtils.promisifyIndexedDBRequest(readRequest, 'onsuccess', 'onerror');
database === null || database === void 0 ? void 0 : database.close();
return (readRequest === null || readRequest === void 0 ? void 0 : readRequest.result) || null;
});
}
findMany(dbName, storeName, values) {
return __awaiter(this, void 0, void 0, function* () {
const entriesMap = {};
for (const value of values) {
const data = yield this.find(dbName, storeName, value);
if (data) {
entriesMap[value + ''] = data;
}
}
return Object.values(entriesMap);
});
}
findManyBy(dbName, storeName, key, values) {
return __awaiter(this, void 0, void 0, function* () {
const entriesMap = {};
for (const value of values) {
const data = yield this.findBy(dbName, storeName, key, value);
if (data) {
entriesMap[value + ''] = data;
}
}
return Object.values(entriesMap);
});
}
fetchAll(dbName, storeName) {
return __awaiter(this, void 0, void 0, function* () {
if (!dbName || !storeName) {
throw new InvalidArgumentsException();
}
const indexedDBOpenRequest = indexedDB.open(dbName);
yield HelperUtils.promisifyIndexedDBRequest(indexedDBOpenRequest, 'onsuccess', 'onerror');
const database = indexedDBOpenRequest.result;
const transaction = database.transaction(storeName, "readwrite");
const store = transaction.objectStore(storeName);
const readRequest = store.getAll();
yield HelperUtils.promisifyIndexedDBRequest(readRequest, 'onsuccess', 'onerror');
database === null || database === void 0 ? void 0 : database.close();
return (readRequest === null || readRequest === void 0 ? void 0 : readRequest.result) || [];
});
}
resetStores(dbName, options) {
return __awaiter(this, void 0, void 0, function* () {
if (!dbName) {
throw new InvalidArgumentsException();
}
const indexedDBOpenRequest = indexedDB.open(dbName);
yield HelperUtils.promisifyIndexedDBRequest(indexedDBOpenRequest, 'onsuccess', 'onerror');
const database = indexedDBOpenRequest.result;
const allObjectStoreNames = Object.values(Object.assign({}, database.objectStoreNames));
const objectStoreNamesToBeCleared = allObjectStoreNames
.filter((storeName) => options ?
(isExcludeConfig(options) ?
!(options.exclude || []).includes(storeName) :
(options.only || allObjectStoreNames).includes(storeName)) :
true);
database === null || database === void 0 ? void 0 : database.close();
const objectStoreClearRequests = objectStoreNamesToBeCleared.map((storeName) => this.clear(dbName, storeName));
return Promise.all(objectStoreClearRequests);
});
}
}
NgxIndexedDatabaseStoreOperationsService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: NgxIndexedDatabaseStoreOperationsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
NgxIndexedDatabaseStoreOperationsService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: NgxIndexedDatabaseStoreOperationsService, providedIn: 'root' });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: NgxIndexedDatabaseStoreOperationsService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: function () { return []; } });
class NgxIndexedDatabaseModule {
}
NgxIndexedDatabaseModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: NgxIndexedDatabaseModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
NgxIndexedDatabaseModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: NgxIndexedDatabaseModule, imports: [CommonModule] });
NgxIndexedDatabaseModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: NgxIndexedDatabaseModule, providers: [
NgxIndexedDatabaseService,
NgxIndexedDatabaseStoreOperationsService,
NgxIndexedDatabaseStoreSchemaService
], imports: [[
CommonModule
]] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: NgxIndexedDatabaseModule, decorators: [{
type: NgModule,
args: [{
imports: [
CommonModule
],
providers: [
NgxIndexedDatabaseService,
NgxIndexedDatabaseStoreOperationsService,
NgxIndexedDatabaseStoreSchemaService
]
}]
}] });
/**
* Generated bundle index. Do not edit.
*/
export { IndexedDBKeysDataType, NgxIndexedDatabaseModule, NgxIndexedDatabaseService, NgxIndexedDatabaseStoreOperationsService };
//# sourceMappingURL=ngx-indexed-database.js.map