export const KNOWN_ERROR_CODES = [ 'missing_permission', 'escalation', 'role_locked', 'own_role', 'role_built_in', 'built_in_name', 'role_conflict', 'user_role_changed', 'session_required', ] as const export type ApiErrorCode = (typeof KNOWN_ERROR_CODES)[number] export interface ApiErrorDetails { code?: ApiErrorCode permission?: string escalationKey?: string } const SESSION_REQUIRED_MESSAGE = 'This action needs a real session.' export function errorCodeOf(body: string | undefined): ApiErrorCode | undefined { if (body === SESSION_REQUIRED_MESSAGE) { return 'session_required' } return KNOWN_ERROR_CODES.find((code) => code === body) } export class ApiError extends Error { status: number retryAfter?: number body?: string code?: ApiErrorCode permission?: string escalationKey?: string constructor(status: number, retryAfter?: number, body?: string, details: ApiErrorDetails = {}) { super(`Request failed with status ${status}`) this.status = status this.retryAfter = retryAfter this.body = body this.code = details.code this.permission = details.permission this.escalationKey = details.escalationKey } }