fully-react
Version:
React Server for Vite
56 lines (50 loc) • 1.77 kB
text/typescript
const REDIRECT_ERROR_CODE = "REDIRECT";
type RedirectError<U extends string> = Error & {
digest: `${typeof REDIRECT_ERROR_CODE};${U}`;
};
/**
* When used in a React server component, this will insert a meta tag to
* redirect the user to the target page. When used in a custom app route, it
* will serve a 302 to the caller.
*
* @param url the url to redirect to
*/
export function redirect(url: string): never {
// eslint-disable-next-line no-throw-literal
const error = new Error(REDIRECT_ERROR_CODE);
(error as RedirectError<typeof url>).digest = `${REDIRECT_ERROR_CODE};${url}`;
throw error;
}
/**
* 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<U extends string>(
error: any,
): error is RedirectError<U> {
return (
typeof error?.digest === "string" &&
error.digest.startsWith(REDIRECT_ERROR_CODE + ";") &&
error.digest.length > REDIRECT_ERROR_CODE.length + 1
);
}
/**
* Returns the encoded URL from the error if it's a RedirectError, null
* otherwise. Note that this does not validate the URL returned.
*
* @param error the error that may be a redirect error
* @return the url if the error was a redirect error
*/
export function getURLFromRedirectError<U extends string>(
error: RedirectError<U>,
): U;
export function getURLFromRedirectError(error: any): string | null;
export function getURLFromRedirectError(error: any): string | null {
if (!isRedirectError(error)) return null;
// Slices off the beginning of the digest that contains the code and the
// separating ';'.
return error.digest.slice(REDIRECT_ERROR_CODE.length + 1);
}