UNPKG

@react-native-firebase/app

Version:

A well tested, feature rich Firebase implementation for React Native, supporting iOS & Android. Individual module support for Admob, Analytics, Auth, Crash Reporting, Cloud Firestore, Database, Dynamic Links, Functions, Messaging (FCM), Remote Config, Sto

173 lines (162 loc) 5.57 kB
import { ConstraintError, DataError } from './errors.js'; import extractKey from './extractKey.js'; import KeyGenerator from './KeyGenerator.js'; import RecordStore from './RecordStore.js'; // http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#dfn-object-store class ObjectStore { deleted = false; records = new RecordStore(); rawIndexes = new Map(); constructor(rawDatabase, name, keyPath, autoIncrement) { this.rawDatabase = rawDatabase; this.keyGenerator = autoIncrement === true ? new KeyGenerator() : null; this.deleted = false; this.name = name; this.keyPath = keyPath; this.autoIncrement = autoIncrement; } // http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#dfn-steps-for-retrieving-a-value-from-an-object-store getKey(key) { const record = this.records.get(key); return record !== undefined ? structuredClone(record.key) : undefined; } // http://w3c.github.io/IndexedDB/#retrieve-multiple-keys-from-an-object-store getAllKeys(range, count) { if (count === undefined || count === 0) { count = Infinity; } const records = []; for (const record of this.records.values(range)) { records.push(structuredClone(record.key)); if (records.length >= count) { break; } } return records; } // http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#dfn-steps-for-retrieving-a-value-from-an-object-store getValue(key) { const record = this.records.get(key); return record !== undefined ? structuredClone(record.value) : undefined; } // http://w3c.github.io/IndexedDB/#retrieve-multiple-values-from-an-object-store getAllValues(range, count) { if (count === undefined || count === 0) { count = Infinity; } const records = []; for (const record of this.records.values(range)) { records.push(structuredClone(record.value)); if (records.length >= count) { break; } } return records; } // http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#dfn-steps-for-storing-a-record-into-an-object-store storeRecord(newRecord, noOverwrite, rollbackLog) { if (this.keyPath !== null) { const key = extractKey(this.keyPath, newRecord.value); if (key !== undefined) { newRecord.key = key; } } if (this.keyGenerator !== null && newRecord.key === undefined) { if (rollbackLog) { const keyGeneratorBefore = this.keyGenerator.num; rollbackLog.push(() => { if (this.keyGenerator) { this.keyGenerator.num = keyGeneratorBefore; } }); } newRecord.key = this.keyGenerator.next(); // Set in value if keyPath defiend but led to no key // http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#dfn-steps-to-assign-a-key-to-a-value-using-a-key-path if (this.keyPath !== null) { if (Array.isArray(this.keyPath)) { throw new Error('Cannot have an array key path in an object store with a key generator'); } let remainingKeyPath = this.keyPath; let object = newRecord.value; let identifier; let i = 0; // Just to run the loop at least once while (i >= 0) { if (typeof object !== 'object') { throw new DataError(); } i = remainingKeyPath.indexOf('.'); if (i >= 0) { identifier = remainingKeyPath.slice(0, i); remainingKeyPath = remainingKeyPath.slice(i + 1); if (!Object.hasOwn(object, identifier)) { object[identifier] = {}; } object = object[identifier]; } } identifier = remainingKeyPath; object[identifier] = newRecord.key; } } else if (this.keyGenerator !== null && typeof newRecord.key === 'number') { this.keyGenerator.setIfLarger(newRecord.key); } const existingRecord = this.records.get(newRecord.key); if (existingRecord) { if (noOverwrite) { throw new ConstraintError(); } this.deleteRecord(newRecord.key, rollbackLog); } this.records.add(newRecord); if (rollbackLog) { rollbackLog.push(() => { this.deleteRecord(newRecord.key); }); } // Update indexes for (const rawIndex of this.rawIndexes.values()) { if (rawIndex.initialized) { rawIndex.storeRecord(newRecord); } } return newRecord.key; } // http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#dfn-steps-for-deleting-records-from-an-object-store deleteRecord(key, rollbackLog) { const deletedRecords = this.records.delete(key); if (rollbackLog) { for (const record of deletedRecords) { rollbackLog.push(() => { this.storeRecord(record, true); }); } } for (const rawIndex of this.rawIndexes.values()) { rawIndex.records.deleteByValue(key); } } // http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#dfn-steps-for-clearing-an-object-store clear(rollbackLog) { const deletedRecords = this.records.clear(); if (rollbackLog) { for (const record of deletedRecords) { rollbackLog.push(() => { this.storeRecord(record, true); }); } } for (const rawIndex of this.rawIndexes.values()) { rawIndex.records.clear(); } } count(range) { let count = 0; // eslint-disable-next-line @typescript-eslint/no-unused-vars for (const record of this.records.values(range)) { count += 1; } return count; } } export default ObjectStore;