2018-10-30 20:42:53 +00:00
|
|
|
|
|
|
|
import consola from 'consola'
|
|
|
|
|
2018-12-22 21:05:13 +00:00
|
|
|
import { sequence } from '@nuxt/utils'
|
2018-10-30 20:42:53 +00:00
|
|
|
|
|
|
|
export default class Hookable {
|
|
|
|
constructor() {
|
|
|
|
this._hooks = {}
|
|
|
|
this._deprecatedHooks = {}
|
|
|
|
|
|
|
|
this.hook = this.hook.bind(this)
|
|
|
|
this.callHook = this.callHook.bind(this)
|
|
|
|
}
|
|
|
|
|
|
|
|
hook(name, fn) {
|
|
|
|
if (!name || typeof fn !== 'function') {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this._deprecatedHooks[name]) {
|
|
|
|
consola.warn(`${name} hook has been deprecated, please use ${this._deprecatedHooks[name]}`)
|
|
|
|
name = this._deprecatedHooks[name]
|
|
|
|
}
|
|
|
|
|
|
|
|
this._hooks[name] = this._hooks[name] || []
|
|
|
|
this._hooks[name].push(fn)
|
|
|
|
}
|
|
|
|
|
|
|
|
async callHook(name, ...args) {
|
|
|
|
if (!this._hooks[name]) {
|
|
|
|
return
|
|
|
|
}
|
2019-03-21 19:52:17 +00:00
|
|
|
|
2018-10-30 20:42:53 +00:00
|
|
|
try {
|
|
|
|
await sequence(this._hooks[name], fn => fn(...args))
|
|
|
|
} catch (err) {
|
2019-01-15 11:02:10 +00:00
|
|
|
name !== 'error' && await this.callHook('error', err)
|
2018-11-02 13:54:58 +00:00
|
|
|
consola.fatal(err)
|
2018-10-30 20:42:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
clearHook(name) {
|
|
|
|
if (name) {
|
|
|
|
delete this._hooks[name]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-09 10:42:22 +00:00
|
|
|
clearHooks() {
|
|
|
|
this._hooks = {}
|
|
|
|
}
|
|
|
|
|
2018-10-30 20:42:53 +00:00
|
|
|
flatHooks(configHooks, hooks = {}, parentName) {
|
|
|
|
Object.keys(configHooks).forEach((key) => {
|
|
|
|
const subHook = configHooks[key]
|
|
|
|
const name = parentName ? `${parentName}:${key}` : key
|
|
|
|
if (typeof subHook === 'object' && subHook !== null) {
|
|
|
|
this.flatHooks(subHook, hooks, name)
|
|
|
|
} else {
|
|
|
|
hooks[name] = subHook
|
|
|
|
}
|
|
|
|
})
|
|
|
|
return hooks
|
|
|
|
}
|
|
|
|
|
|
|
|
addHooks(configHooks) {
|
|
|
|
const hooks = this.flatHooks(configHooks)
|
|
|
|
Object.keys(hooks).filter(Boolean).forEach((key) => {
|
|
|
|
[].concat(hooks[key]).forEach(h => this.hook(key, h))
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|