hookable 5.1.2 → 5.2.0

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 CHANGED
@@ -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);
@@ -138,13 +145,36 @@ class Hookable {
138
145
  }
139
146
  }
140
147
  callHook(name, ...args) {
141
- return serialCaller(this._hooks[name] || [], args);
148
+ return this.callHookWith(serialCaller, name, ...args);
142
149
  }
143
150
  callHookParallel(name, ...args) {
144
- return parallelCaller(this._hooks[name] || [], args);
151
+ return this.callHookWith(parallelCaller, name, ...args);
145
152
  }
146
153
  callHookWith(caller, name, ...args) {
147
- return caller(this._hooks[name] || [], args);
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
+ return result;
170
+ }
171
+ beforeEach(fn) {
172
+ this._before = this._before || [];
173
+ this._before.push(fn);
174
+ }
175
+ afterEach(fn) {
176
+ this._after = this._after || [];
177
+ this._after.push(fn);
148
178
  }
149
179
  }
150
180
  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>>): void;
56
+ deprecateHooks(deprecatedHooks: Partial<Record<HookNameT, DeprecatedHook<HooksT>>>): void;
48
57
  addHooks(configHooks: NestedHooks<HooksT>): () => void;
49
58
  removeHooks(configHooks: NestedHooks<HooksT>): void;
50
- callHook<NameT extends HookNameT>(name: NameT, ...args: Parameters<InferCallback<HooksT, NameT>>): Promise<any>;
51
- callHookParallel<NameT extends HookNameT>(name: NameT, ...args: Parameters<InferCallback<HooksT, NameT>>): Promise<any[]>;
59
+ callHook<NameT extends HookNameT>(name: NameT, ...args: Parameters<InferCallback<HooksT, NameT>>): void | Promise<any>;
60
+ callHookParallel<NameT extends HookNameT>(name: NameT, ...args: Parameters<InferCallback<HooksT, NameT>>): void | Promise<any[]>;
52
61
  callHookWith<NameT extends HookNameT, CallFunction extends (hooks: HookCallback[], args: Parameters<InferCallback<HooksT, NameT>>) => any>(caller: CallFunction, name: NameT, ...args: Parameters<InferCallback<HooksT, NameT>>): void | 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);
@@ -134,13 +141,36 @@ class Hookable {
134
141
  }
135
142
  }
136
143
  callHook(name, ...args) {
137
- return serialCaller(this._hooks[name] || [], args);
144
+ return this.callHookWith(serialCaller, name, ...args);
138
145
  }
139
146
  callHookParallel(name, ...args) {
140
- return parallelCaller(this._hooks[name] || [], args);
147
+ return this.callHookWith(parallelCaller, name, ...args);
141
148
  }
142
149
  callHookWith(caller, name, ...args) {
143
- return caller(this._hooks[name] || [], args);
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
+ return result;
166
+ }
167
+ beforeEach(fn) {
168
+ this._before = this._before || [];
169
+ this._before.push(fn);
170
+ }
171
+ afterEach(fn) {
172
+ this._after = this._after || [];
173
+ this._after.push(fn);
144
174
  }
145
175
  }
146
176
  function createHooks() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hookable",
3
- "version": "5.1.2",
3
+ "version": "5.2.0",
4
4
  "description": "Awaitable hook system",
5
5
  "keywords": [
6
6
  "hook",
@@ -23,22 +23,22 @@
23
23
  ],
24
24
  "devDependencies": {
25
25
  "@nuxtjs/eslint-config-typescript": "latest",
26
- "c8": "latest",
27
- "codecov": "latest",
26
+ "@vitest/coverage-c8": "^0.22.1",
28
27
  "eslint": "latest",
29
28
  "expect-type": "^0.13.0",
30
- "vitest": "latest",
31
29
  "standard-version": "latest",
32
30
  "typescript": "latest",
33
- "unbuild": "latest"
31
+ "unbuild": "latest",
32
+ "vitest": "latest"
34
33
  },
35
- "packageManager": "pnpm@7.9.0",
34
+ "packageManager": "pnpm@7.9.4",
36
35
  "scripts": {
37
36
  "build": "unbuild",
37
+ "dev": "vitest",
38
38
  "lint": "eslint --ext .ts src",
39
39
  "prepublish": "pnpm build",
40
40
  "release": "pnpm test && pnpm build && standard-version && git push --follow-tags && pnpm publish",
41
- "test": "pnpm lint && vitest run",
41
+ "test": "pnpm lint && vitest run --coverage",
42
42
  "test:types": "tsc --noEmit"
43
43
  }
44
44
  }