Files
kandev/apps/web/lib/ws/request-error.ts
T
2026-09-13 12:14:45 +01:00

52 lines
1.8 KiB
TypeScript

export type WebSocketRequestErrorDetails = Record<string, unknown>;
/** Error returned when a WebSocket request does not receive a response in time. */
export class WebSocketRequestTimeoutError extends Error {
readonly action: string;
readonly kind = "timeout" as const;
constructor(action: string) {
super(`WebSocket request timed out: ${action}`);
this.name = "WebSocketRequestTimeoutError";
this.action = action;
}
}
export function isWebSocketRequestTimeoutError(
error: unknown,
): error is WebSocketRequestTimeoutError {
return error instanceof WebSocketRequestTimeoutError;
}
/** Error returned when the backend rejects a request with a typed payload. */
export class WebSocketRequestError extends Error {
readonly code?: string;
readonly details?: WebSocketRequestErrorDetails;
constructor(message: string, code?: string, details?: WebSocketRequestErrorDetails) {
super(message);
this.name = "WebSocketRequestError";
this.code = code;
this.details = details;
}
}
/** Preserve the structured fields from a rejected WebSocket request. */
export function toWebSocketRequestError(payload: unknown): WebSocketRequestError {
const record =
typeof payload === "object" && payload !== null
? (payload as { code?: unknown; message?: unknown; details?: unknown })
: undefined;
// i18n-exempt: transport fallback used when the backend supplies no message.
const message =
typeof record?.message === "string" && record.message
? record.message
: "WebSocket request failed";
const code = typeof record?.code === "string" ? record.code : undefined;
const details =
typeof record?.details === "object" && record.details !== null
? (record.details as WebSocketRequestErrorDetails)
: undefined;
return new WebSocketRequestError(message, code, details);
}