export interface MintApiErrorEnvelope { code: string message: string status: number request_id: string | null details: unknown detail?: unknown } const STATUS_MESSAGES: Readonly> = { 400: 'Bad request', 401: 'Authentication required', 403: 'Permission denied', 404: 'Resource not found', 405: 'Method not allowed', 409: 'Conflict', 413: 'Payload too large', 415: 'Unsupported media type', 422: 'Validation error', 429: 'Rate limit exceeded', 500: 'Internal server error', 502: 'Bad gateway', 503: 'Service unavailable', } function asRecord(value: unknown): Record | null { if (!value || typeof value !== 'object' || Array.isArray(value)) return null return value as Record } /** Public error thrown by typed MINT SDK requests. */ export class MintApiError extends Error { override readonly name: string = 'MintApiError' constructor( message: string, readonly code: string, readonly status: number, readonly requestId: string | null, readonly details: unknown, readonly detail: unknown, readonly body: unknown, readonly cause?: unknown, ) { super(message) } } export interface MintApiErrorOptions { requestId?: string | null cause?: unknown } /** Normalize current typed envelopes and the previous FastAPI detail shape. */ export function mintApiErrorFromResponse( status: number, payload: unknown, options: MintApiErrorOptions = {}, ): MintApiError { const body = asRecord(payload) const legacyDetail = body?.detail const inner = asRecord(legacyDetail) ?? body const text = (value: unknown): string | undefined => typeof value === 'string' && value ? value : undefined // Complete envelopes own the public code; older wrappers defer to the plugin payload. const canonical = typeof body?.status === 'number' && text(body.code) && text(body.message) const code = (canonical ? text(body.code) : text(inner?.error) ?? text(inner?.code)) ?? text(body?.code) ?? 'unknown' const message = (canonical ? text(body.message) : text(inner?.message)) ?? text(body?.message) ?? text(legacyDetail) ?? STATUS_MESSAGES[status] ?? `HTTP ${status}` const details = body?.details ?? inner?.details ?? null const requestId = text(body?.request_id) ?? text(inner?.request_id) ?? options.requestId ?? null return new MintApiError( message, code, status, requestId, details, legacyDetail, payload, options.cause, ) }