1 | // Copyright IBM Corp. 2018. All Rights Reserved.
|
2 | // Node module: loopback-datasource-juggler
|
3 | // This file is licensed under the MIT License.
|
4 | // License text available at https://opensource.org/licenses/MIT
|
5 |
|
6 | import {Callback, PromiseOrVoid} from './common';
|
7 | import {ModelBase} from './model';
|
8 |
|
9 | export interface OperationHookContext<T extends typeof ModelBase> {
|
10 | /**
|
11 | * The constructor of the model that triggered the operation.
|
12 | */
|
13 | Model: T;
|
14 |
|
15 | /**
|
16 | * Additional context properties, not typed yet.
|
17 | * See https://loopback.io/doc/en/lb3/Operation-hooks.html#hooks
|
18 | */
|
19 | [property: string]: any;
|
20 | }
|
21 |
|
22 | export type Listener<Ctx = OperationHookContext<typeof ModelBase>> = (
|
23 | ctx: Ctx, next: (err?: any) => void
|
24 | ) => PromiseOrVoid<void>;
|
25 |
|
26 | export interface ObserverMixin {
|
27 | /**
|
28 | * Register an asynchronous observer for the given operation (event).
|
29 | *
|
30 | * Example:
|
31 | *
|
32 | * Registers a `before save` observer for a given model.
|
33 | *
|
34 | * ```javascript
|
35 | * MyModel.observe('before save', function filterProperties(ctx, next) {
|
36 | * if (ctx.options && ctx.options.skipPropertyFilter) return next();
|
37 | * if (ctx.instance) {
|
38 | * FILTERED_PROPERTIES.forEach(function(p) {
|
39 | * ctx.instance.unsetAttribute(p);
|
40 | * });
|
41 | * } else {
|
42 | * FILTERED_PROPERTIES.forEach(function(p) {
|
43 | * delete ctx.data[p];
|
44 | * });
|
45 | * }
|
46 | * next();
|
47 | * });
|
48 | * ```
|
49 | *
|
50 | * @param {String} operation The operation name.
|
51 | * @callback {function} listener The listener function. It will be invoked with
|
52 | * `this` set to the model constructor, e.g. `User`.
|
53 | * @end
|
54 | */
|
55 | observe<T extends typeof ModelBase>(
|
56 | this: T,
|
57 | operation: string,
|
58 | listener: Listener<OperationHookContext<T>>,
|
59 | ): void;
|
60 |
|
61 | /**
|
62 | * Unregister an asynchronous observer for the given operation (event).
|
63 | *
|
64 | * Example:
|
65 | *
|
66 | * ```javascript
|
67 | * MyModel.removeObserver('before save', function removedObserver(ctx, next) {
|
68 | * // some logic user want to apply to the removed observer...
|
69 | * next();
|
70 | * });
|
71 | * ```
|
72 | *
|
73 | * @param {String} operation The operation name.
|
74 | * @callback {function} listener The listener function.
|
75 | * @end
|
76 | */
|
77 | removeObserver<T extends typeof ModelBase>(
|
78 | this: T,
|
79 | operation: string,
|
80 | listener: Listener<OperationHookContext<T>>,
|
81 | ): Listener<OperationHookContext<T>> | undefined;
|
82 |
|
83 | /**
|
84 | * Unregister all asynchronous observers for the given operation (event).
|
85 | *
|
86 | * Example:
|
87 | *
|
88 | * Remove all observers connected to the `before save` operation.
|
89 | *
|
90 | * ```javascript
|
91 | * MyModel.clearObservers('before save');
|
92 | * ```
|
93 | *
|
94 | * @param {String} operation The operation name.
|
95 | * @end
|
96 | */
|
97 | clearObservers(operation: string): void;
|
98 |
|
99 | /**
|
100 | * Invoke all async observers for the given operation(s).
|
101 | *
|
102 | * Example:
|
103 | *
|
104 | * Notify all async observers for the `before save` operation.
|
105 | *
|
106 | * ```javascript
|
107 | * var context = {
|
108 | * Model: Model,
|
109 | * instance: obj,
|
110 | * isNewInstance: true,
|
111 | * hookState: hookState,
|
112 | * options: options,
|
113 | * };
|
114 | * Model.notifyObserversOf('before save', context, function(err) {
|
115 | * if (err) return cb(err);
|
116 | * // user can specify the logic after the observers have been notified
|
117 | * });
|
118 | * ```
|
119 | *
|
120 | * @param {String|String[]} operation The operation name(s).
|
121 | * @param {Object} context Operation-specific context.
|
122 | * @callback {function(Error=)} callback The callback to call when all observers
|
123 | * have finished.
|
124 | */
|
125 | notifyObserversOf(
|
126 | operation: string,
|
127 | context: object,
|
128 | callback?: Callback,
|
129 | ): PromiseOrVoid;
|
130 |
|
131 | _notifyBaseObservers(
|
132 | operation: string,
|
133 | context: object,
|
134 | callback?: Callback,
|
135 | ): PromiseOrVoid;
|
136 |
|
137 | /**
|
138 | * Run the given function with before/after observers.
|
139 | *
|
140 | * It's done in three serial asynchronous steps:
|
141 | *
|
142 | * - Notify the registered observers under 'before ' + operation
|
143 | * - Execute the function
|
144 | * - Notify the registered observers under 'after ' + operation
|
145 | *
|
146 | * If an error happens, it fails first and calls the callback with err.
|
147 | *
|
148 | * Example:
|
149 | *
|
150 | * ```javascript
|
151 | * var context = {
|
152 | * Model: Model,
|
153 | * instance: obj,
|
154 | * isNewInstance: true,
|
155 | * hookState: hookState,
|
156 | * options: options,
|
157 | * };
|
158 | * function work(done) {
|
159 | * process.nextTick(function() {
|
160 | * done(null, 1);
|
161 | * });
|
162 | * }
|
163 | * Model.notifyObserversAround('execute', context, work, function(err) {
|
164 | * if (err) return cb(err);
|
165 | * // user can specify the logic after the observers have been notified
|
166 | * });
|
167 | * ```
|
168 | *
|
169 | * @param {String} operation The operation name
|
170 | * @param {Context} context The context object
|
171 | * @param {Function} fn The task to be invoked as fn(done) or fn(context, done)
|
172 | * @callback {Function} callback The callback function
|
173 | * @returns {*}
|
174 | */
|
175 | notifyObserversAround(
|
176 | operation: string,
|
177 | context: object,
|
178 | fn: Function,
|
179 | callback?: Callback,
|
180 | ): PromiseOrVoid;
|
181 | }
|