Spaces:
Paused
Paused
File size: 2,460 Bytes
fb4d8fe | 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 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | type FetchWithPreconnect = typeof fetch & {
preconnect: (url: string, init?: { credentials?: RequestCredentials }) => void;
};
type RequestInitWithDuplex = RequestInit & { duplex?: "half" };
function withDuplex(
init: RequestInit | undefined,
input: RequestInfo | URL,
): RequestInit | undefined {
const hasInitBody = init?.body != null;
const hasRequestBody =
!hasInitBody &&
typeof Request !== "undefined" &&
input instanceof Request &&
input.body != null;
if (!hasInitBody && !hasRequestBody) {
return init;
}
if (init && "duplex" in (init as Record<string, unknown>)) {
return init;
}
return init
? ({ ...init, duplex: "half" as const } as RequestInitWithDuplex)
: ({ duplex: "half" as const } as RequestInitWithDuplex);
}
export function wrapFetchWithAbortSignal(fetchImpl: typeof fetch): typeof fetch {
const wrapped = ((input: RequestInfo | URL, init?: RequestInit) => {
const patchedInit = withDuplex(init, input);
const signal = patchedInit?.signal;
if (!signal) {
return fetchImpl(input, patchedInit);
}
if (typeof AbortSignal !== "undefined" && signal instanceof AbortSignal) {
return fetchImpl(input, patchedInit);
}
if (typeof AbortController === "undefined") {
return fetchImpl(input, patchedInit);
}
if (typeof signal.addEventListener !== "function") {
return fetchImpl(input, patchedInit);
}
const controller = new AbortController();
const onAbort = () => controller.abort();
if (signal.aborted) {
controller.abort();
} else {
signal.addEventListener("abort", onAbort, { once: true });
}
const response = fetchImpl(input, { ...patchedInit, signal: controller.signal });
if (typeof signal.removeEventListener === "function") {
void response.finally(() => {
signal.removeEventListener("abort", onAbort);
});
}
return response;
}) as FetchWithPreconnect;
const fetchWithPreconnect = fetchImpl as FetchWithPreconnect;
wrapped.preconnect =
typeof fetchWithPreconnect.preconnect === "function"
? fetchWithPreconnect.preconnect.bind(fetchWithPreconnect)
: () => {};
return Object.assign(wrapped, fetchImpl);
}
export function resolveFetch(fetchImpl?: typeof fetch): typeof fetch | undefined {
const resolved = fetchImpl ?? globalThis.fetch;
if (!resolved) {
return undefined;
}
return wrapFetchWithAbortSignal(resolved);
}
|