UNPKG

@graphql-mesh/utils

Version:
86 lines (85 loc) 3.42 kB
import { getInstrumented } from '@envelop/instrumentation'; import { handleMaybePromise, iterateAsync } from '@whatwg-node/promise-helpers'; import { DefaultLogger } from './logger.js'; export const requestIdByRequest = new WeakMap(); export const loggerForExecutionRequest = new WeakMap(); export function wrapFetchWithHooks(onFetchHooks, instrumentation, defaultLogger) { let wrappedFetchFn = function wrappedFetchFn(url, options, context, info) { let fetchFn; let response$; const onFetchDoneHooks = []; return handleMaybePromise(() => iterateAsync(onFetchHooks, (onFetch, endEarly) => onFetch({ fetchFn, setFetchFn(newFetchFn) { fetchFn = newFetchFn; }, url, setURL(newUrl) { url = String(newUrl); }, options, setOptions(newOptions) { options = newOptions; }, context, info, get executionRequest() { return info?.executionRequest; }, get requestId() { if (context?.request) { return requestIdByRequest.get(context.request); } }, get logger() { let logger; if (info?.executionRequest) { logger = loggerForExecutionRequest.get(info.executionRequest); } if (!logger) { logger = defaultLogger?.child('fetch') || new DefaultLogger('fetch'); } if (context?.request) { const requestId = requestIdByRequest.get(context.request); if (requestId) { logger = logger.child({ requestId }); } } if (info?.executionRequest) { loggerForExecutionRequest.set(info.executionRequest, logger); } return logger; }, endResponse(newResponse) { response$ = newResponse; endEarly(); }, }), onFetchDoneHooks), function handleIterationResult() { return handleMaybePromise(() => response$ || fetchFn(url, options, context, info), function (response) { return handleMaybePromise(() => iterateAsync(onFetchDoneHooks, onFetchDone => onFetchDone({ response, setResponse(newResponse) { response = newResponse; }, })), function handleOnFetchDone() { return response; }); }); }); }; if (instrumentation) { const originalWrappedFetch = wrappedFetchFn; wrappedFetchFn = function wrappedFetchFn(url, options, context, info) { const fetchInstrument = instrumentation()?.fetch; const instrumentedFetch = fetchInstrument ? getInstrumented({ get executionRequest() { return info?.executionRequest; }, }).asyncFn(fetchInstrument, originalWrappedFetch) : originalWrappedFetch; return instrumentedFetch(url, options, context, info); }; } return wrappedFetchFn; }