-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
16 changed files
with
995 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
'use strict'; | ||
|
||
module.exports = { | ||
table_name: 'user_data', // eslint-disable-line | ||
fields: { | ||
email: { | ||
type: 'string', | ||
email: true | ||
}, | ||
username: { | ||
type: 'string', | ||
min: 3, | ||
max: 20, | ||
unique: true | ||
}, | ||
dob: { type: 'date' } | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
'use strict'; | ||
|
||
var Joi = require('joi'); | ||
|
||
var mapObj = require('./create_table_map.js').mapObj; | ||
|
||
// non empty, alphanumeric, no leading number, less than 64 | ||
var dbNameRegEx = /^[A-Za-z_]\w{0,62}$/; | ||
var fieldTypes = Object.keys(mapObj); | ||
|
||
var fieldSchema = Joi.object() | ||
.keys({ type: Joi.any().valid(fieldTypes) }) | ||
.unknown() | ||
; | ||
var configSchema = Joi.object().keys({ | ||
table_name: Joi.string().regex(dbNameRegEx).required(), // eslint-disable-line | ||
fields: Joi.object().pattern(dbNameRegEx, fieldSchema).required() // eslint-disable-line | ||
}); | ||
|
||
module.exports = function (config) { | ||
return Joi.assert(config, configSchema); | ||
}; | ||
|
||
module.exports.dbNameRegEx = dbNameRegEx; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
'use strict'; | ||
|
||
var mapObj = { | ||
number: function (opts) { | ||
return opts.integer ? 'BIGINT' : 'DOUBLE PRECISION'; | ||
}, | ||
string: function (opts) { | ||
var length = opts.max || 80; | ||
|
||
return 'VARCHAR(' + length + ')'; | ||
}, | ||
boolean: function () { | ||
return 'BOOLEAN'; | ||
}, | ||
date: function (opts) { | ||
return opts.timestamp ? 'TIMESTAMP' : 'DATE'; | ||
} | ||
}; | ||
|
||
function mapper (name, type, options) { | ||
var opts = options || {}; | ||
var constraints = ''; | ||
|
||
if (opts.unique) { | ||
constraints += ' CONSTRAINT ' + name + '_unique UNIQUE'; | ||
} | ||
|
||
return name + ' ' + mapObj[type](opts) + constraints; | ||
} | ||
|
||
module.exports = mapper; | ||
module.exports.mapObj = mapObj; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
'use strict'; | ||
|
||
var sqlGen = require('./sql_gen.js'); | ||
var configValidator = require('./config_validator.js'); | ||
|
||
var methods = { | ||
init: function (client, config, _, cb) { | ||
var callback = (!cb && typeof _ === 'function') ? _ : cb; | ||
|
||
configValidator(config); | ||
|
||
return client.query(sqlGen.init(config), callback); | ||
} | ||
}; | ||
|
||
['select', 'update', 'delete', 'insert'].forEach(function (method) { | ||
methods[method] = function (client, config, options, cb) { | ||
var tableName = config.table_name; | ||
var args = sqlGen[method](tableName, options).concat([cb]); | ||
|
||
return client.query.apply(client, args); | ||
}; | ||
}); | ||
|
||
methods.bindAll = function (pool, schema) { | ||
return [ | ||
'select', 'update', 'delete', 'insert' | ||
].reduce(function (acc, method) { | ||
acc[method] = function (options, cb) { | ||
return pool.connect() | ||
.then(function (client) { | ||
return methods[method](client, schema, options) | ||
.then(function (result) { | ||
client.release(); | ||
|
||
return cb ? cb(null, result) : result; | ||
}) | ||
.catch(function (err) { | ||
client.release(); | ||
|
||
return cb ? cb(err) : null; | ||
}); | ||
}); | ||
}; | ||
|
||
return acc; | ||
}, {}); | ||
}; | ||
|
||
module.exports = methods; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
/* | ||
* Abase DB plugin | ||
* | ||
* Accepts path the schema defining the user model in the plugin options, | ||
* or relies on the schema attached to the server settings object. | ||
* | ||
* Provides database helper functions to do schema-compatible CRUD operations. | ||
* Attaches these methods to the request object at the pre-handler lifecycle | ||
* point. | ||
*/ | ||
'use strict'; | ||
|
||
var pg = require('pg'); | ||
var db = require('./helpers.js'); | ||
var parse = require('./parse.js'); | ||
|
||
exports.register = function (server, options, next) { | ||
var schema = parse.schema(server.app.abase || {}, options.schemaPath); | ||
|
||
var connection = parse.dbConfig(options.dbConnection); | ||
var pool = new pg.Pool(connection); | ||
|
||
pool.connect(function (dbConnErr, client, release) { | ||
if (dbConnErr) { | ||
return next(dbConnErr); | ||
} | ||
|
||
return db.init(client, schema, function (dbErr) { | ||
release(); | ||
|
||
if (dbErr) { | ||
return next(dbErr); | ||
} | ||
|
||
server.ext('onPreHandler', function (request, reply) { | ||
request.abase = { db: db.bindAll(pool, schema) }; | ||
reply.continue(); | ||
}); | ||
|
||
server.decorate('server', 'endAbaseDb', function () { | ||
pool.end(); | ||
}); | ||
|
||
return next(); | ||
}); | ||
}); | ||
}; | ||
|
||
exports.register.attributes = { name: 'abase-db' }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
'use strict'; | ||
|
||
var url = require('url'); | ||
|
||
exports.schema = function (schema, schemaPath) { | ||
var sch; | ||
|
||
if (!schema || Object.keys(schema).length === 0) { | ||
sch = require(schemaPath); // eslint-disable-line | ||
} else { | ||
sch = schema; | ||
} | ||
|
||
return sch; | ||
}; | ||
|
||
|
||
exports.dbConfig = function (dbConnection) { | ||
var parsed; | ||
|
||
if (typeof dbConnection === 'string') { | ||
parsed = url.parse(dbConnection); | ||
|
||
return { | ||
host: parsed.hostname, | ||
port: parsed.port, | ||
database: parsed.pathname.split('/')[1], | ||
user: (parsed.auth || '').split(':')[0], | ||
password: (parsed.auth || '').split(':')[1] | ||
}; | ||
} | ||
|
||
return dbConnection; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
'use strict'; | ||
|
||
var mapper = require('./create_table_map.js'); | ||
var _ = require('./utils.js'); | ||
|
||
|
||
function paramStr (columns, opts) { | ||
var offset = (opts && opts.offset) || 0; | ||
var assign = (opts && opts.assign) || false; | ||
|
||
return columns.map(function (k, i) { | ||
var suff = '$' + (1 + i + (offset || 0)); | ||
var pref = assign ? k + '=' : ''; | ||
|
||
return pref + suff; | ||
}); | ||
} | ||
|
||
|
||
function processWhere (where, query, values) { | ||
var keys = Object.keys(where); | ||
var conds = paramStr(keys, { offset: values.length, assign: true }); | ||
var vals = _.values(where, keys); | ||
|
||
return { | ||
query: query.concat('WHERE').concat(conds.join(' AND ')), | ||
values: values.concat(vals) | ||
}; | ||
} | ||
|
||
|
||
exports.init = function init (config) { | ||
var tableName = config.table_name; | ||
var fields = config.fields; | ||
|
||
var columns = Object.keys(fields).map(function (key) { | ||
var type = fields[key].type; | ||
var opts = _.except(['type'], fields[key]); | ||
|
||
return mapper(key, type, opts); | ||
}); | ||
|
||
return ['CREATE TABLE IF NOT EXISTS "' + tableName + '"'] | ||
.concat('(' + columns.join(', ') + ')') | ||
.join(' ') | ||
.trim(); | ||
}; | ||
|
||
|
||
exports.select = function select (tableName, options) { | ||
var columns = options.select || ['*']; | ||
var values = []; | ||
var query = ['SELECT'] | ||
.concat(columns.join(', ')) | ||
.concat('FROM') | ||
.concat('"' + tableName + '"'); | ||
var result; | ||
|
||
if (options.where) { | ||
result = processWhere(options.where, query, values); | ||
query = result.query; | ||
values = result.values; | ||
} | ||
|
||
query = query.join(' ').trim(); | ||
|
||
return [query, values]; | ||
}; | ||
|
||
|
||
exports.insert = function insert (tableName, options) { | ||
var fields = options.fields || {}; | ||
var columns = Object.keys(fields); | ||
var values = _.values(fields, columns); | ||
var params = paramStr(columns); | ||
|
||
var query = ['INSERT INTO "' + tableName + '"'] | ||
.concat('(' + columns.join(', ') + ')') | ||
.concat('VALUES') | ||
.concat('(' + params.join(', ') + ')') | ||
.join(' ') | ||
.trim(); | ||
|
||
return [query, values]; | ||
}; | ||
|
||
|
||
exports.update = function update (tableName, options) { | ||
var fields = options.fields || {}; | ||
var columns = Object.keys(fields); | ||
var conditions = paramStr(columns, { assign: true }); | ||
var values = _.values(fields, columns); | ||
|
||
var query = ['UPDATE "' + tableName + '"'] | ||
.concat('SET') | ||
.concat(conditions.join(', ')); | ||
var result; | ||
|
||
if (options.where) { | ||
result = processWhere(options.where, query, values); | ||
query = result.query; | ||
values = result.values; | ||
} | ||
|
||
query = query.join(' ').trim(); | ||
|
||
return [query, values]; | ||
}; | ||
|
||
|
||
exports.delete = function _delete (tableName, options) { | ||
var query = ['DELETE FROM "' + tableName + '"']; | ||
var values = []; | ||
var result = processWhere(options.where, query, values); | ||
|
||
query = result.query; | ||
values = result.values; | ||
|
||
query = query.join(' ').trim(); | ||
|
||
return [query, values]; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
'use strict'; | ||
|
||
exports.values = function (obj, keys) { | ||
return (keys || Object.keys(obj)) | ||
.map(function (k) { return obj[k] }); | ||
}; | ||
|
||
|
||
function except (fields, obj) { | ||
var o = {}; | ||
|
||
Object.keys(obj).forEach(function (k) { | ||
if (fields.indexOf(k) === -1) { | ||
o[k] = obj[k]; | ||
} | ||
}); | ||
|
||
return o; | ||
} | ||
|
||
|
||
exports.except = except; | ||
|
||
exports.shallowCopy = function (obj) { | ||
return except([], obj); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.