Skip to content

Instantly share code, notes, and snippets.

@Loupax
Last active August 29, 2015 13:56
Show Gist options
  • Save Loupax/8800449 to your computer and use it in GitHub Desktop.
Save Loupax/8800449 to your computer and use it in GitHub Desktop.
ClientDB, a library that allows you to emulate db api in the client.
var ClientDB = function(){
var DB = this;
var localStorage = window.localStorage;
// This object will contain an array for every data type
var tables = {};
// This object will contain the latest id for every table in the app.
var table_ids = {};
// This record will contain any records that are deleted from the local DB, but are not yet synched with the server
var deleted_records = {};
// Creates a new record
this.insert = function(table_name, row){
tables[table_name] = tables[table_name] || [];
row.client_id = getClientId(table_name);
tables[table_name].push(row);
return row;
};
var getClientId = function(table_name){
// Generate the proper client id for the record
if(table_ids[table_name]){
table_ids[table_name]++;
}
else{
table_ids[table_name] = 1;
}
return table_ids[table_name];
};
// Gets all the records of the provided table that match the contents of the where object
this.get = function(table_name, where){
var results = [], current_row, i, table_length, property, match_found;
// Gather all the rows in that table that match the properties of the where object
if(tables[table_name] && (typeof where === 'object'))
{
table_length = tables[table_name].length;
for(i = 0; i < table_length; i++)
{
current_row = tables[table_name][i];
match_found = true;
for(property in where)
{
if(!((property in current_row) && (current_row[property] == where[property])))
{
match_found = false;
}
}
if(match_found)
{
results.push(current_row);
}
}
return results;
}
// No where clause is provided? Get everyting
if(where === undefined)
{
return tables[table_name];
}
// If we miss something just return an empty array
return [];
};
// Remove all the records that match the properties of the where object
// from the Client DB
this.delete = function(table_name, where){
var records_to_delete = [], current_row, i, table_length, property, match_found, index;
// Gather all the rows in that table that match the properties of the where object
if(tables[table_name] && (typeof where === 'object'))
{
table_length = tables[table_name].length;
for(i = 0; i < table_length; i++)
{
current_row = tables[table_name][i];
match_found = true;
for(property in where)
{
if(!((property in current_row) && (current_row[property] == where[property])))
{
match_found = false;
}
}
if(match_found)
{
records_to_delete.push(current_row);
}
}
// Remove all the deleted records from the table itself
for(i = 0 ; i < records_to_delete.length; i++)
{
index = tables[table_name].indexOf(records_to_delete[i]);
if(index > -1)
{
tables[table_name].splice(index, 1);
}
}
}
// No where clause is provided? Delete everyting
if(where === undefined)
{
records_to_delete = tables[table_name].slice(0);
tables[table_name].length = 0;
}
// After we have gathered all the records that we have deleted, update the global deleted_records object
deleted_records[table_name] = deleted_records[table_name] || [];
for(i = 0; i < records_to_delete.length; i++)
{
deleted_records[table_name].push(records_to_delete[i]);
}
};
// Synchronises the current db with the one in the server.
//
// Any records in the client that don't have a server id
// will be stored in the database and receive their id
//
// Any records in the client that have a server id will be
// updated in the remote database
//
// All the records inside the deleted_records object will be
// requested to be deleted and removed from the local
// db once succesfull.
//
// When everything is complete, the local storage will be updated
//
// For this functionality to work, the server must be set up to
// receive tables and deleted_records tables, and must respond
// with an array that contains all the inserted and updated records
// in their current status, and an array containing all the records
// that have been succesfully deleted.
// Everything will happen in only one request
this.sync = function(sync_url, callback){
prepareForSync();
$.post(sync_url, {client_db: tables, deleted_records: deleted_records}, function(response){
tables = (response.records instanceof Array)?{}:response.records;
deleted_records = {};
DB.saveToLocalStorage();
},'json').done(function(){
if(callback)
{
callback(true);
}
}).fail(function(){
callback(false);
});
};
// Makes sure all the data are valid before syncing with the server
var prepareForSync = function(){
var table_name, i, record;
for(table_name in tables)
{
for(i = 0; i < tables[table_name].length; i++)
{
record = tables[table_name][i];
// Set a client id for all the records that don't have one
if(record.client_id === null)
{
record.client_id = getClientId(table_name);
}
}
}
};
// Initializes the localDB with data stored in the local storage
this.loadFromLocalStorage = function(){
tables = JSON.parse(localStorage.getItem('tables')) || {};
table_ids = JSON.parse(localStorage.getItem('table_ids')) || {};
deleted_records = JSON.parse(localStorage.getItem('deleted_records')) || {};
};
// Saves the current state of localDb to the local storage
this.saveToLocalStorage = function(){
localStorage.setItem('table_ids', JSON.stringify(table_ids));
localStorage.setItem('tables', JSON.stringify(tables));
localStorage.setItem('deleted_records', JSON.stringify(deleted_records));
};
// Does a GET request to the provided URL, and adds the response to the proper table
// It should be up to the server to perform security and permission checks
this.loadFromRemote = function(table_name, url, callback){
$.get(url, function(response){
console.log(response);
var duplicates;
for(var i = 0; i < response.length; i++)
{
// Is the row already in the local db? If that's so, update the record with the current data
duplicates = DB.get(table_name, {id: response[i].id});
if( duplicates.length > 0)
{
// Update the record
for(var prop in response[i])
{
duplicates[0][prop] = response[i][prop];
}
}
else
// Else, just insert it
{
DB.insert(table_name, response[i]);
}
}
if(callback)
{
callback();
}
},'json');
};
this.init = function(callback){
DB.loadFromLocalStorage();
// Load all the notes. The controller will send only the documents that belong to the currently logged in user
};
this.debug = function(){
console.log(tables, table_ids, deleted_records,localStorage);
};
this.getTables = function(){
return tables;
};
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment