UNPKG

@urql/exchange-graphcache

Version:

A normalized and configurable cache exchange for urql

159 lines (154 loc) 5.28 kB
Object.defineProperty(exports, '__esModule', { value: true }); var getRequestPromise = request => { return new Promise((resolve, reject) => { request.onerror = () => { reject(request.error); }; request.onsuccess = () => { resolve(request.result); }; }); }; var getTransactionPromise = transaction => { return new Promise((resolve, reject) => { transaction.onerror = () => { reject(transaction.error); }; transaction.oncomplete = resolve; }); }; /** Sample storage adapter persisting to IndexedDB. */ /** Creates a default {@link StorageAdapter} which uses IndexedDB for storage. * * @param opts - A {@link StorageOptions} configuration object. * @returns the created {@link StorageAdapter}. * * @remarks * The default storage uses IndexedDB to persist the normalized cache for * offline use. It demonstrates that the cache can be chunked by timestamps. * * Note: We have no data on stability of this storage and our Offline Support * for large APIs or longterm use. Proceed with caution. */ var makeDefaultStorage = opts => { if (!opts) opts = {}; var callback; var DB_NAME = opts.idbName || 'graphcache-v4'; var ENTRIES_STORE_NAME = 'entries'; var METADATA_STORE_NAME = 'metadata'; var batch = Object.create(null); var timestamp = Math.floor(new Date().valueOf() / (1000 * 60 * 60 * 24)); var maxAge = timestamp - (opts.maxAge || 7); var req = indexedDB.open(DB_NAME, 1); var database$ = getRequestPromise(req); req.onupgradeneeded = () => { req.result.createObjectStore(ENTRIES_STORE_NAME); req.result.createObjectStore(METADATA_STORE_NAME); }; var serializeEntry = entry => entry.replace(/:/g, '%3a'); var deserializeEntry = entry => entry.replace(/%3a/g, ':'); var serializeBatch = () => { var data = ''; for (var key in batch) { var value = batch[key]; data += serializeEntry(key); data += ':'; if (value) data += serializeEntry(value); data += ':'; } return data; }; var deserializeBatch = input => { var data = {}; var char = ''; var key = ''; var entry = ''; var mode = 0; var index = 0; while (index < input.length) { entry = ''; while ((char = input[index++]) !== ':' && char) { entry += char; } if (mode) { data[key] = deserializeEntry(entry) || undefined; mode = 0; } else { key = deserializeEntry(entry); mode = 1; } } return data; }; return { clear() { return database$.then(database => { var transaction = database.transaction([METADATA_STORE_NAME, ENTRIES_STORE_NAME], 'readwrite'); transaction.objectStore(METADATA_STORE_NAME).clear(); transaction.objectStore(ENTRIES_STORE_NAME).clear(); batch = Object.create(null); return getTransactionPromise(transaction); }); }, readMetadata() { return database$.then(database => { return getRequestPromise(database.transaction(METADATA_STORE_NAME, 'readonly').objectStore(METADATA_STORE_NAME).get(METADATA_STORE_NAME)); }, () => null); }, writeMetadata(metadata) { database$.then(database => { return getRequestPromise(database.transaction(METADATA_STORE_NAME, 'readwrite').objectStore(METADATA_STORE_NAME).put(metadata, METADATA_STORE_NAME)); }, () => { /* noop */ }); }, writeData(entries) { Object.assign(batch, entries); var toUndefined = () => undefined; return database$.then(database => { return getRequestPromise(database.transaction(ENTRIES_STORE_NAME, 'readwrite').objectStore(ENTRIES_STORE_NAME).put(serializeBatch(), timestamp)); }).then(toUndefined, toUndefined); }, readData() { var chunks = []; return database$.then(database => { var transaction = database.transaction(ENTRIES_STORE_NAME, 'readwrite'); var store = transaction.objectStore(ENTRIES_STORE_NAME); var request = (store.openKeyCursor || store.openCursor).call(store); request.onsuccess = function () { if (this.result) { var { key } = this.result; if (typeof key !== 'number' || key < maxAge) { store.delete(key); } else { var _request = store.get(key); var index = chunks.length; chunks.push(''); _request.onsuccess = () => { var result = '' + _request.result; if (key === timestamp) Object.assign(batch, deserializeBatch(result)); chunks[index] = result; }; } this.result.continue(); } }; return getTransactionPromise(transaction); }).then(() => deserializeBatch(chunks.join('')), () => batch); }, onCacheHydrated: opts.onCacheHydrated, onOnline(cb) { if (callback) { window.removeEventListener('online', callback); callback = undefined; } window.addEventListener('online', callback = () => { cb(); }); } }; }; exports.makeDefaultStorage = makeDefaultStorage; //# sourceMappingURL=urql-exchange-graphcache-default-storage.js.map