Skip to content

Commit ff5b5c0

Browse files
committed
fix: handle missing user theme_preference on sign in
1 parent ae51d0e commit ff5b5c0

File tree

3 files changed

+25
-49
lines changed

3 files changed

+25
-49
lines changed

Coder Desktop/CoderSDK/Client.swift

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public struct Client {
4444
throw .network(error)
4545
}
4646
guard let httpResponse = resp as? HTTPURLResponse else {
47-
throw .unexpectedResponse(data)
47+
throw .unexpectedResponse(String(data: data, encoding: .utf8) ?? "<non-utf8 data>")
4848
}
4949
return HTTPResponse(resp: httpResponse, data: data, req: req)
5050
}
@@ -72,7 +72,7 @@ public struct Client {
7272

7373
func responseAsError(_ resp: HTTPResponse) -> ClientError {
7474
do {
75-
let body = try Client.decoder.decode(Response.self, from: resp.data)
75+
let body = try decode(Response.self, from: resp.data)
7676
let out = APIError(
7777
response: body,
7878
statusCode: resp.resp.statusCode,
@@ -81,7 +81,24 @@ public struct Client {
8181
)
8282
return .api(out)
8383
} catch {
84-
return .unexpectedResponse(resp.data.prefix(1024))
84+
return .unexpectedResponse(String(data: resp.data, encoding: .utf8) ?? "<non-utf8 data>")
85+
}
86+
}
87+
88+
// Wrapper around JSONDecoder.decode that displays useful error messages from `DecodingError`.
89+
func decode<T>(_: T.Type, from data: Data) throws(ClientError) -> T where T: Decodable {
90+
do {
91+
return try Client.decoder.decode(T.self, from: data)
92+
} catch let DecodingError.keyNotFound(_, context) {
93+
throw .unexpectedResponse("Key not found: \(context.debugDescription)")
94+
} catch let DecodingError.valueNotFound(_, context) {
95+
throw .unexpectedResponse("Value not found: \(context.debugDescription)")
96+
} catch let DecodingError.typeMismatch(_, context) {
97+
throw .unexpectedResponse("Type mismatch: \(context.debugDescription)")
98+
} catch let DecodingError.dataCorrupted(context) {
99+
throw .unexpectedResponse("Data corrupted: \(context.debugDescription)")
100+
} catch {
101+
throw .unexpectedResponse(String(data: data.prefix(1024), encoding: .utf8) ?? "<non-utf8 data>")
85102
}
86103
}
87104
}
@@ -119,7 +136,7 @@ public struct FieldValidation: Decodable, Sendable {
119136
public enum ClientError: Error {
120137
case api(APIError)
121138
case network(any Error)
122-
case unexpectedResponse(Data)
139+
case unexpectedResponse(String)
123140
case encodeFailure(any Error)
124141

125142
public var description: String {
@@ -129,7 +146,7 @@ public enum ClientError: Error {
129146
case let .network(error):
130147
error.localizedDescription
131148
case let .unexpectedResponse(data):
132-
"Unexpected or non HTTP response: \(data)"
149+
"Unexpected response: \(data)"
133150
case let .encodeFailure(error):
134151
"Failed to encode body: \(error.localizedDescription)"
135152
}

Coder Desktop/CoderSDK/Deployment.swift

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,7 @@ public extension Client {
66
guard res.resp.statusCode == 200 else {
77
throw responseAsError(res)
88
}
9-
do {
10-
return try Client.decoder.decode(BuildInfoResponse.self, from: res.data)
11-
} catch {
12-
throw .unexpectedResponse(res.data.prefix(1024))
13-
}
9+
return try decode(BuildInfoResponse.self, from: res.data)
1410
}
1511
}
1612

Coder Desktop/CoderSDK/User.swift

Lines changed: 2 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -6,57 +6,20 @@ public extension Client {
66
guard res.resp.statusCode == 200 else {
77
throw responseAsError(res)
88
}
9-
do {
10-
return try Client.decoder.decode(User.self, from: res.data)
11-
} catch {
12-
throw .unexpectedResponse(res.data.prefix(1024))
13-
}
9+
return try decode(User.self, from: res.data)
1410
}
1511
}
1612

1713
public struct User: Encodable, Decodable, Equatable, Sendable {
1814
public let id: UUID
1915
public let username: String
20-
public let avatar_url: String
21-
public let name: String
22-
public let email: String
23-
public let created_at: Date
24-
public let updated_at: Date
25-
public let last_seen_at: Date
26-
public let status: String
27-
public let login_type: String
28-
public let theme_preference: String
29-
public let organization_ids: [UUID]
30-
public let roles: [Role]
3116

3217
public init(
3318
id: UUID,
34-
username: String,
35-
avatar_url: String,
36-
name: String,
37-
email: String,
38-
created_at: Date,
39-
updated_at: Date,
40-
last_seen_at: Date,
41-
status: String,
42-
login_type: String,
43-
theme_preference: String,
44-
organization_ids: [UUID],
45-
roles: [Role]
19+
username: String
4620
) {
4721
self.id = id
4822
self.username = username
49-
self.avatar_url = avatar_url
50-
self.name = name
51-
self.email = email
52-
self.created_at = created_at
53-
self.updated_at = updated_at
54-
self.last_seen_at = last_seen_at
55-
self.status = status
56-
self.login_type = login_type
57-
self.theme_preference = theme_preference
58-
self.organization_ids = organization_ids
59-
self.roles = roles
6023
}
6124
}
6225

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy