Something went wrong. Try again.
Atproto AMA app
Something went wrong. Try again.
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162const ASCII_EQUIVALENTS: Record<string, string> = { "—": "-", "–": "-", "‘": "'", "“": '"', "”": '"', "…": "...",};
/** * Error messages thrown from server actions are forwarded to the client via * the `X-Error` response header, which only accepts Latin-1 (ByteString) * values — undici throws a TypeError on anything above U+00FF and the request * dies with a 500 before the client can display the message. Map common * typographic characters to ASCII and drop anything else outside Latin-1. */export function clientSafeMessage(message: string): string { const mapped = message.replace(/[—–‘“”…]/g, (char) => ASCII_EQUIVALENTS[char] ?? char); return mapped.replace(/[^\t\n\r\x20-\x7E\u00A0-\u00FF]/g, "");}
export class RouteError extends Error { constructor( message: string, public statusCode: number = 500, public title: string = "Error", public code: string = "internal_error", ) { super(message); this.name = "RouteError"; }}
export class NotFoundError extends RouteError { constructor(message: string = "Page not found") { super(message, 404, "Not Found", "not_found"); }}
export class ForbiddenError extends RouteError { constructor(message: string = "Access denied", code: string = "forbidden") { super(message, 403, "Forbidden", code); }}
export class UnauthorizedError extends RouteError { constructor(message: string = "Please sign in to continue") { super(message, 401, "Unauthorized", "unauthorized"); }}
export function isRouteError(error: unknown): error is RouteError { return ( error instanceof RouteError || (error instanceof Error && error.name === "RouteError") || (typeof error === "object" && error !== null && "name" in error && (error as { name: unknown }).name === "RouteError") );}