Skip to content

Commit

Permalink
feat: mergeHooks helper (#26)
Browse files Browse the repository at this point in the history
  • Loading branch information
pooya parsa committed Nov 6, 2020
1 parent 7393a92 commit 8c52d03
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 2 deletions.
12 changes: 10 additions & 2 deletions src/hookable.ts
@@ -1,11 +1,14 @@
import { serial, flatHooks } from './utils'
import { serial, flatHooks, mergeHooks } from './utils'
import { LoggerT, hookFnT, configHooksT, deprecatedHookT, deprecatedHooksT } from './types'

export default class Hookable {
class Hookable {
private _hooks: { [name: string]: hookFnT[] }
private _deprecatedHooks: deprecatedHooksT
private _logger: LoggerT | false

static mergeHooks: typeof mergeHooks
mergeHooks: typeof mergeHooks

constructor (logger: LoggerT | false = console) {
this._logger = logger
this._hooks = {}
Expand Down Expand Up @@ -124,3 +127,8 @@ export default class Hookable {
}
}
}

Hookable.mergeHooks = mergeHooks
Hookable.prototype.mergeHooks = mergeHooks

export default Hookable
22 changes: 22 additions & 0 deletions src/utils.ts
Expand Up @@ -13,6 +13,28 @@ export function flatHooks (configHooks: configHooksT, hooks: flatHooksT = {}, pa
return hooks
}

export function mergeHooks (...hooks: configHooksT[]): flatHooksT {
const finalHooks: any = {}

for (let _hook of hooks) {
_hook = flatHooks(_hook)
for (const key in _hook) {
if (finalHooks[key]) {
finalHooks[key].push(_hook[key])
} else {
finalHooks[key] = [_hook[key]]
}
}
}

for (const key in finalHooks) {
const arr = finalHooks[key]
finalHooks[key] = (...args) => serial(arr, (fn: any) => fn(...args))
}

return finalHooks
}

export function serial<T> (tasks: T[], fn: (task: T) => Promise<any> | any) {
return tasks.reduce((promise, task) => promise.then(() => fn(task)), Promise.resolve(null))
}
52 changes: 52 additions & 0 deletions test/hookable.test.ts
Expand Up @@ -275,4 +275,56 @@ describe('core: hookable', () => {

expect(x).toBe(1)
})

test('mergeHooks util', () => {
const fn = () => { }
const hooks1 = {
foo: fn,
bar: fn,
'a:b': fn,
'a:c': fn
}
const hooks2 = {
foo: fn,
baz: fn,
a: {
b: fn,
d: fn
}
}

const merged = Hookable.mergeHooks(hooks1, hooks2)

expect(Object.keys(merged)).toMatchObject([
'foo',
'bar',
'a:b',
'a:c',
'baz',
'a:d'
])
})

test('mergeHooks util (proto)', async () => {
const hook = new Hookable()

const hooks1 = {
'test:hook': () => console.log('test:hook called1')
}

const hooks2 = {
test: {
hook: () => console.log('test:hook called2')
}
}

const mergedHooks = hook.mergeHooks(hooks1, hooks2)

hook.addHooks(mergedHooks)

await hook.callHook('test:hook')

expect(console.log).toBeCalledWith('test:hook called1')
expect(console.log).toBeCalledWith('test:hook called2')
})
})

0 comments on commit 8c52d03

Please sign in to comment.