Files
bsky-social-app/src/lib/xrpc-error.ts
T
Samuel Newman e6f73fc110 add dual-world xrpc error helpers and toLex migration escape hatch
Phase 3 foundations (task 1): src/lib/xrpc-error.ts matches both the old
@atproto/api XRPCError and lex-client XrpcError/XrpcResponseError during
the migration; errors.ts token-invalid matching goes through it. toLex<T>()
added to #/types/bsky as a marked interim cast for mixed-world boundaries.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-30 18:07:26 +03:00

45 lines
1.6 KiB
TypeScript

import {XRPCError} from '@atproto/api'
import {XrpcError, XrpcResponseError} from '@atproto/lex-client'
/**
* True for an XRPC error from either the old bridge agent (`@atproto/api`
* `XRPCError`) or a lex `Client` (`@atproto/lex-client` `XrpcError`, the
* abstract base of `XrpcResponseError`/`XrpcInvalidResponseError`/
* `XrpcInternalError`). During the migration both worlds can throw, so matchers
* must accept both.
*/
export function isXrpcError(e: unknown): e is XRPCError | XrpcError {
return e instanceof XRPCError || e instanceof XrpcError
}
/**
* HTTP status, or undefined if not an XRPC error / no response. Only lex
* `XrpcResponseError` (a server response) carries a status; the internal/fetch
* lex errors do not.
*/
export function getErrorStatus(e: unknown): number | undefined {
if (e instanceof XRPCError) return e.status
if (e instanceof XrpcResponseError) return e.status
return undefined
}
/** The lexicon error code (`err.error`), from either world. */
export function getErrorName(e: unknown): string | undefined {
if (isXrpcError(e)) return (e as {error?: string}).error
return undefined
}
/**
* Read a response header off an XRPC error, normalizing the shape change:
* old XRPCError.headers is a plain record; lex XrpcResponseError.headers is a
* WHATWG Headers object.
*/
export function getErrorHeader(e: unknown, name: string): string | undefined {
if (e instanceof XrpcResponseError) return e.headers.get(name) ?? undefined
if (e instanceof XRPCError) {
const h = (e as {headers?: Record<string, string>}).headers
return h?.[name.toLowerCase()]
}
return undefined
}