1 | # Hookable
|
2 |
|
3 | [![npm version][npm-version-src]][npm-version-href]
|
4 | [![npm downloads][npm-downloads-src]][npm-downloads-href]
|
5 | [![packagephobia][packagephobia-src]][packagephobia-href]
|
6 | [![Github Actions CI][github-actions-ci-src]][github-actions-ci-href]
|
7 | > Awaitable hook system
|
8 |
|
9 | ## Install
|
10 |
|
11 | Using yarn:
|
12 |
|
13 | ```bash
|
14 | yarn add sync-hookable
|
15 | ```
|
16 |
|
17 | Using npm:
|
18 |
|
19 | ```bash
|
20 | npm install sync-hookable
|
21 | ```
|
22 |
|
23 | ## Usage
|
24 |
|
25 | **Method A: Create a sync-hookable instance:**
|
26 |
|
27 | ```js
|
28 | import { createHooks } from 'sync-hookable'
|
29 |
|
30 | // Create a sync-hookable instance
|
31 | const hooks = createHooks()
|
32 |
|
33 | // Hook on 'hello'
|
34 | hooks.hook('hello', () => { console.log('Hello World' )})
|
35 |
|
36 | // Call 'hello' hook
|
37 | hooks.callHook('hello')
|
38 | ```
|
39 |
|
40 | **Method B: Extend your base class from Hookable:**
|
41 |
|
42 | ```js
|
43 | import { Hookable } from 'sync-hookable'
|
44 |
|
45 | export default class FooLib extends Hookable {
|
46 | constructor() {
|
47 | // Call to parent to initialize
|
48 | super()
|
49 | // Initialize Hookable with custom logger
|
50 | // super(consola)
|
51 | }
|
52 |
|
53 | someFunction() {
|
54 | // Call for `hook1` hooks (if any) sequential
|
55 | this.callHook('hook1')
|
56 | }
|
57 | }
|
58 | ```
|
59 |
|
60 | **Inside plugins, register for any hook:**
|
61 |
|
62 | ```js
|
63 | const lib = new FooLib()
|
64 |
|
65 | // Register a handler for `hook2`
|
66 | lib.hook('hook2', () => { /* ... */ })
|
67 |
|
68 | // Register multiply handlers at once
|
69 | lib.addHooks({
|
70 | hook1: () => { /* ... */ },
|
71 | hook2: [ /* can be also an array */ ]
|
72 | })
|
73 | ```
|
74 |
|
75 | **Unregistering hooks:**
|
76 |
|
77 | ```js
|
78 | const lib = new FooLib()
|
79 |
|
80 | const hook0 = () => { /* ... */ }
|
81 | const hook1 = () => { /* ... */ }
|
82 | const hook2 = () => { /* ... */ }
|
83 |
|
84 | // The hook() method returns an "unregister" function
|
85 | const unregisterHook0 = lib.hook('hook0', hook0)
|
86 | const unregisterHooks1and2 = lib.addHooks({ hook1, hook2 })
|
87 |
|
88 | /* ... */
|
89 |
|
90 | unregisterHook0()
|
91 | unregisterHooks1and2()
|
92 |
|
93 | // or
|
94 |
|
95 | lib.removeHooks({ hook0, hook1 })
|
96 | lib.removeHook('hook2', hook2)
|
97 | ```
|
98 |
|
99 | **Triggering a hook handler once:**
|
100 |
|
101 | ```js
|
102 | const lib = new FooLib()
|
103 |
|
104 | const unregister = lib.hook('hook0', () => {
|
105 | // Unregister as soon as the hook is executed
|
106 | unregister()
|
107 |
|
108 | /* ... */
|
109 | })
|
110 | ```
|
111 |
|
112 |
|
113 | ## Hookable class
|
114 |
|
115 | ### `constructor()`
|
116 |
|
117 | ### `hook (name, fn)`
|
118 |
|
119 | Register a handler for a specific hook. `fn` must be a function.
|
120 |
|
121 | Returns an `unregister` function that, when called, will remove the registered handler.
|
122 |
|
123 | ### `hookOnce (name, fn)`
|
124 |
|
125 | Similar to `hook` but unregisters hook once called.
|
126 |
|
127 | Returns an `unregister` function that, when called, will remove the registered handler before first call.
|
128 |
|
129 | ### `addHooks(configHooks)`
|
130 |
|
131 | Flatten and register hooks object.
|
132 |
|
133 | Example:
|
134 |
|
135 | ```js
|
136 | hookable.addHooks({
|
137 | test: {
|
138 | before: () => {},
|
139 | after: () => {}
|
140 | }
|
141 | })
|
142 |
|
143 | ```
|
144 |
|
145 | This registers `test:before` and `test:after` hooks at bulk.
|
146 |
|
147 | Returns an `unregister` function that, when called, will remove all the registered handlers.
|
148 |
|
149 | ### `callHook (name, ...args)`
|
150 |
|
151 | Used by class itself to **sequentially** call handlers of a specific hook.
|
152 |
|
153 | ### `callHookWith (name, callerFn)`
|
154 |
|
155 | If you need custom control over how hooks are called, you can provide a custom function that will receive an array of handlers of a specific hook.
|
156 |
|
157 | `callerFn` if a callback function that accepts two arguments, `hooks` and `args`:
|
158 | - `hooks`: Array of user hooks to be called
|
159 | - `args`: Array of arguments that should be passed each time calling a hook
|
160 |
|
161 | ### `deprecateHook (old, name)`
|
162 |
|
163 | Deprecate hook called `old` in favor of `name` hook.
|
164 |
|
165 | ### `deprecateHooks (deprecatedHooks)`
|
166 |
|
167 | Deprecate all hooks from an object (keys are old and values or newer ones).
|
168 |
|
169 | ### `removeHook (name, fn)`
|
170 |
|
171 | Remove a particular hook handler, if the `fn` handler is present.
|
172 |
|
173 | ### `removeHooks (configHooks)`
|
174 |
|
175 | Remove multiple hook handlers.
|
176 |
|
177 | Example:
|
178 |
|
179 | ```js
|
180 | const handler = () => { /* ... */ }
|
181 |
|
182 | hookable.hook('test:before', handler)
|
183 | hookable.addHooks({ test: { after: handler } })
|
184 |
|
185 | // ...
|
186 |
|
187 | hookable.removeHooks({
|
188 | test: {
|
189 | before: handler,
|
190 | after: handler
|
191 | }
|
192 | })
|
193 | ```
|
194 |
|
195 | ### `beforeEach (syncCallback)`
|
196 |
|
197 | Registers a (sync) callback to be called before each hook is being called.
|
198 |
|
199 | ```js
|
200 | hookable.beforeEach((event) => { console.log(`${event.name} hook is being called with ${event.args}`)})
|
201 | hookable.hook('test', () => { console.log('running test hook') })
|
202 |
|
203 | // test hook is being called with []
|
204 | // running test hook
|
205 | hookable.callHook('test')
|
206 | ```
|
207 |
|
208 | ### `afterEach (syncCallback)`
|
209 |
|
210 | Registers a (sync) callback to be called after each hook is being called.
|
211 |
|
212 | ```js
|
213 | hookable.afterEach((event) => { console.log(`${event.name} hook called with ${event.args}`)})
|
214 | hookable.hook('test', () => { console.log('running test hook') })
|
215 |
|
216 | // running test hook
|
217 | // test hook called with []
|
218 | hookable.callHook('test')
|
219 | ```
|
220 |
|
221 | ### `createDebugger`
|
222 |
|
223 | Automatically logs each hook that is called and how long it takes to run.
|
224 |
|
225 | ```js
|
226 | const debug = hookable.createDebugger(hooks, { tag: 'something' })
|
227 |
|
228 | hooks.callHook('some-hook', 'some-arg')
|
229 | // [something] some-hook: 0.21ms
|
230 |
|
231 | debug.close()
|
232 | ```
|
233 |
|
234 | ## Credits
|
235 |
|
236 | Extracted from [Nuxt](https://github.com/nuxt/nuxt.js) hooks system originally introduced by [Sébastien Chopin](https://github.com/Atinux)
|
237 |
|
238 | ## License
|
239 |
|
240 | MIT - Made with 💖
|
241 |
|
242 |
|
243 | [npm-version-src]: https://flat.badgen.net/npm/dt/sync-hookable
|
244 | [npm-version-href]: https://npmjs.com/package/sync-hookable
|
245 |
|
246 | [npm-downloads-src]: https://flat.badgen.net/npm/v/sync-hookable
|
247 | [npm-downloads-href]: https://npmjs.com/package/sync-hookable
|
248 |
|
249 | [github-actions-ci-src]: https://flat.badgen.net/github/checks/Vinccool96/sync-hookable/master
|
250 | [github-actions-ci-href]: https://github.com/Vinccool96/sync-hookable/actions
|
251 |
|
252 | [packagephobia-src]: https://flat.badgen.net/packagephobia/install/sync-hookable
|
253 | [packagephobia-href]: https://packagephobia.now.sh/result?p=sync-hookable
|