Instrumentation hooks
Tap into console, fetch, XMLHttpRequest, clicks, and uncaught errors, for a monitoring
backend, a debug overlay, or tests.
Every one of them returns a teardown function. Keep it and call it. Instrumenting a global with no way to undo it means tests cannot clean up after themselves, and a hot reload re-patches an already-patched global until each call is nested through a dozen wrappers and every event is reported N times.
API
| Function | Instruments | Returns |
|---|---|---|
handleConsole(hook) |
console.log/info/warn/error/assert |
restore |
handleFetchHook(options) |
window.fetch |
restore |
handleXhrHook(options) |
XMLHttpRequest#open / #send |
restore |
handleError(hook) |
error + unhandledrejection |
unsubscribe |
handleClick(hook) |
document clicks (capture phase) | unsubscribe |
replaceOld(obj, key, wrap) |
any property on any object | restore |
handleFetchHook / handleXhrHook take { requestHook, responseHook, errorHook }.
Example
import { handleConsole, handleError, handleFetchHook } from 'ranuts';
const teardown = [
handleConsole((type, ...args) => send({ type, args })),
handleError((error) => send({ type: 'error', error: String(error) })),
handleFetchHook({ errorHook: (url, error) => send({ type: 'fetchError', url }) }),
];
// on teardown (HMR, route change, test cleanup)
teardown.forEach((off) => off());Notes
- Original behaviour is preserved. Responses pass through, errors are re-thrown, console output still prints.
replaceOld's restore only undoes its own patch. If another layer patched on top afterwards, restoring blindly would silently uninstall that layer, so it declines instead.handleXhrHookpatches the prototype, so it applies to every instance; its listeners are registered with{ once: true }so a reused XHR object does not accumulate them.- Do not report console output to a console-logging backend: the hook fires on the very
call it produces. (This is why
Monitor'sconsolechannel is off by default.)