Skip to content

Instantly share code, notes, and snippets.

@zbabtkis
Last active August 29, 2015 13:56
Show Gist options
  • Save zbabtkis/9263520 to your computer and use it in GitHub Desktop.
Save zbabtkis/9263520 to your computer and use it in GitHub Desktop.
IndexedDB Made Easy
;(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