loopback-datasource-juggler/lib/hooks.js

114 lines
3.5 KiB
JavaScript
Raw Permalink Normal View History

// Copyright IBM Corp. 2013,2019. All Rights Reserved.
2016-04-01 22:25:16 +00:00
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
2016-08-22 19:55:22 +00:00
'use strict';
2018-12-07 14:54:29 +00:00
const deprecated = require('depd')('loopback-datasource-juggler');
const g = require('strong-globalize')();
2014-06-18 23:42:00 +00:00
/*!
2013-04-11 23:23:34 +00:00
* Module exports
*/
2013-05-28 05:20:30 +00:00
module.exports = Hookable;
2014-06-18 23:42:00 +00:00
/*
* Hooks object.
* @class Hookable
2013-04-11 23:23:34 +00:00
*/
2013-05-28 05:20:30 +00:00
function Hookable() {
}
2013-04-11 23:23:34 +00:00
/**
* List of hooks available
*/
2011-11-20 05:36:15 +00:00
Hookable.afterInitialize = null;
Hookable.beforeValidate = null;
Hookable.afterValidate = null;
2011-11-20 05:36:15 +00:00
Hookable.beforeSave = null;
Hookable.afterSave = null;
Hookable.beforeCreate = null;
Hookable.afterCreate = null;
Hookable.beforeUpdate = null;
Hookable.afterUpdate = null;
Hookable.beforeDestroy = null;
Hookable.afterDestroy = null;
2017-05-23 16:12:11 +00:00
/**
* @deprecated
* Setup a Model-based hook to trigger when the specified action occurs.
* The trigger is broken up into three segments: `beforeHook`, `work` and
* `afterHook`.
* @param {string} actionName The name of the action that triggers the hook.
* @param {Function} work The 2nd phase of the trigger.
* @param {*} data The value(s) to provide to the 1st phase (`beforeHook`) call.
* @callback
* @param {Function} callback
*/
Hookable.prototype.trigger = function trigger(actionName, work, data, callback) {
2018-12-07 14:54:29 +00:00
const capitalizedName = capitalize(actionName);
let beforeHook = this.constructor['before' + capitalizedName] ||
2016-04-01 13:23:42 +00:00
this.constructor['pre' + capitalizedName];
2018-12-07 14:54:29 +00:00
let afterHook = this.constructor['after' + capitalizedName] ||
2016-04-01 13:23:42 +00:00
this.constructor['post' + capitalizedName];
2014-01-24 17:09:53 +00:00
if (actionName === 'validate') {
beforeHook = beforeHook || this.constructor.beforeValidation;
afterHook = afterHook || this.constructor.afterValidation;
}
2018-12-07 14:54:29 +00:00
const inst = this;
2011-11-20 05:36:15 +00:00
if (actionName !== 'initialize') {
if (beforeHook)
deprecateHook(inst.constructor, ['before', 'pre'], capitalizedName);
if (afterHook)
deprecateHook(inst.constructor, ['after', 'post'], capitalizedName);
}
2014-01-24 17:09:53 +00:00
// we only call "before" hook when we have actual action (work) to perform
if (work) {
if (beforeHook) {
// before hook should be called on instance with two parameters: next and data
2016-04-01 11:48:17 +00:00
beforeHook.call(inst, function() {
// Check arguments to next(err, result)
if (arguments.length) {
return callback && callback.apply(null, arguments);
}
// No err & result is present, proceed with the real work
2014-01-24 17:09:53 +00:00
// actual action also have one param: callback
work.call(inst, next);
}, data);
2011-11-20 05:36:15 +00:00
} else {
2014-01-24 17:09:53 +00:00
work.call(inst, next);
2011-11-20 05:36:15 +00:00
}
2014-01-24 17:09:53 +00:00
} else {
next();
}
2014-01-24 17:09:53 +00:00
function next(done) {
if (afterHook) {
afterHook.call(inst, done);
} else if (done) {
done.call(this);
}
2014-01-24 17:09:53 +00:00
}
};
function capitalize(string) {
2014-01-24 17:09:53 +00:00
return string.charAt(0).toUpperCase() + string.slice(1);
}
function deprecateHook(ctor, prefixes, capitalizedName) {
2018-12-07 14:54:29 +00:00
const candidateNames = prefixes.map(function(p) { return p + capitalizedName; });
if (capitalizedName === 'Validate')
candidateNames.push(prefixes[0] + 'Validation');
2018-12-07 14:54:29 +00:00
let hookName = candidateNames.filter(function(hook) { return !!ctor[hook]; })[0];
if (!hookName) return; // just to be sure, this should never happen
2018-06-12 07:13:32 +00:00
if (ctor.modelName) hookName = ctor.modelName + '.' + hookName;
2016-07-22 19:26:07 +00:00
deprecated(g.f('Model hook "%s" is deprecated, ' +
'use Operation hooks instead. ' +
2016-07-22 19:26:07 +00:00
'{{http://docs.strongloop.com/display/LB/Operation+hooks}}', hookName));
}