var Sequelize = require('sequelize'); exports.initialize = function initializeSchema(schema) { schema.adapter = new SequelizeAdapter(schema); }; function SequelizeAdapter(schema) { this.schema = schema; this._models = {}; this._modelDefinitions = {}; this.client = new Sequelize( schema.settings.database, schema.settings.username, schema.settings.password, { host: schema.settings.host, port: schema.settings.port, logging: schema.settings.port, maxConcurrentQueries: schema.settings.maxConcurrentQueries } ); } SequelizeAdapter.prototype.define = function (d) { var model = d.model; var settings = d.settings; var properties = d.properties; var translate = { 'String': Sequelize.STRING, 'Text': Sequelize.TEXT, 'Number': Sequelize.INTEGER, 'Boolean': Sequelize.BOOLEAN, 'Date': Sequelize.DATE }; var props = {}; Object.keys(properties).forEach(function (property) { props[property] = translate[properties[property].type.name]; }); this._modelDefinitions[model.modelName] = props; this._models[model.modelName] = this.client.define(model.modelName, props, settings); }; SequelizeAdapter.prototype.model = function getModel(name) { return this._models[name]; }; SequelizeAdapter.prototype.cleanup = function (model, obj) { if (!obj) { return null; } var def = this._modelDefinitions[model]; var data = {}; Object.keys(def).concat(['id']).forEach(function (key) { data[key] = obj[key]; }); return data; }; SequelizeAdapter.prototype.save = function (model, data, callback) { this.model(model).find(data.id) .on('success', function (record) { record.updateAttributes(data) .on('success', callback.bind(data, null)) .on('failure', callback); }) .on('failure', callback); }; SequelizeAdapter.prototype.updateAttributes = function (model, id, data, callback) { data.id = id; this.save(model, data, callback); }; SequelizeAdapter.prototype.create = function (model, data, callback) { this.model(model) .build(data) .save() .on('success', function (obj) { callback(null, obj.id); }) .on('failure', callback); }; SequelizeAdapter.prototype.automigrate = function (cb) { this.client.sync({force: true}) .on('success', cb.bind(this, null)) .on('failure', cb); }; SequelizeAdapter.prototype.exists = function (model, id, callback) { this.model(model) .find(id) .on('success', function (data) { if (callback) { callback.calledOnce = true; callback(null, data); } }) .on('failure', co(callback)); }; function co(cb, args) { return function () { if (!cb.calledOnce) { cb.calledOnce = true; cb.call.apply(cb, args || []); } } } SequelizeAdapter.prototype.find = function find(model, id, callback) { this.model(model) .find(id) .on('success', function (data) { callback(null, this.cleanup(model, data)); }.bind(this)) .on('failure', callback); }; SequelizeAdapter.prototype.destroy = function destroy(model, id, callback) { this.model(model) .find(id) .on('success', function (data) { data.destroy() .on('success', callback.bind(null, null)) .on('failure', callback); }.bind(this)) .on('failure', callback); }; SequelizeAdapter.prototype.all = function all(model, filter, callback) { this.model(model).all.on('success', function (data) { // TODO: filter callback(null, data); }).on('failure', callback); }; function applyFilter(filter) { if (typeof filter === 'function') { return filter; } var keys = Object.keys(filter); return function (obj) { var pass = true; keys.forEach(function (key) { if (!test(filter[key], obj[key])) { pass = false; } }); return pass; } function test(example, value) { if (typeof value === 'string' && example && example.constructor.name === 'RegExp') { return value.match(example); } // not strict equality return example == value; } } SequelizeAdapter.prototype.destroyAll = function destroyAll(model, callback) { callback(); }; SequelizeAdapter.prototype.count = function count(model, callback) { this.model(model).count() .on('success', function (c) { if (callback) callback(null, c); }) .on('failure', callback); };