GitFOSS
.ts
TypeScript
(application/typescript)
// 3rd-party
import type { FastifyError } from "fastify";
import type { ReactView } from "@ethicdevs/react-monolith";
import React from "react";

// app
import type { CommonProps } from "../types";
import { Card, Layout, PageWrapper } from "../components";
// app islands
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;