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.
 
 
 
 
 

148 lines
4.6 KiB

"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;
const getProxiedHooks = (hookType) => hookTypes[hookType].proxies ? hookTypes[hookType].proxies.concat(hookType) : [hookType];
function getHooks(hooked, hookType) {
return (hooked.options.hooks || {})[hookType] || [];
}
const Hooks = {
_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];
}
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;
}
for (let hook of hooks) {
if (typeof hook === "object") {
hook = hook.fn;
}
debug(`running hook ${hookType}`);
await hook.apply(this, hookArgs);
}
},
addHook(hookType, name, fn) {
if (typeof name === "function") {
fn = name;
name = null;
}
debug(`adding hook ${hookType}`);
hookType = getProxiedHooks(hookType);
hookType.forEach((type) => {
const hooks = getHooks(this, type);
hooks.push(name ? { name, fn } : fn);
this.options.hooks[type] = hooks;
});
return this;
},
removeHook(hookType, name) {
const isReference = typeof name === "function" ? true : false;
if (!this.hasHook(hookType)) {
return this;
}
debug(`removing hook ${hookType}`);
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;
}
if (!isReference && typeof hook === "object") {
return hook.name !== name;
}
return true;
});
}
return this;
},
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;
//# sourceMappingURL=hooks.js.map