type FetchLike = typeof fetch; const vercelProtectionCookieCache = new Map>(); async function awaitWithSignal( promise: Promise, signal: AbortSignal | undefined, ): Promise { if (!signal) return await promise; if (signal.aborted) throw signal.reason; return await new Promise((resolve, reject) => { const onAbort = () => { cleanup(); reject(signal.reason); }; const cleanup = () => signal.removeEventListener('abort', onAbort); signal.addEventListener('abort', onAbort, { once: true }); promise.then( (value) => { cleanup(); resolve(value); }, (error) => { cleanup(); reject(error); }, ); }); } export function addVercelProtectionBypassSearchParams( url: URL, token: string | null | undefined, ): void { const normalized = token?.trim(); if (!normalized) return; url.searchParams.set('x-vercel-set-bypass-cookie', 'true'); url.searchParams.set('x-vercel-protection-bypass', normalized); } export function vercelProtectionBypassHeader( token: string | null | undefined, ): Record { const normalized = token?.trim(); return normalized ? { 'x-vercel-protection-bypass': normalized } : {}; } function setCookieHeaders(headers: Headers): string[] { const getter = (headers as Headers & { getSetCookie?: () => string[] }) .getSetCookie; if (typeof getter === 'function') { return getter.call(headers); } const single = headers.get('set-cookie'); return single ? [single] : []; } export function cookieHeaderFromSetCookie(headers: Headers): string | null { const cookies = setCookieHeaders(headers) .flatMap((header) => header.split(/,(?=\s*[^;,=]+=[^;,]+)/g)) .map((header) => header.split(';', 1)[0]?.trim() ?? '') .filter(Boolean); return cookies.length > 0 ? cookies.join('; ') : null; } export async function resolveVercelProtectionBypassCookie(input: { baseUrl: string | null | undefined; token: string | null | undefined; fetchImpl?: FetchLike; signal?: AbortSignal; }): Promise { const token = input.token?.trim(); const baseUrl = input.baseUrl?.trim().replace(/\/$/, ''); if (!token || !baseUrl) return null; const cacheKey = `${baseUrl}\n${token}`; const cached = vercelProtectionCookieCache.get(cacheKey); if (cached) return await awaitWithSignal(cached, input.signal); const promise = (async () => { const url = new URL(`${baseUrl}/api/v2/health`); addVercelProtectionBypassSearchParams(url, token); const response = await (input.fetchImpl ?? fetch)(url.toString(), { headers: { 'x-vercel-protection-bypass': token }, }).catch(() => null); return response ? cookieHeaderFromSetCookie(response.headers) : null; })(); vercelProtectionCookieCache.set(cacheKey, promise); void promise.catch(() => { if (vercelProtectionCookieCache.get(cacheKey) === promise) { vercelProtectionCookieCache.delete(cacheKey); } }); return await awaitWithSignal(promise, input.signal); } export async function vercelProtectionBypassHeaders(input: { baseUrl: string | null | undefined; token: string | null | undefined; fetchImpl?: FetchLike; signal?: AbortSignal; }): Promise> { const token = input.token?.trim(); if (!token) return {}; const cookie = await resolveVercelProtectionBypassCookie({ baseUrl: input.baseUrl, token, fetchImpl: input.fetchImpl, signal: input.signal, }); return { ...vercelProtectionBypassHeader(token), ...(cookie ? { cookie } : {}), }; }