Last active
August 29, 2015 13:56
-
-
Save zbabtkis/9263520 to your computer and use it in GitHub Desktop.
IndexedDB Made Easy
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;(function(exports) { | |
var IDB = this.indexedDB || this.mozIndexedDB || this.webkitIndexedDB || this.msIndexedDB; | |
function Database(options) { | |
if (!options) throw new Database.DatabaseConstructorError; | |
this.version = options.version; | |
this.name = options.database; | |
this.initialize = options.initialize; | |
} | |
Database.ERRORS = {} | |
Database.ERRORS.DatabaseConstructorError = function() { | |
Error.call(this, "The arguments you specified are invalid. Please check the docs"); | |
}; | |
Database.ERRORS.DatabaseConstructorError.prototype = new Error(); | |
Database.ERRORS.DatabaseVersionError = function() { | |
Error.call(this, "You are opening an outdated version of this DB"); | |
}; | |
Database.ERRORS.DatabaseVersionError.prototype = new Error(); | |
function DBConnection(DB) { | |
var con = IDB.open(DB.name, DB.version), | |
buffer = [], | |
db, API; | |
con.onupgradeneeded = function(e) { | |
DB.initialize(e.target.result); | |
}; | |
con.onsuccess = function(e) { | |
db = e.target.result; | |
_flushBuffer(); | |
}; | |
/** | |
* Private interface | |
*/ | |
// Runs all built up DB requests. | |
function _flushBuffer() { | |
buffer = buffer.reduce(function(last, req) { | |
_provideDB.apply({}, req); | |
}, []); | |
} | |
// Resolves promise to DB transaction. | |
function _provideDB(table, fn, resolve, reject) { | |
var tx = db.transaction(table, 'readwrite') | |
, ps = []; | |
tx.oncomplete = resolve; | |
tx.onerror = reject; | |
function resource(name, req) { | |
ps.push(new Promise(function(rs, rj) { | |
req.onsuccess = function(e) { | |
rs({resource: name, e: e}); | |
}; | |
})); | |
} | |
fn.call(tx, resource); | |
Promise.all(ps) | |
.then(resolve, reject); | |
} | |
API = { | |
use: function(table, fn) { | |
var p = new Promise(function(resolve, reject) { | |
if (db) { | |
provideDB(table, fn, resolve, reject); | |
} else { | |
buffer.push([table, fn, resolve, reject]); | |
} | |
}); | |
return { | |
as: function(cb) { | |
p.then(cb); | |
} | |
}; | |
} | |
} | |
return API; | |
}; | |
var Model = function(db, values) { | |
this.store = db.store; | |
this.db = db.db; | |
for(var i in values) { | |
this[i] = values[i]; | |
} | |
} | |
Model.extend = function(name, db, index) { | |
function _getFields(obj) { | |
return Object.keys(obj).join(','); | |
} | |
function _getValuesArray(obj) { | |
return Object.keys(obj).map(function(itm) { | |
return obj[itm]; | |
}); | |
} | |
var M = function(values) { | |
return new Model({store: name, db: db, key: index}, values); | |
}; | |
M.findAll = function() { | |
return Promise(function(resolve, reject) { | |
var results = []; | |
db.use(name, function(query) { | |
var os = this.objectStore(name) | |
, c = os.openCursor(); | |
query(c); | |
}) | |
.as(function(e) { | |
var c = e.target.result; | |
if(c) { | |
results.push(c.value); | |
} else { | |
resolve(results); | |
} | |
}); | |
}); | |
}; | |
M.find = function(query) { | |
return Promise(function(resolve, reject) { | |
if(!query) { | |
M._findAll(); | |
} | |
var results = []; | |
db.use(name, function(query) { | |
var os = this.objectStore(name) | |
.index(_getFields(query)) | |
.get(_getFieldValues(query)); | |
}) | |
.as(function(e) { | |
var c = e.target.result; | |
if(c) { | |
return c; | |
} | |
}); | |
}); | |
}; | |
Model.prototype.save = function() { | |
var _this = this; | |
this.con.use(this.store, function(query) { | |
query(this.objectStore(_this.store).put(this)); | |
}); | |
}; | |
Model.prototype.delete = function() { | |
var _this = this; | |
this.con.use(this.store, function(query) { | |
query( | |
this.objectStore(_this.store) | |
.delete(this[_this.key] || this.id) | |
); | |
}); | |
}; | |
exports.Database = Database; | |
exports.DBConnection = DBConnection; | |
}).call(this, this); | |
/** | |
* Begin App | |
*/ | |
var myDB = new Database({ | |
database: "my.pp", | |
version: 1.0, | |
initialize: function(db) { | |
if(db.objectStoreNames.contains('People')) { | |
db.deleteStore('People'); | |
} | |
this.People = db.createObjectStore('People', { | |
keyPath: 'id', | |
autoIncrement: true | |
}); | |
} | |
}); | |
var con = new DBConnection(myDB); | |
var People = new Model('People', DB); | |
People.all(); | |
function addPerson(person) { | |
con.use('People', function(query) { | |
query('people.all', this.objectStore('People').put(person)); | |
}) | |
.as(function(data) { | |
console.log(data); | |
}); | |
} | |
function getPeople() { | |
con.use('People', function(query) { | |
query('people', this.objectStore('People'). |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment