1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 | 'use strict';
|
7 |
|
8 | const deprecated = require('depd')('loopback-datasource-juggler');
|
9 | const g = require('strong-globalize')();
|
10 |
|
11 |
|
12 |
|
13 |
|
14 | module.exports = Hookable;
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 | function Hookable() {
|
22 | }
|
23 |
|
24 |
|
25 |
|
26 |
|
27 | Hookable.afterInitialize = null;
|
28 | Hookable.beforeValidate = null;
|
29 | Hookable.afterValidate = null;
|
30 | Hookable.beforeSave = null;
|
31 | Hookable.afterSave = null;
|
32 | Hookable.beforeCreate = null;
|
33 | Hookable.afterCreate = null;
|
34 | Hookable.beforeUpdate = null;
|
35 | Hookable.afterUpdate = null;
|
36 | Hookable.beforeDestroy = null;
|
37 | Hookable.afterDestroy = null;
|
38 |
|
39 |
|
40 |
|
41 |
|
42 |
|
43 |
|
44 |
|
45 |
|
46 |
|
47 |
|
48 |
|
49 |
|
50 | Hookable.prototype.trigger = function trigger(actionName, work, data, callback) {
|
51 | const capitalizedName = capitalize(actionName);
|
52 | let beforeHook = this.constructor['before' + capitalizedName] ||
|
53 | this.constructor['pre' + capitalizedName];
|
54 | let afterHook = this.constructor['after' + capitalizedName] ||
|
55 | this.constructor['post' + capitalizedName];
|
56 | if (actionName === 'validate') {
|
57 | beforeHook = beforeHook || this.constructor.beforeValidation;
|
58 | afterHook = afterHook || this.constructor.afterValidation;
|
59 | }
|
60 | const inst = this;
|
61 |
|
62 | if (actionName !== 'initialize') {
|
63 | if (beforeHook)
|
64 | deprecateHook(inst.constructor, ['before', 'pre'], capitalizedName);
|
65 | if (afterHook)
|
66 | deprecateHook(inst.constructor, ['after', 'post'], capitalizedName);
|
67 | }
|
68 |
|
69 |
|
70 | if (work) {
|
71 | if (beforeHook) {
|
72 |
|
73 | beforeHook.call(inst, function() {
|
74 |
|
75 | if (arguments.length) {
|
76 | return callback && callback.apply(null, arguments);
|
77 | }
|
78 |
|
79 |
|
80 | work.call(inst, next);
|
81 | }, data);
|
82 | } else {
|
83 | work.call(inst, next);
|
84 | }
|
85 | } else {
|
86 | next();
|
87 | }
|
88 |
|
89 | function next(done) {
|
90 | if (afterHook) {
|
91 | afterHook.call(inst, done);
|
92 | } else if (done) {
|
93 | done.call(this);
|
94 | }
|
95 | }
|
96 | };
|
97 |
|
98 | function capitalize(string) {
|
99 | return string.charAt(0).toUpperCase() + string.slice(1);
|
100 | }
|
101 |
|
102 | function deprecateHook(ctor, prefixes, capitalizedName) {
|
103 | const candidateNames = prefixes.map(function(p) { return p + capitalizedName; });
|
104 | if (capitalizedName === 'Validate')
|
105 | candidateNames.push(prefixes[0] + 'Validation');
|
106 |
|
107 | let hookName = candidateNames.filter(function(hook) { return !!ctor[hook]; })[0];
|
108 | if (!hookName) return;
|
109 | if (ctor.modelName) hookName = ctor.modelName + '.' + hookName;
|
110 | deprecated(g.f('Model hook "%s" is deprecated, ' +
|
111 | 'use Operation hooks instead. ' +
|
112 | '{{http://docs.strongloop.com/display/LB/Operation+hooks}}', hookName));
|
113 | }
|