mirror of
https://github.com/mickael-kerjean/filestash.git
synced 2025-11-02 11:57:04 +08:00
190 lines
6.3 KiB
JavaScript
190 lines
6.3 KiB
JavaScript
"use strict";
|
|
// window.indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
|
|
// window.IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.msIDBTransaction || {READ_WRITE: "readwrite"}; // This line should only be needed if it is needed to support the object's constants for older browsers
|
|
// window.IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange || window.msIDBKeyRange;
|
|
|
|
function Data(){
|
|
this.FILE_PATH = "file_path";
|
|
this.FILE_CONTENT = "file_content";
|
|
this.db_version = 'v1.1';
|
|
this.db = null;
|
|
this.intervalId = window.setInterval(this._vacuum.bind(this), 5000);
|
|
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 = err;
|
|
});
|
|
}
|
|
|
|
Data.prototype._setup = function(db){
|
|
let store;
|
|
if(!db.objectStoreNames.contains(this.FILE_PATH)){
|
|
store = db.createObjectStore(this.FILE_PATH, {keyPath: "path"});
|
|
}
|
|
//store.createIndex("stale", ["last_access"])
|
|
|
|
if(!db.objectStoreNames.contains(this.FILE_CONTENT)){
|
|
store = db.createObjectStore(this.FILE_CONTENT, {keyPath: "path"});
|
|
}
|
|
//store.createIndex("stale", ["last_access"])
|
|
}
|
|
|
|
Data.prototype._vacuum = function(){
|
|
|
|
}
|
|
|
|
/*
|
|
* Fetch a record using its path, can be whether a file path or content
|
|
*/
|
|
Data.prototype.get = function(type, path, _record_access = true){
|
|
if(type !== this.FILE_PATH && type !== this.FILE_CONTENT) return Promise.reject({});
|
|
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) => {
|
|
let data = query.result;
|
|
done(query.result || null);
|
|
if(data && _record_access === true){
|
|
data.last_access = new Date();
|
|
if(!data.access_count) data.access_count = 0;
|
|
data.access_count += 1;
|
|
this.put(type, data.path, data);
|
|
}
|
|
};
|
|
tx.onerror = error;
|
|
});
|
|
});
|
|
}
|
|
|
|
Data.prototype.put = function(type, path, data){
|
|
if(type !== this.FILE_PATH && type !== this.FILE_CONTENT) return Promise.reject({});
|
|
|
|
return this.get(type, path, false)
|
|
.then((res) => {
|
|
let new_data;
|
|
if(res === null){
|
|
new_data = data;
|
|
new_data.last_update = new Date();
|
|
new_data.path = path;
|
|
}else{
|
|
new_data = Object.assign(res, data);
|
|
}
|
|
|
|
return this.db.then((db) => {
|
|
const tx = db.transaction(type, "readwrite");
|
|
const store = tx.objectStore(type);
|
|
|
|
return new Promise((done, error) => {
|
|
let request = store.put(new_data);
|
|
request.onsuccess = () => done(new_data.result || new_data.results);
|
|
request.onerror = (e) => error(e);
|
|
tx.onerror = (e) => error(e);
|
|
tx.oncomplete = () => done(new_data.result || new_data.results);
|
|
});
|
|
});
|
|
});
|
|
}
|
|
|
|
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();
|
|
return new Promise((done, err) => {
|
|
request.onsuccess = function(event) {
|
|
const cursor = event.target.result;
|
|
if(cursor){
|
|
if(cursor.value.path.indexOf(path) === 0 && path !== cursor.value.path){
|
|
store.delete(cursor.value.path);
|
|
}
|
|
cursor.continue();
|
|
}else{
|
|
done();
|
|
}
|
|
};
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
Data.prototype.update_path = function(updater_fn){
|
|
this.db.then((db) => {
|
|
const tx = db.transaction(this.FILE_PATH, "readwrite");
|
|
const store = tx.objectStore(this.FILE_PATH);
|
|
const request = store.openCursor();
|
|
request.onsuccess = function(event) {
|
|
const cursor = event.target.result;
|
|
if(cursor){
|
|
updater_fn(cursor.value, store)
|
|
cursor.continue();
|
|
}
|
|
};
|
|
|
|
});
|
|
}
|
|
Data.prototype.update_content = function(updater_fn){
|
|
this.db.then((db) => {
|
|
const tx = db.transaction(this.FILE_CONTENT, "readwrite");
|
|
const store = tx.objectStore(this.FILE_CONTENT);
|
|
const request = store.openCursor();
|
|
request.onsuccess = function(event) {
|
|
const cursor = event.target.result;
|
|
if(cursor){
|
|
const action = updater_fn(cursor.value, store);
|
|
cursor.continue();
|
|
}
|
|
};
|
|
|
|
});
|
|
}
|
|
|
|
Data.prototype.destroy = function(){
|
|
this.db.then((db) => db.close())
|
|
clearTimeout(this.intervalId);
|
|
window.indexedDB.deleteDatabase('nuage');
|
|
this._init();
|
|
}
|
|
|
|
// // test
|
|
// cache = new Data();
|
|
// cache.put(cache.FILE_PATH, '/', {a:3});
|
|
// cache.get(cache.FILE_PATH, '/').then((r) => {
|
|
// console.log(r);
|
|
// cache.remove(cache.FILE_PATH, '/');
|
|
// cache.get(cache.FILE_PATH, '/').then((r) => {
|
|
// console.log(r);
|
|
// //cache.destroy();
|
|
// });
|
|
// });
|
|
|
|
|
|
export const cache = new Data();
|
|
window._cache = cache;
|
|
|
|
_cache._debug = () => {
|
|
window._cache.update_path((e) => window.log("- path: "+e.path, e.results.slice(0,5).map((f) => {
|
|
if(f.type === 'directory'){ f.name = "d:"+f.name;} else{ f.name = "f:"+f.name;}
|
|
if(f.icon === 'loading') return "("+f.name+")";
|
|
else if(f.icon === 'error') return "_"+f.name+"_";
|
|
return f.name;
|
|
})));
|
|
}
|