mirror of
				https://github.com/mickael-kerjean/filestash.git
				synced 2025-10-31 18:16:00 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			172 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			172 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| "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;
 | 
