hookable 5.4.0 → 5.4.2
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/LICENSE.md +1 -1
- package/dist/index.cjs +98 -90
- package/dist/index.d.ts +32 -31
- package/dist/index.mjs +98 -88
- package/package.json +11 -10
package/LICENSE.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
The MIT License (MIT)
|
|
2
2
|
|
|
3
|
-
Copyright (c)
|
|
3
|
+
Copyright (c) Pooya Parsa <pooya@pi0.io>
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
-
|
|
5
3
|
function flatHooks(configHooks, hooks = {}, parentName) {
|
|
6
4
|
for (const key in configHooks) {
|
|
7
5
|
const subHook = configHooks[key];
|
|
@@ -28,82 +26,42 @@ function mergeHooks(...hooks) {
|
|
|
28
26
|
}
|
|
29
27
|
for (const key in finalHooks) {
|
|
30
28
|
if (finalHooks[key].length > 1) {
|
|
31
|
-
const
|
|
32
|
-
finalHooks[key] = (...
|
|
29
|
+
const array = finalHooks[key];
|
|
30
|
+
finalHooks[key] = (...arguments_) => serial(array, (function_) => function_(...arguments_));
|
|
33
31
|
} else {
|
|
34
32
|
finalHooks[key] = finalHooks[key][0];
|
|
35
33
|
}
|
|
36
34
|
}
|
|
37
35
|
return finalHooks;
|
|
38
36
|
}
|
|
39
|
-
function serial(tasks,
|
|
40
|
-
return tasks.reduce((promise, task) => promise.then(() =>
|
|
37
|
+
function serial(tasks, function_) {
|
|
38
|
+
return tasks.reduce((promise, task) => promise.then(() => function_(task)), Promise.resolve());
|
|
41
39
|
}
|
|
42
|
-
function serialCaller(hooks,
|
|
43
|
-
return hooks.reduce((promise,
|
|
40
|
+
function serialCaller(hooks, arguments_) {
|
|
41
|
+
return hooks.reduce((promise, hookFunction) => promise.then(() => hookFunction.apply(void 0, arguments_)), Promise.resolve());
|
|
44
42
|
}
|
|
45
|
-
function parallelCaller(hooks,
|
|
46
|
-
return Promise.all(hooks.map((hook) => hook.apply(void 0,
|
|
43
|
+
function parallelCaller(hooks, arguments_) {
|
|
44
|
+
return Promise.all(hooks.map((hook) => hook.apply(void 0, arguments_)));
|
|
47
45
|
}
|
|
48
|
-
function callEachWith(callbacks,
|
|
49
|
-
for (const
|
|
50
|
-
|
|
46
|
+
function callEachWith(callbacks, argument0) {
|
|
47
|
+
for (const callback of callbacks) {
|
|
48
|
+
callback(argument0);
|
|
51
49
|
}
|
|
52
50
|
}
|
|
53
|
-
const isBrowser = typeof window !== "undefined";
|
|
54
|
-
function createDebugger(hooks, _options = {}) {
|
|
55
|
-
const options = {
|
|
56
|
-
inspect: isBrowser,
|
|
57
|
-
group: isBrowser,
|
|
58
|
-
filter: () => true,
|
|
59
|
-
..._options
|
|
60
|
-
};
|
|
61
|
-
const _filter = options.filter;
|
|
62
|
-
const filter = typeof _filter === "string" ? (name) => name.startsWith(_filter) : _filter;
|
|
63
|
-
const logPrefix = options.tag ? `[${options.tag}] ` : "";
|
|
64
|
-
const unsubscribeBefore = hooks.beforeEach(({ name }) => {
|
|
65
|
-
if (!filter(name)) {
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
console.time(logPrefix + name);
|
|
69
|
-
});
|
|
70
|
-
const unsubscribeAfter = hooks.afterEach(({ name, args }) => {
|
|
71
|
-
if (!filter(name)) {
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
if (options.group) {
|
|
75
|
-
console.groupCollapsed(name);
|
|
76
|
-
}
|
|
77
|
-
if (options.inspect) {
|
|
78
|
-
console.timeLog(logPrefix + name, args);
|
|
79
|
-
} else {
|
|
80
|
-
console.timeEnd(logPrefix + name);
|
|
81
|
-
}
|
|
82
|
-
if (options.group) {
|
|
83
|
-
console.groupEnd();
|
|
84
|
-
}
|
|
85
|
-
});
|
|
86
|
-
return {
|
|
87
|
-
close: () => {
|
|
88
|
-
unsubscribeBefore();
|
|
89
|
-
unsubscribeAfter();
|
|
90
|
-
}
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
51
|
|
|
94
52
|
class Hookable {
|
|
95
53
|
constructor() {
|
|
96
54
|
this._hooks = {};
|
|
97
|
-
this._before =
|
|
98
|
-
this._after =
|
|
99
|
-
this._deprecatedMessages =
|
|
55
|
+
this._before = void 0;
|
|
56
|
+
this._after = void 0;
|
|
57
|
+
this._deprecatedMessages = void 0;
|
|
100
58
|
this._deprecatedHooks = {};
|
|
101
59
|
this.hook = this.hook.bind(this);
|
|
102
60
|
this.callHook = this.callHook.bind(this);
|
|
103
61
|
this.callHookWith = this.callHookWith.bind(this);
|
|
104
62
|
}
|
|
105
|
-
hook(name,
|
|
106
|
-
if (!name || typeof
|
|
63
|
+
hook(name, function_, options = {}) {
|
|
64
|
+
if (!name || typeof function_ !== "function") {
|
|
107
65
|
return () => {
|
|
108
66
|
};
|
|
109
67
|
}
|
|
@@ -113,7 +71,7 @@ class Hookable {
|
|
|
113
71
|
dep = this._deprecatedHooks[name];
|
|
114
72
|
name = dep.to;
|
|
115
73
|
}
|
|
116
|
-
if (dep && !
|
|
74
|
+
if (dep && !options.allowDeprecated) {
|
|
117
75
|
let message = dep.message;
|
|
118
76
|
if (!message) {
|
|
119
77
|
message = `${originalName} hook has been deprecated` + (dep.to ? `, please use ${dep.to}` : "");
|
|
@@ -127,30 +85,32 @@ class Hookable {
|
|
|
127
85
|
}
|
|
128
86
|
}
|
|
129
87
|
this._hooks[name] = this._hooks[name] || [];
|
|
130
|
-
this._hooks[name].push(
|
|
88
|
+
this._hooks[name].push(function_);
|
|
131
89
|
return () => {
|
|
132
|
-
if (
|
|
133
|
-
this.removeHook(name,
|
|
134
|
-
|
|
90
|
+
if (function_) {
|
|
91
|
+
this.removeHook(name, function_);
|
|
92
|
+
function_ = void 0;
|
|
135
93
|
}
|
|
136
94
|
};
|
|
137
95
|
}
|
|
138
|
-
hookOnce(name,
|
|
96
|
+
hookOnce(name, function_) {
|
|
139
97
|
let _unreg;
|
|
140
|
-
let
|
|
141
|
-
_unreg
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
98
|
+
let _function = (...arguments_) => {
|
|
99
|
+
if (typeof _unreg === "function") {
|
|
100
|
+
_unreg();
|
|
101
|
+
}
|
|
102
|
+
_unreg = void 0;
|
|
103
|
+
_function = void 0;
|
|
104
|
+
return function_(...arguments_);
|
|
145
105
|
};
|
|
146
|
-
_unreg = this.hook(name,
|
|
106
|
+
_unreg = this.hook(name, _function);
|
|
147
107
|
return _unreg;
|
|
148
108
|
}
|
|
149
|
-
removeHook(name,
|
|
109
|
+
removeHook(name, function_) {
|
|
150
110
|
if (this._hooks[name]) {
|
|
151
|
-
const
|
|
152
|
-
if (
|
|
153
|
-
this._hooks[name].splice(
|
|
111
|
+
const index = this._hooks[name].indexOf(function_);
|
|
112
|
+
if (index !== -1) {
|
|
113
|
+
this._hooks[name].splice(index, 1);
|
|
154
114
|
}
|
|
155
115
|
if (this._hooks[name].length === 0) {
|
|
156
116
|
delete this._hooks[name];
|
|
@@ -175,7 +135,9 @@ class Hookable {
|
|
|
175
135
|
const hooks = flatHooks(configHooks);
|
|
176
136
|
const removeFns = Object.keys(hooks).map((key) => this.hook(key, hooks[key]));
|
|
177
137
|
return () => {
|
|
178
|
-
removeFns.splice(0, removeFns.length)
|
|
138
|
+
for (const unreg of removeFns.splice(0, removeFns.length)) {
|
|
139
|
+
unreg();
|
|
140
|
+
}
|
|
179
141
|
};
|
|
180
142
|
}
|
|
181
143
|
removeHooks(configHooks) {
|
|
@@ -184,45 +146,45 @@ class Hookable {
|
|
|
184
146
|
this.removeHook(key, hooks[key]);
|
|
185
147
|
}
|
|
186
148
|
}
|
|
187
|
-
callHook(name, ...
|
|
188
|
-
return this.callHookWith(serialCaller, name, ...
|
|
149
|
+
callHook(name, ...arguments_) {
|
|
150
|
+
return this.callHookWith(serialCaller, name, ...arguments_);
|
|
189
151
|
}
|
|
190
|
-
callHookParallel(name, ...
|
|
191
|
-
return this.callHookWith(parallelCaller, name, ...
|
|
152
|
+
callHookParallel(name, ...arguments_) {
|
|
153
|
+
return this.callHookWith(parallelCaller, name, ...arguments_);
|
|
192
154
|
}
|
|
193
|
-
callHookWith(caller, name, ...
|
|
194
|
-
const event = this._before || this._after ? { name, args, context: {} } : void 0;
|
|
155
|
+
callHookWith(caller, name, ...arguments_) {
|
|
156
|
+
const event = this._before || this._after ? { name, args: arguments_, context: {} } : void 0;
|
|
195
157
|
if (this._before) {
|
|
196
158
|
callEachWith(this._before, event);
|
|
197
159
|
}
|
|
198
|
-
const result = caller(this._hooks[name] || [],
|
|
160
|
+
const result = caller(this._hooks[name] || [], arguments_);
|
|
199
161
|
if (result instanceof Promise) {
|
|
200
162
|
return result.finally(() => {
|
|
201
|
-
if (this._after) {
|
|
163
|
+
if (this._after && event) {
|
|
202
164
|
callEachWith(this._after, event);
|
|
203
165
|
}
|
|
204
166
|
});
|
|
205
167
|
}
|
|
206
|
-
if (this._after) {
|
|
168
|
+
if (this._after && event) {
|
|
207
169
|
callEachWith(this._after, event);
|
|
208
170
|
}
|
|
209
171
|
return result;
|
|
210
172
|
}
|
|
211
|
-
beforeEach(
|
|
173
|
+
beforeEach(function_) {
|
|
212
174
|
this._before = this._before || [];
|
|
213
|
-
this._before.push(
|
|
175
|
+
this._before.push(function_);
|
|
214
176
|
return () => {
|
|
215
|
-
const index = this._before.indexOf(
|
|
177
|
+
const index = this._before.indexOf(function_);
|
|
216
178
|
if (index !== -1) {
|
|
217
179
|
this._before.splice(index, 1);
|
|
218
180
|
}
|
|
219
181
|
};
|
|
220
182
|
}
|
|
221
|
-
afterEach(
|
|
183
|
+
afterEach(function_) {
|
|
222
184
|
this._after = this._after || [];
|
|
223
|
-
this._after.push(
|
|
185
|
+
this._after.push(function_);
|
|
224
186
|
return () => {
|
|
225
|
-
const index = this._after.indexOf(
|
|
187
|
+
const index = this._after.indexOf(function_);
|
|
226
188
|
if (index !== -1) {
|
|
227
189
|
this._after.splice(index, 1);
|
|
228
190
|
}
|
|
@@ -233,6 +195,52 @@ function createHooks() {
|
|
|
233
195
|
return new Hookable();
|
|
234
196
|
}
|
|
235
197
|
|
|
198
|
+
const isBrowser = typeof window !== "undefined";
|
|
199
|
+
function createDebugger(hooks, _options = {}) {
|
|
200
|
+
const options = {
|
|
201
|
+
inspect: isBrowser,
|
|
202
|
+
group: isBrowser,
|
|
203
|
+
filter: () => true,
|
|
204
|
+
..._options
|
|
205
|
+
};
|
|
206
|
+
const _filter = options.filter;
|
|
207
|
+
const filter = typeof _filter === "string" ? (name) => name.startsWith(_filter) : _filter;
|
|
208
|
+
const _tag = options.tag ? `[${options.tag}] ` : "";
|
|
209
|
+
const logPrefix = (event) => _tag + event.name + "".padEnd(event._id, "\0");
|
|
210
|
+
const _idCtr = {};
|
|
211
|
+
const unsubscribeBefore = hooks.beforeEach((event) => {
|
|
212
|
+
if (!filter(event.name)) {
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
_idCtr[event.name] = _idCtr[event.name] || 0;
|
|
216
|
+
event._id = _idCtr[event.name]++;
|
|
217
|
+
console.time(logPrefix(event));
|
|
218
|
+
});
|
|
219
|
+
const unsubscribeAfter = hooks.afterEach((event) => {
|
|
220
|
+
if (!filter(event.name)) {
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
if (options.group) {
|
|
224
|
+
console.groupCollapsed(event.name);
|
|
225
|
+
}
|
|
226
|
+
if (options.inspect) {
|
|
227
|
+
console.timeLog(logPrefix(event), event.args);
|
|
228
|
+
} else {
|
|
229
|
+
console.timeEnd(logPrefix(event));
|
|
230
|
+
}
|
|
231
|
+
if (options.group) {
|
|
232
|
+
console.groupEnd();
|
|
233
|
+
}
|
|
234
|
+
_idCtr[event.name]--;
|
|
235
|
+
});
|
|
236
|
+
return {
|
|
237
|
+
close: () => {
|
|
238
|
+
unsubscribeBefore();
|
|
239
|
+
unsubscribeAfter();
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
|
|
236
244
|
exports.Hookable = Hookable;
|
|
237
245
|
exports.createDebugger = createDebugger;
|
|
238
246
|
exports.createHooks = createHooks;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
declare type HookCallback = (...
|
|
1
|
+
declare type HookCallback = (...arguments_: any) => Promise<void> | void;
|
|
2
2
|
interface Hooks {
|
|
3
3
|
[key: string]: HookCallback;
|
|
4
4
|
}
|
|
@@ -34,24 +34,6 @@ declare type NestedHooks<T> = (Partial<StripGeneric<T>> | Partial<OnlyGeneric<T>
|
|
|
34
34
|
}> & Partial<{
|
|
35
35
|
[key in BareHooks<StripGeneric<T>>]: T[key];
|
|
36
36
|
}>;
|
|
37
|
-
interface CreateDebuggerOptions {
|
|
38
|
-
/** An optional tag to prefix console logs with */
|
|
39
|
-
tag?: string;
|
|
40
|
-
/**
|
|
41
|
-
* Show hook params to the console output
|
|
42
|
-
*
|
|
43
|
-
* Enabled for browsers by default
|
|
44
|
-
*/
|
|
45
|
-
inspect?: boolean;
|
|
46
|
-
/**
|
|
47
|
-
* Use group/groupEnd wrapper around logs happening during a specific hook
|
|
48
|
-
*
|
|
49
|
-
* Enabled for browsers by default
|
|
50
|
-
*/
|
|
51
|
-
group?: boolean;
|
|
52
|
-
/** Filter which hooks to enable debugger for. Can be a string prefix or fn. */
|
|
53
|
-
filter?: string | ((event: string) => boolean);
|
|
54
|
-
}
|
|
55
37
|
|
|
56
38
|
declare type InferCallback<HT, HN extends keyof HT> = HT[HN] extends HookCallback ? HT[HN] : never;
|
|
57
39
|
declare type InferSpyEvent<HT extends Record<string, any>> = {
|
|
@@ -68,30 +50,49 @@ declare class Hookable<HooksT = Record<string, HookCallback>, HookNameT extends
|
|
|
68
50
|
private _deprecatedHooks;
|
|
69
51
|
private _deprecatedMessages;
|
|
70
52
|
constructor();
|
|
71
|
-
hook<NameT extends HookNameT>(name: NameT,
|
|
53
|
+
hook<NameT extends HookNameT>(name: NameT, function_: InferCallback<HooksT, NameT>, options?: {
|
|
72
54
|
allowDeprecated?: boolean;
|
|
73
55
|
}): () => void;
|
|
74
|
-
hookOnce<NameT extends HookNameT>(name: NameT,
|
|
75
|
-
removeHook<NameT extends HookNameT>(name: NameT,
|
|
56
|
+
hookOnce<NameT extends HookNameT>(name: NameT, function_: InferCallback<HooksT, NameT>): () => void;
|
|
57
|
+
removeHook<NameT extends HookNameT>(name: NameT, function_: InferCallback<HooksT, NameT>): void;
|
|
76
58
|
deprecateHook<NameT extends HookNameT>(name: NameT, deprecated: HookKeys<HooksT> | DeprecatedHook<HooksT>): void;
|
|
77
59
|
deprecateHooks(deprecatedHooks: Partial<Record<HookNameT, DeprecatedHook<HooksT>>>): void;
|
|
78
60
|
addHooks(configHooks: NestedHooks<HooksT>): () => void;
|
|
79
61
|
removeHooks(configHooks: NestedHooks<HooksT>): void;
|
|
80
|
-
callHook<NameT extends HookNameT>(name: NameT, ...
|
|
81
|
-
callHookParallel<NameT extends HookNameT>(name: NameT, ...
|
|
82
|
-
callHookWith<NameT extends HookNameT, CallFunction extends (hooks: HookCallback[],
|
|
83
|
-
beforeEach(
|
|
84
|
-
afterEach(
|
|
62
|
+
callHook<NameT extends HookNameT>(name: NameT, ...arguments_: Parameters<InferCallback<HooksT, NameT>>): Promise<any>;
|
|
63
|
+
callHookParallel<NameT extends HookNameT>(name: NameT, ...arguments_: Parameters<InferCallback<HooksT, NameT>>): Promise<any[]>;
|
|
64
|
+
callHookWith<NameT extends HookNameT, CallFunction extends (hooks: HookCallback[], arguments_: Parameters<InferCallback<HooksT, NameT>>) => any>(caller: CallFunction, name: NameT, ...arguments_: Parameters<InferCallback<HooksT, NameT>>): ReturnType<CallFunction>;
|
|
65
|
+
beforeEach(function_: (event: InferSpyEvent<HooksT>) => void): () => void;
|
|
66
|
+
afterEach(function_: (event: InferSpyEvent<HooksT>) => void): () => void;
|
|
85
67
|
}
|
|
86
68
|
declare function createHooks<T>(): Hookable<T>;
|
|
87
69
|
|
|
88
70
|
declare function flatHooks<T>(configHooks: NestedHooks<T>, hooks?: T, parentName?: string): T;
|
|
89
71
|
declare function mergeHooks<T>(...hooks: NestedHooks<T>[]): T;
|
|
90
|
-
declare function serial<T>(tasks: T[],
|
|
91
|
-
declare function serialCaller(hooks: HookCallback[],
|
|
92
|
-
declare function parallelCaller(hooks: HookCallback[],
|
|
72
|
+
declare function serial<T>(tasks: T[], function_: (task: T) => Promise<any> | any): Promise<any>;
|
|
73
|
+
declare function serialCaller(hooks: HookCallback[], arguments_?: any[]): Promise<any>;
|
|
74
|
+
declare function parallelCaller(hooks: HookCallback[], arguments_?: any[]): Promise<any[]>;
|
|
75
|
+
|
|
76
|
+
interface CreateDebuggerOptions {
|
|
77
|
+
/** An optional tag to prefix console logs with */
|
|
78
|
+
tag?: string;
|
|
79
|
+
/**
|
|
80
|
+
* Show hook params to the console output
|
|
81
|
+
*
|
|
82
|
+
* Enabled for browsers by default
|
|
83
|
+
*/
|
|
84
|
+
inspect?: boolean;
|
|
85
|
+
/**
|
|
86
|
+
* Use group/groupEnd wrapper around logs happening during a specific hook
|
|
87
|
+
*
|
|
88
|
+
* Enabled for browsers by default
|
|
89
|
+
*/
|
|
90
|
+
group?: boolean;
|
|
91
|
+
/** Filter which hooks to enable debugger for. Can be a string prefix or fn. */
|
|
92
|
+
filter?: string | ((event: string) => boolean);
|
|
93
|
+
}
|
|
93
94
|
/** Start debugging hook names and timing in console */
|
|
94
|
-
declare function createDebugger(hooks: Hookable
|
|
95
|
+
declare function createDebugger(hooks: Hookable<any>, _options?: CreateDebuggerOptions): {
|
|
95
96
|
/** Stop debugging and remove listeners */
|
|
96
97
|
close: () => void;
|
|
97
98
|
};
|
package/dist/index.mjs
CHANGED
|
@@ -24,82 +24,42 @@ function mergeHooks(...hooks) {
|
|
|
24
24
|
}
|
|
25
25
|
for (const key in finalHooks) {
|
|
26
26
|
if (finalHooks[key].length > 1) {
|
|
27
|
-
const
|
|
28
|
-
finalHooks[key] = (...
|
|
27
|
+
const array = finalHooks[key];
|
|
28
|
+
finalHooks[key] = (...arguments_) => serial(array, (function_) => function_(...arguments_));
|
|
29
29
|
} else {
|
|
30
30
|
finalHooks[key] = finalHooks[key][0];
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
return finalHooks;
|
|
34
34
|
}
|
|
35
|
-
function serial(tasks,
|
|
36
|
-
return tasks.reduce((promise, task) => promise.then(() =>
|
|
35
|
+
function serial(tasks, function_) {
|
|
36
|
+
return tasks.reduce((promise, task) => promise.then(() => function_(task)), Promise.resolve());
|
|
37
37
|
}
|
|
38
|
-
function serialCaller(hooks,
|
|
39
|
-
return hooks.reduce((promise,
|
|
38
|
+
function serialCaller(hooks, arguments_) {
|
|
39
|
+
return hooks.reduce((promise, hookFunction) => promise.then(() => hookFunction.apply(void 0, arguments_)), Promise.resolve());
|
|
40
40
|
}
|
|
41
|
-
function parallelCaller(hooks,
|
|
42
|
-
return Promise.all(hooks.map((hook) => hook.apply(void 0,
|
|
41
|
+
function parallelCaller(hooks, arguments_) {
|
|
42
|
+
return Promise.all(hooks.map((hook) => hook.apply(void 0, arguments_)));
|
|
43
43
|
}
|
|
44
|
-
function callEachWith(callbacks,
|
|
45
|
-
for (const
|
|
46
|
-
|
|
44
|
+
function callEachWith(callbacks, argument0) {
|
|
45
|
+
for (const callback of callbacks) {
|
|
46
|
+
callback(argument0);
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
|
-
const isBrowser = typeof window !== "undefined";
|
|
50
|
-
function createDebugger(hooks, _options = {}) {
|
|
51
|
-
const options = {
|
|
52
|
-
inspect: isBrowser,
|
|
53
|
-
group: isBrowser,
|
|
54
|
-
filter: () => true,
|
|
55
|
-
..._options
|
|
56
|
-
};
|
|
57
|
-
const _filter = options.filter;
|
|
58
|
-
const filter = typeof _filter === "string" ? (name) => name.startsWith(_filter) : _filter;
|
|
59
|
-
const logPrefix = options.tag ? `[${options.tag}] ` : "";
|
|
60
|
-
const unsubscribeBefore = hooks.beforeEach(({ name }) => {
|
|
61
|
-
if (!filter(name)) {
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
console.time(logPrefix + name);
|
|
65
|
-
});
|
|
66
|
-
const unsubscribeAfter = hooks.afterEach(({ name, args }) => {
|
|
67
|
-
if (!filter(name)) {
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
if (options.group) {
|
|
71
|
-
console.groupCollapsed(name);
|
|
72
|
-
}
|
|
73
|
-
if (options.inspect) {
|
|
74
|
-
console.timeLog(logPrefix + name, args);
|
|
75
|
-
} else {
|
|
76
|
-
console.timeEnd(logPrefix + name);
|
|
77
|
-
}
|
|
78
|
-
if (options.group) {
|
|
79
|
-
console.groupEnd();
|
|
80
|
-
}
|
|
81
|
-
});
|
|
82
|
-
return {
|
|
83
|
-
close: () => {
|
|
84
|
-
unsubscribeBefore();
|
|
85
|
-
unsubscribeAfter();
|
|
86
|
-
}
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
49
|
|
|
90
50
|
class Hookable {
|
|
91
51
|
constructor() {
|
|
92
52
|
this._hooks = {};
|
|
93
|
-
this._before =
|
|
94
|
-
this._after =
|
|
95
|
-
this._deprecatedMessages =
|
|
53
|
+
this._before = void 0;
|
|
54
|
+
this._after = void 0;
|
|
55
|
+
this._deprecatedMessages = void 0;
|
|
96
56
|
this._deprecatedHooks = {};
|
|
97
57
|
this.hook = this.hook.bind(this);
|
|
98
58
|
this.callHook = this.callHook.bind(this);
|
|
99
59
|
this.callHookWith = this.callHookWith.bind(this);
|
|
100
60
|
}
|
|
101
|
-
hook(name,
|
|
102
|
-
if (!name || typeof
|
|
61
|
+
hook(name, function_, options = {}) {
|
|
62
|
+
if (!name || typeof function_ !== "function") {
|
|
103
63
|
return () => {
|
|
104
64
|
};
|
|
105
65
|
}
|
|
@@ -109,7 +69,7 @@ class Hookable {
|
|
|
109
69
|
dep = this._deprecatedHooks[name];
|
|
110
70
|
name = dep.to;
|
|
111
71
|
}
|
|
112
|
-
if (dep && !
|
|
72
|
+
if (dep && !options.allowDeprecated) {
|
|
113
73
|
let message = dep.message;
|
|
114
74
|
if (!message) {
|
|
115
75
|
message = `${originalName} hook has been deprecated` + (dep.to ? `, please use ${dep.to}` : "");
|
|
@@ -123,30 +83,32 @@ class Hookable {
|
|
|
123
83
|
}
|
|
124
84
|
}
|
|
125
85
|
this._hooks[name] = this._hooks[name] || [];
|
|
126
|
-
this._hooks[name].push(
|
|
86
|
+
this._hooks[name].push(function_);
|
|
127
87
|
return () => {
|
|
128
|
-
if (
|
|
129
|
-
this.removeHook(name,
|
|
130
|
-
|
|
88
|
+
if (function_) {
|
|
89
|
+
this.removeHook(name, function_);
|
|
90
|
+
function_ = void 0;
|
|
131
91
|
}
|
|
132
92
|
};
|
|
133
93
|
}
|
|
134
|
-
hookOnce(name,
|
|
94
|
+
hookOnce(name, function_) {
|
|
135
95
|
let _unreg;
|
|
136
|
-
let
|
|
137
|
-
_unreg
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
96
|
+
let _function = (...arguments_) => {
|
|
97
|
+
if (typeof _unreg === "function") {
|
|
98
|
+
_unreg();
|
|
99
|
+
}
|
|
100
|
+
_unreg = void 0;
|
|
101
|
+
_function = void 0;
|
|
102
|
+
return function_(...arguments_);
|
|
141
103
|
};
|
|
142
|
-
_unreg = this.hook(name,
|
|
104
|
+
_unreg = this.hook(name, _function);
|
|
143
105
|
return _unreg;
|
|
144
106
|
}
|
|
145
|
-
removeHook(name,
|
|
107
|
+
removeHook(name, function_) {
|
|
146
108
|
if (this._hooks[name]) {
|
|
147
|
-
const
|
|
148
|
-
if (
|
|
149
|
-
this._hooks[name].splice(
|
|
109
|
+
const index = this._hooks[name].indexOf(function_);
|
|
110
|
+
if (index !== -1) {
|
|
111
|
+
this._hooks[name].splice(index, 1);
|
|
150
112
|
}
|
|
151
113
|
if (this._hooks[name].length === 0) {
|
|
152
114
|
delete this._hooks[name];
|
|
@@ -171,7 +133,9 @@ class Hookable {
|
|
|
171
133
|
const hooks = flatHooks(configHooks);
|
|
172
134
|
const removeFns = Object.keys(hooks).map((key) => this.hook(key, hooks[key]));
|
|
173
135
|
return () => {
|
|
174
|
-
removeFns.splice(0, removeFns.length)
|
|
136
|
+
for (const unreg of removeFns.splice(0, removeFns.length)) {
|
|
137
|
+
unreg();
|
|
138
|
+
}
|
|
175
139
|
};
|
|
176
140
|
}
|
|
177
141
|
removeHooks(configHooks) {
|
|
@@ -180,45 +144,45 @@ class Hookable {
|
|
|
180
144
|
this.removeHook(key, hooks[key]);
|
|
181
145
|
}
|
|
182
146
|
}
|
|
183
|
-
callHook(name, ...
|
|
184
|
-
return this.callHookWith(serialCaller, name, ...
|
|
147
|
+
callHook(name, ...arguments_) {
|
|
148
|
+
return this.callHookWith(serialCaller, name, ...arguments_);
|
|
185
149
|
}
|
|
186
|
-
callHookParallel(name, ...
|
|
187
|
-
return this.callHookWith(parallelCaller, name, ...
|
|
150
|
+
callHookParallel(name, ...arguments_) {
|
|
151
|
+
return this.callHookWith(parallelCaller, name, ...arguments_);
|
|
188
152
|
}
|
|
189
|
-
callHookWith(caller, name, ...
|
|
190
|
-
const event = this._before || this._after ? { name, args, context: {} } : void 0;
|
|
153
|
+
callHookWith(caller, name, ...arguments_) {
|
|
154
|
+
const event = this._before || this._after ? { name, args: arguments_, context: {} } : void 0;
|
|
191
155
|
if (this._before) {
|
|
192
156
|
callEachWith(this._before, event);
|
|
193
157
|
}
|
|
194
|
-
const result = caller(this._hooks[name] || [],
|
|
158
|
+
const result = caller(this._hooks[name] || [], arguments_);
|
|
195
159
|
if (result instanceof Promise) {
|
|
196
160
|
return result.finally(() => {
|
|
197
|
-
if (this._after) {
|
|
161
|
+
if (this._after && event) {
|
|
198
162
|
callEachWith(this._after, event);
|
|
199
163
|
}
|
|
200
164
|
});
|
|
201
165
|
}
|
|
202
|
-
if (this._after) {
|
|
166
|
+
if (this._after && event) {
|
|
203
167
|
callEachWith(this._after, event);
|
|
204
168
|
}
|
|
205
169
|
return result;
|
|
206
170
|
}
|
|
207
|
-
beforeEach(
|
|
171
|
+
beforeEach(function_) {
|
|
208
172
|
this._before = this._before || [];
|
|
209
|
-
this._before.push(
|
|
173
|
+
this._before.push(function_);
|
|
210
174
|
return () => {
|
|
211
|
-
const index = this._before.indexOf(
|
|
175
|
+
const index = this._before.indexOf(function_);
|
|
212
176
|
if (index !== -1) {
|
|
213
177
|
this._before.splice(index, 1);
|
|
214
178
|
}
|
|
215
179
|
};
|
|
216
180
|
}
|
|
217
|
-
afterEach(
|
|
181
|
+
afterEach(function_) {
|
|
218
182
|
this._after = this._after || [];
|
|
219
|
-
this._after.push(
|
|
183
|
+
this._after.push(function_);
|
|
220
184
|
return () => {
|
|
221
|
-
const index = this._after.indexOf(
|
|
185
|
+
const index = this._after.indexOf(function_);
|
|
222
186
|
if (index !== -1) {
|
|
223
187
|
this._after.splice(index, 1);
|
|
224
188
|
}
|
|
@@ -229,4 +193,50 @@ function createHooks() {
|
|
|
229
193
|
return new Hookable();
|
|
230
194
|
}
|
|
231
195
|
|
|
196
|
+
const isBrowser = typeof window !== "undefined";
|
|
197
|
+
function createDebugger(hooks, _options = {}) {
|
|
198
|
+
const options = {
|
|
199
|
+
inspect: isBrowser,
|
|
200
|
+
group: isBrowser,
|
|
201
|
+
filter: () => true,
|
|
202
|
+
..._options
|
|
203
|
+
};
|
|
204
|
+
const _filter = options.filter;
|
|
205
|
+
const filter = typeof _filter === "string" ? (name) => name.startsWith(_filter) : _filter;
|
|
206
|
+
const _tag = options.tag ? `[${options.tag}] ` : "";
|
|
207
|
+
const logPrefix = (event) => _tag + event.name + "".padEnd(event._id, "\0");
|
|
208
|
+
const _idCtr = {};
|
|
209
|
+
const unsubscribeBefore = hooks.beforeEach((event) => {
|
|
210
|
+
if (!filter(event.name)) {
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
_idCtr[event.name] = _idCtr[event.name] || 0;
|
|
214
|
+
event._id = _idCtr[event.name]++;
|
|
215
|
+
console.time(logPrefix(event));
|
|
216
|
+
});
|
|
217
|
+
const unsubscribeAfter = hooks.afterEach((event) => {
|
|
218
|
+
if (!filter(event.name)) {
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
if (options.group) {
|
|
222
|
+
console.groupCollapsed(event.name);
|
|
223
|
+
}
|
|
224
|
+
if (options.inspect) {
|
|
225
|
+
console.timeLog(logPrefix(event), event.args);
|
|
226
|
+
} else {
|
|
227
|
+
console.timeEnd(logPrefix(event));
|
|
228
|
+
}
|
|
229
|
+
if (options.group) {
|
|
230
|
+
console.groupEnd();
|
|
231
|
+
}
|
|
232
|
+
_idCtr[event.name]--;
|
|
233
|
+
});
|
|
234
|
+
return {
|
|
235
|
+
close: () => {
|
|
236
|
+
unsubscribeBefore();
|
|
237
|
+
unsubscribeAfter();
|
|
238
|
+
}
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
|
|
232
242
|
export { Hookable, createDebugger, createHooks, flatHooks, mergeHooks, parallelCaller, serial, serialCaller };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hookable",
|
|
3
|
-
"version": "5.4.
|
|
3
|
+
"version": "5.4.2",
|
|
4
4
|
"description": "Awaitable hook system",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"hook",
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
"license": "MIT",
|
|
14
14
|
"exports": {
|
|
15
15
|
"import": "./dist/index.mjs",
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
16
17
|
"require": "./dist/index.cjs"
|
|
17
18
|
},
|
|
18
19
|
"main": "./dist/index.cjs",
|
|
@@ -22,16 +23,16 @@
|
|
|
22
23
|
"dist"
|
|
23
24
|
],
|
|
24
25
|
"devDependencies": {
|
|
25
|
-
"@
|
|
26
|
-
"
|
|
27
|
-
"eslint": "
|
|
28
|
-
"expect-type": "^0.
|
|
29
|
-
"standard-version": "
|
|
30
|
-
"typescript": "
|
|
31
|
-
"unbuild": "
|
|
32
|
-
"vitest": "
|
|
26
|
+
"@vitest/coverage-c8": "^0.25.2",
|
|
27
|
+
"eslint": "^8.27.0",
|
|
28
|
+
"eslint-config-unjs": "^0.0.2",
|
|
29
|
+
"expect-type": "^0.15.0",
|
|
30
|
+
"standard-version": "^9.5.0",
|
|
31
|
+
"typescript": "^4.8.4",
|
|
32
|
+
"unbuild": "^0.9.4",
|
|
33
|
+
"vitest": "^0.25.2"
|
|
33
34
|
},
|
|
34
|
-
"packageManager": "pnpm@7.
|
|
35
|
+
"packageManager": "pnpm@7.16.0",
|
|
35
36
|
"scripts": {
|
|
36
37
|
"build": "unbuild",
|
|
37
38
|
"dev": "vitest",
|