// Copyright IBM Corp. 2018. All Rights Reserved. // Node module: loopback-datasource-juggler // This file is licensed under the MIT License. // License text available at https://opensource.org/licenses/MIT import {Callback, PromiseOrVoid} from './common'; export type Listener = (ctx: object, next: (err?: any) => void) => void; export interface ObserverMixin { /** * Register an asynchronous observer for the given operation (event). * * Example: * * Registers a `before save` observer for a given model. * * ```javascript * MyModel.observe('before save', function filterProperties(ctx, next) { * if (ctx.options && ctx.options.skipPropertyFilter) return next(); * if (ctx.instance) { * FILTERED_PROPERTIES.forEach(function(p) { * ctx.instance.unsetAttribute(p); * }); * } else { * FILTERED_PROPERTIES.forEach(function(p) { * delete ctx.data[p]; * }); * } * next(); * }); * ``` * * @param {String} operation The operation name. * @callback {function} listener The listener function. It will be invoked with * `this` set to the model constructor, e.g. `User`. * @end */ observe(operation: string, listener: Listener): void; /** * Unregister an asynchronous observer for the given operation (event). * * Example: * * ```javascript * MyModel.removeObserver('before save', function removedObserver(ctx, next) { * // some logic user want to apply to the removed observer... * next(); * }); * ``` * * @param {String} operation The operation name. * @callback {function} listener The listener function. * @end */ removeObserver(operation: string, listener: Listener): Listener | undefined; /** * Unregister all asynchronous observers for the given operation (event). * * Example: * * Remove all observers connected to the `before save` operation. * * ```javascript * MyModel.clearObservers('before save'); * ``` * * @param {String} operation The operation name. * @end */ clearObservers(operation: string): void; /** * Invoke all async observers for the given operation(s). * * Example: * * Notify all async observers for the `before save` operation. * * ```javascript * var context = { * Model: Model, * instance: obj, * isNewInstance: true, * hookState: hookState, * options: options, * }; * Model.notifyObserversOf('before save', context, function(err) { * if (err) return cb(err); * // user can specify the logic after the observers have been notified * }); * ``` * * @param {String|String[]} operation The operation name(s). * @param {Object} context Operation-specific context. * @callback {function(Error=)} callback The callback to call when all observers * have finished. */ notifyObserversOf( operation: string, context: object, callback?: Callback, ): PromiseOrVoid; _notifyBaseObservers( operation: string, context: object, callback?: Callback, ): PromiseOrVoid; /** * Run the given function with before/after observers. * * It's done in three serial asynchronous steps: * * - Notify the registered observers under 'before ' + operation * - Execute the function * - Notify the registered observers under 'after ' + operation * * If an error happens, it fails first and calls the callback with err. * * Example: * * ```javascript * var context = { * Model: Model, * instance: obj, * isNewInstance: true, * hookState: hookState, * options: options, * }; * function work(done) { * process.nextTick(function() { * done(null, 1); * }); * } * Model.notifyObserversAround('execute', context, work, function(err) { * if (err) return cb(err); * // user can specify the logic after the observers have been notified * }); * ``` * * @param {String} operation The operation name * @param {Context} context The context object * @param {Function} fn The task to be invoked as fn(done) or fn(context, done) * @callback {Function} callback The callback function * @returns {*} */ notifyObserversAround( operation: string, context: object, fn: Function, callback?: Callback, ): PromiseOrVoid; }