You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
553 lines
15 KiB
553 lines
15 KiB
'use strict';
|
|
|
|
const _ = require('lodash');
|
|
const Utils = require('./utils');
|
|
const Promise = require('./promise');
|
|
const debug = Utils.getLogger().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},
|
|
afterDefine: {params: 1, sync: true},
|
|
beforeInit: {params: 2, sync: true},
|
|
afterInit: {params: 1, sync: true},
|
|
beforeConnect: {params: 1},
|
|
afterConnect: {params: 2},
|
|
beforeSync: {params: 1},
|
|
afterSync: {params: 1},
|
|
beforeBulkSync: {params: 1},
|
|
afterBulkSync: {params: 1}
|
|
};
|
|
exports.hooks = hookTypes;
|
|
|
|
const hookAliases = {
|
|
beforeDelete: 'beforeDestroy',
|
|
afterDelete: 'afterDestroy',
|
|
beforeBulkDelete: 'beforeBulkDestroy',
|
|
afterBulkDelete: 'afterBulkDestroy',
|
|
beforeConnection: 'beforeConnect'
|
|
};
|
|
exports.hookAliases = hookAliases;
|
|
|
|
/**
|
|
* get array of current hook and its proxied hooks combined
|
|
* @private
|
|
*/
|
|
const getProxiedHooks = hookType =>
|
|
hookTypes[hookType].proxies
|
|
? hookTypes[hookType].proxies.concat(hookType)
|
|
: [hookType]
|
|
;
|
|
|
|
function getHooks(hookType) {
|
|
return (this.options.hooks || {})[hookType] || [];
|
|
};
|
|
|
|
const Hooks = {
|
|
/**
|
|
* Process user supplied hooks definition
|
|
*
|
|
* @param {Object} hooks
|
|
*
|
|
* @private
|
|
* @memberOf Sequelize
|
|
* @memberOf Sequelize.Model
|
|
*/
|
|
_setupHooks(hooks) {
|
|
this.options.hooks = {};
|
|
_.map(hooks || {}, (hooksArray, hookName) => {
|
|
if (!_.isArray(hooksArray)) hooksArray = [hooksArray];
|
|
hooksArray.forEach(hookFn => this.addHook(hookName, hookFn));
|
|
});
|
|
},
|
|
|
|
runHooks(hooks) {
|
|
if (!hooks) throw new Error('runHooks requires at least 1 argument');
|
|
|
|
const hookArgs = Utils.sliceArgs(arguments, 1);
|
|
let hookType;
|
|
|
|
if (typeof hooks === 'string') {
|
|
hookType = hooks;
|
|
hooks = getHooks.call(this, hookType);
|
|
|
|
if (this.sequelize) {
|
|
hooks = hooks.concat(getHooks.call(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)
|
|
return Promise.each(hooks, hook => {
|
|
if (typeof hook === 'object') {
|
|
hook = hook.fn;
|
|
}
|
|
|
|
debug(`running hook ${hookType}`);
|
|
return Promise.resolve(hook.apply(this, hookArgs));
|
|
}).return();
|
|
},
|
|
|
|
hook() {
|
|
Utils.deprecate('hook() method has been deprecated, please use addHook() method instead');
|
|
return Hooks.addHook.apply(this, arguments);
|
|
},
|
|
|
|
/**
|
|
* Add a hook to the model
|
|
*
|
|
* @param {String} hookType
|
|
* @param {String} [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}`);
|
|
const originalHookType = hookType;
|
|
hookType = hookAliases[hookType] || hookType;
|
|
|
|
if (hookAliases[originalHookType]) {
|
|
Utils.deprecate(`${originalHookType} hook has been deprecated, please use ${hookType} hook instead`);
|
|
}
|
|
|
|
// check for proxies, add them too
|
|
hookType = getProxiedHooks(hookType);
|
|
|
|
_.each(hookType, type => {
|
|
this.options.hooks[type] = getHooks.call(this, type);
|
|
this.options.hooks[type].push(name ? {name, fn} : fn);
|
|
});
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Remove hook from the model
|
|
*
|
|
* @param {String} hookType
|
|
* @param {String|Function} name
|
|
*
|
|
* @memberOf Sequelize
|
|
* @memberOf Sequelize.Model
|
|
*/
|
|
removeHook(hookType, name) {
|
|
hookType = hookAliases[hookType] || hookType;
|
|
const isReference = typeof name === 'function' ? true : false;
|
|
|
|
if (!this.hasHook(hookType)) {
|
|
return this;
|
|
}
|
|
|
|
Utils.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
|
|
} else 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
|
|
*
|
|
* @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) {
|
|
_.mixin(target, Hooks);
|
|
|
|
const allHooks = Object.keys(hookTypes).concat(Object.keys(hookAliases));
|
|
for (const hook of allHooks) {
|
|
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 attributes, 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
|
|
* @alias beforeDelete
|
|
* @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
|
|
* @alias afterDelete
|
|
* @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
|
|
* @alias beforeBulkDelete
|
|
* @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
|
|
* @alias afterBulkDelete
|
|
* @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 thye config passed to connection
|
|
* @name afterConnect
|
|
* @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
|
|
*/
|
|
|