त्रुटियाँ
हर विफलता throw करती है। दो क्लास, और हर API error पर एक request id।
इसे पकड़ना
import { OpenEmailApiError, OpenEmailNetworkError, openemail } from '@openemail/sdk' try { await openemail.emails.send(message)} catch (error) { if (error instanceof OpenEmailApiError) { if (error.isValidation) console.error(error.code, error.param, error.message) if (error.isPermission) console.error(await openemail.addresses.list()) if (error.isRateLimited) console.error('try again in', error.retryAfterSeconds, 'seconds') console.error(error.status, error.requestId) } if (error instanceof OpenEmailNetworkError && error.isTimeout) console.error('no answer in time') throw error}किसी send पर आया permission_error आमतौर पर वर्कस्पेस का नहीं बल्कि KEY के send scope का मामला होता है — कोई डोमेन या पता जो उसे दिया ही नहीं गया; इसीलिए यह नमूना वह छापता है जो addresses.list() बताता है कि यह key किस रूप में भेज सकती है।
क्लास
| क्लास | कब |
|---|---|
| `OpenEmailApiError` | API ने उत्तर दिया, और सफलता के साथ नहीं। इसमें status, type, code, param, docUrl, requestId और retryAfterSeconds होते हैं। |
| `OpenEmailNetworkError` | कोई रिस्पॉन्स नहीं आया: DNS, TLS, टूटा हुआ कनेक्शन, timeout, या आपका अपना AbortSignal। इसमें cause होता है, और जब कारण timeout हो तो isTimeout true होता है। |
| `Error` | कुछ भी भेजे जाने से पहले throw होती है: अनुपस्थित या खराब key, अनुपयोगी baseUrl, कोई ब्राउज़र, खाली id। |
| गेटर | true कब |
|---|---|
| `isAuth` | type authentication_error है, यानी 401: कोई key नहीं, गलत किस्म का क्रेडेंशियल, या ऐसी key जो हमने जारी नहीं की। |
| `isPermission` | permission_error, यानी 403: असली key, पर उसके पास ज़रूरी scope या From पता नहीं। |
| `isScopeMissing` | code insufficient_scope है, वह 403 जो अनुपस्थित scope का नाम बताता है। |
| `isInvalidRequest` | invalid_request_error, यानी 400: ऐसा request जिसे समझा नहीं जा सका। आकार की सीमा से बड़ा संदेश 422 message_too_large बनकर लौटता है, इसलिए उसे पकड़ने वाला गेटर isValidation है। |
| `isValidation` | validation_error, यानी 422: schema ने इसे अस्वीकार किया, और param उस फ़ील्ड का नाम बताता है। |
| `isNotFound` | not_found_error, यानी 404: ऐसा कोई संसाधन नहीं। |
| `isConflict` | conflict_error, यानी 409: संसाधन उस बिंदु से आगे निकल चुका है जहाँ उसके साथ यह किया जा सकता था। |
| `isRateLimited` | rate_limit_error, यानी 429। जब सर्वर प्रतीक्षा बताता है तो वह retryAfterSeconds में होती है। |
| `isServerError` | status 500 या उससे ऊपर है। सपोर्ट से संपर्क करें तो requestId बताएँ। |
| `isRetryable` | status 408, 429, 500, 502, 503 या 504 है। |
गेटर type पढ़ते हैं, जो envelope का जमा हुआ आधा हिस्सा है। code string ही रहता है, क्योंकि API की गारंटी है कि वह खुला और जोड़ने योग्य है, इसलिए जिसे आप न पहचानें उसे उसके type की तरह बरतें। बंद union का मतलब होता कि नई विफलता पढ़ने की कीमत एक SDK अपग्रेड है।
जो body API का error envelope नहीं है वह भी OpenEmailApiError ही बनती है, जिसमें type status से अनुमानित होता है और code unrecognised_response रखा जाता है। जिस सफलता की body JSON नहीं है वह भी यही throw करती है।
abort भी OpenEmailNetworkError ही है, चाहे वह request के दौरान आए या किसी retry से पहले की प्रतीक्षा के दौरान, और abort को cause पर रखा जाता है। जब आपको अपनी रद्दीकरण को नेटवर्क विफलता से अलग पहचानना हो तो signal.aborted जाँचें।
requestId
हर OpenEmailApiError वह request id लिए चलती है जो सर्वर ने भेजी — error body से या x-request-id header से — और यही एकमात्र चीज़ है जो आपकी विफलता को सर्वर के लॉग की एक पंक्ति से जोड़ती है। सफलता केवल पार्स की गई body में resolve होती है, इसलिए उस पर पढ़ने को कोई request id नहीं होती।