brest-maria
Version:
MariaDB layer with some bREST API binding
186 lines (162 loc) • 7.54 kB
JavaScript
var Client = require('mariasql'),
Table = require('./table');
var async = require('async'),
EventEmitter = require('events').EventEmitter,
fs = require('fs'),
inherits = require('util').inherits,
path = require('path'),
_ = require('lodash');
var DB = function(settings) {
var self = this;
self.settings = settings;
self.tables = {};
self.client = new Client();
self.client.connect({
host: settings.host,
db: settings.db,
user: settings.user,
password: settings.password
});
self.client.on('connect', function() {
self.connected = true;
self.query('SHOW TABLES', function(err, res){
if (err) console.log('ERROR:', err);
else {
//Get the path to the custom modeles, or use default
var modulePath = path.join(path.dirname(require.main.filename),self.settings.models || 'model');
//Check if we can use custom models (if path exists)
fs.exists(modulePath, function(useCustomModules) {
async.each(res, function (row, callback) {
async.waterfall([
// Get the table name and check, if custome model exists
function (callback) {
var name = row['Tables_in_' + self.settings.db];
if (useCustomModules) {
var customFile = path.join(modulePath, name + '.js');
fs.exists(customFile, function (customModuleExists) {
callback(null, name, customFile, customModuleExists);
});
} else {
callback(null, name);
}
},
function (tableName, customFile, customModuleExists, callback) {
try {
var settings = {
table: tableName
};
if (customModuleExists) {
var CustomModule = require(customFile);
if (_.isFunction(CustomModule)) {
inherits(CustomModule, Table);
self.tables[tableName] = new CustomModule();
if (CustomModule.settings)
settings = _.defaults(CustomModule.settings, settings);
CustomModule.super_.apply(self.tables[tableName], [self, settings]);
} else {
if (_.isObject(CustomModule)) {
settings = _.defaults(CustomModule, settings);
self.tables[tableName] = new Table(self, settings);
}
}
} else {
self.tables[tableName] = new Table(self, settings);
}
callback();
} catch (e) {
callback(e);
}
}
],
function (err) {
callback(err);
});
}, function (err) {
if (err) self.emit('error', err);
else self.emit('ready');
});
});
}
});
})
.on('error', function(err) {
console.log('Client error: ' + err);
})
.on('close', function(hadError) {
console.log('Client closed');
});
this.query = function(query, params, callback){
if (_.isFunction(params)) {
callback = params;
params = {};
}
var out = [];
var q = self.client.query(query, params)
.on('result', function(res){
res.on('row', function(row){
out.push(row);
});
})
.on('error', function(err){
console.log('\nERROR in query:\n'+ q._query);
console.log('\n'+err+'\n');
if (self.settings.concealErrors) err = {MariaDB: 'Request failed'};
else err = {MariaDB: err+''};
callback(err);
q.abort(); //For some unknown reason, "end" function still fires on error
})
.on('end', function(){
callback(null, out);
});
if (self.settings.log) console.log('\nQuery: ', q._query);
return q;
};
this.queryRow = function(query, params, callback){
return self.query(query, params, function(err, res){
if (err) callback(err);
else callback(null, res[0]);
});
};
this.injectFilters = function(query, filters, filterQueries) {
var self = this;
var injections = {};
var used = {};
_.each(filters, function(value, filter){
if (filterQueries[filter]) {
//Preprocess value if needed
if (filterQueries[filter]._pre) {
value = filterQueries[filter]._pre(value);
}
if (filterQueries[filter]._esc) {
value = filterQueries[filter]._esc(value);
} else {
if (_.isArray(value)){
value = "'"+_.map(value, self.esc).join("','")+"'";
} else value = self.esc(""+value);
}
_.each(filterQueries[filter], function(injection, place){
if (place[0]!="_"){ //We use underscored keys for handlers
if (!used[place]) used[place] = [];
if (used[place].indexOf(injection)==-1){
used[place].push(injection);
if (injections[place]) injections[place] += " " + injection.replace(/\?/gi, value);
else injections[place] = injection.replace(/\?/gi, value);
}
}
});
}
});
_.each(injections, function(injection, key){
query = query.replace("{{"+key+"}}", " "+injection);
});
return query.replace(/({{.*?}})*/g,"");
};
this.table = function(table){
return self.tables[table];
};
this.esc = function(str){
return self.client.escape(str);
};
};
inherits(DB, EventEmitter);
module.exports = DB;