|
(function(global) { |
|
var SECRET = Object.create(null); |
|
var DB_PREFIX = '$SimpleDB$'; |
|
var STORE = 'store'; |
|
|
|
function SimpleDBFactory(secret) { |
|
if (secret !== SECRET) throw TypeError('Invalid constructor'); |
|
} |
|
SimpleDBFactory.prototype = { |
|
open: function(name) { |
|
return new Promise(function(resolve, reject) { |
|
var request = indexedDB.open(DB_PREFIX + name); |
|
request.onupgradeneeded = function() { |
|
var db = request.result; |
|
db.createObjectStore(STORE); |
|
}; |
|
request.onsuccess = function() { |
|
var db = request.result; |
|
resolve(new SimpleDB(SECRET, name, db)); |
|
}; |
|
request.onerror = function() { |
|
reject(request.error); |
|
}; |
|
}); |
|
}, |
|
delete: function(name) { |
|
return new Promise(function(resolve, reject) { |
|
var request = indexedDB.deleteDatabase(DB_PREFIX + name); |
|
request.onsuccess = function() { |
|
resolve(undefined); |
|
}; |
|
request.onerror = function() { |
|
reject(request.error); |
|
}; |
|
}); |
|
} |
|
}; |
|
|
|
function SimpleDB(secret, name, db) { |
|
if (secret !== SECRET) throw TypeError('Invalid constructor'); |
|
this._name = name; |
|
this._db = db; |
|
} |
|
SimpleDB.cmp = indexedDB.cmp; |
|
SimpleDB.prototype = { |
|
get name() { |
|
return this._name; |
|
}, |
|
get: function(key) { |
|
var that = this; |
|
return new Promise(function(resolve, reject) { |
|
var tx = that._db.transaction(STORE, 'readwrite'); |
|
var store = tx.objectStore(STORE); |
|
var req = store.get(key); |
|
// NOTE: Could also use req.onsuccess/onerror |
|
tx.oncomplete = function() { resolve(req.result); }; |
|
tx.onabort = function() { reject(tx.error); }; |
|
}); |
|
}, |
|
set: function(key, value) { |
|
var that = this; |
|
return new Promise(function(resolve, reject) { |
|
var tx = that._db.transaction(STORE, 'readwrite'); |
|
var store = tx.objectStore(STORE); |
|
var req = store.put(value, key); |
|
tx.oncomplete = function() { resolve(undefined); }; |
|
tx.onabort = function() { reject(tx.error); }; |
|
}); |
|
}, |
|
delete: function(key) { |
|
var that = this; |
|
return new Promise(function(resolve, reject) { |
|
var tx = that._db.transaction(STORE, 'readwrite'); |
|
var store = tx.objectStore(STORE); |
|
var req = store.delete(key); |
|
tx.oncomplete = function() { resolve(undefined); }; |
|
tx.onabort = function() { reject(tx.error); }; |
|
}); |
|
}, |
|
clear: function() { |
|
var that = this; |
|
return new Promise(function(resolve, reject) { |
|
var tx = that._db.transaction(STORE, 'readwrite'); |
|
var store = tx.objectStore(STORE); |
|
var request = store.clear(); |
|
tx.oncomplete = function() { resolve(undefined); }; |
|
tx.onabort = function() { reject(tx.error); }; |
|
}); |
|
}, |
|
forEach: function(callback, options) { |
|
var that = this; |
|
return new Promise(function(resolve, reject) { |
|
options = options || {}; |
|
var tx = that._db.transaction(STORE, 'readwrite'); |
|
var store = tx.objectStore(STORE); |
|
var request = store.openCursor( |
|
options.range, |
|
options.direction === 'reverse' ? 'prev' : 'next'); |
|
request.onsuccess = function() { |
|
var cursor = request.result; |
|
if (!cursor) return; |
|
try { |
|
var terminate = callback(cursor.key, cursor.value); |
|
if (!terminate) cursor.continue(); |
|
} catch (ex) { |
|
tx.abort(); // ??? |
|
} |
|
}; |
|
tx.oncomplete = function() { resolve(undefined); }; |
|
tx.onabort = function() { reject(tx.error); }; |
|
}); |
|
}, |
|
getMany: function(keys) { |
|
var that = this; |
|
return new Promise(function(resolve, reject) { |
|
var tx = that._db.transaction(STORE, 'readwrite'); |
|
var store = tx.objectStore(STORE); |
|
var results = []; |
|
for (var key of keys) { |
|
store.get(key).onsuccess(function(result) { |
|
results.push(result); |
|
}); |
|
} |
|
tx.oncomplete = function() { resolve(results); }; |
|
tx.onabort = function() { reject(tx.error); }; |
|
}); |
|
}, |
|
setMany: function(entries) { |
|
var that = this; |
|
return new Promise(function(resolve, reject) { |
|
var tx = that._db.transaction(STORE, 'readwrite'); |
|
var store = tx.objectStore(STORE); |
|
for (var entry of entries) { |
|
store.put(entry.value, entry.key); |
|
} |
|
tx.oncomplete = function() { resolve(undefined); }; |
|
tx.onabort = function() { reject(tx.error); }; |
|
}); |
|
}, |
|
deleteMany: function(keys) { |
|
var that = this; |
|
return new Promise(function(resolve, reject) { |
|
var tx = that._db.transaction(STORE, 'readwrite'); |
|
var store = tx.objectStore(STORE); |
|
for (var key of keys) |
|
store.delete(key); |
|
tx.oncomplete = function() { resolve(undefined); }; |
|
tx.onabort = function() { reject(tx.error); }; |
|
}); |
|
} |
|
}; |
|
|
|
global.simpleDB = new SimpleDBFactory(SECRET); |
|
global.SimpleDBKeyRange = IDBKeyRange; |
|
}(self)); |