/
hook.js
61 lines (53 loc) · 1.58 KB
/
hook.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import funHooks from 'fun-hooks/no-eval/index.js';
import {defer} from './utils/promise.js';
export let hook = funHooks({
ready: funHooks.SYNC | funHooks.ASYNC | funHooks.QUEUE
});
const readyCtl = defer();
hook.ready = (() => {
const ready = hook.ready;
return function () {
try {
return ready.apply(hook, arguments);
} finally {
readyCtl.resolve();
}
}
})();
/**
* A promise that resolves when hooks are ready.
* @type {Promise}
*/
export const ready = readyCtl.promise;
export const getHook = hook.get;
export function setupBeforeHookFnOnce(baseFn, hookFn, priority = 15) {
let result = baseFn.getHooks({hook: hookFn});
if (result.length === 0) {
baseFn.before(hookFn, priority);
}
}
const submoduleInstallMap = {};
export function module(name, install, {postInstallAllowed = false} = {}) {
hook('async', function (submodules) {
submodules.forEach(args => install(...args));
if (postInstallAllowed) submoduleInstallMap[name] = install;
}, name)([]); // will be queued until hook.ready() called in pbjs.processQueue();
}
export function submodule(name, ...args) {
const install = submoduleInstallMap[name];
if (install) return install(...args);
getHook(name).before((next, modules) => {
modules.push(args);
next(modules);
});
}
/**
* Copy hook methods (.before, .after, etc) from a given hook to a given wrapper object.
*/
export function wrapHook(hook, wrapper) {
Object.defineProperties(
wrapper,
Object.fromEntries(['before', 'after', 'getHooks', 'removeAll'].map((m) => [m, {get: () => hook[m]}]))
);
return wrapper;
}