import type { FastifyError } from "fastify";
import type { ReactView } from "@ethicdevs/react-monolith";
import React from "react";
import type { CommonProps } from "../types";
import { Card, Layout, PageWrapper } from "../components";
import Code, { getThemedCodeCss } from "../islands/Code";
export interface InternalErrorViewProps extends CommonProps {
error: FastifyError;
}
const DEV = process.env.NODE_ENV === "development";
const DEBUG = !!(
process.env.DEBUG != null && ["true", "1", true].includes(process.env.DEBUG)
);
const InternalErrorView: ReactView<InternalErrorViewProps> = ({
commonProps,
error,
}) => {
let { code } = error;
const { message, stack, validation } = error;
const statusCode = Array.isArray(message.match(/404 - Not Found/i))
? 404
: error.statusCode || 500;
if (code == null || code.trim() === "") {
code = statusCode.toString();
}
const isNotFoundError = statusCode === 404;
const isRequestError =
!isNotFoundError && statusCode >= 400 && statusCode <= 499;
const isInternalError = statusCode >= 500;
const isRecoverableError =
isRequestError && !isNotFoundError && !isInternalError;
return (
<Layout {...commonProps}>
<PageWrapper>
{isRequestError && (
<h1>🤔 Mh, something was not correct with your request</h1>
)}
{isNotFoundError && (
<h1>
🔭 Looks like this page is missing, or has never been there...
</h1>
)}
{isInternalError && (
<h1>
😵💫 Woops... we've encountered an internal error, please
apologize.
</h1>
)}
<div style={{ marginTop: 8 }}>
{!isNotFoundError &&
(isRecoverableError ? (
<a href="/" role={"button"}>
Try again 🔄
</a>
) : (
<p>Sorry but it is not possible to recover from this error.</p>
))}
</div>
{(DEBUG || DEV) && (
<div style={{ marginTop: 24 }}>
{getThemedCodeCss(commonProps.themeScheme)}
<details open>
<summary>[DEBUG] Full error details:</summary>
{message != null && message.trim() !== "" && (
<div style={{ marginTop: 16 }}>
<label
style={{ fontWeight: "bold", textDecoration: "underline" }}
>
Message:
</label>
<pre>
<code>{message.trim()}</code>
</pre>
</div>
)}
{stack != null && stack.trim() !== "" && (
<div style={{ marginTop: 16 }}>
<label
style={{ fontWeight: "bold", textDecoration: "underline" }}
>
Stack:
</label>
<Card
data-islandid={`${Code.name}$$0`}
style={{ width: "100%", marginTop: 32 }}
themeScheme={commonProps.themeScheme}
>
<Code
language={"python"}
code={stack.replace(message, "").trim()}
themeScheme={commonProps.themeScheme}
/>
</Card>
</div>
)}
{validation != null && (
<div style={{ marginTop: 16 }}>
<label
style={{ fontWeight: "bold", textDecoration: "underline" }}
>
Validation:
</label>
<Card
data-islandid={`${Code.name}$$1`}
style={{ width: "100%", marginTop: 32 }}
themeScheme={commonProps.themeScheme}
>
<Code
language={"json"}
code={JSON.stringify(validation, null, 2)}
themeScheme={commonProps.themeScheme}
/>
</Card>
</div>
)}
</details>
</div>
)}
</PageWrapper>
</Layout>
);
};
export default InternalErrorView;