hookable 5.1.1 → 5.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -4
- package/dist/index.cjs +47 -4
- package/dist/index.d.ts +13 -2
- package/dist/index.mjs +47 -4
- package/package.json +16 -16
package/README.md
CHANGED
|
@@ -44,7 +44,7 @@ hooks.callHook('hello')
|
|
|
44
44
|
```js
|
|
45
45
|
import { Hookable } from 'hookable'
|
|
46
46
|
|
|
47
|
-
export default class
|
|
47
|
+
export default class FooLib extends Hookable {
|
|
48
48
|
constructor() {
|
|
49
49
|
// Call to parent to initialize
|
|
50
50
|
super()
|
|
@@ -62,7 +62,7 @@ export default class Foo extends Hookable {
|
|
|
62
62
|
**Inside plugins, register for any hook:**
|
|
63
63
|
|
|
64
64
|
```js
|
|
65
|
-
const lib =
|
|
65
|
+
const lib = new FooLib()
|
|
66
66
|
|
|
67
67
|
// Register a handler for `hook2`
|
|
68
68
|
lib.hook('hook2', async () => { /* ... */ })
|
|
@@ -77,7 +77,7 @@ lib.addHooks({
|
|
|
77
77
|
**Unregistering hooks:**
|
|
78
78
|
|
|
79
79
|
```js
|
|
80
|
-
const lib =
|
|
80
|
+
const lib = new FooLib()
|
|
81
81
|
|
|
82
82
|
const hook0 = async () => { /* ... */ }
|
|
83
83
|
const hook1 = async () => { /* ... */ }
|
|
@@ -101,7 +101,7 @@ lib.removeHook('hook2', hook2)
|
|
|
101
101
|
**Triggering a hook handler once:**
|
|
102
102
|
|
|
103
103
|
```js
|
|
104
|
-
const lib =
|
|
104
|
+
const lib = new FooLib()
|
|
105
105
|
|
|
106
106
|
const unregister = lib.hook('hook0', async () => {
|
|
107
107
|
// Unregister as soon as the hook is executed
|
|
@@ -194,6 +194,32 @@ hookable.removeHooks({
|
|
|
194
194
|
})
|
|
195
195
|
```
|
|
196
196
|
|
|
197
|
+
### `beforeEach (syncCallback)`
|
|
198
|
+
|
|
199
|
+
Registers a (sync) callback to be called before each hook is being called.
|
|
200
|
+
|
|
201
|
+
```js
|
|
202
|
+
hookable.beforeEach((event) => { console.log(`${event.name} hook is being called with ${event.args}`)})
|
|
203
|
+
hookable.hook('test', () => { console.log('running test hook') })
|
|
204
|
+
|
|
205
|
+
// test hook is being called with []
|
|
206
|
+
// running test hook
|
|
207
|
+
await hookable.callHook('test')
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### `afterEach (syncCallback)`
|
|
211
|
+
|
|
212
|
+
Registers a (sync) callback to be called after each hook is being called.
|
|
213
|
+
|
|
214
|
+
```js
|
|
215
|
+
hookable.afterEach((event) => { console.log(`${event.name} hook called with ${event.args}`)})
|
|
216
|
+
hookable.hook('test', () => { console.log('running test hook') })
|
|
217
|
+
|
|
218
|
+
// running test hook
|
|
219
|
+
// test hook called with []
|
|
220
|
+
await hookable.callHook('test')
|
|
221
|
+
```
|
|
222
|
+
|
|
197
223
|
## Migration
|
|
198
224
|
|
|
199
225
|
### From `4.x` to `5.x`
|
package/dist/index.cjs
CHANGED
|
@@ -45,10 +45,17 @@ function serialCaller(hooks, args) {
|
|
|
45
45
|
function parallelCaller(hooks, args) {
|
|
46
46
|
return Promise.all(hooks.map((hook) => hook.apply(void 0, args)));
|
|
47
47
|
}
|
|
48
|
+
function callEachWith(callbacks, arg0) {
|
|
49
|
+
for (const cb of callbacks) {
|
|
50
|
+
cb(arg0);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
48
53
|
|
|
49
54
|
class Hookable {
|
|
50
55
|
constructor() {
|
|
51
56
|
this._hooks = {};
|
|
57
|
+
this._before = null;
|
|
58
|
+
this._after = null;
|
|
52
59
|
this._deprecatedHooks = {};
|
|
53
60
|
this.hook = this.hook.bind(this);
|
|
54
61
|
this.callHook = this.callHook.bind(this);
|
|
@@ -72,7 +79,9 @@ class Hookable {
|
|
|
72
79
|
}
|
|
73
80
|
if (deprecatedHookObj) {
|
|
74
81
|
if (!deprecatedHookObj.message) {
|
|
75
|
-
console.warn(
|
|
82
|
+
console.warn(
|
|
83
|
+
`${originalName} hook has been deprecated` + (deprecatedHookObj.to ? `, please use ${deprecatedHookObj.to}` : "")
|
|
84
|
+
);
|
|
76
85
|
} else {
|
|
77
86
|
console.warn(deprecatedHookObj.message);
|
|
78
87
|
}
|
|
@@ -110,9 +119,17 @@ class Hookable {
|
|
|
110
119
|
}
|
|
111
120
|
deprecateHook(name, deprecated) {
|
|
112
121
|
this._deprecatedHooks[name] = deprecated;
|
|
122
|
+
const _hooks = this._hooks[name] || [];
|
|
123
|
+
this._hooks[name] = void 0;
|
|
124
|
+
for (const hook of _hooks) {
|
|
125
|
+
this.hook(name, hook);
|
|
126
|
+
}
|
|
113
127
|
}
|
|
114
128
|
deprecateHooks(deprecatedHooks) {
|
|
115
129
|
Object.assign(this._deprecatedHooks, deprecatedHooks);
|
|
130
|
+
for (const name in deprecatedHooks) {
|
|
131
|
+
this.deprecateHook(name, deprecatedHooks[name]);
|
|
132
|
+
}
|
|
116
133
|
}
|
|
117
134
|
addHooks(configHooks) {
|
|
118
135
|
const hooks = flatHooks(configHooks);
|
|
@@ -128,13 +145,39 @@ class Hookable {
|
|
|
128
145
|
}
|
|
129
146
|
}
|
|
130
147
|
callHook(name, ...args) {
|
|
131
|
-
return
|
|
148
|
+
return this.callHookWith(serialCaller, name, ...args);
|
|
132
149
|
}
|
|
133
150
|
callHookParallel(name, ...args) {
|
|
134
|
-
return
|
|
151
|
+
return this.callHookWith(parallelCaller, name, ...args);
|
|
135
152
|
}
|
|
136
153
|
callHookWith(caller, name, ...args) {
|
|
137
|
-
|
|
154
|
+
const event = this._before || this._after ? { name, args, context: {} } : void 0;
|
|
155
|
+
if (this._before) {
|
|
156
|
+
callEachWith(this._before, event);
|
|
157
|
+
}
|
|
158
|
+
const result = caller(this._hooks[name] || [], args);
|
|
159
|
+
if (result instanceof Promise) {
|
|
160
|
+
return result.finally(() => {
|
|
161
|
+
if (this._after) {
|
|
162
|
+
callEachWith(this._after, event);
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
if (this._after) {
|
|
167
|
+
callEachWith(this._after, event);
|
|
168
|
+
}
|
|
169
|
+
if (result instanceof Promise) {
|
|
170
|
+
return result;
|
|
171
|
+
}
|
|
172
|
+
return Promise.resolve(result);
|
|
173
|
+
}
|
|
174
|
+
beforeEach(fn) {
|
|
175
|
+
this._before = this._before || [];
|
|
176
|
+
this._before.push(fn);
|
|
177
|
+
}
|
|
178
|
+
afterEach(fn) {
|
|
179
|
+
this._after = this._after || [];
|
|
180
|
+
this._after.push(fn);
|
|
138
181
|
}
|
|
139
182
|
}
|
|
140
183
|
function createHooks() {
|
package/dist/index.d.ts
CHANGED
|
@@ -36,20 +36,31 @@ declare type NestedHooks<T> = (Partial<StripGeneric<T>> | Partial<OnlyGeneric<T>
|
|
|
36
36
|
}>;
|
|
37
37
|
|
|
38
38
|
declare type InferCallback<HT, HN extends keyof HT> = HT[HN] extends HookCallback ? HT[HN] : never;
|
|
39
|
+
declare type InferSpyEvent<HT extends Record<string, any>> = {
|
|
40
|
+
[key in keyof HT]: {
|
|
41
|
+
name: key;
|
|
42
|
+
args: Parameters<HT[key]>;
|
|
43
|
+
context: Record<string, any>;
|
|
44
|
+
};
|
|
45
|
+
}[keyof HT];
|
|
39
46
|
declare class Hookable<HooksT = Record<string, HookCallback>, HookNameT extends HookKeys<HooksT> = HookKeys<HooksT>> {
|
|
40
47
|
private _hooks;
|
|
48
|
+
private _before;
|
|
49
|
+
private _after;
|
|
41
50
|
private _deprecatedHooks;
|
|
42
51
|
constructor();
|
|
43
52
|
hook<NameT extends HookNameT>(name: NameT, fn: InferCallback<HooksT, NameT>): () => void;
|
|
44
53
|
hookOnce<NameT extends HookNameT>(name: NameT, fn: InferCallback<HooksT, NameT>): () => void;
|
|
45
54
|
removeHook<NameT extends HookNameT>(name: NameT, fn: InferCallback<HooksT, NameT>): void;
|
|
46
55
|
deprecateHook<NameT extends HookNameT>(name: NameT, deprecated: DeprecatedHook<HooksT>): void;
|
|
47
|
-
deprecateHooks(deprecatedHooks: Record<HookNameT, DeprecatedHook<HooksT
|
|
56
|
+
deprecateHooks(deprecatedHooks: Partial<Record<HookNameT, DeprecatedHook<HooksT>>>): void;
|
|
48
57
|
addHooks(configHooks: NestedHooks<HooksT>): () => void;
|
|
49
58
|
removeHooks(configHooks: NestedHooks<HooksT>): void;
|
|
50
59
|
callHook<NameT extends HookNameT>(name: NameT, ...args: Parameters<InferCallback<HooksT, NameT>>): Promise<any>;
|
|
51
60
|
callHookParallel<NameT extends HookNameT>(name: NameT, ...args: Parameters<InferCallback<HooksT, NameT>>): Promise<any[]>;
|
|
52
|
-
callHookWith<NameT extends HookNameT, CallFunction extends (hooks: HookCallback[], args: Parameters<InferCallback<HooksT, NameT>>) => any>(caller: CallFunction, name: NameT, ...args: Parameters<InferCallback<HooksT, NameT>>):
|
|
61
|
+
callHookWith<NameT extends HookNameT, CallFunction extends (hooks: HookCallback[], args: Parameters<InferCallback<HooksT, NameT>>) => any>(caller: CallFunction, name: NameT, ...args: Parameters<InferCallback<HooksT, NameT>>): ReturnType<CallFunction>;
|
|
62
|
+
beforeEach(fn: (event: InferSpyEvent<HooksT>) => void): void;
|
|
63
|
+
afterEach(fn: (event: InferSpyEvent<HooksT>) => void): void;
|
|
53
64
|
}
|
|
54
65
|
declare function createHooks<T>(): Hookable<T>;
|
|
55
66
|
|
package/dist/index.mjs
CHANGED
|
@@ -41,10 +41,17 @@ function serialCaller(hooks, args) {
|
|
|
41
41
|
function parallelCaller(hooks, args) {
|
|
42
42
|
return Promise.all(hooks.map((hook) => hook.apply(void 0, args)));
|
|
43
43
|
}
|
|
44
|
+
function callEachWith(callbacks, arg0) {
|
|
45
|
+
for (const cb of callbacks) {
|
|
46
|
+
cb(arg0);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
44
49
|
|
|
45
50
|
class Hookable {
|
|
46
51
|
constructor() {
|
|
47
52
|
this._hooks = {};
|
|
53
|
+
this._before = null;
|
|
54
|
+
this._after = null;
|
|
48
55
|
this._deprecatedHooks = {};
|
|
49
56
|
this.hook = this.hook.bind(this);
|
|
50
57
|
this.callHook = this.callHook.bind(this);
|
|
@@ -68,7 +75,9 @@ class Hookable {
|
|
|
68
75
|
}
|
|
69
76
|
if (deprecatedHookObj) {
|
|
70
77
|
if (!deprecatedHookObj.message) {
|
|
71
|
-
console.warn(
|
|
78
|
+
console.warn(
|
|
79
|
+
`${originalName} hook has been deprecated` + (deprecatedHookObj.to ? `, please use ${deprecatedHookObj.to}` : "")
|
|
80
|
+
);
|
|
72
81
|
} else {
|
|
73
82
|
console.warn(deprecatedHookObj.message);
|
|
74
83
|
}
|
|
@@ -106,9 +115,17 @@ class Hookable {
|
|
|
106
115
|
}
|
|
107
116
|
deprecateHook(name, deprecated) {
|
|
108
117
|
this._deprecatedHooks[name] = deprecated;
|
|
118
|
+
const _hooks = this._hooks[name] || [];
|
|
119
|
+
this._hooks[name] = void 0;
|
|
120
|
+
for (const hook of _hooks) {
|
|
121
|
+
this.hook(name, hook);
|
|
122
|
+
}
|
|
109
123
|
}
|
|
110
124
|
deprecateHooks(deprecatedHooks) {
|
|
111
125
|
Object.assign(this._deprecatedHooks, deprecatedHooks);
|
|
126
|
+
for (const name in deprecatedHooks) {
|
|
127
|
+
this.deprecateHook(name, deprecatedHooks[name]);
|
|
128
|
+
}
|
|
112
129
|
}
|
|
113
130
|
addHooks(configHooks) {
|
|
114
131
|
const hooks = flatHooks(configHooks);
|
|
@@ -124,13 +141,39 @@ class Hookable {
|
|
|
124
141
|
}
|
|
125
142
|
}
|
|
126
143
|
callHook(name, ...args) {
|
|
127
|
-
return
|
|
144
|
+
return this.callHookWith(serialCaller, name, ...args);
|
|
128
145
|
}
|
|
129
146
|
callHookParallel(name, ...args) {
|
|
130
|
-
return
|
|
147
|
+
return this.callHookWith(parallelCaller, name, ...args);
|
|
131
148
|
}
|
|
132
149
|
callHookWith(caller, name, ...args) {
|
|
133
|
-
|
|
150
|
+
const event = this._before || this._after ? { name, args, context: {} } : void 0;
|
|
151
|
+
if (this._before) {
|
|
152
|
+
callEachWith(this._before, event);
|
|
153
|
+
}
|
|
154
|
+
const result = caller(this._hooks[name] || [], args);
|
|
155
|
+
if (result instanceof Promise) {
|
|
156
|
+
return result.finally(() => {
|
|
157
|
+
if (this._after) {
|
|
158
|
+
callEachWith(this._after, event);
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
if (this._after) {
|
|
163
|
+
callEachWith(this._after, event);
|
|
164
|
+
}
|
|
165
|
+
if (result instanceof Promise) {
|
|
166
|
+
return result;
|
|
167
|
+
}
|
|
168
|
+
return Promise.resolve(result);
|
|
169
|
+
}
|
|
170
|
+
beforeEach(fn) {
|
|
171
|
+
this._before = this._before || [];
|
|
172
|
+
this._before.push(fn);
|
|
173
|
+
}
|
|
174
|
+
afterEach(fn) {
|
|
175
|
+
this._after = this._after || [];
|
|
176
|
+
this._after.push(fn);
|
|
134
177
|
}
|
|
135
178
|
}
|
|
136
179
|
function createHooks() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hookable",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.2.1",
|
|
4
4
|
"description": "Awaitable hook system",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"hook",
|
|
@@ -21,24 +21,24 @@
|
|
|
21
21
|
"files": [
|
|
22
22
|
"dist"
|
|
23
23
|
],
|
|
24
|
-
"scripts": {
|
|
25
|
-
"build": "unbuild",
|
|
26
|
-
"lint": "eslint --ext .ts src",
|
|
27
|
-
"prepublish": "yarn build",
|
|
28
|
-
"release": "yarn test && yarn build && standard-version && git push --follow-tags && npm publish",
|
|
29
|
-
"test": "yarn lint && yarn jest"
|
|
30
|
-
},
|
|
31
24
|
"devDependencies": {
|
|
32
25
|
"@nuxtjs/eslint-config-typescript": "latest",
|
|
33
|
-
"@
|
|
34
|
-
"babel-jest": "latest",
|
|
35
|
-
"codecov": "latest",
|
|
26
|
+
"@vitest/coverage-c8": "^0.22.1",
|
|
36
27
|
"eslint": "latest",
|
|
37
|
-
"expect-type": "^0.
|
|
38
|
-
"jest": "latest",
|
|
28
|
+
"expect-type": "^0.13.0",
|
|
39
29
|
"standard-version": "latest",
|
|
40
|
-
"ts-jest": "latest",
|
|
41
30
|
"typescript": "latest",
|
|
42
|
-
"unbuild": "latest"
|
|
31
|
+
"unbuild": "latest",
|
|
32
|
+
"vitest": "latest"
|
|
33
|
+
},
|
|
34
|
+
"packageManager": "pnpm@7.9.4",
|
|
35
|
+
"scripts": {
|
|
36
|
+
"build": "unbuild",
|
|
37
|
+
"dev": "vitest",
|
|
38
|
+
"lint": "eslint --ext .ts src",
|
|
39
|
+
"prepublish": "pnpm build",
|
|
40
|
+
"release": "pnpm test && pnpm build && standard-version && git push --follow-tags && pnpm publish",
|
|
41
|
+
"test": "pnpm lint && vitest run --coverage",
|
|
42
|
+
"test:types": "tsc --noEmit"
|
|
43
43
|
}
|
|
44
|
-
}
|
|
44
|
+
}
|