UNPKG

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
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