api-swift / Sources / IrdAPI / Core / Errors.swift
396 words
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import Foundation

/// Every failure the client throws, tagged by kind. Behaviour matches the sibling
/// TypeScript client: a non-2xx answer is `.api`, a network or decoding failure is
/// `.transport`, a bad call is `.config`, and only a poll deadline is `.timeout`.
public enum IrdError: Error, Sendable, Equatable, CustomStringConvertible {
    /// The API answered with a non-2xx status. `code` is the API's error code when the
    /// body carried one; `message` is its message, or the raw text for non-JSON bodies.
    case api(status: Int, code: String?, message: String, body: JSONValue?)
    /// DNS, TLS, socket, timeout, or an unparseable 2xx body.
    case transport(String)
    /// A mistake detected before any request was sent.
    case config(String)
    /// The client-side domain gate refused a mutation.
    case domainDenied(domain: String?, pattern: String?, op: String)
    /// A poll loop passed its deadline; `last` is the last response seen.
    case timeout(message: String, last: JSONValue?)
    /// `jobs.run`: the job reached the `failed` state.
    case jobFailed(Job)
    /// `ipfs.addFile`: the upload ended `failed` or `expired`.
    case uploadFailed(Upload)

    public var status: Int? { if case .api(let s, _, _, _) = self { return s }; return nil }
    public var code: String? { if case .api(_, let c, _, _) = self { return c }; return nil }

    public var isAuth: Bool { status == 401 }
    public var isInsufficientCredits: Bool { status == 402 }
    public var isForbidden: Bool { status == 403 }
    public var isNotFound: Bool { status == 404 }
    public var isRateLimited: Bool { status == 429 }
    /// A sensitive-domain step-up: the call must be repeated with a fresh `totp_code`.
    public var needsTOTP: Bool { code == "totp-required" || code == "invalid-totp" }
    /// Sensitive domains refuse API keys; sign in with an account session instead.
    public var isAPIKeyBlocked: Bool { code == "sensitive-domain-api-key-blocked" }

    public var description: String {
        switch self {
        case .api(let status, let code, let message, _):
            return code.map { "\(message) (\($0), HTTP \(status))" } ?? "\(message) (HTTP \(status))"
        case .transport(let detail): return "Transport error: \(detail)"
        case .config(let detail): return "Configuration error: \(detail)"
        case .domainDenied(let domain, _, let op):
            return "Domain gate: \(domain ?? "(unknown domain)") may not be touched by \(op)"
        case .timeout(let message, _): return message
        case .jobFailed(let job): return "Job \(job.id) failed: \(job.error ?? "no error reported")"
        case .uploadFailed(let upload): return "Upload \(upload.id) \(upload.status.rawValue): \(upload.error ?? "no error reported")"
        }
    }
}

static mirror of HEAD · about · clone: git clone https://ird.cod-sursa.ro/api-swift.git