Skip to content

Commit aa922f6

Browse files
committed
chore: better error logging on prepareRunHook
1 parent babf546 commit aa922f6

File tree

1 file changed

+85
-79
lines changed

1 file changed

+85
-79
lines changed

src/utils/prepareRunHook.ts

Lines changed: 85 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -3,104 +3,110 @@ import createReadOnlyProxy from './createReadOnlyProxy';
33

44
// TODO: How do we get types to the user when they are writing plugins, etc?
55
function prepareRunHook({ hooks, allSupportedHooks, settings }) {
6+
// eslint-disable-next-line consistent-return
67
return async function processHook(hookName, props: any = {}) {
7-
if (props.perf) props.perf.start(`hook.${hookName}`);
8+
try {
9+
if (props.perf) props.perf.start(`hook.${hookName}`);
810

9-
// do we have a contract for the hook
10-
const hookDefinition = allSupportedHooks.find((h) => h.hook === hookName);
11-
if (!hookDefinition) {
12-
throw new Error(`Hook ${hookName} not defined in hookInterface or via plugins.`);
13-
}
11+
// do we have a contract for the hook
12+
const hookDefinition = allSupportedHooks.find((h) => h.hook === hookName);
13+
if (!hookDefinition) {
14+
throw new Error(`Hook ${hookName} not defined in hookInterface or via plugins.`);
15+
}
1416

15-
const hookProps = hookDefinition.props.reduce((out, cv) => {
16-
if (cv === 'perf') return out; // perf added and prefixed below
17+
const hookProps = hookDefinition.props.reduce((out, cv) => {
18+
if (cv === 'perf') return out; // perf added and prefixed below
1719

18-
if (Object.hasOwnProperty.call(props, cv)) {
19-
if (!hookDefinition.mutable.includes(cv) && cv !== 'perf') {
20-
out[cv] = createReadOnlyProxy(props[cv], cv, hookName);
20+
if (Object.hasOwnProperty.call(props, cv)) {
21+
if (!hookDefinition.mutable.includes(cv)) {
22+
out[cv] = createReadOnlyProxy(props[cv], cv, hookName);
23+
} else {
24+
out[cv] = props[cv];
25+
}
2126
} else {
22-
out[cv] = props[cv];
27+
console.error(
28+
`Hook named '${hookName}' cannot be run because prop ${cv} is not in scope to pass to the hook. Hook contract broken.`,
29+
);
2330
}
24-
} else {
25-
console.error(
26-
`Hook named '${hookName}' cannot be run because prop ${cv} is not in scope to pass to the hook. Hook contract broken.`,
27-
);
28-
}
2931

30-
return out;
31-
}, {});
32+
return out;
33+
}, {});
3234

33-
const theseHooks = hooks.filter((h) => h.hook === hookName);
34-
if (theseHooks && Array.isArray(theseHooks) && theseHooks.length > 0) {
35-
// higher priority is more important.
36-
const hookList = theseHooks.sort((a, b) => b.priority - a.priority);
35+
const theseHooks = hooks.filter((h) => h.hook === hookName);
36+
if (theseHooks && Array.isArray(theseHooks) && theseHooks.length > 0) {
37+
// higher priority is more important.
38+
const hookList = theseHooks.sort((a, b) => b.priority - a.priority);
3739

38-
if (settings && settings.debug && settings.debug.hooks) {
39-
console.log(`Hooks registered on ${hookName}:`, hookList);
40-
}
40+
if (settings && settings.debug && settings.debug.hooks) {
41+
console.log(`Hooks registered on ${hookName}:`, hookList);
42+
}
4143

42-
const hookOutput = {};
44+
const hookOutput = {};
4345

44-
// loop through the hooks, updating the output and the props in order
45-
await hookList.reduce((p, hook) => {
46-
return p.then(async () => {
47-
if (props.perf) props.perf.start(`hook.${hookName}.${hook.name}`);
48-
try {
49-
let hookResponse = await hook.run({
50-
...hookProps,
51-
perf: props.perf.prefix(`hook.${hookName}.${hook.name}`),
52-
});
46+
// loop through the hooks, updating the output and the props in order
47+
await hookList.reduce((p, hook) => {
48+
return p.then(async () => {
49+
if (props.perf) props.perf.start(`hook.${hookName}.${hook.name}`);
50+
try {
51+
let hookResponse = await hook.run({
52+
...hookProps,
53+
perf: props.perf.prefix(`hook.${hookName}.${hook.name}`),
54+
});
5355

54-
if (!hookResponse) hookResponse = {};
56+
if (!hookResponse) hookResponse = {};
5557

56-
if (settings && settings.debug && settings.debug.hooks) {
57-
console.log(`${hook.name} ran on ${hookName} and returned`, hookResponse);
58+
if (settings && settings.debug && settings.debug.hooks) {
59+
console.log(`${hook.name} ran on ${hookName} and returned`, hookResponse);
60+
}
61+
62+
Object.keys(hookResponse).forEach((key) => {
63+
if (hookDefinition.mutable && hookDefinition.mutable.includes(key)) {
64+
hookOutput[key] = hookResponse[key];
65+
hookProps[key] = hookResponse[key];
66+
} else {
67+
console.error(
68+
`Received attempted mutation on "${hookName}" from "${hook.name}" on the object "${key}". ${key} is not mutable on this hook `,
69+
hook.$$meta,
70+
);
71+
}
72+
});
73+
} catch (e) {
74+
console.error(e);
75+
e.message = `Hook: "${hook.name}" threw an error: ${e.message}`;
76+
props.errors.push(e);
77+
if (hookName === 'buildComplete') console.error(e);
78+
}
79+
if (props.perf) props.perf.end(`hook.${hookName}.${hook.name}`);
80+
});
81+
}, Promise.resolve());
82+
83+
// this actually mutates the props.
84+
if (
85+
Object.keys(hookOutput).length > 0 &&
86+
Array.isArray(hookDefinition.mutable) &&
87+
hookDefinition.mutable.length > 0
88+
) {
89+
hookDefinition.mutable.forEach((key) => {
90+
if ({}.hasOwnProperty.call(hookOutput, key)) {
91+
props[key] = hookOutput[key];
5892
}
93+
});
94+
}
5995

60-
Object.keys(hookResponse).forEach((key) => {
61-
if (hookDefinition.mutable && hookDefinition.mutable.includes(key)) {
62-
hookOutput[key] = hookResponse[key];
63-
hookProps[key] = hookResponse[key];
64-
} else {
65-
console.error(
66-
`Received attempted mutation on "${hookName}" from "${hook.name}" on the object "${key}". ${key} is not mutable on this hook `,
67-
hook.$$meta,
68-
);
69-
}
70-
});
71-
} catch (e) {
72-
e.message = `Hook: "${hook.name}" threw an error: ${e.message}`;
73-
props.errors.push(e);
74-
if (hookName === 'buildComplete') console.error(e);
75-
}
76-
if (props.perf) props.perf.end(`hook.${hookName}.${hook.name}`);
77-
});
78-
}, Promise.resolve());
79-
80-
// this actually mutates the props.
81-
if (
82-
Object.keys(hookOutput).length > 0 &&
83-
Array.isArray(hookDefinition.mutable) &&
84-
hookDefinition.mutable.length > 0
85-
) {
86-
hookDefinition.mutable.forEach((key) => {
87-
if ({}.hasOwnProperty.call(hookOutput, key)) {
88-
props[key] = hookOutput[key];
89-
}
90-
});
91-
}
96+
if (settings && settings.debug && settings.debug.hooks) console.log(`${hookName} finished`);
9297

93-
if (settings && settings.debug && settings.debug.hooks) console.log(`${hookName} finished`);
98+
if (props.perf) props.perf.end(`hook.${hookName}`);
99+
return hookOutput;
100+
}
101+
if (settings && settings.debug && settings.debug.hooks) {
102+
console.log(`${hookName} finished without executing any functions`);
103+
}
94104

95105
if (props.perf) props.perf.end(`hook.${hookName}`);
96-
return hookOutput;
106+
return props;
107+
} catch (e) {
108+
console.error(e);
97109
}
98-
if (settings && settings.debug && settings.debug.hooks) {
99-
console.log(`${hookName} finished without executing any functions`);
100-
}
101-
102-
if (props.perf) props.perf.end(`hook.${hookName}`);
103-
return props;
104110
};
105111
}
106112

0 commit comments

Comments
 (0)