2015-07-22 00:58:34 +00:00
|
|
|
'use strict';
|
|
|
|
|
|
|
|
var sqlite3 = require('sqlite3');
|
2015-11-10 12:16:50 +00:00
|
|
|
// TODO expire unused dbs from cache
|
2015-07-22 00:58:34 +00:00
|
|
|
var dbs = {};
|
|
|
|
|
|
|
|
function sanitize(str) {
|
|
|
|
return String(str).replace("'", "''");
|
|
|
|
}
|
|
|
|
|
2015-11-09 20:49:53 +00:00
|
|
|
function create(opts, verbs) {
|
|
|
|
if (!verbs) {
|
|
|
|
verbs = {};
|
|
|
|
}
|
2015-07-22 00:58:34 +00:00
|
|
|
if (!opts) {
|
|
|
|
opts = {};
|
|
|
|
}
|
|
|
|
|
2015-11-10 12:16:50 +00:00
|
|
|
var db;
|
|
|
|
var PromiseA = verbs.Promise || require('bluebird');
|
2015-11-09 20:49:53 +00:00
|
|
|
var dbname = "";
|
2015-11-10 12:16:50 +00:00
|
|
|
|
|
|
|
dbname += (opts.prefix || '');
|
2015-11-09 20:49:53 +00:00
|
|
|
if (opts.subtenant) {
|
|
|
|
dbname += opts.subtenant + '.';
|
|
|
|
}
|
|
|
|
if (opts.tenant) {
|
|
|
|
dbname += opts.tenant + '.';
|
|
|
|
}
|
2015-11-10 12:16:50 +00:00
|
|
|
dbname += (opts.dbname || '');
|
|
|
|
dbname += (opts.suffix || '');
|
|
|
|
dbname += (opts.ext || '');
|
2015-11-17 08:33:54 +00:00
|
|
|
dbname = require('path').resolve(opts.dirname || '', dbname);
|
2015-11-09 20:49:53 +00:00
|
|
|
|
2015-11-10 12:16:50 +00:00
|
|
|
function initDb(newOpts) {
|
|
|
|
if (dbs[dbname].initPromise) {
|
|
|
|
return dbs[dbname].initPromise;
|
|
|
|
}
|
2015-07-22 00:58:34 +00:00
|
|
|
|
2015-07-29 00:04:54 +00:00
|
|
|
if (!newOpts) {
|
|
|
|
newOpts = {};
|
|
|
|
}
|
2015-07-22 00:58:34 +00:00
|
|
|
|
2015-07-29 00:04:54 +00:00
|
|
|
var key = newOpts.key || opts.key;
|
|
|
|
var bits = newOpts.bits || opts.bits;
|
|
|
|
|
2015-11-10 12:16:50 +00:00
|
|
|
dbs[dbname].initPromise = new PromiseA(function (resolve, reject) {
|
|
|
|
if (dbs[dbname].db._initialized) {
|
2015-07-29 00:04:54 +00:00
|
|
|
resolve(db);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!key) {
|
|
|
|
if (!bits) {
|
2015-11-10 12:16:50 +00:00
|
|
|
//console.log("INITIALIZED WITHOUT KEY");
|
|
|
|
//console.log(opts);
|
|
|
|
dbs[dbname].db._initialized = true;
|
2015-07-29 00:04:54 +00:00
|
|
|
}
|
2015-11-10 12:16:50 +00:00
|
|
|
dbs[dbname].db = db;
|
2015-07-29 00:04:54 +00:00
|
|
|
resolve(db);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO test key length
|
|
|
|
|
|
|
|
db.serialize(function () {
|
|
|
|
var setup = [];
|
|
|
|
|
|
|
|
if (!bits) {
|
|
|
|
bits = 128;
|
2015-07-22 00:58:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// TODO db.run(sql, function () { resolve() });
|
2015-07-31 21:06:29 +00:00
|
|
|
setup.push(new PromiseA(function (resolve, reject) {
|
2015-07-29 00:04:54 +00:00
|
|
|
db.run("PRAGMA KEY = \"x'" + sanitize(key) + "'\"", [], function (err) {
|
2015-07-22 00:58:34 +00:00
|
|
|
if (err) { reject(err); return; }
|
|
|
|
resolve(this);
|
|
|
|
});
|
|
|
|
}));
|
2015-07-31 21:06:29 +00:00
|
|
|
setup.push(new PromiseA(function (resolve, reject) {
|
2015-07-29 00:04:54 +00:00
|
|
|
//process.nextTick(function () {
|
|
|
|
db.run("PRAGMA CIPHER = 'aes-" + sanitize(bits) + "-cbc'", [], function (err) {
|
2015-07-22 00:58:34 +00:00
|
|
|
if (err) { reject(err); return; }
|
|
|
|
resolve(this);
|
|
|
|
});
|
2015-07-29 00:04:54 +00:00
|
|
|
//});
|
2015-07-22 00:58:34 +00:00
|
|
|
}));
|
|
|
|
|
2015-07-31 21:06:29 +00:00
|
|
|
PromiseA.all(setup).then(function () {
|
2015-07-29 00:04:54 +00:00
|
|
|
// restore original functions
|
2015-11-10 12:16:50 +00:00
|
|
|
dbs[dbname].db._initialized = true;
|
|
|
|
dbs[dbname].db = db;
|
|
|
|
|
2015-07-29 00:04:54 +00:00
|
|
|
resolve(db);
|
|
|
|
}, reject);
|
|
|
|
});
|
2015-07-22 00:58:34 +00:00
|
|
|
});
|
2015-07-29 00:04:54 +00:00
|
|
|
|
2015-11-10 12:16:50 +00:00
|
|
|
return dbs[dbname].initPromise;
|
|
|
|
}
|
|
|
|
|
|
|
|
function newDb() {
|
|
|
|
// dbs[dbname] = db //
|
|
|
|
db = new sqlite3.Database(dbname);
|
|
|
|
db.init = initDb;
|
|
|
|
db.sanitize = sanitize;
|
|
|
|
db.escape = sanitize;
|
|
|
|
|
|
|
|
if (opts.verbose) {
|
|
|
|
sqlite3.verbose();
|
|
|
|
}
|
|
|
|
|
|
|
|
return db;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Could be any of:
|
|
|
|
// * db object
|
|
|
|
// * init promise
|
|
|
|
|
|
|
|
if (!dbs[dbname]) {
|
|
|
|
dbs[dbname] = { db: newDb() };
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dbs[dbname].db._initialized) {
|
|
|
|
return PromiseA.resolve(dbs[dbname].db);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (opts.init || ('init' === opts.type) || (opts.bits && opts.key)) {
|
|
|
|
dbs[dbname].initPromise = db.init(opts);
|
|
|
|
}
|
|
|
|
|
|
|
|
return dbs[dbname].initPromise || PromiseA.resolve(dbs[dbname].db);
|
2015-07-22 00:58:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
module.exports.sanitize = sanitize;
|
2015-07-24 20:47:11 +00:00
|
|
|
module.exports.escape = sanitize;
|
2015-07-22 00:58:34 +00:00
|
|
|
module.exports.Database = sqlite3.Database;
|
|
|
|
module.exports.create = create;
|