"use strict"; function Data(){ this.FILE_PATH = "file_path"; this.FILE_CONTENT = "file_content"; this.db = null; this._init(); } Data.prototype._init = function(){ const request = window.indexedDB.open('nuage', 1); request.onupgradeneeded = (e) => this._setup(e.target.result); this.db = new Promise((done, err) => { request.onsuccess = (e) => { done(e.target.result); } request.onerror = (e) => { err(e); }; }); } Data.prototype._setup = function(db){ let store; if(!db.objectStoreNames.contains(this.FILE_PATH)){ store = db.createObjectStore(this.FILE_PATH, {keyPath: "path"}); } if(!db.objectStoreNames.contains(this.FILE_CONTENT)){ store = db.createObjectStore(this.FILE_CONTENT, {keyPath: "path"}); } } /* * Fetch a record using its path, can be whether a file path or content */ Data.prototype.get = function(type, path){ if(type !== this.FILE_PATH && type !== this.FILE_CONTENT) return Promise.reject({}); return this.db.then((db) => { const tx = db.transaction(type, "readonly"); const store = tx.objectStore(type); const query = store.get(path); return new Promise((done, error) => { query.onsuccess = (e) => { let data = query.result; done(query.result || null); }; query.onerror = error; }); }); } Data.prototype.update = function(type, path, fn, exact = true){ return this.db.then((db) => { const tx = db.transaction(type, "readwrite"); const store = tx.objectStore(type); const range = exact === true? IDBKeyRange.only(path) : IDBKeyRange.bound( path, path+'\uFFFF', false, true ); const request = store.openCursor(range); let new_data = null; return new Promise((done, err) => { request.onsuccess = function(event) { const cursor = event.target.result; if(!cursor) return done(new_data); new_data = fn(cursor.value || null); cursor.delete(cursor.value.path); store.put(new_data); cursor.continue(); }; }); }); } Data.prototype.upsert = function(type, path, fn){ return this.db.then((db) => { const tx = db.transaction(type, "readwrite"); const store = tx.objectStore(type); const query = store.get(path); return new Promise((done, error) => { query.onsuccess = (e) => { const new_data = fn(query.result || null); if(!new_data) return done(query.result || null); const request = store.put(new_data); request.onsuccess = () => done(new_data); request.onerror = (e) => error(e); }; query.onerror = error; }); }); } Data.prototype.add = function(type, path, data){ if(type !== this.FILE_PATH && type !== this.FILE_CONTENT) return Promise.reject({}); return this.db.then((db) => { return new Promise((done, error) => { const tx = db.transaction(type, "readwrite"); const store = tx.objectStore(type); const request = store.put(data); request.onsuccess = () => done(data); request.onerror = (e) => error(e); }); }); } Data.prototype.remove = function(type, path, exact = true){ return this.db.then((db) => { const tx = db.transaction(type, "readwrite"); const store = tx.objectStore(type); if(exact === true){ const req = store.delete(path); return new Promise((done, err) => { req.onsuccess = () => done(); req.onerror = err; }); }else{ const request = store.openCursor(IDBKeyRange.bound( path, path+'\uFFFF', true, true )); return new Promise((done, err) => { request.onsuccess = function(event) { const cursor = event.target.result; if(cursor){ cursor.delete(cursor.value.path); cursor.continue(); }else{ done(); } }; }); } }); } Data.prototype.fetchAll = function(fn, type = this.FILE_PATH){ return this.db.then((db) => { const tx = db.transaction(type, "readwrite"); const store = tx.objectStore(type); const request = store.openCursor(); return new Promise((done, error) => { request.onsuccess = function(event) { const cursor = event.target.result; if(!cursor) return done(); const new_value = fn(cursor.value); cursor.continue(); }; }); }); } Data.prototype.destroy = function(){ this.db.then((db) => db.close()) clearTimeout(this.intervalId); window.indexedDB.deleteDatabase('nuage'); this._init(); } export const cache = new Data(); window._cache = cache;