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

Commit 4fa35163 by Felix Becker Committed by Mick Hansen

ES6 refactor: sequelize.js (#6037)

* Make Sequelize an ES6 class

* ES6 refactor of sequelize.js

let, const, arrow functions, property shorthands, for of, export default
1 parent 25eaaff0
Showing with 408 additions and 416 deletions
'use strict';
var url = require('url')
, Path = require('path')
, retry = require('retry-as-promised')
, Utils = require('./utils')
, Model = require('./model')
, DataTypes = require('./data-types')
, Deferrable = require('./deferrable')
, ModelManager = require('./model-manager')
, QueryInterface = require('./query-interface')
, Transaction = require('./transaction')
, QueryTypes = require('./query-types')
, sequelizeErrors = require('./errors')
, Promise = require('./promise')
, Hooks = require('./hooks')
, Association = require('./associations/index')
, _ = require('lodash');
const url = require('url');
const Path = require('path');
const retry = require('retry-as-promised');
const Utils = require('./utils');
const Model = require('./model');
const DataTypes = require('./data-types');
const Deferrable = require('./deferrable');
const ModelManager = require('./model-manager');
const QueryInterface = require('./query-interface');
const Transaction = require('./transaction');
const QueryTypes = require('./query-types');
const sequelizeErrors = require('./errors');
const Promise = require('./promise');
const Hooks = require('./hooks');
const Association = require('./associations/index');
const _ = require('lodash');
/**
* This is the main class, the entry point to sequelize. To use it, you just need to import sequelize:
*
* ```js
* var Sequelize = require('sequelize');
* const Sequelize = require('sequelize');
* ```
*
* In addition to sequelize, the connection library for the dialect you want to use should also be installed in your project. You don't need to import it however, as sequelize will take care of that.
......@@ -36,19 +36,19 @@ var url = require('url')
*
* ```javascript
* // without password and options
* var sequelize = new Sequelize('database', 'username')
* const sequelize = new Sequelize('database', 'username')
*
* // without options
* var sequelize = new Sequelize('database', 'username', 'password')
* const sequelize = new Sequelize('database', 'username', 'password')
*
* // without password / with blank password
* var sequelize = new Sequelize('database', 'username', null, {})
* const sequelize = new Sequelize('database', 'username', null, {})
*
* // with password and options
* var sequelize = new Sequelize('my_database', 'john', 'doe', {})
* const sequelize = new Sequelize('my_database', 'john', 'doe', {})
*
* // with uri (see below)
* var sequelize = new Sequelize('mysql://localhost:3306/database', {})
* const sequelize = new Sequelize('mysql://localhost:3306/database', {})
* ```
*
* @name Sequelize
......@@ -90,7 +90,7 @@ var url = require('url')
* @param {Array} [options.retry.match] Only retry a query if the error matches one of these strings.
* @param {Integer} [options.retry.max] How many times a failing query is automatically retried. Set to 0 to disable retrying on SQL_BUSY error.
* @param {Boolean} [options.typeValidation=false] Run built in type validators on insert and update, e.g. validate that arguments passed to integer fields are integer-like.
*/
*/
/**
* Instantiate sequelize with an URI
......@@ -99,7 +99,7 @@ var url = require('url')
*
* @param {String} uri A full database URI
* @param {object} [options={}] See above for possible options
*/
*/
/**
* Instantiate sequelize with an options object
......@@ -107,9 +107,11 @@ var url = require('url')
* @constructor
*
* @param {object} [options={}] See above for possible options
*/
var Sequelize = function(database, username, password, options) {
var config;
*/
class Sequelize {
constructor(database, username, password, options) {
let config;
if (arguments.length === 1 && typeof database === 'object') {
// new Sequelize({ ... options })
......@@ -121,7 +123,7 @@ var Sequelize = function(database, username, password, options) {
config = {};
options = username || {};
var urlParts = url.parse(arguments[0]);
const urlParts = url.parse(arguments[0]);
// SQLite don't have DB in connection url
if (urlParts.pathname) {
......@@ -142,7 +144,7 @@ var Sequelize = function(database, username, password, options) {
} else {
// new Sequelize(database, username, password, { ... options })
options = options || {};
config = {database: database, username: username, password: password};
config = {database, username, password};
}
Sequelize.runHooks('beforeInit', config, options);
......@@ -211,7 +213,7 @@ var Sequelize = function(database, username, password, options) {
dialectOptions: this.options.dialectOptions
};
var Dialect;
let Dialect;
// Requiring the dialect in a switch-case to keep the
// require calls static. (Browserify fix)
switch (this.getDialect()){
......@@ -247,235 +249,35 @@ var Sequelize = function(database, username, password, options) {
this.test = {
$trackRunningQueries: false,
$runningQueries: 0,
trackRunningQueries: function() {
trackRunningQueries() {
this.$trackRunningQueries = true;
},
verifyNoRunningQueries: function() {
verifyNoRunningQueries() {
if (this.$runningQueries > 0) throw new Error('Expected 0 running queries. '+this.$runningQueries+' queries still running');
}
};
Sequelize.runHooks('afterInit', this);
};
/**
* Sequelize version number.
* @property version
*/
Sequelize.version = require('../package.json').version;
Sequelize.options = {hooks: {}};
/**
* A reference to Sequelize constructor from sequelize. Useful for accessing DataTypes, Errors etc.
* @property Sequelize
* @see {Sequelize}
*/
Sequelize.prototype.Sequelize = Sequelize;
/**
* A reference to sequelize utilities. Most users will not need to use these utils directly. However, you might want to use `Sequelize.Utils._`, which is a reference to the lodash library, if you don't already have it imported in your project.
* @property Utils
*/
Sequelize.prototype.Utils = Sequelize.Utils = Utils;
/**
* A handy reference to the bluebird Promise class
* @property Promise
*/
Sequelize.prototype.Promise = Sequelize.Promise = Promise;
/**
* Available query types for use with `sequelize.query`
* @property QueryTypes
*/
Sequelize.prototype.QueryTypes = Sequelize.QueryTypes = QueryTypes;
/**
* Exposes the validator.js object, so you can extend it with custom validation functions. The validator is exposed both on the instance, and on the constructor.
* @property Validator
* @see https://github.com/chriso/validator.js
*/
Sequelize.prototype.Validator = Sequelize.Validator = require('validator');
Sequelize.prototype.Model = Sequelize.Model = Model;
for (var dataType in DataTypes) {
Sequelize[dataType] = DataTypes[dataType];
}
}
Object.defineProperty(Sequelize.prototype, 'connectorManager', {
get: function() {
get connectorManager() {
return this.transactionManager.getConnectorManager();
}
});
/**
* A reference to the sequelize transaction class. Use this to access isolationLevels and types when creating a transaction
* @property Transaction
* @see {Transaction}
* @see {Sequelize#transaction}
*/
Sequelize.prototype.Transaction = Sequelize.Transaction = Transaction;
/**
* A reference to the deferrable collection. Use this to access the different deferrable options.
* @property Deferrable
* @see {Deferrable}
* @see {Sequelize#transaction}
*/
Sequelize.prototype.Deferrable = Sequelize.Deferrable = Deferrable;
/**
* A reference to the sequelize association class.
* @property Association
* @see {Association}
*/
Sequelize.prototype.Association = Sequelize.Association = Association;
/**
* Allow hooks to be defined on Sequelize + on sequelize instance as universal hooks to run on all models
* and on Sequelize/sequelize methods e.g. Sequelize(), Sequelize#define()
*/
Hooks.applyTo(Sequelize);
/**
* A general error class
* @property Error
* @see {Errors#BaseError}
*/
Sequelize.prototype.Error = Sequelize.Error =
sequelizeErrors.BaseError;
/**
* Emitted when a validation fails
* @property ValidationError
* @see {Errors#ValidationError}
*/
Sequelize.prototype.ValidationError = Sequelize.ValidationError =
sequelizeErrors.ValidationError;
/**
* Describes a validation error on an instance path
* @property ValidationErrorItem
* @see {Errors#ValidationErrorItem}
*/
Sequelize.prototype.ValidationErrorItem = Sequelize.ValidationErrorItem =
sequelizeErrors.ValidationErrorItem;
/**
* A base class for all database related errors.
* @see {Errors#DatabaseError}
*/
Sequelize.prototype.DatabaseError = Sequelize.DatabaseError =
sequelizeErrors.DatabaseError;
/**
* Thrown when a database query times out because of a deadlock
* @see {Errors#TimeoutError}
*/
Sequelize.prototype.TimeoutError = Sequelize.TimeoutError =
sequelizeErrors.TimeoutError;
/**
* Thrown when a unique constraint is violated in the database
* @see {Errors#UniqueConstraintError}
*/
Sequelize.prototype.UniqueConstraintError = Sequelize.UniqueConstraintError =
sequelizeErrors.UniqueConstraintError;
/**
* Thrown when an exclusion constraint is violated in the database
* @see {Errors#ExclusionConstraintError}
*/
Sequelize.prototype.ExclusionConstraintError = Sequelize.ExclusionConstraintError =
sequelizeErrors.ExclusionConstraintError;
/**
* Thrown when a foreign key constraint is violated in the database
* @see {Errors#ForeignKeyConstraintError}
*/
Sequelize.prototype.ForeignKeyConstraintError = Sequelize.ForeignKeyConstraintError =
sequelizeErrors.ForeignKeyConstraintError;
/**
* A base class for all connection related errors.
* @see {Errors#ConnectionError}
*/
Sequelize.prototype.ConnectionError = Sequelize.ConnectionError =
sequelizeErrors.ConnectionError;
/**
* Thrown when a connection to a database is refused
* @see {Errors#ConnectionRefusedError}
*/
Sequelize.prototype.ConnectionRefusedError = Sequelize.ConnectionRefusedError =
sequelizeErrors.ConnectionRefusedError;
/**
* Thrown when a connection to a database is refused due to insufficient access
* @see {Errors#AccessDeniedError}
*/
Sequelize.prototype.AccessDeniedError = Sequelize.AccessDeniedError =
sequelizeErrors.AccessDeniedError;
/**
* Thrown when a connection to a database has a hostname that was not found
* @see {Errors#HostNotFoundError}
*/
Sequelize.prototype.HostNotFoundError = Sequelize.HostNotFoundError =
sequelizeErrors.HostNotFoundError;
/**
* Thrown when a connection to a database has a hostname that was not reachable
* @see {Errors#HostNotReachableError}
*/
Sequelize.prototype.HostNotReachableError = Sequelize.HostNotReachableError =
sequelizeErrors.HostNotReachableError;
/**
* Thrown when a connection to a database has invalid values for any of the connection parameters
* @see {Errors#InvalidConnectionError}
*/
Sequelize.prototype.InvalidConnectionError = Sequelize.InvalidConnectionError =
sequelizeErrors.InvalidConnectionError;
/**
* Thrown when a connection to a database times out
* @see {Errors#ConnectionTimedOutError}
*/
Sequelize.prototype.ConnectionTimedOutError = Sequelize.ConnectionTimedOutError =
sequelizeErrors.ConnectionTimedOutError;
/**
* Thrown when a some problem occurred with Instance methods (see message for details)
* @see {Errors#InstanceError}
*/
Sequelize.prototype.InstanceError = Sequelize.InstanceError =
sequelizeErrors.InstanceError;
/**
* Thrown when a record was not found, Usually used with rejectOnEmpty mode (see message for details)
* @see {Errors#RecordNotFoundError}
*/
Sequelize.prototype.EmptyResultError = Sequelize.EmptyResultError =
sequelizeErrors.EmptyResultError;
Sequelize.prototype.refreshTypes = function () {
refreshTypes() {
this.connectionManager.refreshTypeParser(DataTypes);
};
}
/**
/**
* Returns the specified dialect.
*
* @return {String} The specified dialect.
*/
Sequelize.prototype.getDialect = function() {
getDialect() {
return this.options.dialect;
};
}
/**
/**
* Returns an instance of QueryInterface.
* @method getQueryInterface
......@@ -483,12 +285,12 @@ Sequelize.prototype.getDialect = function() {
*
* @see {QueryInterface}
*/
Sequelize.prototype.getQueryInterface = function() {
getQueryInterface() {
this.queryInterface = this.queryInterface || new QueryInterface(this);
return this.queryInterface;
};
}
/**
/**
* Define a new model, representing a table in the DB.
*
* The table columns are define by the hash that is given as the second argument. Each attribute of the hash represents a column. A short table definition might look like this:
......@@ -586,9 +388,9 @@ Sequelize.prototype.getQueryInterface = function() {
*
* @return {Model}
*/
Sequelize.prototype.define = function(modelName, attributes, options) { // testhint options:none
define(modelName, attributes, options) { // testhint options:none
options = options || {};
var globalOptions = this.options;
const globalOptions = this.options;
if (globalOptions.define) {
options = Utils.merge(globalOptions.define, options);
......@@ -615,7 +417,7 @@ Sequelize.prototype.define = function(modelName, attributes, options) { // testh
modelName = options.modelName;
delete options.modelName;
var model = class extends Model {};
const model = class extends Model {};
Object.defineProperty(model, 'name', {value: modelName});
model.init(attributes, options, this.modelManager);
this.modelManager.addModel(model);
......@@ -623,35 +425,35 @@ Sequelize.prototype.define = function(modelName, attributes, options) { // testh
this.runHooks('afterDefine', model);
return model;
};
}
/**
/**
* Fetch a Model which is already defined
*
* @param {String} modelName The name of a model defined with Sequelize.define
* @throws Will throw an error if the model is not defined (that is, if sequelize#isDefined returns false)
* @return {Model}
*/
Sequelize.prototype.model = function(modelName) {
model(modelName) {
if (!this.isDefined(modelName)) {
throw new Error(modelName + ' has not been defined');
}
return this.modelManager.getModel(modelName);
};
}
/**
/**
* Checks whether a model with the given name is defined
*
* @param {String} modelName The name of a model defined with Sequelize.define
* @return {Boolean}
*/
Sequelize.prototype.isDefined = function(modelName) {
var models = this.modelManager.models;
return (models.filter(function(model) { return model.name === modelName; }).length !== 0);
};
isDefined(modelName) {
const models = this.modelManager.models;
return (models.filter(model => model.name === modelName).length !== 0);
}
/**
/**
* Imports a model defined in another file
*
* Imported models are cached, so multiple calls to import with the same path will not load the file multiple times
......@@ -660,18 +462,18 @@ Sequelize.prototype.isDefined = function(modelName) {
* @param {String} path The path to the file that holds the model you want to import. If the part is relative, it will be resolved relatively to the calling file
* @return {Model}
*/
Sequelize.prototype.import = function(path) {
import(path) {
// is it a relative path?
if(Path.normalize(path) !== Path.resolve(path)){
// make path relative to the caller
var callerFilename = Utils.stack()[1].getFileName()
, callerPath = Path.dirname(callerFilename);
const callerFilename = Utils.stack()[1].getFileName();
const callerPath = Path.dirname(callerFilename);
path = Path.resolve(callerPath, path);
}
if (!this.importCache[path]) {
var defineCall = (arguments.length > 1 ? arguments[1] : require(path));
let defineCall = (arguments.length > 1 ? arguments[1] : require(path));
if (typeof defineCall === 'object' && defineCall.__esModule) {
// Babel/ES6 module compatability
defineCall = defineCall['default'];
......@@ -680,9 +482,9 @@ Sequelize.prototype.import = function(path) {
}
return this.importCache[path];
};
}
/**
/**
* Execute a query on the DB, with the possibility to bypass all the sequelize goodness.
*
* By default, the function will return two arguments: an array of results, and a metadata object, containing number of affected rows etc. Use `.spread` to access the results.
......@@ -690,11 +492,11 @@ Sequelize.prototype.import = function(path) {
* If you are running a type of query where you don't need the metadata, for example a `SELECT` query, you can pass in a query type to make sequelize format the results:
*
* ```js
* sequelize.query('SELECT...').spread(function (results, metadata) {
* sequelize.query('SELECT...').spread((results, metadata) => {
* // Raw query - use spread
* });
*
* sequelize.query('SELECT...', { type: sequelize.QueryTypes.SELECT }).then(function (results) {
* sequelize.query('SELECT...', { type: sequelize.QueryTypes.SELECT }).then(results => {
* // SELECT query - use then
* })
* ```
......@@ -725,14 +527,12 @@ Sequelize.prototype.import = function(path) {
*
* @see {Model#build} for more information about instance option.
*/
Sequelize.prototype.query = function(sql, options) {
query(sql, options) {
if (arguments.length > 2) {
// TODO: Remove this note in the next major version (4.0)
throw new Error('Sequelize.query was refactored to only use the parameters `sql` and `options`. Please read the changelog about BC.');
}
var self = this;
options = _.assign({}, this.options.query, options);
if (options.instance && !options.model) {
......@@ -783,9 +583,9 @@ Sequelize.prototype.query = function(sql, options) {
sql = Utils.formatNamedParameters(sql, options.replacements, this.options.dialect);
}
}
var bindParameters;
let bindParameters;
if (options.bind) {
var bindSql = self.dialect.Query.formatBindParameters(sql, options.bind, this.options.dialect);
const bindSql = this.dialect.Query.formatBindParameters(sql, options.bind, this.options.dialect);
sql = bindSql[0];
bindParameters = bindSql[1];
}
......@@ -808,7 +608,7 @@ Sequelize.prototype.query = function(sql, options) {
}
if (options.transaction && options.transaction.finished) {
var error = new Error(options.transaction.finished+' has been called on this transaction('+options.transaction.id+'), you can no longer use it. (The rejected query is attached as the \'sql\' property of this error)');
const error = new Error(options.transaction.finished+' has been called on this transaction('+options.transaction.id+'), you can no longer use it. (The rejected query is attached as the \'sql\' property of this error)');
error.sql = sql;
return Promise.reject(error);
}
......@@ -819,7 +619,7 @@ Sequelize.prototype.query = function(sql, options) {
//if dialect doesn't support search_path or dialect option
//to prepend searchPath is not true delete the searchPath option
if (!self.dialect.supports.searchPath || !this.options.dialectOptions || !this.options.dialectOptions.prependSearchPath ||
if (!this.dialect.supports.searchPath || !this.options.dialectOptions || !this.options.dialectOptions.prependSearchPath ||
options.supportsSearchPath === false) {
delete options.searchPath;
} else if (!options.searchPath) {
......@@ -829,24 +629,23 @@ Sequelize.prototype.query = function(sql, options) {
}
return Promise.resolve(
options.transaction ? options.transaction.connection : self.connectionManager.getConnection(options)
).then(function (connection) {
var query = new self.dialect.Query(connection, self, options);
return retry(function() {
return query.run(sql, bindParameters).finally(function() {
if (options.transaction) return;
return self.connectionManager.releaseConnection(connection);
});
}, Utils._.extend(self.options.retry, options.retry || {}));
}).finally(function () {
if (self.test.$trackRunningQueries) {
self.test.$runningQueries--;
options.transaction ? options.transaction.connection : this.connectionManager.getConnection(options)
).then(connection => {
const query = new this.dialect.Query(connection, this, options);
return retry(() => query.run(sql, bindParameters).finally(() => {
if (!options.transaction) {
return this.connectionManager.releaseConnection(connection);
}
}), Utils._.extend(this.options.retry, options.retry || {}));
}).finally(() => {
if (this.test.$trackRunningQueries) {
this.test.$runningQueries--;
}
});
};
}
/**
/**
* Execute a query which would set an environment or user variable. The variables are set per connection, so this function needs a transaction.
* Only works for MySQL.
*
......@@ -857,8 +656,7 @@ Sequelize.prototype.query = function(sql, options) {
*
* @return {Promise}
*/
Sequelize.prototype.set = function( variables, options ) {
var query;
set(variables, options) {
// Prepare options
options = Utils._.extend({}, this.options.set, typeof options === 'object' && options || {});
......@@ -876,26 +674,24 @@ Sequelize.prototype.set = function( variables, options ) {
options.type = 'SET';
// Generate SQL Query
query =
const query =
'SET '+
Utils._.map( variables, function ( v, k ) {
return '@'+k +' := '+ ( typeof v === 'string' ? '"'+v+'"' : v );
}).join(', ');
Utils._.map(variables, (v, k) => '@'+k +' := '+ (typeof v === 'string' ? '"'+v+'"' : v)).join(', ');
return this.query(query, options);
};
}
/**
/**
* Escape value.
*
* @param {String} value
* @return {String}
*/
Sequelize.prototype.escape = function(value) {
escape(value) {
return this.getQueryInterface().escape(value);
};
}
/**
/**
* Create a new database schema.
*
* Note,that this is a schema in the [postgres sense of the word](http://www.postgresql.org/docs/9.1/static/ddl-schemas.html),
......@@ -907,11 +703,11 @@ Sequelize.prototype.escape = function(value) {
* @param {Boolean|function} options.logging A function that logs sql queries, or false for no logging
* @return {Promise}
*/
Sequelize.prototype.createSchema = function(schema, options) {
createSchema(schema, options) {
return this.getQueryInterface().createSchema(schema, options);
};
}
/**
/**
* Show all defined schemas
*
* Note,that this is a schema in the [postgres sense of the word](http://www.postgresql.org/docs/9.1/static/ddl-schemas.html),
......@@ -920,11 +716,11 @@ Sequelize.prototype.createSchema = function(schema, options) {
* @param {Boolean|function} options.logging A function that logs sql queries, or false for no logging
* @return {Promise}
*/
Sequelize.prototype.showAllSchemas = function(options) {
showAllSchemas(options) {
return this.getQueryInterface().showAllSchemas(options);
};
}
/**
/**
* Drop a single schema
*
* Note,that this is a schema in the [postgres sense of the word](http://www.postgresql.org/docs/9.1/static/ddl-schemas.html),
......@@ -934,11 +730,11 @@ Sequelize.prototype.showAllSchemas = function(options) {
* @param {Boolean|function} options.logging A function that logs sql queries, or false for no logging
* @return {Promise}
*/
Sequelize.prototype.dropSchema = function(schema, options) {
dropSchema(schema, options) {
return this.getQueryInterface().dropSchema(schema, options);
};
}
/**
/**
* Drop all schemas
*
* Note,that this is a schema in the [postgres sense of the word](http://www.postgresql.org/docs/9.1/static/ddl-schemas.html),
......@@ -947,11 +743,11 @@ Sequelize.prototype.dropSchema = function(schema, options) {
* @param {Boolean|function} options.logging A function that logs sql queries, or false for no logging
* @return {Promise}
*/
Sequelize.prototype.dropAllSchemas = function(options) {
dropAllSchemas(options) {
return this.getQueryInterface().dropAllSchemas(options);
};
}
/**
/**
* Sync all defined models to the DB.
*
* @param {Object} [options={}]
......@@ -963,8 +759,7 @@ Sequelize.prototype.dropAllSchemas = function(options) {
* @param {Boolean} [options.hooks=true] If hooks is true then beforeSync, afterSync, beforBulkSync, afterBulkSync hooks will be called
* @return {Promise}
*/
Sequelize.prototype.sync = function(options) {
var self = this;
sync(options) {
options = _.clone(options) || {};
options.hooks = options.hooks === undefined ? true : !!options.hooks;
......@@ -977,20 +772,20 @@ Sequelize.prototype.sync = function(options) {
}
}
return Promise.try(function () {
return Promise.try(() => {
if (options.hooks) {
return self.runHooks('beforeBulkSync', options);
return this.runHooks('beforeBulkSync', options);
}
}).then(function () {
}).then(() => {
if (options.force) {
return self.drop(options);
return this.drop(options);
}
}).then(function() {
var models = [];
}).then(() => {
const models = [];
// Topologically sort by foreign key constraints to give us an appropriate
// creation order
self.modelManager.forEachModel(function(model) {
this.modelManager.forEachModel(model => {
if (model) {
models.push(model);
} else {
......@@ -998,17 +793,15 @@ Sequelize.prototype.sync = function(options) {
}
});
return Promise.each(models, function(model) {
return model.sync(options);
});
}).then(function () {
return Promise.each(models, model => model.sync(options));
}).then(() => {
if (options.hooks) {
return self.runHooks('afterBulkSync', options);
return this.runHooks('afterBulkSync', options);
}
}).return(this);
}
}).return(self);
};
/**
/**
* Truncate all tables defined through the sequelize models. This is done
* by calling Model.truncate() on each model.
*
......@@ -1019,27 +812,25 @@ Sequelize.prototype.sync = function(options) {
*
* @see {Model#truncate} for more information
*/
Sequelize.prototype.truncate = function(options) {
var models = [];
truncate(options) {
const models = [];
this.modelManager.forEachModel(function(model) {
this.modelManager.forEachModel(model => {
if (model) {
models.push(model);
}
}, { reverse: false });
var truncateModel = function(model) {
return model.truncate(options);
};
const truncateModel = model => model.truncate(options);
if (options && options.cascade) {
return Promise.each(models, truncateModel);
} else {
return Promise.map(models, truncateModel);
}
};
}
/**
/**
* Drop all tables defined through this sequelize instance. This is done by calling Model.drop on each model
* @see {Model#drop} for options
*
......@@ -1047,21 +838,19 @@ Sequelize.prototype.truncate = function(options) {
* @param {Boolean|function} options.logging A function that logs sql queries, or false for no logging
* @return {Promise}
*/
Sequelize.prototype.drop = function(options) {
var models = [];
drop(options) {
const models = [];
this.modelManager.forEachModel(function(model) {
this.modelManager.forEachModel(model => {
if (model) {
models.push(model);
}
}, { reverse: false });
return Promise.each(models, function(model) {
return model.drop(options);
});
};
return Promise.each(models, model => model.drop(options));
}
/**
/**
* Test the connection by trying to authenticate
*
* @fires success If authentication was successful
......@@ -1069,17 +858,15 @@ Sequelize.prototype.drop = function(options) {
* @alias validate
* @return {Promise}
*/
Sequelize.prototype.authenticate = function(options) {
authenticate(options) {
return this.query('SELECT 1+1 AS result', Utils._.assign({ raw: true, plain: true }, options)).return();
};
}
Sequelize.prototype.databaseVersion = function(options) {
databaseVersion(options) {
return this.getQueryInterface().databaseVersion(options);
};
Sequelize.prototype.validate = Sequelize.prototype.authenticate;
}
/**
/**
* Creates a object representing a database function. This can be used in search queries, both in where and order parts, and as default values in column definitions.
* If you want to refer to columns in your function, you should use `sequelize.col`, so that the columns are properly interpreted as columns and not a strings.
*
......@@ -1102,11 +889,11 @@ Sequelize.prototype.validate = Sequelize.prototype.authenticate;
* @since v2.0.0-dev3
* @return {Sequelize.fn}
*/
Sequelize.fn = Sequelize.prototype.fn = function(fn) {
static fn(fn) {
return new Utils.fn(fn, Utils.sliceArgs(arguments, 1));
};
}
/**
/**
* Creates a object representing a column in the DB. This is often useful in conjunction with `sequelize.fn`, since raw string arguments to fn will be escaped.
* @see {Sequelize#fn}
*
......@@ -1115,12 +902,11 @@ Sequelize.fn = Sequelize.prototype.fn = function(fn) {
* @since v2.0.0-dev3
* @return {Sequelize.col}
*/
Sequelize.col = Sequelize.prototype.col = function(col) {
static col(col) {
return new Utils.col(col);
};
}
/**
/**
* Creates a object representing a call to the cast function.
*
* @method cast
......@@ -1129,11 +915,11 @@ Sequelize.col = Sequelize.prototype.col = function(col) {
* @since v2.0.0-dev3
* @return {Sequelize.cast}
*/
Sequelize.cast = Sequelize.prototype.cast = function(val, type) {
static cast(val, type) {
return new Utils.cast(val, type);
};
}
/**
/**
* Creates a object representing a literal, i.e. something that will not be escaped.
*
* @method literal
......@@ -1142,11 +928,11 @@ Sequelize.cast = Sequelize.prototype.cast = function(val, type) {
* @since v2.0.0-dev3
* @return {Sequelize.literal}
*/
Sequelize.literal = Sequelize.asIs = Sequelize.prototype.asIs = Sequelize.prototype.literal = function(val) {
static literal(val) {
return new Utils.literal(val);
};
}
/**
/**
* An AND query
* @see {Model#find}
*
......@@ -1155,11 +941,11 @@ Sequelize.literal = Sequelize.asIs = Sequelize.prototype.asIs = Sequelize.protot
* @since v2.0.0-dev3
* @return {Sequelize.and}
*/
Sequelize.and = Sequelize.prototype.and = function() {
static and() {
return { $and: Utils.sliceArgs(arguments) };
};
}
/**
/**
* An OR query
* @see {Model#find}
*
......@@ -1168,11 +954,11 @@ Sequelize.and = Sequelize.prototype.and = function() {
* @since v2.0.0-dev3
* @return {Sequelize.or}
*/
Sequelize.or = Sequelize.prototype.or = function() {
static or() {
return { $or: Utils.sliceArgs(arguments) };
};
}
/**
/**
* Creates an object representing nested where conditions for postgres's json data-type.
* @see {Model#find}
*
......@@ -1181,11 +967,11 @@ Sequelize.or = Sequelize.prototype.or = function() {
* @param {String|Number|Boolean} [value] An optional value to compare against. Produces a string of the form "<json path> = '<value>'".
* @return {Sequelize.json}
*/
Sequelize.json = Sequelize.prototype.json = function (conditionsOrPath, value) {
static json(conditionsOrPath, value) {
return new Utils.json(conditionsOrPath, value);
};
}
/*
/**
* A way of specifying attr = condition.
*
* The attr can either be an object taken from `Model.rawAttributes` (for example `Model.rawAttributes.id` or `Model.rawAttributes.name`). The
......@@ -1203,33 +989,31 @@ Sequelize.json = Sequelize.prototype.json = function (conditionsOrPath, value) {
* @since v2.0.0-dev3
* @return {Sequelize.where}
*/
Sequelize.where = Sequelize.condition = Sequelize.prototype.condition = Sequelize.prototype.where = function(attr, comparator, logic) {
static where(attr, comparator, logic) {
return new Utils.where(attr, comparator, logic);
};
}
/**
/**
* Start a transaction. When using transactions, you should pass the transaction in the options argument in order for the query to happen under that transaction
*
* ```js
* sequelize.transaction().then(function (t) {
* return User.find(..., { transaction: t}).then(function (user) {
* return user.updateAttributes(..., { transaction: t});
* })
* .then(t.commit.bind(t))
* .catch(t.rollback.bind(t));
* sequelize.transaction().then(transaction => {
* return User.find(..., {transaction})
* .then(user => user.updateAttributes(..., {transaction}))
* .then(() => transaction.commit())
* .catch(() => transaction.rollback());
* })
* ```
*
* A syntax for automatically committing or rolling back based on the promise chain resolution is also supported:
*
* ```js
* sequelize.transaction(function (t) { // Note that we use a callback rather than a promise.then()
* return User.find(..., { transaction: t}).then(function (user) {
* return user.updateAttributes(..., { transaction: t});
* });
* }).then(function () {
* sequelize.transaction(transaction => { // Note that we use a callback rather than a promise.then()
* return User.find(..., {transaction})
* .then(user => user.updateAttributes(..., {transaction}))
* }).then(() => {
* // Committed
* }).catch(function (err) {
* }).catch(err => {
* // Rolled back
* console.error(err);
* });
......@@ -1239,15 +1023,14 @@ Sequelize.where = Sequelize.condition = Sequelize.prototype.condition = Sequeliz
* To enable CLS, add it do your project, create a namespace and set it on the sequelize constructor:
*
* ```js
* var cls = require('continuation-local-storage'),
* ns = cls.createNamespace('....');
* var Sequelize = require('sequelize');
* const cls = require('continuation-local-storage');
* const ns = cls.createNamespace('....');
* const Sequelize = require('sequelize');
* Sequelize.cls = ns;
* ```
* Note, that CLS is enabled for all sequelize instances, and all instances will share the same namespace
*
* @see {Transaction}
* @param {Object} [options={}]
* @param {Boolean} [options.autocommit]
* @param {String} [options.type='DEFERRED'] See `Sequelize.Transaction.TYPES` for possible options. Sqlite only.
......@@ -1257,37 +1040,35 @@ Sequelize.where = Sequelize.condition = Sequelize.prototype.condition = Sequeliz
* @fires error If there is an uncaught error during the transaction
* @fires success When the transaction has ended (either committed or rolled back)
*/
Sequelize.prototype.transaction = function(options, autoCallback) {
transaction(options, autoCallback) {
if (typeof options === 'function') {
autoCallback = options;
options = undefined;
}
// testhint argsConform.end
var transaction = new Transaction(this, options)
, ns = Sequelize.cls;
const transaction = new Transaction(this, options);
const ns = Sequelize.cls;
if (autoCallback) {
var transactionResolver = function (resolve, reject) {
transaction.prepareEnvironment().then(function () {
let transactionResolver = (resolve, reject) => {
transaction.prepareEnvironment().then(() => {
if (ns) {
autoCallback = ns.bind(autoCallback);
}
var result = autoCallback(transaction);
const result = autoCallback(transaction);
if (!result || !result.then) throw new Error('You need to return a promise chain/thenable to the sequelize.transaction() callback');
return result.then(function (result) {
return transaction.commit().then(function () {
return result.then(result => transaction.commit()).then(() => {
resolve(result);
});
});
}).catch(function(err) {
}).catch(err => {
// If the transaction has already finished (commit, rollback, etc), reject with the original error
if (transaction.finished) {
reject(err);
} else {
return transaction.rollback().finally(function () {
return transaction.rollback().finally(() => {
reject(err);
});
}
......@@ -1302,12 +1083,12 @@ Sequelize.prototype.transaction = function(options, autoCallback) {
} else {
return transaction.prepareEnvironment().return(transaction);
}
};
}
Sequelize.prototype.log = function() {
var args = Utils.sliceArgs(arguments)
, last = Utils._.last(args)
, options;
log() {
let options;
let args = Utils.sliceArgs(arguments);
const last = Utils._.last(args);
if (last && Utils._.isPlainObject(last) && last.hasOwnProperty('logging')) {
options = last;
......@@ -1331,21 +1112,21 @@ Sequelize.prototype.log = function() {
options.logging.apply(null, args);
}
};
}
/**
/**
* Close all connections used by this sequelize instance, and free all references so the instance can be garbage collected.
*
* Normally this is done on process exit, so you only need to call this method if you are creating multiple instances, and want
* to garbage collect some of them.
*/
Sequelize.prototype.close = function () {
close() {
this.connectionManager.close();
};
}
Sequelize.prototype.normalizeDataType = function(Type) {
var type = typeof Type === 'function' ? new Type() : Type
, dialectTypes = this.dialect.DataTypes || {};
normalizeDataType(Type) {
let type = typeof Type === 'function' ? new Type() : Type;
const dialectTypes = this.dialect.DataTypes || {};
if (dialectTypes[type.key]) {
type = dialectTypes[type.key].extend(type);
......@@ -1355,8 +1136,8 @@ Sequelize.prototype.normalizeDataType = function(Type) {
type.type = dialectTypes[type.type.key].extend(type.type);
}
return type;
};
Sequelize.prototype.normalizeAttribute = function(attribute) {
}
normalizeAttribute(attribute) {
if (!Utils._.isPlainObject(attribute)) {
attribute = { type: attribute };
}
......@@ -1389,7 +1170,218 @@ Sequelize.prototype.normalizeAttribute = function(attribute) {
}
return attribute;
};
}
}
// Aliases
Sequelize.prototype.fn = Sequelize.fn;
Sequelize.prototype.col = Sequelize.col;
Sequelize.prototype.cast = Sequelize.cast;
Sequelize.prototype.literal = Sequelize.asIs = Sequelize.prototype.asIs = Sequelize.literal;
Sequelize.prototype.and = Sequelize.and;
Sequelize.prototype.or = Sequelize.or;
Sequelize.prototype.json = Sequelize.json;
Sequelize.prototype.where = Sequelize.condition = Sequelize.prototype.condition = Sequelize.where;
Sequelize.prototype.validate = Sequelize.prototype.authenticate;
/**
* Sequelize version number.
* @property version
*/
Sequelize.version = require('../package.json').version;
Sequelize.options = {hooks: {}};
/**
* A reference to Sequelize constructor from sequelize. Useful for accessing DataTypes, Errors etc.
* @property Sequelize
* @see {Sequelize}
*/
Sequelize.prototype.Sequelize = Sequelize;
/**
* A reference to sequelize utilities. Most users will not need to use these utils directly. However, you might want to use `Sequelize.Utils._`, which is a reference to the lodash library, if you don't already have it imported in your project.
* @property Utils
*/
Sequelize.prototype.Utils = Sequelize.Utils = Utils;
/**
* A handy reference to the bluebird Promise class
* @property Promise
*/
Sequelize.prototype.Promise = Sequelize.Promise = Promise;
/**
* Available query types for use with `sequelize.query`
* @property QueryTypes
*/
Sequelize.prototype.QueryTypes = Sequelize.QueryTypes = QueryTypes;
/**
* Exposes the validator.js object, so you can extend it with custom validation functions. The validator is exposed both on the instance, and on the constructor.
* @property Validator
* @see https://github.com/chriso/validator.js
*/
Sequelize.prototype.Validator = Sequelize.Validator = require('validator');
Sequelize.prototype.Model = Sequelize.Model = Model;
for (const dataType in DataTypes) {
Sequelize[dataType] = DataTypes[dataType];
}
/**
* A reference to the sequelize transaction class. Use this to access isolationLevels and types when creating a transaction
* @property Transaction
* @see {Transaction}
* @see {Sequelize#transaction}
*/
Sequelize.prototype.Transaction = Sequelize.Transaction = Transaction;
/**
* A reference to the deferrable collection. Use this to access the different deferrable options.
* @property Deferrable
* @see {Deferrable}
* @see {Sequelize#transaction}
*/
Sequelize.prototype.Deferrable = Sequelize.Deferrable = Deferrable;
/**
* A reference to the sequelize association class.
* @property Association
* @see {Association}
*/
Sequelize.prototype.Association = Sequelize.Association = Association;
/**
* Allow hooks to be defined on Sequelize + on sequelize instance as universal hooks to run on all models
* and on Sequelize/sequelize methods e.g. Sequelize(), Sequelize#define()
*/
Hooks.applyTo(Sequelize);
/**
* A general error class
* @property Error
* @see {Errors#BaseError}
*/
Sequelize.prototype.Error = Sequelize.Error =
sequelizeErrors.BaseError;
/**
* Emitted when a validation fails
* @property ValidationError
* @see {Errors#ValidationError}
*/
Sequelize.prototype.ValidationError = Sequelize.ValidationError =
sequelizeErrors.ValidationError;
/**
* Describes a validation error on an instance path
* @property ValidationErrorItem
* @see {Errors#ValidationErrorItem}
*/
Sequelize.prototype.ValidationErrorItem = Sequelize.ValidationErrorItem =
sequelizeErrors.ValidationErrorItem;
/**
* A base class for all database related errors.
* @see {Errors#DatabaseError}
*/
Sequelize.prototype.DatabaseError = Sequelize.DatabaseError =
sequelizeErrors.DatabaseError;
/**
* Thrown when a database query times out because of a deadlock
* @see {Errors#TimeoutError}
*/
Sequelize.prototype.TimeoutError = Sequelize.TimeoutError =
sequelizeErrors.TimeoutError;
/**
* Thrown when a unique constraint is violated in the database
* @see {Errors#UniqueConstraintError}
*/
Sequelize.prototype.UniqueConstraintError = Sequelize.UniqueConstraintError =
sequelizeErrors.UniqueConstraintError;
/**
* Thrown when an exclusion constraint is violated in the database
* @see {Errors#ExclusionConstraintError}
*/
Sequelize.prototype.ExclusionConstraintError = Sequelize.ExclusionConstraintError =
sequelizeErrors.ExclusionConstraintError;
/**
* Thrown when a foreign key constraint is violated in the database
* @see {Errors#ForeignKeyConstraintError}
*/
Sequelize.prototype.ForeignKeyConstraintError = Sequelize.ForeignKeyConstraintError =
sequelizeErrors.ForeignKeyConstraintError;
/**
* A base class for all connection related errors.
* @see {Errors#ConnectionError}
*/
Sequelize.prototype.ConnectionError = Sequelize.ConnectionError =
sequelizeErrors.ConnectionError;
/**
* Thrown when a connection to a database is refused
* @see {Errors#ConnectionRefusedError}
*/
Sequelize.prototype.ConnectionRefusedError = Sequelize.ConnectionRefusedError =
sequelizeErrors.ConnectionRefusedError;
/**
* Thrown when a connection to a database is refused due to insufficient access
* @see {Errors#AccessDeniedError}
*/
Sequelize.prototype.AccessDeniedError = Sequelize.AccessDeniedError =
sequelizeErrors.AccessDeniedError;
/**
* Thrown when a connection to a database has a hostname that was not found
* @see {Errors#HostNotFoundError}
*/
Sequelize.prototype.HostNotFoundError = Sequelize.HostNotFoundError =
sequelizeErrors.HostNotFoundError;
/**
* Thrown when a connection to a database has a hostname that was not reachable
* @see {Errors#HostNotReachableError}
*/
Sequelize.prototype.HostNotReachableError = Sequelize.HostNotReachableError =
sequelizeErrors.HostNotReachableError;
/**
* Thrown when a connection to a database has invalid values for any of the connection parameters
* @see {Errors#InvalidConnectionError}
*/
Sequelize.prototype.InvalidConnectionError = Sequelize.InvalidConnectionError =
sequelizeErrors.InvalidConnectionError;
/**
* Thrown when a connection to a database times out
* @see {Errors#ConnectionTimedOutError}
*/
Sequelize.prototype.ConnectionTimedOutError = Sequelize.ConnectionTimedOutError =
sequelizeErrors.ConnectionTimedOutError;
/**
* Thrown when a some problem occurred with Instance methods (see message for details)
* @see {Errors#InstanceError}
*/
Sequelize.prototype.InstanceError = Sequelize.InstanceError =
sequelizeErrors.InstanceError;
/**
* Thrown when a record was not found, Usually used with rejectOnEmpty mode (see message for details)
* @see {Errors#RecordNotFoundError}
*/
Sequelize.prototype.EmptyResultError = Sequelize.EmptyResultError =
sequelizeErrors.EmptyResultError;
// Allows the promise to access cls namespaces
module.exports = Promise.Sequelize = Sequelize;
module.exports.Sequelize = Sequelize;
module.exports.default = Sequelize;
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!