// from https://github.com/vercel/next.js/blob/canary/packages/next/src/client/components/redirect-error.ts export const RedirectStatusCode = { SeeOther: 303, TemporaryRedirect: 307, PermanentRedirect: 308, } as const; export type RedirectStatusCode = (typeof RedirectStatusCode)[keyof typeof RedirectStatusCode]; export const REDIRECT_ERROR_CODE = 'NEXT_REDIRECT'; export enum RedirectType { push = 'push', replace = 'replace', } export type RedirectError = Error & { digest: `${typeof REDIRECT_ERROR_CODE};${RedirectType};${string};${RedirectStatusCode};`; }; /** * Checks an error to determine if it's an error generated by the * `redirect(url)` helper. * * @param error the error that may reference a redirect error * @returns true if the error is a redirect error */ export function isRedirectError(error: unknown): error is RedirectError { if (typeof error !== 'object' || error === null || !('digest' in error) || typeof error.digest !== 'string') { return false; } const digest = error.digest.split(';'); const [errorCode, type] = digest; const destination = digest.slice(2, -2).join(';'); const status = digest.at(-2); const statusCode = Number(status); return ( errorCode === REDIRECT_ERROR_CODE && (type === 'replace' || type === 'push') && typeof destination === 'string' && !isNaN(statusCode) && Object.values(RedirectStatusCode).includes(statusCode as RedirectStatusCode) ); } export function getRedirectStatus(error: RedirectError): RedirectStatusCode { const status = error.digest.split(';').at(-2); return Number(status) as RedirectStatusCode; }