Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/openstatusHQ/openstatus. ๐ซ Status page with uptime monitoring & API monitoring as code ๐ซ openstatus.dev
bun drizzle-orm monitoring monitoring-as-code nextjs observability on-call open-source shadcn-ui status-page statuspage synthetic-monitoring tinybird turso uptime uptime-checker uptime-monitor
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157import { z } from "@hono/zod-openapi";import { getLogger } from "@logtape/logtape";import type { ErrorCode } from "@openstatus/error";import { ErrorCodes, SchemaError, codeToStatus, statusToCode,} from "@openstatus/error";// Props to Unkey: https://github.com/unkeyed/unkey/blob/main/apps/api/src/pkg/errors/http.tsimport type { Context } from "hono";import { HTTPException } from "hono/http-exception";import { ZodError } from "zod";
const logger = getLogger("api-server");export class OpenStatusApiError extends HTTPException { public readonly code: ErrorCode;
constructor({ code, message, }: { code: ErrorCode; message: HTTPException["message"]; }) { const status = codeToStatus(code); super(status, { message }); this.code = code; }}
export function handleError(err: Error, c: Context): Response { if (err instanceof ZodError) { const error = SchemaError.fromZod(err, c);
// If the error is a client error, we disable Sentry c.get("sentry").setEnabled(false);
return c.json<ErrorSchema>( { code: "BAD_REQUEST", message: error.message, docs: "https://www.openstatus.dev/docs/api-references/errors/code/BAD_REQUEST", requestId: c.get("requestId"), }, { status: 400 }, ); }
/** * This is a custom error that we throw in our code so we can handle it */ if (err instanceof OpenStatusApiError) { const code = statusToCode(err.status);
// If the error is a client error, we disable Sentry if (err.status < 499) { c.get("sentry").setEnabled(false); }
return c.json<ErrorSchema>( { code: code, message: err.message, docs: `https://www.openstatus.dev/docs/api-references/errors/code/${code}`, requestId: c.get("requestId"), }, { status: err.status }, ); }
if (err instanceof HTTPException) { const code = statusToCode(err.status); return c.json<ErrorSchema>( { code: code, message: err.message, docs: `https://www.openstatus.dev/docs/api-references/errors/code/${code}`, requestId: c.get("requestId"), }, { status: err.status }, ); }
logger.error("Request error", { error: { name: err.name, message: err.message, stack: err.stack, }, method: c.req.method, url: c.req.url, }); c.get("sentry").captureException(err);
return c.json<ErrorSchema>( { code: "INTERNAL_SERVER_ERROR", message: err.message ?? "Something went wrong", docs: "https://www.openstatus.dev/docs/api-references/errors/code/INTERNAL_SERVER_ERROR", requestId: c.get("requestId"), },
{ status: 500 }, );}
export function handleZodError( result: | { success: true; data: unknown; } | { success: false; error: ZodError; }, c: Context,) { if (!result.success) { const error = SchemaError.fromZod(result.error, c); return c.json<z.infer<ReturnType<typeof createErrorSchema>>>( { code: "BAD_REQUEST", docs: "https://www.openstatus.dev/docs/api-references/errors/code/BAD_REQUEST", message: error.message, requestId: c.get("requestId"), }, { status: 400 }, ); }}
export function createErrorSchema(code: ErrorCode) { return z.object({ code: z.enum(ErrorCodes).openapi({ example: code, description: "The error code related to the status code.", }), message: z.string().openapi({ description: "A human readable message describing the issue.", example: "<string>", }), docs: z.string().openapi({ description: "A link to the documentation for the error.", example: `https://www.openstatus.dev/docs/api-references/errors/code/${code}`, }), requestId: z.string().openapi({ description: "The request id to be used for debugging and error reporting.", example: "<uuid>", }), });}
export type ErrorSchema = z.infer<ReturnType<typeof createErrorSchema>>;