UNPKG

brest-maria

Version:
186 lines (162 loc) 7.54 kB
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;