@graphql-mesh/utils
Version:
86 lines (85 loc) • 3.42 kB
JavaScript
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;
}