UNPKG

sequelize

Version:

Sequelize is a promise-based Node.js ORM tool for Postgres, MySQL, MariaDB, SQLite, Microsoft SQL Server, Amazon Redshift and Snowflake’s Data Cloud. It features solid transaction support, relations, eager and lazy loading, read replication and more.

597 lines (527 loc) 15.4 kB
'use strict'; const _ = require('lodash'); const { logger } = require('./utils/logger'); const debug = logger.debugContext('hooks'); const hookTypes = { beforeValidate: { params: 2 }, afterValidate: { params: 2 }, validationFailed: { params: 3 }, beforeCreate: { params: 2 }, afterCreate: { params: 2 }, beforeDestroy: { params: 2 }, afterDestroy: { params: 2 }, beforeRestore: { params: 2 }, afterRestore: { params: 2 }, beforeUpdate: { params: 2 }, afterUpdate: { params: 2 }, beforeSave: { params: 2, proxies: ['beforeUpdate', 'beforeCreate'] }, afterSave: { params: 2, proxies: ['afterUpdate', 'afterCreate'] }, beforeUpsert: { params: 2 }, afterUpsert: { params: 2 }, beforeBulkCreate: { params: 2 }, afterBulkCreate: { params: 2 }, beforeBulkDestroy: { params: 1 }, afterBulkDestroy: { params: 1 }, beforeBulkRestore: { params: 1 }, afterBulkRestore: { params: 1 }, beforeBulkUpdate: { params: 1 }, afterBulkUpdate: { params: 1 }, beforeFind: { params: 1 }, beforeFindAfterExpandIncludeAll: { params: 1 }, beforeFindAfterOptions: { params: 1 }, afterFind: { params: 2 }, beforeCount: { params: 1 }, beforeDefine: { params: 2, sync: true, noModel: true }, afterDefine: { params: 1, sync: true, noModel: true }, beforeInit: { params: 2, sync: true, noModel: true }, afterInit: { params: 1, sync: true, noModel: true }, beforeAssociate: { params: 2, sync: true }, afterAssociate: { params: 2, sync: true }, beforeConnect: { params: 1, noModel: true }, afterConnect: { params: 2, noModel: true }, beforeDisconnect: { params: 1, noModel: true }, afterDisconnect: { params: 1, noModel: true }, beforeSync: { params: 1 }, afterSync: { params: 1 }, beforeBulkSync: { params: 1 }, afterBulkSync: { params: 1 }, beforeQuery: { params: 2 }, afterQuery: { params: 2 } }; exports.hooks = hookTypes; /** * get array of current hook and its proxies combined * * @param {string} hookType any hook type @see {@link hookTypes} * * @private */ const getProxiedHooks = hookType => hookTypes[hookType].proxies ? hookTypes[hookType].proxies.concat(hookType) : [hookType] ; function getHooks(hooked, hookType) { return (hooked.options.hooks || {})[hookType] || []; } const Hooks = { /** * Process user supplied hooks definition * * @param {object} hooks hooks definition * * @private * @memberof Sequelize * @memberof Sequelize.Model */ _setupHooks(hooks) { this.options.hooks = {}; _.map(hooks || {}, (hooksArray, hookName) => { if (!Array.isArray(hooksArray)) hooksArray = [hooksArray]; hooksArray.forEach(hookFn => this.addHook(hookName, hookFn)); }); }, async runHooks(hooks, ...hookArgs) { if (!hooks) throw new Error('runHooks requires at least 1 argument'); let hookType; if (typeof hooks === 'string') { hookType = hooks; hooks = getHooks(this, hookType); if (this.sequelize) { hooks = hooks.concat(getHooks(this.sequelize, hookType)); } } if (!Array.isArray(hooks)) { hooks = [hooks]; } // synchronous hooks if (hookTypes[hookType] && hookTypes[hookType].sync) { for (let hook of hooks) { if (typeof hook === 'object') { hook = hook.fn; } debug(`running hook(sync) ${hookType}`); hook.apply(this, hookArgs); } return; } // asynchronous hooks (default) for (let hook of hooks) { if (typeof hook === 'object') { hook = hook.fn; } debug(`running hook ${hookType}`); await hook.apply(this, hookArgs); } }, /** * Add a hook to the model * * @param {string} hookType hook name @see {@link hookTypes} * @param {string|Function} [name] Provide a name for the hook function. It can be used to remove the hook later or to order hooks based on some sort of priority system in the future. * @param {Function} fn The hook function * * @memberof Sequelize * @memberof Sequelize.Model */ addHook(hookType, name, fn) { if (typeof name === 'function') { fn = name; name = null; } debug(`adding hook ${hookType}`); // check for proxies, add them too hookType = getProxiedHooks(hookType); hookType.forEach(type => { const hooks = getHooks(this, type); hooks.push(name ? { name, fn } : fn); this.options.hooks[type] = hooks; }); return this; }, /** * Remove hook from the model * * @param {string} hookType @see {@link hookTypes} * @param {string|Function} name name of hook or function reference which was attached * * @memberof Sequelize * @memberof Sequelize.Model */ removeHook(hookType, name) { const isReference = typeof name === 'function' ? true : false; if (!this.hasHook(hookType)) { return this; } debug(`removing hook ${hookType}`); // check for proxies, add them too hookType = getProxiedHooks(hookType); for (const type of hookType) { this.options.hooks[type] = this.options.hooks[type].filter(hook => { if (isReference && typeof hook === 'function') { return hook !== name; // check if same method } if (!isReference && typeof hook === 'object') { return hook.name !== name; } return true; }); } return this; }, /** * Check whether the mode has any hooks of this type * * @param {string} hookType @see {@link hookTypes} * * @alias hasHooks * * @memberof Sequelize * @memberof Sequelize.Model */ hasHook(hookType) { return this.options.hooks[hookType] && !!this.options.hooks[hookType].length; } }; Hooks.hasHooks = Hooks.hasHook; function applyTo(target, isModel = false) { _.mixin(target, Hooks); for (const hook of Object.keys(hookTypes)) { if (isModel && hookTypes[hook].noModel) { continue; } target[hook] = function(name, callback) { return this.addHook(hook, name, callback); }; } } exports.applyTo = applyTo; /** * A hook that is run before validation * * @param {string} name * @param {Function} fn A callback function that is called with instance, options * @name beforeValidate * @memberof Sequelize.Model */ /** * A hook that is run after validation * * @param {string} name * @param {Function} fn A callback function that is called with instance, options * @name afterValidate * @memberof Sequelize.Model */ /** * A hook that is run when validation fails * * @param {string} name * @param {Function} fn A callback function that is called with instance, options, error. Error is the * SequelizeValidationError. If the callback throws an error, it will replace the original validation error. * @name validationFailed * @memberof Sequelize.Model */ /** * A hook that is run before creating a single instance * * @param {string} name * @param {Function} fn A callback function that is called with attributes, options * @name beforeCreate * @memberof Sequelize.Model */ /** * A hook that is run after creating a single instance * * @param {string} name * @param {Function} fn A callback function that is called with attributes, options * @name afterCreate * @memberof Sequelize.Model */ /** * A hook that is run before creating or updating a single instance, It proxies `beforeCreate` and `beforeUpdate` * * @param {string} name * @param {Function} fn A callback function that is called with attributes, options * @name beforeSave * @memberof Sequelize.Model */ /** * A hook that is run before upserting * * @param {string} name * @param {Function} fn A callback function that is called with attributes, options * @name beforeUpsert * @memberof Sequelize.Model */ /** * A hook that is run after upserting * * @param {string} name * @param {Function} fn A callback function that is called with the result of upsert(), options * @name afterUpsert * @memberof Sequelize.Model */ /** * A hook that is run after creating or updating a single instance, It proxies `afterCreate` and `afterUpdate` * * @param {string} name * @param {Function} fn A callback function that is called with attributes, options * @name afterSave * @memberof Sequelize.Model */ /** * A hook that is run before destroying a single instance * * @param {string} name * @param {Function} fn A callback function that is called with instance, options * * @name beforeDestroy * @memberof Sequelize.Model */ /** * A hook that is run after destroying a single instance * * @param {string} name * @param {Function} fn A callback function that is called with instance, options * * @name afterDestroy * @memberof Sequelize.Model */ /** * A hook that is run before restoring a single instance * * @param {string} name * @param {Function} fn A callback function that is called with instance, options * * @name beforeRestore * @memberof Sequelize.Model */ /** * A hook that is run after restoring a single instance * * @param {string} name * @param {Function} fn A callback function that is called with instance, options * * @name afterRestore * @memberof Sequelize.Model */ /** * A hook that is run before updating a single instance * * @param {string} name * @param {Function} fn A callback function that is called with instance, options * @name beforeUpdate * @memberof Sequelize.Model */ /** * A hook that is run after updating a single instance * * @param {string} name * @param {Function} fn A callback function that is called with instance, options * @name afterUpdate * @memberof Sequelize.Model */ /** * A hook that is run before creating instances in bulk * * @param {string} name * @param {Function} fn A callback function that is called with instances, options * @name beforeBulkCreate * @memberof Sequelize.Model */ /** * A hook that is run after creating instances in bulk * * @param {string} name * @param {Function} fn A callback function that is called with instances, options * @name afterBulkCreate * @memberof Sequelize.Model */ /** * A hook that is run before destroying instances in bulk * * @param {string} name * @param {Function} fn A callback function that is called with options * * @name beforeBulkDestroy * @memberof Sequelize.Model */ /** * A hook that is run after destroying instances in bulk * * @param {string} name * @param {Function} fn A callback function that is called with options * * @name afterBulkDestroy * @memberof Sequelize.Model */ /** * A hook that is run before restoring instances in bulk * * @param {string} name * @param {Function} fn A callback function that is called with options * * @name beforeBulkRestore * @memberof Sequelize.Model */ /** * A hook that is run after restoring instances in bulk * * @param {string} name * @param {Function} fn A callback function that is called with options * * @name afterBulkRestore * @memberof Sequelize.Model */ /** * A hook that is run before updating instances in bulk * * @param {string} name * @param {Function} fn A callback function that is called with options * @name beforeBulkUpdate * @memberof Sequelize.Model */ /** * A hook that is run after updating instances in bulk * * @param {string} name * @param {Function} fn A callback function that is called with options * @name afterBulkUpdate * @memberof Sequelize.Model */ /** * A hook that is run before a find (select) query * * @param {string} name * @param {Function} fn A callback function that is called with options * @name beforeFind * @memberof Sequelize.Model */ /** * A hook that is run before a find (select) query, after any { include: {all: ...} } options are expanded * * @param {string} name * @param {Function} fn A callback function that is called with options * @name beforeFindAfterExpandIncludeAll * @memberof Sequelize.Model */ /** * A hook that is run before a find (select) query, after all option parsing is complete * * @param {string} name * @param {Function} fn A callback function that is called with options * @name beforeFindAfterOptions * @memberof Sequelize.Model */ /** * A hook that is run after a find (select) query * * @param {string} name * @param {Function} fn A callback function that is called with instance(s), options * @name afterFind * @memberof Sequelize.Model */ /** * A hook that is run before a count query * * @param {string} name * @param {Function} fn A callback function that is called with options * @name beforeCount * @memberof Sequelize.Model */ /** * A hook that is run before a define call * * @param {string} name * @param {Function} fn A callback function that is called with attributes, options * @name beforeDefine * @memberof Sequelize */ /** * A hook that is run after a define call * * @param {string} name * @param {Function} fn A callback function that is called with factory * @name afterDefine * @memberof Sequelize */ /** * A hook that is run before Sequelize() call * * @param {string} name * @param {Function} fn A callback function that is called with config, options * @name beforeInit * @memberof Sequelize */ /** * A hook that is run after Sequelize() call * * @param {string} name * @param {Function} fn A callback function that is called with sequelize * @name afterInit * @memberof Sequelize */ /** * A hook that is run before a connection is created * * @param {string} name * @param {Function} fn A callback function that is called with config passed to connection * @name beforeConnect * @memberof Sequelize */ /** * A hook that is run after a connection is created * * @param {string} name * @param {Function} fn A callback function that is called with the connection object and the config passed to connection * @name afterConnect * @memberof Sequelize */ /** * A hook that is run before a connection is disconnected * * @param {string} name * @param {Function} fn A callback function that is called with the connection object * @name beforeDisconnect * @memberof Sequelize */ /** * A hook that is run after a connection is disconnected * * @param {string} name * @param {Function} fn A callback function that is called with the connection object * @name afterDisconnect * @memberof Sequelize */ /** * A hook that is run before Model.sync call * * @param {string} name * @param {Function} fn A callback function that is called with options passed to Model.sync * @name beforeSync * @memberof Sequelize */ /** * A hook that is run after Model.sync call * * @param {string} name * @param {Function} fn A callback function that is called with options passed to Model.sync * @name afterSync * @memberof Sequelize */ /** * A hook that is run before sequelize.sync call * * @param {string} name * @param {Function} fn A callback function that is called with options passed to sequelize.sync * @name beforeBulkSync * @memberof Sequelize */ /** * A hook that is run after sequelize.sync call * * @param {string} name * @param {Function} fn A callback function that is called with options passed to sequelize.sync * @name afterBulkSync * @memberof Sequelize */