next-safe-action
Version:
Type safe and validated Server Actions in your Next.js project.
138 lines (130 loc) • 5.01 kB
JavaScript
//#region src/next/errors/bailout-to-csr.ts
const BAILOUT_TO_CSR = "BAILOUT_TO_CLIENT_SIDE_RENDERING";
/** Checks if a passed argument is an error that is thrown if we want to bail out to client-side rendering. */
function isBailoutToCSRError(err) {
if (typeof err !== "object" || err === null || !("digest" in err)) return false;
return err.digest === BAILOUT_TO_CSR;
}
//#endregion
//#region src/next/errors/http-access-fallback.ts
const ALLOWED_CODES = new Set(
Object.values({
NOT_FOUND: 404,
FORBIDDEN: 403,
UNAUTHORIZED: 401,
})
);
const HTTP_ERROR_FALLBACK_ERROR_CODE = "NEXT_HTTP_ERROR_FALLBACK";
/**
* Checks an error to determine if it's an error generated by
* the HTTP navigation APIs `notFound()`, `forbidden()` or `unauthorized()`.
*
* @param error the error that may reference a HTTP access error
* @returns true if the error is a HTTP access error
*/
function isHTTPAccessFallbackError(error) {
if (typeof error !== "object" || error === null || !("digest" in error) || typeof error.digest !== "string")
return false;
const [prefix, httpStatus] = error.digest.split(";");
return prefix === HTTP_ERROR_FALLBACK_ERROR_CODE && ALLOWED_CODES.has(Number(httpStatus));
}
function getAccessFallbackHTTPStatus(error) {
const httpStatus = error.digest.split(";")[1];
return Number(httpStatus);
}
//#endregion
//#region src/next/errors/redirect.ts
var RedirectStatusCode = /* @__PURE__ */ (function (RedirectStatusCode) {
RedirectStatusCode[(RedirectStatusCode["SeeOther"] = 303)] = "SeeOther";
RedirectStatusCode[(RedirectStatusCode["TemporaryRedirect"] = 307)] = "TemporaryRedirect";
RedirectStatusCode[(RedirectStatusCode["PermanentRedirect"] = 308)] = "PermanentRedirect";
return RedirectStatusCode;
})(RedirectStatusCode || {});
const REDIRECT_ERROR_CODE = "NEXT_REDIRECT";
/**
* 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
*/
function isRedirectError(error) {
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) &&
statusCode in RedirectStatusCode
);
}
//#endregion
//#region src/next/errors/router.ts
/**
* Returns true if the error is a navigation signal error. These errors are
* thrown by user code to perform navigation operations and interrupt the React
* render.
*/
function isNextRouterError(error) {
return isRedirectError(error) || isHTTPAccessFallbackError(error);
}
//#endregion
//#region src/next/errors/dynamic-usage.ts
const DYNAMIC_ERROR_CODE = "DYNAMIC_SERVER_USAGE";
function isDynamicServerError(err) {
if (typeof err !== "object" || err === null || !("digest" in err) || typeof err.digest !== "string") return false;
return err.digest === DYNAMIC_ERROR_CODE;
}
function isDynamicPostponeReason(reason) {
return (
reason.includes("needs to bail out of prerendering at this point because it used") &&
reason.includes("Learn more: https://nextjs.org/docs/messages/ppr-caught-error")
);
}
function isDynamicPostpone(err) {
if (typeof err === "object" && err !== null && typeof err.message === "string")
return isDynamicPostponeReason(err.message);
return false;
}
const isDynamicUsageError = (err) =>
isDynamicServerError(err) || isBailoutToCSRError(err) || isNextRouterError(err) || isDynamicPostpone(err);
//#endregion
//#region src/next/errors/postpone.ts
const REACT_POSTPONE_TYPE = Symbol.for("react.postpone");
function isPostpone(error) {
return typeof error === "object" && error !== null && error.$$typeof === REACT_POSTPONE_TYPE;
}
//#endregion
//#region src/next/errors/index.ts
var FrameworkErrorHandler = class FrameworkErrorHandler {
#frameworkError;
static isNavigationError(error) {
return isNextRouterError(error) || isBailoutToCSRError(error) || isDynamicUsageError(error) || isPostpone(error);
}
static getNavigationKind(error) {
if (isRedirectError(error)) return "redirect";
else if (isHTTPAccessFallbackError(error) && getAccessFallbackHTTPStatus(error) === 404) return "notFound";
else if (isHTTPAccessFallbackError(error) && getAccessFallbackHTTPStatus(error) === 403) return "forbidden";
else if (isHTTPAccessFallbackError(error) && getAccessFallbackHTTPStatus(error) === 401) return "unauthorized";
else return "other";
}
handleError(e) {
if (FrameworkErrorHandler.isNavigationError(e)) {
this.#frameworkError = e;
return;
}
throw e;
}
get error() {
return this.#frameworkError;
}
};
//#endregion
export { FrameworkErrorHandler as t };
//# sourceMappingURL=errors-BsNXg-5Q.mjs.map