不要怂,就是干,撸起袖子干!

Commit f8f732ea by Mick Hansen

Merge pull request #5688 from sequelize/before-connection-hook

Before connection hook
2 parents 35e68f67 1656c76d
...@@ -243,7 +243,11 @@ ConnectionManager.prototype.releaseConnection = function(connection) { ...@@ -243,7 +243,11 @@ ConnectionManager.prototype.releaseConnection = function(connection) {
}; };
ConnectionManager.prototype.$connect = function(config) { ConnectionManager.prototype.$connect = function(config) {
return this.dialect.connectionManager.connect(config); return this.sequelize.runHooks('beforeConnect', config).bind(this).then(function () {
return this.dialect.connectionManager.connect(config).then(function (connection) {
return connection;
});
});
}; };
ConnectionManager.prototype.$disconnect = function(connection) { ConnectionManager.prototype.$disconnect = function(connection) {
return this.dialect.connectionManager.disconnect(connection); return this.dialect.connectionManager.disconnect(connection);
......
...@@ -65,6 +65,7 @@ var hookTypes = { ...@@ -65,6 +65,7 @@ var hookTypes = {
afterDefine: {params: 1, sync: true}, afterDefine: {params: 1, sync: true},
beforeInit: {params: 2, sync: true}, beforeInit: {params: 2, sync: true},
afterInit: {params: 1, sync: true}, afterInit: {params: 1, sync: true},
beforeConnect: {params: 1},
beforeSync: {params: 1}, beforeSync: {params: 1},
afterSync: {params: 1}, afterSync: {params: 1},
beforeBulkSync: {params: 1}, beforeBulkSync: {params: 1},
...@@ -75,7 +76,8 @@ var hookAliases = { ...@@ -75,7 +76,8 @@ var hookAliases = {
beforeDelete: 'beforeDestroy', beforeDelete: 'beforeDestroy',
afterDelete: 'afterDestroy', afterDelete: 'afterDestroy',
beforeBulkDelete: 'beforeBulkDestroy', beforeBulkDelete: 'beforeBulkDestroy',
afterBulkDelete: 'afterBulkDestroy' afterBulkDelete: 'afterBulkDestroy',
beforeConnection: 'beforeConnect'
}; };
var Hooks = { var Hooks = {
...@@ -421,6 +423,13 @@ Hooks.hasHooks = Hooks.hasHook; ...@@ -421,6 +423,13 @@ Hooks.hasHooks = Hooks.hasHook;
*/ */
/** /**
* A hook that is run before a connection is created
* @param {String} name
* @param {Function} fn A callback function that is called with config passed to connection
* @name beforeConnect
*/
/**
* A hook that is run before Model.sync call * A hook that is run before Model.sync call
* @param {String} name * @param {String} name
* @param {Function} fn A callback function that is called with options passed to Model.sync * @param {Function} fn A callback function that is called with options passed to Model.sync
......
...@@ -15,7 +15,8 @@ var url = require('url') ...@@ -15,7 +15,8 @@ var url = require('url')
, Promise = require('./promise') , Promise = require('./promise')
, Hooks = require('./hooks') , Hooks = require('./hooks')
, Instance = require('./instance') , Instance = require('./instance')
, Association = require('./associations/index'); , Association = require('./associations/index')
, _ = require('lodash');
/** /**
* This is the main class, the entry point to sequelize. To use it, you just need to import sequelize: * This is the main class, the entry point to sequelize. To use it, you just need to import sequelize:
...@@ -58,12 +59,15 @@ var url = require('url') ...@@ -58,12 +59,15 @@ var url = require('url')
* @param {String} [username=null] The username which is used to authenticate against the database. * @param {String} [username=null] The username which is used to authenticate against the database.
* @param {String} [password=null] The password which is used to authenticate against the database. * @param {String} [password=null] The password which is used to authenticate against the database.
* @param {Object} [options={}] An object with options. * @param {Object} [options={}] An object with options.
* @param {String} [options.host='localhost'] The host of the relational database.
* @param {Integer} [options.port=] The port of the relational database.
* @param {String} [options.username=null] The username which is used to authenticate against the database.
* @param {String} [options.password=null] The password which is used to authenticate against the database.
* @param {String} [options.database=null] The name of the database
* @param {String} [options.dialect='mysql'] The dialect of the database you are connecting to. One of mysql, postgres, sqlite, mariadb and mssql. * @param {String} [options.dialect='mysql'] The dialect of the database you are connecting to. One of mysql, postgres, sqlite, mariadb and mssql.
* @param {String} [options.dialectModulePath=null] If specified, load the dialect library from this path. For example, if you want to use pg.js instead of pg when connecting to a pg database, you should specify 'pg.js' here * @param {String} [options.dialectModulePath=null] If specified, load the dialect library from this path. For example, if you want to use pg.js instead of pg when connecting to a pg database, you should specify 'pg.js' here
* @param {Object} [options.dialectOptions] An object of additional options, which are passed directly to the connection library * @param {Object} [options.dialectOptions] An object of additional options, which are passed directly to the connection library
* @param {String} [options.storage] Only used by sqlite. Defaults to ':memory:' * @param {String} [options.storage] Only used by sqlite. Defaults to ':memory:'
* @param {String} [options.host='localhost'] The host of the relational database.
* @param {Integer} [options.port=] The port of the relational database.
* @param {String} [options.protocol='tcp'] The protocol of the relational database. * @param {String} [options.protocol='tcp'] The protocol of the relational database.
* @param {Object} [options.define={}] Default options for model definitions. See sequelize.define for options * @param {Object} [options.define={}] Default options for model definitions. See sequelize.define for options
* @param {Object} [options.query={}] Default options for sequelize.query * @param {Object} [options.query={}] Default options for sequelize.query
...@@ -97,20 +101,32 @@ var url = require('url') ...@@ -97,20 +101,32 @@ var url = require('url')
* @param {String} uri A full database URI * @param {String} uri A full database URI
* @param {object} [options={}] See above for possible options * @param {object} [options={}] See above for possible options
*/ */
/**
* Instantiate sequelize with an options object
* @name Sequelize
* @constructor
*
* @param {object} [options={}] See above for possible options
*/
var Sequelize = function(database, username, password, options) { var Sequelize = function(database, username, password, options) {
var urlParts; var config;
options = options || {};
if (arguments.length === 1 && typeof database === 'object') {
// new Sequelize({ ... options })
options = database;
config = _.pick(options, 'host', 'port', 'database', 'username', 'password');
} else if ((arguments.length === 1 && typeof database === 'string') || (arguments.length === 2 && typeof username === 'object')) {
// new Sequelize(URI, { ... options })
if (arguments.length === 1 || (arguments.length === 2 && typeof username === 'object')) { config = {};
options = username || {}; options = username || {};
urlParts = url.parse(arguments[0]);
// reset username and password to null so we don't pass the options as the username var urlParts = url.parse(arguments[0]);
username = null;
password = null;
// SQLite don't have DB in connection url // SQLite don't have DB in connection url
if (urlParts.pathname) { if (urlParts.pathname) {
database = urlParts.pathname.replace(/^\//, ''); config.database = urlParts.pathname.replace(/^\//, '');
} }
options.dialect = urlParts.protocol.replace(/:$/, ''); options.dialect = urlParts.protocol.replace(/:$/, '');
...@@ -121,16 +137,16 @@ var Sequelize = function(database, username, password, options) { ...@@ -121,16 +137,16 @@ var Sequelize = function(database, username, password, options) {
} }
if (urlParts.auth) { if (urlParts.auth) {
username = urlParts.auth.split(':')[0]; config.username = urlParts.auth.split(':')[0];
password = urlParts.auth.split(':')[1]; config.password = urlParts.auth.split(':')[1];
} }
} else {
// new Sequelize(database, username, password, { ... options })
options = options || {};
config = {database: database, username: username, password: password};
} }
var config = {database: database, username: username, password: password};
Sequelize.runHooks('beforeInit', config, options); Sequelize.runHooks('beforeInit', config, options);
database = config.database;
username = config.username;
password = config.password;
this.options = Utils._.extend({ this.options = Utils._.extend({
dialect: 'mysql', dialect: 'mysql',
...@@ -172,12 +188,16 @@ var Sequelize = function(database, username, password, options) { ...@@ -172,12 +188,16 @@ var Sequelize = function(database, username, password, options) {
this.options.hooks = this.replaceHookAliases(this.options.hooks); this.options.hooks = this.replaceHookAliases(this.options.hooks);
if ((['', null, false].indexOf(config.password) > -1) || (typeof config.password === 'undefined')) {
config.password = null;
}
this.config = { this.config = {
database: database, database: config.database,
username: username, username: config.username,
password: (((['', null, false].indexOf(password) > -1) || (typeof password === 'undefined')) ? null : password), password: config.password,
host: this.options.host, host: config.host || this.options.host,
port: this.options.port, port: config.port || this.options.port,
pool: this.options.pool, pool: this.options.pool,
protocol: this.options.protocol, protocol: this.options.protocol,
native: this.options.native, native: this.options.native,
......
'use strict';
/* jshint -W030 */
var chai = require('chai')
, sinon = require('sinon')
, expect = chai.expect
, Support = require(__dirname + '/support')
, Sequelize = require(__dirname + '/../../index')
, ConnectionManager = require(__dirname + '/../../lib/dialects/abstract/connection-manager')
, Promise = Sequelize.Promise;
describe('connection manager', function () {
describe('$connect', function () {
beforeEach(function () {
this.sinon = sinon.sandbox.create();
this.dialect = {
connectionManager: {
connect: this.sinon.stub().returns(Promise.resolve())
}
};
this.sequelize = Support.createSequelizeInstance();
});
afterEach(function () {
this.sinon.restore();
});
it('should resolve connection on dialect connection manager', function () {
var connection = {};
this.dialect.connectionManager.connect.returns(Promise.resolve(connection));
var connectionManager = new ConnectionManager(this.dialect, this.sequelize);
var config = {};
return expect(connectionManager.$connect(config)).to.eventually.equal(connection).then(function () {
expect(this.dialect.connectionManager.connect).to.have.been.calledWith(config);
}.bind(this));
});
it('should let beforeConnect hook modify config', function () {
var username = Math.random().toString()
, password = Math.random().toString();
this.sequelize.beforeConnect(function (config) {
config.username = username;
config.password = password;
return config;
});
var connectionManager = new ConnectionManager(this.dialect, this.sequelize);
return connectionManager.$connect({}).then(function () {
expect(this.dialect.connectionManager.connect).to.have.been.calledWith({
username: username,
password: password
});
}.bind(this));
});
});
});
'use strict';
/* jshint -W030 */
var chai = require('chai')
, expect = chai.expect
, Sequelize = require(__dirname + '/../../index');
describe('sequelize constructor', function () {
it('should support database, username, password, options', function () {
var database = Math.random().toString()
, username = Math.random().toString()
, password = Math.random().toString()
, host = Math.random().toString()
, port = Math.random().toString();
var sequelize = new Sequelize(database, username, password, {
host: host,
port: port
});
expect(sequelize.config.database).to.equal(database);
expect(sequelize.config.username).to.equal(username);
expect(sequelize.config.password).to.equal(password);
expect(sequelize.config.host).to.equal(host);
expect(sequelize.config.port).to.equal(port);
});
it('should support connection uri, options', function () {
var dialect = 'postgres'
, database = Math.ceil(Math.random() * 9999).toString()
, username = Math.ceil(Math.random() * 9999).toString()
, password = Math.ceil(Math.random() * 9999).toString()
, host = Math.ceil(Math.random() * 9999).toString()
, port = Math.ceil(Math.random() * 9999).toString();
var uri = dialect + '://' + username + ':' + password + '@' + host + ':' + port + '/' + database;
var sequelize = new Sequelize(uri);
expect(sequelize.config.database).to.equal(database);
expect(sequelize.config.username).to.equal(username);
expect(sequelize.config.password).to.equal(password);
expect(sequelize.config.host).to.equal(host);
expect(sequelize.config.port).to.equal(port);
});
it('should support options', function () {
var database = Math.random().toString()
, username = Math.random().toString()
, password = Math.random().toString()
, host = Math.random().toString()
, port = Math.random().toString();
var sequelize = new Sequelize({
host: host,
port: port,
database: database,
username: username,
password: password
});
expect(sequelize.config.database).to.equal(database);
expect(sequelize.config.username).to.equal(username);
expect(sequelize.config.password).to.equal(password);
expect(sequelize.config.host).to.equal(host);
expect(sequelize.config.port).to.equal(port);
});
});
\ No newline at end of file
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!