krz/hutch
an ios client for sourcehut
clone: git clone https://gitbay.org/krz/hutch.git
v2: Hutch/Networking/SRHTError.swift · raw
1import Foundation
2
3/// Errors produced by the Sourcehut GraphQL client.
4enum SRHTError: LocalizedError, Sendable {
5 /// The server returned one or more GraphQL-level errors.
6 case graphQLErrors([GraphQLError])
7 /// The HTTP response had a non-2xx status code.
8 case httpError(Int)
9 /// The client refused to send credentials to an unexpected URL.
10 case invalidAuthenticatedURL(URL)
11 /// The response data could not be decoded.
12 case decodingError(any Error)
13 /// A networking error from URLSession (timeout, DNS, connectivity, etc.).
14 case networkError(any Error)
15 /// 401 or no authentication token configured.
16 case unauthorized
17
18 var errorDescription: String? {
19 switch self {
20 case .graphQLErrors(let errors):
21 let messages = errors.map(\.message).joined(separator: "\n")
22 return "GraphQL error: \(messages)"
23 case .httpError(let code):
24 return "Server returned HTTP \(code)."
25 case .invalidAuthenticatedURL(let url):
26 return "Refused to authenticate request to unexpected URL: \(url.absoluteString)"
27 case .decodingError(let error):
28 return "Failed to decode response: \(error.localizedDescription)"
29 case .networkError(let error):
30 return "Network error: \(error.localizedDescription)"
31 case .unauthorized:
32 return "Authentication required. Please sign in again."
33 }
34 }
35
36 /// Whether this error represents a connectivity issue (no internet, timeout, DNS).
37 var isConnectivityError: Bool {
38 switch self {
39 case .networkError(let error):
40 let nsError = error as NSError
41 let connectivityCodes: Set<Int> = [
42 NSURLErrorNotConnectedToInternet,
43 NSURLErrorNetworkConnectionLost,
44 NSURLErrorTimedOut,
45 NSURLErrorCannotFindHost,
46 NSURLErrorCannotConnectToHost,
47 NSURLErrorDNSLookupFailed,
48 NSURLErrorInternationalRoamingOff,
49 NSURLErrorDataNotAllowed
50 ]
51 return connectivityCodes.contains(nsError.code)
52 default:
53 return false
54 }
55 }
56}
57
58/// A single error entry from the GraphQL `errors` array.
59struct GraphQLError: Decodable, Sendable {
60 let message: String
61 let locations: [GraphQLErrorLocation]?
62}
63
64struct GraphQLErrorLocation: Decodable, Sendable {
65 let line: Int
66 let column: Int
67}