The Hook will compile a method with the most efficient way of running your plugins. It generates code depending on:
* The number of registered plugins (none, one, many)
* The kind of registered plugins (sync, async, promise)
* The used call method (sync, async, promise)
* The number of arguments
* Whether interception is used
This ensures fastest possible execution.
## Hook types
Each hook can be tapped with one or several functions. How they are executed depends on the hook type:
* Basic hook (without “Waterfall”, “Bail” or “Loop” in its name). This hook simply calls every function it’s tapped with in a row.
* __Waterfall__. A waterfall hook also calls each tapped function in a row. Unlike the basic hook, it passes a return value from each function to the next function.
* __Bail__. A bail hook allows exitting early. When any of the tapped function returns anything, the bail hook will stop executing the remaining ones.
* __Loop__. TODO
Additionally, hooks can be synchronous or asynchronous. To reflect this, there’re “Sync”, “AsyncSeries” and “AsyncParallel” hook classes:
* __Sync__. A sync hooks can only be tapped with synchronous functions (using `myHook.tap()`).
* __AsyncSeries__. Async-series hooks can be tapped with synchronous, callback-based and promise-based functions (using `myHook.tap()`, `myHook.tapAsync()` and `myHook.tapPromise()`). They call each async method in a row.
* __AsyncParallel__. Async-parallel hooks can also be tapped with synchronous, callback-based and promise-based functions (using `myHook.tap()`, `myHook.tapAsync()` and `myHook.tapPromise()`). However, they run each async method in parallel.
The hook type is reflected in its class name. E.g., `AsyncSeriesWaterfallHook` allows asynchronous functions and runs them in series passing each function’s return value into the next function.
return tapInfo; // may return a new tapInfo object
}
})
```
**call**: `(...args) => void` Adding `call` to your interceptor will trigger when hooks are triggered. You have access to the hooks arguments.
**tap**: `(tap: Tap) => void` Adding `tap` to your interceptor will trigger when a plugin taps into a hook. Provided is the `Tap` object. `Tap` object can't be changed.
**loop**: `(...args) => void` Adding `loop` to your interceptor will trigger for each loop of a looping hook.
**register**: `(tap: Tap) => Tap | undefined` Adding `register` to your interceptor will trigger for each added `Tap` and allows to modify it.
## Context
Plugins and interceptors can opt-in to access an optional `context` object, which can be used to pass arbitrary values to subsequent plugins and interceptors.