UNPKG

52 kBJavaScriptView Raw
1'use strict';
2
3const url = require('url');
4const path = require('path');
5const retry = require('retry-as-promised');
6const _ = require('lodash');
7
8const Utils = require('./utils');
9const Model = require('./model');
10const DataTypes = require('./data-types');
11const Deferrable = require('./deferrable');
12const ModelManager = require('./model-manager');
13const Transaction = require('./transaction');
14const QueryTypes = require('./query-types');
15const TableHints = require('./table-hints');
16const IndexHints = require('./index-hints');
17const sequelizeErrors = require('./errors');
18const Hooks = require('./hooks');
19const Association = require('./associations/index');
20const Validator = require('./utils/validator-extras').validator;
21const Op = require('./operators');
22const deprecations = require('./utils/deprecations');
23
24/**
25 * This is the main class, the entry point to sequelize.
26 */
27class Sequelize {
28 /**
29 * Instantiate sequelize with name of database, username and password.
30 *
31 * @example
32 * // without password / with blank password
33 * const sequelize = new Sequelize('database', 'username', null, {
34 * dialect: 'mysql'
35 * })
36 *
37 * // with password and options
38 * const sequelize = new Sequelize('my_database', 'john', 'doe', {
39 * dialect: 'postgres'
40 * })
41 *
42 * // with database, username, and password in the options object
43 * const sequelize = new Sequelize({ database, username, password, dialect: 'mssql' });
44 *
45 * // with uri
46 * const sequelize = new Sequelize('mysql://localhost:3306/database', {})
47 *
48 * // option examples
49 * const sequelize = new Sequelize('database', 'username', 'password', {
50 * // the sql dialect of the database
51 * // currently supported: 'mysql', 'sqlite', 'postgres', 'mssql'
52 * dialect: 'mysql',
53 *
54 * // custom host; default: localhost
55 * host: 'my.server.tld',
56 * // for postgres, you can also specify an absolute path to a directory
57 * // containing a UNIX socket to connect over
58 * // host: '/sockets/psql_sockets'.
59 *
60 * // custom port; default: dialect default
61 * port: 12345,
62 *
63 * // custom protocol; default: 'tcp'
64 * // postgres only, useful for Heroku
65 * protocol: null,
66 *
67 * // disable logging or provide a custom logging function; default: console.log
68 * logging: false,
69 *
70 * // you can also pass any dialect options to the underlying dialect library
71 * // - default is empty
72 * // - currently supported: 'mysql', 'postgres', 'mssql'
73 * dialectOptions: {
74 * socketPath: '/Applications/MAMP/tmp/mysql/mysql.sock',
75 * supportBigNumbers: true,
76 * bigNumberStrings: true
77 * },
78 *
79 * // the storage engine for sqlite
80 * // - default ':memory:'
81 * storage: 'path/to/database.sqlite',
82 *
83 * // disable inserting undefined values as NULL
84 * // - default: false
85 * omitNull: true,
86 *
87 * // a flag for using a native library or not.
88 * // in the case of 'pg' -- set this to true will allow SSL support
89 * // - default: false
90 * native: true,
91 *
92 * // Specify options, which are used when sequelize.define is called.
93 * // The following example:
94 * // define: { timestamps: false }
95 * // is basically the same as:
96 * // Model.init(attributes, { timestamps: false });
97 * // sequelize.define(name, attributes, { timestamps: false });
98 * // so defining the timestamps for each model will be not necessary
99 * define: {
100 * underscored: false,
101 * freezeTableName: false,
102 * charset: 'utf8',
103 * dialectOptions: {
104 * collate: 'utf8_general_ci'
105 * },
106 * timestamps: true
107 * },
108 *
109 * // similar for sync: you can define this to always force sync for models
110 * sync: { force: true },
111 *
112 * // pool configuration used to pool database connections
113 * pool: {
114 * max: 5,
115 * idle: 30000,
116 * acquire: 60000,
117 * },
118 *
119 * // isolation level of each transaction
120 * // defaults to dialect default
121 * isolationLevel: Transaction.ISOLATION_LEVELS.REPEATABLE_READ
122 * })
123 *
124 * @param {string} [database] The name of the database
125 * @param {string} [username=null] The username which is used to authenticate against the database.
126 * @param {string} [password=null] The password which is used to authenticate against the database. Supports SQLCipher encryption for SQLite.
127 * @param {object} [options={}] An object with options.
128 * @param {string} [options.host='localhost'] The host of the relational database.
129 * @param {number} [options.port=] The port of the relational database.
130 * @param {string} [options.username=null] The username which is used to authenticate against the database.
131 * @param {string} [options.password=null] The password which is used to authenticate against the database.
132 * @param {string} [options.database=null] The name of the database
133 * @param {string} [options.dialect] The dialect of the database you are connecting to. One of mysql, postgres, sqlite and mssql.
134 * @param {string} [options.dialectModule=null] If specified, use this dialect library. For example, if you want to use pg.js instead of pg when connecting to a pg database, you should specify 'require("pg.js")' here
135 * @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 '/path/to/pg.js' here
136 * @param {object} [options.dialectOptions] An object of additional options, which are passed directly to the connection library
137 * @param {string} [options.storage] Only used by sqlite. Defaults to ':memory:'
138 * @param {string} [options.protocol='tcp'] The protocol of the relational database.
139 * @param {object} [options.define={}] Default options for model definitions. See {@link Model.init}.
140 * @param {object} [options.query={}] Default options for sequelize.query
141 * @param {string} [options.schema=null] A schema to use
142 * @param {object} [options.set={}] Default options for sequelize.set
143 * @param {object} [options.sync={}] Default options for sequelize.sync
144 * @param {string} [options.timezone='+00:00'] The timezone used when converting a date from the database into a JavaScript date. The timezone is also used to SET TIMEZONE when connecting to the server, to ensure that the result of NOW, CURRENT_TIMESTAMP and other time related functions have in the right timezone. For best cross platform performance use the format +/-HH:MM. Will also accept string versions of timezones used by moment.js (e.g. 'America/Los_Angeles'); this is useful to capture daylight savings time changes.
145 * @param {string|boolean} [options.clientMinMessages='warning'] The PostgreSQL `client_min_messages` session parameter. Set to `false` to not override the database's default.
146 * @param {boolean} [options.standardConformingStrings=true] The PostgreSQL `standard_conforming_strings` session parameter. Set to `false` to not set the option. WARNING: Setting this to false may expose vulnerabilities and is not recommended!
147 * @param {Function} [options.logging=console.log] A function that gets executed every time Sequelize would log something. Function may receive multiple parameters but only first one is printed by `console.log`. To print all values use `(...msg) => console.log(msg)`
148 * @param {boolean} [options.benchmark=false] Pass query execution time in milliseconds as second argument to logging function (options.logging).
149 * @param {boolean} [options.omitNull=false] A flag that defines if null values should be passed as values to CREATE/UPDATE SQL queries or not.
150 * @param {boolean} [options.native=false] A flag that defines if native library shall be used or not. Currently only has an effect for postgres
151 * @param {boolean} [options.replication=false] Use read / write replication. To enable replication, pass an object, with two properties, read and write. Write should be an object (a single server for handling writes), and read an array of object (several servers to handle reads). Each read/write server can have the following properties: `host`, `port`, `username`, `password`, `database`
152 * @param {object} [options.pool] sequelize connection pool configuration
153 * @param {number} [options.pool.max=5] Maximum number of connection in pool
154 * @param {number} [options.pool.min=0] Minimum number of connection in pool
155 * @param {number} [options.pool.idle=10000] The maximum time, in milliseconds, that a connection can be idle before being released.
156 * @param {number} [options.pool.acquire=60000] The maximum time, in milliseconds, that pool will try to get connection before throwing error
157 * @param {number} [options.pool.evict=1000] The time interval, in milliseconds, after which sequelize-pool will remove idle connections.
158 * @param {Function} [options.pool.validate] A function that validates a connection. Called with client. The default function checks that client is an object, and that its state is not disconnected
159 * @param {number} [options.pool.maxUses=Infinity] The number of times a connection can be used before discarding it for a replacement, [`used for eventual cluster rebalancing`](https://github.com/sequelize/sequelize-pool).
160 * @param {boolean} [options.quoteIdentifiers=true] Set to `false` to make table names and attributes case-insensitive on Postgres and skip double quoting of them. WARNING: Setting this to false may expose vulnerabilities and is not recommended!
161 * @param {string} [options.transactionType='DEFERRED'] Set the default transaction type. See `Sequelize.Transaction.TYPES` for possible options. Sqlite only.
162 * @param {string} [options.isolationLevel] Set the default transaction isolation level. See `Sequelize.Transaction.ISOLATION_LEVELS` for possible options.
163 * @param {object} [options.retry] Set of flags that control when a query is automatically retried. Accepts all options for [`retry-as-promised`](https://github.com/mickhansen/retry-as-promised).
164 * @param {Array} [options.retry.match] Only retry a query if the error matches one of these strings.
165 * @param {number} [options.retry.max] How many times a failing query is automatically retried. Set to 0 to disable retrying on SQL_BUSY error.
166 * @param {boolean} [options.typeValidation=false] Run built-in type validators on insert and update, and select with where clause, e.g. validate that arguments passed to integer fields are integer-like.
167 * @param {object} [options.operatorsAliases] String based operator alias. Pass object to limit set of aliased operators.
168 * @param {object} [options.hooks] An object of global hook functions that are called before and after certain lifecycle events. Global hooks will run after any model-specific hooks defined for the same event (See `Sequelize.Model.init()` for a list). Additionally, `beforeConnect()`, `afterConnect()`, `beforeDisconnect()`, and `afterDisconnect()` hooks may be defined here.
169 * @param {boolean} [options.minifyAliases=false] A flag that defines if aliases should be minified (mostly useful to avoid Postgres alias character limit of 64)
170 * @param {boolean} [options.logQueryParameters=false] A flag that defines if show bind parameters in log.
171 */
172 constructor(database, username, password, options) {
173 let config;
174
175 if (arguments.length === 1 && typeof database === 'object') {
176 // new Sequelize({ ... options })
177 options = database;
178 config = _.pick(options, 'host', 'port', 'database', 'username', 'password');
179 } else if (arguments.length === 1 && typeof database === 'string' || arguments.length === 2 && typeof username === 'object') {
180 // new Sequelize(URI, { ... options })
181
182 config = {};
183 options = username || {};
184
185 const urlParts = url.parse(arguments[0], true);
186
187 options.dialect = urlParts.protocol.replace(/:$/, '');
188 options.host = urlParts.hostname;
189
190 if (options.dialect === 'sqlite' && urlParts.pathname && !urlParts.pathname.startsWith('/:memory')) {
191 const storagePath = path.join(options.host, urlParts.pathname);
192 options.storage = path.resolve(options.storage || storagePath);
193 }
194
195 if (urlParts.pathname) {
196 config.database = urlParts.pathname.replace(/^\//, '');
197 }
198
199 if (urlParts.port) {
200 options.port = urlParts.port;
201 }
202
203 if (urlParts.auth) {
204 const authParts = urlParts.auth.split(':');
205
206 config.username = authParts[0];
207
208 if (authParts.length > 1)
209 config.password = authParts.slice(1).join(':');
210 }
211
212 if (urlParts.query) {
213 // Allow host query argument to override the url host.
214 // Enables specifying domain socket hosts which cannot be specified via the typical
215 // host part of a url.
216 if (urlParts.query.host) {
217 options.host = urlParts.query.host;
218 }
219
220 if (options.dialectOptions) {
221 Object.assign(options.dialectOptions, urlParts.query);
222 } else {
223 options.dialectOptions = urlParts.query;
224 if (urlParts.query.options) {
225 try {
226 const o = JSON.parse(urlParts.query.options);
227 options.dialectOptions.options = o;
228 } catch (e) {
229 // Nothing to do, string is not a valid JSON
230 // an thus does not need any further processing
231 }
232 }
233 }
234 }
235 } else {
236 // new Sequelize(database, username, password, { ... options })
237 options = options || {};
238 config = { database, username, password };
239 }
240
241 Sequelize.runHooks('beforeInit', config, options);
242
243 this.options = {
244 dialect: null,
245 dialectModule: null,
246 dialectModulePath: null,
247 host: 'localhost',
248 protocol: 'tcp',
249 define: {},
250 query: {},
251 sync: {},
252 timezone: '+00:00',
253 clientMinMessages: 'warning',
254 standardConformingStrings: true,
255 // eslint-disable-next-line no-console
256 logging: console.log,
257 omitNull: false,
258 native: false,
259 replication: false,
260 ssl: undefined,
261 pool: {},
262 quoteIdentifiers: true,
263 hooks: {},
264 retry: {
265 max: 5,
266 match: [
267 'SQLITE_BUSY: database is locked'
268 ]
269 },
270 transactionType: Transaction.TYPES.DEFERRED,
271 isolationLevel: null,
272 databaseVersion: 0,
273 typeValidation: false,
274 benchmark: false,
275 minifyAliases: false,
276 logQueryParameters: false,
277 ...options
278 };
279
280 if (!this.options.dialect) {
281 throw new Error('Dialect needs to be explicitly supplied as of v4.0.0');
282 }
283
284 if (this.options.dialect === 'postgresql') {
285 this.options.dialect = 'postgres';
286 }
287
288 if (this.options.dialect === 'sqlite' && this.options.timezone !== '+00:00') {
289 throw new Error('Setting a custom timezone is not supported by SQLite, dates are always returned as UTC. Please remove the custom timezone parameter.');
290 }
291
292 if (this.options.logging === true) {
293 deprecations.noTrueLogging();
294 // eslint-disable-next-line no-console
295 this.options.logging = console.log;
296 }
297
298 this._setupHooks(options.hooks);
299
300 this.config = {
301 database: config.database || this.options.database,
302 username: config.username || this.options.username,
303 password: config.password || this.options.password || null,
304 host: config.host || this.options.host,
305 port: config.port || this.options.port,
306 pool: this.options.pool,
307 protocol: this.options.protocol,
308 native: this.options.native,
309 ssl: this.options.ssl,
310 replication: this.options.replication,
311 dialectModule: this.options.dialectModule,
312 dialectModulePath: this.options.dialectModulePath,
313 keepDefaultTimezone: this.options.keepDefaultTimezone,
314 dialectOptions: this.options.dialectOptions
315 };
316
317 let Dialect;
318 // Requiring the dialect in a switch-case to keep the
319 // require calls static. (Browserify fix)
320 switch (this.getDialect()) {
321 case 'mariadb':
322 Dialect = require('./dialects/mariadb');
323 break;
324 case 'mssql':
325 Dialect = require('./dialects/mssql');
326 break;
327 case 'mysql':
328 Dialect = require('./dialects/mysql');
329 break;
330 case 'postgres':
331 Dialect = require('./dialects/postgres');
332 break;
333 case 'sqlite':
334 Dialect = require('./dialects/sqlite');
335 break;
336 default:
337 throw new Error(`The dialect ${this.getDialect()} is not supported. Supported dialects: mssql, mariadb, mysql, postgres, and sqlite.`);
338 }
339
340 this.dialect = new Dialect(this);
341 this.dialect.queryGenerator.typeValidation = options.typeValidation;
342
343 if (_.isPlainObject(this.options.operatorsAliases)) {
344 deprecations.noStringOperators();
345 this.dialect.queryGenerator.setOperatorsAliases(this.options.operatorsAliases);
346 } else if (typeof this.options.operatorsAliases === 'boolean') {
347 deprecations.noBoolOperatorAliases();
348 }
349
350 this.queryInterface = this.dialect.queryInterface;
351
352 /**
353 * Models are stored here under the name given to `sequelize.define`
354 */
355 this.models = {};
356 this.modelManager = new ModelManager(this);
357 this.connectionManager = this.dialect.connectionManager;
358
359 Sequelize.runHooks('afterInit', this);
360 }
361
362 /**
363 * Refresh data types and parsers.
364 *
365 * @private
366 */
367 refreshTypes() {
368 this.connectionManager.refreshTypeParser(DataTypes);
369 }
370
371 /**
372 * Returns the specified dialect.
373 *
374 * @returns {string} The specified dialect.
375 */
376 getDialect() {
377 return this.options.dialect;
378 }
379
380 /**
381 * Returns the database name.
382 *
383 * @returns {string} The database name.
384 */
385 getDatabaseName() {
386 return this.config.database;
387 }
388
389 /**
390 * Returns an instance of QueryInterface.
391 *
392 * @returns {QueryInterface} An instance (singleton) of QueryInterface.
393 */
394 getQueryInterface() {
395 return this.queryInterface;
396 }
397
398 /**
399 * Define a new model, representing a table in the database.
400 *
401 * The table columns are defined by the object that is given as the second argument. Each key of the object represents a column
402 *
403 * @param {string} modelName The name of the model. The model will be stored in `sequelize.models` under this name
404 * @param {object} attributes An object, where each attribute is a column of the table. See {@link Model.init}
405 * @param {object} [options] These options are merged with the default define options provided to the Sequelize constructor and passed to Model.init()
406 *
407 * @see
408 * {@link Model.init} for a more comprehensive specification of the `options` and `attributes` objects.
409 * @see
410 * <a href="/master/manual/model-basics.html">Model Basics</a> guide
411 *
412 * @returns {Model} Newly defined model
413 *
414 * @example
415 * sequelize.define('modelName', {
416 * columnA: {
417 * type: Sequelize.BOOLEAN,
418 * validate: {
419 * is: ["[a-z]",'i'], // will only allow letters
420 * max: 23, // only allow values <= 23
421 * isIn: {
422 * args: [['en', 'zh']],
423 * msg: "Must be English or Chinese"
424 * }
425 * },
426 * field: 'column_a'
427 * },
428 * columnB: Sequelize.STRING,
429 * columnC: 'MY VERY OWN COLUMN TYPE'
430 * });
431 *
432 * sequelize.models.modelName // The model will now be available in models under the name given to define
433 */
434 define(modelName, attributes, options = {}) {
435 options.modelName = modelName;
436 options.sequelize = this;
437
438 const model = class extends Model {};
439
440 model.init(attributes, options);
441
442 return model;
443 }
444
445 /**
446 * Fetch a Model which is already defined
447 *
448 * @param {string} modelName The name of a model defined with Sequelize.define
449 *
450 * @throws Will throw an error if the model is not defined (that is, if sequelize#isDefined returns false)
451 * @returns {Model} Specified model
452 */
453 model(modelName) {
454 if (!this.isDefined(modelName)) {
455 throw new Error(`${modelName} has not been defined`);
456 }
457
458 return this.modelManager.getModel(modelName);
459 }
460
461 /**
462 * Checks whether a model with the given name is defined
463 *
464 * @param {string} modelName The name of a model defined with Sequelize.define
465 *
466 * @returns {boolean} Returns true if model is already defined, otherwise false
467 */
468 isDefined(modelName) {
469 return !!this.modelManager.models.find(model => model.name === modelName);
470 }
471
472 /**
473 * Execute a query on the DB, optionally bypassing all the Sequelize goodness.
474 *
475 * By default, the function will return two arguments: an array of results, and a metadata object, containing number of affected rows etc.
476 *
477 * 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:
478 *
479 * ```js
480 * const [results, metadata] = await sequelize.query('SELECT...'); // Raw query - use array destructuring
481 *
482 * const results = await sequelize.query('SELECT...', { type: sequelize.QueryTypes.SELECT }); // SELECT query - no destructuring
483 * ```
484 *
485 * @param {string} sql
486 * @param {object} [options={}] Query options.
487 * @param {boolean} [options.raw] If true, sequelize will not try to format the results of the query, or build an instance of a model from the result
488 * @param {Transaction} [options.transaction=null] The transaction that the query should be executed under
489 * @param {QueryTypes} [options.type='RAW'] The type of query you are executing. The query type affects how results are formatted before they are passed back. The type is a string, but `Sequelize.QueryTypes` is provided as convenience shortcuts.
490 * @param {boolean} [options.nest=false] If true, transforms objects with `.` separated property names into nested objects using [dottie.js](https://github.com/mickhansen/dottie.js). For example { 'user.username': 'john' } becomes { user: { username: 'john' }}. When `nest` is true, the query type is assumed to be `'SELECT'`, unless otherwise specified
491 * @param {boolean} [options.plain=false] Sets the query type to `SELECT` and return a single row
492 * @param {object|Array} [options.replacements] Either an object of named parameter replacements in the format `:param` or an array of unnamed replacements to replace `?` in your SQL.
493 * @param {object|Array} [options.bind] Either an object of named bind parameter in the format `_param` or an array of unnamed bind parameter to replace `$1, $2, ...` in your SQL.
494 * @param {boolean} [options.useMaster=false] Force the query to use the write pool, regardless of the query type.
495 * @param {Function} [options.logging=false] A function that gets executed while running the query to log the sql.
496 * @param {Model} [options.instance] A sequelize model instance whose Model is to be used to build the query result
497 * @param {typeof Model} [options.model] A sequelize model used to build the returned model instances
498 * @param {object} [options.retry] Set of flags that control when a query is automatically retried. Accepts all options for [`retry-as-promised`](https://github.com/mickhansen/retry-as-promised).
499 * @param {Array} [options.retry.match] Only retry a query if the error matches one of these strings.
500 * @param {Integer} [options.retry.max] How many times a failing query is automatically retried.
501 * @param {string} [options.searchPath=DEFAULT] An optional parameter to specify the schema search_path (Postgres only)
502 * @param {boolean} [options.supportsSearchPath] If false do not prepend the query with the search_path (Postgres only)
503 * @param {boolean} [options.mapToModel=false] Map returned fields to model's fields if `options.model` or `options.instance` is present. Mapping will occur before building the model instance.
504 * @param {object} [options.fieldMap] Map returned fields to arbitrary names for `SELECT` query type.
505 *
506 * @returns {Promise}
507 *
508 * @see {@link Model.build} for more information about instance option.
509 */
510
511 async query(sql, options) {
512 options = { ...this.options.query, ...options };
513
514 if (options.instance && !options.model) {
515 options.model = options.instance.constructor;
516 }
517
518 if (!options.instance && !options.model) {
519 options.raw = true;
520 }
521
522 // map raw fields to model attributes
523 if (options.mapToModel) {
524 options.fieldMap = _.get(options, 'model.fieldAttributeMap', {});
525 }
526
527 options = _.defaults(options, {
528 // eslint-disable-next-line no-console
529 logging: Object.prototype.hasOwnProperty.call(this.options, 'logging') ? this.options.logging : console.log,
530 searchPath: Object.prototype.hasOwnProperty.call(this.options, 'searchPath') ? this.options.searchPath : 'DEFAULT'
531 });
532
533 if (!options.type) {
534 if (options.model || options.nest || options.plain) {
535 options.type = QueryTypes.SELECT;
536 } else {
537 options.type = QueryTypes.RAW;
538 }
539 }
540
541 //if dialect doesn't support search_path or dialect option
542 //to prepend searchPath is not true delete the searchPath option
543 if (
544 !this.dialect.supports.searchPath ||
545 !this.options.dialectOptions ||
546 !this.options.dialectOptions.prependSearchPath ||
547 options.supportsSearchPath === false
548 ) {
549 delete options.searchPath;
550 } else if (!options.searchPath) {
551 //if user wants to always prepend searchPath (dialectOptions.preprendSearchPath = true)
552 //then set to DEFAULT if none is provided
553 options.searchPath = 'DEFAULT';
554 }
555
556 if (typeof sql === 'object') {
557 if (sql.values !== undefined) {
558 if (options.replacements !== undefined) {
559 throw new Error('Both `sql.values` and `options.replacements` cannot be set at the same time');
560 }
561 options.replacements = sql.values;
562 }
563
564 if (sql.bind !== undefined) {
565 if (options.bind !== undefined) {
566 throw new Error('Both `sql.bind` and `options.bind` cannot be set at the same time');
567 }
568 options.bind = sql.bind;
569 }
570
571 if (sql.query !== undefined) {
572 sql = sql.query;
573 }
574 }
575
576 sql = sql.trim();
577
578 if (options.replacements && options.bind) {
579 throw new Error('Both `replacements` and `bind` cannot be set at the same time');
580 }
581
582 if (options.replacements) {
583 if (Array.isArray(options.replacements)) {
584 sql = Utils.format([sql].concat(options.replacements), this.options.dialect);
585 } else {
586 sql = Utils.formatNamedParameters(sql, options.replacements, this.options.dialect);
587 }
588 }
589
590 let bindParameters;
591
592 if (options.bind) {
593 [sql, bindParameters] = this.dialect.Query.formatBindParameters(sql, options.bind, this.options.dialect);
594 }
595
596 const checkTransaction = () => {
597 if (options.transaction && options.transaction.finished && !options.completesTransaction) {
598 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)`);
599 error.sql = sql;
600 throw error;
601 }
602 };
603
604 const retryOptions = { ...this.options.retry, ...options.retry };
605
606 return retry(async () => {
607 if (options.transaction === undefined && Sequelize._cls) {
608 options.transaction = Sequelize._cls.get('transaction');
609 }
610
611 checkTransaction();
612
613 const connection = await (options.transaction ? options.transaction.connection : this.connectionManager.getConnection(options));
614 const query = new this.dialect.Query(connection, this, options);
615
616 try {
617 await this.runHooks('beforeQuery', options, query);
618 checkTransaction();
619 return await query.run(sql, bindParameters);
620 } finally {
621 await this.runHooks('afterQuery', options, query);
622 if (!options.transaction) {
623 await this.connectionManager.releaseConnection(connection);
624 }
625 }
626 }, retryOptions);
627 }
628
629 /**
630 * Execute a query which would set an environment or user variable. The variables are set per connection, so this function needs a transaction.
631 * Only works for MySQL.
632 *
633 * @param {object} variables Object with multiple variables.
634 * @param {object} [options] query options.
635 * @param {Transaction} [options.transaction] The transaction that the query should be executed under
636 *
637 * @memberof Sequelize
638 *
639 * @returns {Promise}
640 */
641 async set(variables, options) {
642
643 // Prepare options
644 options = { ...this.options.set, ...typeof options === 'object' && options };
645
646 if (this.options.dialect !== 'mysql') {
647 throw new Error('sequelize.set is only supported for mysql');
648 }
649 if (!options.transaction || !(options.transaction instanceof Transaction) ) {
650 throw new TypeError('options.transaction is required');
651 }
652
653 // Override some options, since this isn't a SELECT
654 options.raw = true;
655 options.plain = true;
656 options.type = 'SET';
657
658 // Generate SQL Query
659 const query =
660 `SET ${
661 _.map(variables, (v, k) => `@${k} := ${typeof v === 'string' ? `"${v}"` : v}`).join(', ')}`;
662
663 return await this.query(query, options);
664 }
665
666 /**
667 * Escape value.
668 *
669 * @param {string} value string value to escape
670 *
671 * @returns {string}
672 */
673 escape(value) {
674 return this.dialect.queryGenerator.escape(value);
675 }
676
677 /**
678 * Create a new database schema.
679 *
680 * **Note:** this is a schema in the [postgres sense of the word](http://www.postgresql.org/docs/9.1/static/ddl-schemas.html),
681 * not a database table. In mysql and sqlite, this command will do nothing.
682 *
683 * @see
684 * {@link Model.schema}
685 *
686 * @param {string} schema Name of the schema
687 * @param {object} [options={}] query options
688 * @param {boolean|Function} [options.logging] A function that logs sql queries, or false for no logging
689 *
690 * @returns {Promise}
691 */
692 async createSchema(schema, options) {
693 return await this.getQueryInterface().createSchema(schema, options);
694 }
695
696 /**
697 * Show all defined schemas
698 *
699 * **Note:** this is a schema in the [postgres sense of the word](http://www.postgresql.org/docs/9.1/static/ddl-schemas.html),
700 * not a database table. In mysql and sqlite, this will show all tables.
701 *
702 * @param {object} [options={}] query options
703 * @param {boolean|Function} [options.logging] A function that logs sql queries, or false for no logging
704 *
705 * @returns {Promise}
706 */
707 async showAllSchemas(options) {
708 return await this.getQueryInterface().showAllSchemas(options);
709 }
710
711 /**
712 * Drop a single schema
713 *
714 * **Note:** this is a schema in the [postgres sense of the word](http://www.postgresql.org/docs/9.1/static/ddl-schemas.html),
715 * not a database table. In mysql and sqlite, this drop a table matching the schema name
716 *
717 * @param {string} schema Name of the schema
718 * @param {object} [options={}] query options
719 * @param {boolean|Function} [options.logging] A function that logs sql queries, or false for no logging
720 *
721 * @returns {Promise}
722 */
723 async dropSchema(schema, options) {
724 return await this.getQueryInterface().dropSchema(schema, options);
725 }
726
727 /**
728 * Drop all schemas.
729 *
730 * **Note:** this is a schema in the [postgres sense of the word](http://www.postgresql.org/docs/9.1/static/ddl-schemas.html),
731 * not a database table. In mysql and sqlite, this is the equivalent of drop all tables.
732 *
733 * @param {object} [options={}] query options
734 * @param {boolean|Function} [options.logging] A function that logs sql queries, or false for no logging
735 *
736 * @returns {Promise}
737 */
738 async dropAllSchemas(options) {
739 return await this.getQueryInterface().dropAllSchemas(options);
740 }
741
742 /**
743 * Sync all defined models to the DB.
744 *
745 * @param {object} [options={}] sync options
746 * @param {boolean} [options.force=false] If force is true, each Model will run `DROP TABLE IF EXISTS`, before it tries to create its own table
747 * @param {RegExp} [options.match] Match a regex against the database name before syncing, a safety check for cases where force: true is used in tests but not live code
748 * @param {boolean|Function} [options.logging=console.log] A function that logs sql queries, or false for no logging
749 * @param {string} [options.schema='public'] The schema that the tables should be created in. This can be overridden for each table in sequelize.define
750 * @param {string} [options.searchPath=DEFAULT] An optional parameter to specify the schema search_path (Postgres only)
751 * @param {boolean} [options.hooks=true] If hooks is true then beforeSync, afterSync, beforeBulkSync, afterBulkSync hooks will be called
752 * @param {boolean|object} [options.alter=false] Alters tables to fit models. Provide an object for additional configuration. Not recommended for production use. If not further configured deletes data in columns that were removed or had their type changed in the model.
753 * @param {boolean} [options.alter.drop=true] Prevents any drop statements while altering a table when set to `false`
754 *
755 * @returns {Promise}
756 */
757 async sync(options) {
758 options = {
759 ...this.options,
760 ...this.options.sync,
761 ...options,
762 hooks: options ? options.hooks !== false : true
763 };
764
765 if (options.match) {
766 if (!options.match.test(this.config.database)) {
767 throw new Error(`Database "${this.config.database}" does not match sync match parameter "${options.match}"`);
768 }
769 }
770
771 if (options.hooks) {
772 await this.runHooks('beforeBulkSync', options);
773 }
774 if (options.force) {
775 await this.drop(options);
776 }
777 const models = [];
778
779 // Topologically sort by foreign key constraints to give us an appropriate
780 // creation order
781 this.modelManager.forEachModel(model => {
782 if (model) {
783 models.push(model);
784 } else {
785 // DB should throw an SQL error if referencing non-existent table
786 }
787 });
788
789 // no models defined, just authenticate
790 if (!models.length) {
791 await this.authenticate(options);
792 } else {
793 for (const model of models) await model.sync(options);
794 }
795 if (options.hooks) {
796 await this.runHooks('afterBulkSync', options);
797 }
798 return this;
799 }
800
801 /**
802 * Truncate all tables defined through the sequelize models.
803 * This is done by calling `Model.truncate()` on each model.
804 *
805 * @param {object} [options] The options passed to Model.destroy in addition to truncate
806 * @param {boolean|Function} [options.logging] A function that logs sql queries, or false for no logging
807 * @returns {Promise}
808 *
809 * @see
810 * {@link Model.truncate} for more information
811 */
812 async truncate(options) {
813 const models = [];
814
815 this.modelManager.forEachModel(model => {
816 if (model) {
817 models.push(model);
818 }
819 }, { reverse: false });
820
821 if (options && options.cascade) {
822 for (const model of models) await model.truncate(options);
823 } else {
824 await Promise.all(models.map(model => model.truncate(options)));
825 }
826 }
827
828 /**
829 * Drop all tables defined through this sequelize instance.
830 * This is done by calling Model.drop on each model.
831 *
832 * @see
833 * {@link Model.drop} for options
834 *
835 * @param {object} [options] The options passed to each call to Model.drop
836 * @param {boolean|Function} [options.logging] A function that logs sql queries, or false for no logging
837 *
838 * @returns {Promise}
839 */
840 async drop(options) {
841 const models = [];
842
843 this.modelManager.forEachModel(model => {
844 if (model) {
845 models.push(model);
846 }
847 }, { reverse: false });
848
849 for (const model of models) await model.drop(options);
850 }
851
852 /**
853 * Test the connection by trying to authenticate. It runs `SELECT 1+1 AS result` query.
854 *
855 * @param {object} [options={}] query options
856 *
857 * @returns {Promise}
858 */
859 async authenticate(options) {
860 options = {
861 raw: true,
862 plain: true,
863 type: QueryTypes.SELECT,
864 ...options
865 };
866
867 await this.query('SELECT 1+1 AS result', options);
868
869 return;
870 }
871
872 async databaseVersion(options) {
873 return await this.getQueryInterface().databaseVersion(options);
874 }
875
876 /**
877 * Get the fn for random based on the dialect
878 *
879 * @returns {Sequelize.fn}
880 */
881 random() {
882 const dia = this.getDialect();
883 if (dia === 'postgres' || dia === 'sqlite') {
884 return this.fn('RANDOM');
885 }
886 return this.fn('RAND');
887 }
888
889 /**
890 * Creates an 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.
891 * 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.
892 *
893 * @see
894 * {@link Model.findAll}
895 * @see
896 * {@link Sequelize.define}
897 * @see
898 * {@link Sequelize.col}
899 *
900 * @param {string} fn The function you want to call
901 * @param {any} args All further arguments will be passed as arguments to the function
902 *
903 * @since v2.0.0-dev3
904 * @memberof Sequelize
905 * @returns {Sequelize.fn}
906 *
907 * @example <caption>Convert a user's username to upper case</caption>
908 * instance.update({
909 * username: sequelize.fn('upper', sequelize.col('username'))
910 * });
911 */
912 static fn(fn, ...args) {
913 return new Utils.Fn(fn, args);
914 }
915
916 /**
917 * Creates an object which represents a column in the DB, this allows referencing another column in your query. This is often useful in conjunction with `sequelize.fn`, since raw string arguments to fn will be escaped.
918 *
919 * @see
920 * {@link Sequelize#fn}
921 *
922 * @param {string} col The name of the column
923 * @since v2.0.0-dev3
924 * @memberof Sequelize
925 *
926 * @returns {Sequelize.col}
927 */
928 static col(col) {
929 return new Utils.Col(col);
930 }
931
932 /**
933 * Creates an object representing a call to the cast function.
934 *
935 * @param {any} val The value to cast
936 * @param {string} type The type to cast it to
937 * @since v2.0.0-dev3
938 * @memberof Sequelize
939 *
940 * @returns {Sequelize.cast}
941 */
942 static cast(val, type) {
943 return new Utils.Cast(val, type);
944 }
945
946 /**
947 * Creates an object representing a literal, i.e. something that will not be escaped.
948 *
949 * @param {any} val literal value
950 * @since v2.0.0-dev3
951 * @memberof Sequelize
952 *
953 * @returns {Sequelize.literal}
954 */
955 static literal(val) {
956 return new Utils.Literal(val);
957 }
958
959 /**
960 * An AND query
961 *
962 * @see
963 * {@link Model.findAll}
964 *
965 * @param {...string|object} args Each argument will be joined by AND
966 * @since v2.0.0-dev3
967 * @memberof Sequelize
968 *
969 * @returns {Sequelize.and}
970 */
971 static and(...args) {
972 return { [Op.and]: args };
973 }
974
975 /**
976 * An OR query
977 *
978 * @see
979 * {@link Model.findAll}
980 *
981 * @param {...string|object} args Each argument will be joined by OR
982 * @since v2.0.0-dev3
983 * @memberof Sequelize
984 *
985 * @returns {Sequelize.or}
986 */
987 static or(...args) {
988 return { [Op.or]: args };
989 }
990
991 /**
992 * Creates an object representing nested where conditions for postgres/sqlite/mysql json data-type.
993 *
994 * @see
995 * {@link Model.findAll}
996 *
997 * @param {string|object} conditionsOrPath A hash containing strings/numbers or other nested hash, a string using dot notation or a string using postgres/sqlite/mysql json syntax.
998 * @param {string|number|boolean} [value] An optional value to compare against. Produces a string of the form "<json path> = '<value>'".
999 * @memberof Sequelize
1000 *
1001 * @returns {Sequelize.json}
1002 */
1003 static json(conditionsOrPath, value) {
1004 return new Utils.Json(conditionsOrPath, value);
1005 }
1006
1007 /**
1008 * A way of specifying attr = condition.
1009 *
1010 * The attr can either be an object taken from `Model.rawAttributes` (for example `Model.rawAttributes.id` or `Model.rawAttributes.name`). The
1011 * attribute should be defined in your model definition. The attribute can also be an object from one of the sequelize utility functions (`sequelize.fn`, `sequelize.col` etc.)
1012 *
1013 * For string attributes, use the regular `{ where: { attr: something }}` syntax. If you don't want your string to be escaped, use `sequelize.literal`.
1014 *
1015 * @see
1016 * {@link Model.findAll}
1017 *
1018 * @param {object} attr The attribute, which can be either an attribute object from `Model.rawAttributes` or a sequelize object, for example an instance of `sequelize.fn`. For simple string attributes, use the POJO syntax
1019 * @param {symbol} [comparator='Op.eq'] operator
1020 * @param {string|object} logic The condition. Can be both a simply type, or a further condition (`or`, `and`, `.literal` etc.)
1021 * @since v2.0.0-dev3
1022 */
1023 static where(attr, comparator, logic) {
1024 return new Utils.Where(attr, comparator, logic);
1025 }
1026
1027 /**
1028 * 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 @see {@link Transaction}
1029 *
1030 * If you have [CLS](https://github.com/Jeff-Lewis/cls-hooked) enabled, the transaction will automatically be passed to any query that runs within the callback
1031 *
1032 * @example
1033 *
1034 * try {
1035 * const transaction = await sequelize.transaction();
1036 * const user = await User.findOne(..., { transaction });
1037 * await user.update(..., { transaction });
1038 * await transaction.commit();
1039 * } catch {
1040 * await transaction.rollback()
1041 * }
1042 *
1043 * @example <caption>A syntax for automatically committing or rolling back based on the promise chain resolution is also supported</caption>
1044 *
1045 * try {
1046 * await sequelize.transaction(transaction => { // Note that we pass a callback rather than awaiting the call with no arguments
1047 * const user = await User.findOne(..., {transaction});
1048 * await user.update(..., {transaction});
1049 * });
1050 * // Committed
1051 * } catch(err) {
1052 * // Rolled back
1053 * console.error(err);
1054 * }
1055 * @example <caption>To enable CLS, add it do your project, create a namespace and set it on the sequelize constructor:</caption>
1056 *
1057 * const cls = require('cls-hooked');
1058 * const namespace = cls.createNamespace('....');
1059 * const Sequelize = require('sequelize');
1060 * Sequelize.useCLS(namespace);
1061 *
1062 * // Note, that CLS is enabled for all sequelize instances, and all instances will share the same namespace
1063 *
1064 * @param {object} [options] Transaction options
1065 * @param {string} [options.type='DEFERRED'] See `Sequelize.Transaction.TYPES` for possible options. Sqlite only.
1066 * @param {string} [options.isolationLevel] See `Sequelize.Transaction.ISOLATION_LEVELS` for possible options
1067 * @param {string} [options.deferrable] Sets the constraints to be deferred or immediately checked. See `Sequelize.Deferrable`. PostgreSQL Only
1068 * @param {Function} [options.logging=false] A function that gets executed while running the query to log the sql.
1069 * @param {Function} [autoCallback] The callback is called with the transaction object, and should return a promise. If the promise is resolved, the transaction commits; if the promise rejects, the transaction rolls back
1070 *
1071 * @returns {Promise}
1072 */
1073 async transaction(options, autoCallback) {
1074 if (typeof options === 'function') {
1075 autoCallback = options;
1076 options = undefined;
1077 }
1078
1079 const transaction = new Transaction(this, options);
1080
1081 if (!autoCallback) {
1082 await transaction.prepareEnvironment(false);
1083 return transaction;
1084 }
1085
1086 // autoCallback provided
1087 return Sequelize._clsRun(async () => {
1088 try {
1089 await transaction.prepareEnvironment();
1090 const result = await autoCallback(transaction);
1091 await transaction.commit();
1092 return await result;
1093 } catch (err) {
1094 try {
1095 if (!transaction.finished) {
1096 await transaction.rollback();
1097 } else {
1098 // release the connection, even if we don't need to rollback
1099 await transaction.cleanup();
1100 }
1101 } catch (err0) {
1102 // ignore
1103 }
1104 throw err;
1105 }
1106 });
1107 }
1108
1109 /**
1110 * Use CLS (Continuation Local Storage) with Sequelize. With Continuation
1111 * Local Storage, all queries within the transaction callback will
1112 * automatically receive the transaction object.
1113 *
1114 * CLS namespace provided is stored as `Sequelize._cls`
1115 *
1116 * @param {object} ns CLS namespace
1117 * @returns {object} Sequelize constructor
1118 */
1119 static useCLS(ns) {
1120 // check `ns` is valid CLS namespace
1121 if (!ns || typeof ns !== 'object' || typeof ns.bind !== 'function' || typeof ns.run !== 'function') throw new Error('Must provide CLS namespace');
1122
1123 // save namespace as `Sequelize._cls`
1124 this._cls = ns;
1125
1126 // return Sequelize for chaining
1127 return this;
1128 }
1129
1130 /**
1131 * Run function in CLS context.
1132 * If no CLS context in use, just runs the function normally
1133 *
1134 * @private
1135 * @param {Function} fn Function to run
1136 * @returns {*} Return value of function
1137 */
1138 static _clsRun(fn) {
1139 const ns = Sequelize._cls;
1140 if (!ns) return fn();
1141
1142 let res;
1143 ns.run(context => res = fn(context));
1144 return res;
1145 }
1146
1147 log(...args) {
1148 let options;
1149
1150 const last = _.last(args);
1151
1152 if (last && _.isPlainObject(last) && Object.prototype.hasOwnProperty.call(last, 'logging')) {
1153 options = last;
1154
1155 // remove options from set of logged arguments if options.logging is equal to console.log
1156 // eslint-disable-next-line no-console
1157 if (options.logging === console.log) {
1158 args.splice(args.length - 1, 1);
1159 }
1160 } else {
1161 options = this.options;
1162 }
1163
1164 if (options.logging) {
1165 if (options.logging === true) {
1166 deprecations.noTrueLogging();
1167 // eslint-disable-next-line no-console
1168 options.logging = console.log;
1169 }
1170
1171 // second argument is sql-timings, when benchmarking option enabled
1172 // eslint-disable-next-line no-console
1173 if ((this.options.benchmark || options.benchmark) && options.logging === console.log) {
1174 args = [`${args[0]} Elapsed time: ${args[1]}ms`];
1175 }
1176
1177 options.logging(...args);
1178 }
1179 }
1180
1181 /**
1182 * Close all connections used by this sequelize instance, and free all references so the instance can be garbage collected.
1183 *
1184 * Normally this is done on process exit, so you only need to call this method if you are creating multiple instances, and want
1185 * to garbage collect some of them.
1186 *
1187 * @returns {Promise}
1188 */
1189 close() {
1190 return this.connectionManager.close();
1191 }
1192
1193 normalizeDataType(Type) {
1194 let type = typeof Type === 'function' ? new Type() : Type;
1195 const dialectTypes = this.dialect.DataTypes || {};
1196
1197 if (dialectTypes[type.key]) {
1198 type = dialectTypes[type.key].extend(type);
1199 }
1200
1201 if (type instanceof DataTypes.ARRAY) {
1202 if (!type.type) {
1203 throw new Error('ARRAY is missing type definition for its values.');
1204 }
1205 if (dialectTypes[type.type.key]) {
1206 type.type = dialectTypes[type.type.key].extend(type.type);
1207 }
1208 }
1209
1210 return type;
1211 }
1212
1213 normalizeAttribute(attribute) {
1214 if (!_.isPlainObject(attribute)) {
1215 attribute = { type: attribute };
1216 }
1217
1218 if (!attribute.type) return attribute;
1219
1220 attribute.type = this.normalizeDataType(attribute.type);
1221
1222 if (Object.prototype.hasOwnProperty.call(attribute, 'defaultValue')) {
1223 if (typeof attribute.defaultValue === 'function' && (
1224 attribute.defaultValue === DataTypes.NOW ||
1225 attribute.defaultValue === DataTypes.UUIDV1 ||
1226 attribute.defaultValue === DataTypes.UUIDV4
1227 )) {
1228 attribute.defaultValue = new attribute.defaultValue();
1229 }
1230 }
1231
1232 if (attribute.type instanceof DataTypes.ENUM) {
1233 // The ENUM is a special case where the type is an object containing the values
1234 if (attribute.values) {
1235 attribute.type.values = attribute.type.options.values = attribute.values;
1236 } else {
1237 attribute.values = attribute.type.values;
1238 }
1239
1240 if (!attribute.values.length) {
1241 throw new Error('Values for ENUM have not been defined.');
1242 }
1243 }
1244
1245 return attribute;
1246 }
1247}
1248
1249// Aliases
1250Sequelize.prototype.fn = Sequelize.fn;
1251Sequelize.prototype.col = Sequelize.col;
1252Sequelize.prototype.cast = Sequelize.cast;
1253Sequelize.prototype.literal = Sequelize.literal;
1254Sequelize.prototype.and = Sequelize.and;
1255Sequelize.prototype.or = Sequelize.or;
1256Sequelize.prototype.json = Sequelize.json;
1257Sequelize.prototype.where = Sequelize.where;
1258Sequelize.prototype.validate = Sequelize.prototype.authenticate;
1259
1260/**
1261 * Sequelize version number.
1262 */
1263Sequelize.version = require('../package.json').version;
1264
1265Sequelize.options = { hooks: {} };
1266
1267/**
1268 * @private
1269 */
1270Sequelize.Utils = Utils;
1271
1272/**
1273 * Operators symbols to be used for querying data
1274 *
1275 * @see {@link Operators}
1276 */
1277Sequelize.Op = Op;
1278
1279/**
1280 * Available table hints to be used for querying data in mssql for table hints
1281 *
1282 * @see {@link TableHints}
1283 */
1284Sequelize.TableHints = TableHints;
1285
1286/**
1287 * Available index hints to be used for querying data in mysql for index hints
1288 *
1289 * @see {@link IndexHints}
1290 */
1291Sequelize.IndexHints = IndexHints;
1292
1293/**
1294 * A reference to the sequelize transaction class. Use this to access isolationLevels and types when creating a transaction
1295 *
1296 * @see {@link Transaction}
1297 * @see {@link Sequelize.transaction}
1298 */
1299Sequelize.Transaction = Transaction;
1300
1301/**
1302 * A reference to Sequelize constructor from sequelize. Useful for accessing DataTypes, Errors etc.
1303 *
1304 * @see {@link Sequelize}
1305 */
1306Sequelize.prototype.Sequelize = Sequelize;
1307
1308/**
1309 * Available query types for use with `sequelize.query`
1310 *
1311 * @see {@link QueryTypes}
1312 */
1313Sequelize.prototype.QueryTypes = Sequelize.QueryTypes = QueryTypes;
1314
1315/**
1316 * 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.
1317 *
1318 * @see https://github.com/chriso/validator.js
1319 */
1320Sequelize.prototype.Validator = Sequelize.Validator = Validator;
1321
1322Sequelize.Model = Model;
1323
1324Sequelize.DataTypes = DataTypes;
1325for (const dataType in DataTypes) {
1326 Sequelize[dataType] = DataTypes[dataType];
1327}
1328
1329/**
1330 * A reference to the deferrable collection. Use this to access the different deferrable options.
1331 *
1332 * @see {@link Transaction.Deferrable}
1333 * @see {@link Sequelize#transaction}
1334 */
1335Sequelize.Deferrable = Deferrable;
1336
1337/**
1338 * A reference to the sequelize association class.
1339 *
1340 * @see {@link Association}
1341 */
1342Sequelize.prototype.Association = Sequelize.Association = Association;
1343
1344/**
1345 * Provide alternative version of `inflection` module to be used by `Utils.pluralize` etc.
1346 *
1347 * @param {object} _inflection - `inflection` module
1348 */
1349Sequelize.useInflection = Utils.useInflection;
1350
1351/**
1352 * Allow hooks to be defined on Sequelize + on sequelize instance as universal hooks to run on all models
1353 * and on Sequelize/sequelize methods e.g. Sequelize(), Sequelize#define()
1354 */
1355Hooks.applyTo(Sequelize);
1356Hooks.applyTo(Sequelize.prototype);
1357
1358/**
1359 * Expose various errors available
1360 */
1361
1362// expose alias to BaseError
1363Sequelize.Error = sequelizeErrors.BaseError;
1364
1365for (const error of Object.keys(sequelizeErrors)) {
1366 Sequelize[error] = sequelizeErrors[error];
1367}
1368
1369module.exports = Sequelize;
1370module.exports.Sequelize = Sequelize;
1371module.exports.default = Sequelize;