Skip to content

Commit

Permalink
feat: Start throwing common errors (box/box-codegen#516) (#147)
Browse files Browse the repository at this point in the history
  • Loading branch information
box-sdk-build authored Jun 26, 2024
1 parent 95391c9 commit d12bbb7
Show file tree
Hide file tree
Showing 20 changed files with 370 additions and 538 deletions.
2 changes: 1 addition & 1 deletion .codegen.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{ "engineHash": "62c749a", "specHash": "fc01415", "version": "0.1.0" }
{ "engineHash": "74a3b04", "specHash": "fc01415", "version": "0.1.0" }
164 changes: 68 additions & 96 deletions BoxSdkGen.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

155 changes: 0 additions & 155 deletions Sources/Box/APIError.swift

This file was deleted.

15 changes: 0 additions & 15 deletions Sources/Box/AuthError.swift

This file was deleted.

15 changes: 0 additions & 15 deletions Sources/Box/BoxAPIError.swift

This file was deleted.

19 changes: 0 additions & 19 deletions Sources/Box/BoxSDKError.swift

This file was deleted.

106 changes: 106 additions & 0 deletions Sources/Box/Errors/BoxAPIError.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif

/// Describes API request related errors.
public class BoxAPIError: BoxSDKError {
/// The request information
public let requestInfo: RequestInfo
/// The response information
public let responseInfo: ResponseInfo

/// Initializer
///
/// - Parameters:
/// - message: The error message
/// - requestInfo: The request information
/// - responseInfo: The response information
/// - timestamp: The timestamp of the error
/// - error: The underlying error which caused this error, if any.
public init(message: String, requestInfo: RequestInfo, responseInfo: ResponseInfo, timestamp: Date? = nil, error: Error? = nil) {
self.requestInfo = requestInfo
self.responseInfo = responseInfo

super.init(message: message, timestamp: timestamp, error: error, name: "BoxAPIError")
}

/// Gets a dictionary representing the APIError.
///
/// - Returns: A dictionary representing the APIError.
override public func getDictionary() -> [String: Any] {
var dict = super.getDictionary()
dict["request"] = requestInfo.getDictionary()
dict["response"] = responseInfo.getDictionary()
return dict
}

}

extension BoxAPIError {
/// Initializer
///
/// - Parameters:
/// - fromConversation: Represents a data combined with the request and the corresponding response.
convenience init(fromConversation conversation: FetchConversation, message: String? = nil) {
let requestHeaders = conversation.options.headers.compactMapValues { $0?.paramValue }
let requestInfo = RequestInfo(
method: conversation.options.method.rawValue,
url: conversation.url,
queryParams: conversation.options.headers.compactMapValues { $0?.paramValue },
headers: requestHeaders,
body: requestHeaders[HTTPHeaderKey.contentType, default: ""].paramValue == HTTPHeaderContentTypeValue.urlEncoded
? try? conversation.options.data?.toUrlParams()
: try? Utils.Strings.from(data: conversation.options.data?.toJson() ?? Data())
)

var body: SerializedData?
var json: [String: Any]?
if case let .data(data) = conversation.responseType {
body = SerializedData(data: data)
json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]
}
let responseInfo = ResponseInfo(
statusCode: conversation.urlResponse.statusCode,
headers: conversation.urlResponse.allHeaderFields as? [String: String] ?? [:],
body: body,
rawBody: try? Utils.Strings.from(data: body?.toJson() ?? Data()),
code: json?["code"] as? String,
contextInfo: json?["context_info"] as? [String: Any],
requestId: json?["request_id"] as? String,
helperUrl: json?["help_url"] as? String,
message: json?["message"] as? String
)

self.init(
message: message ?? Self.createMessage(fromResponse: responseInfo),
requestInfo: requestInfo,
responseInfo: responseInfo
)
}

/// Gets a formatted user-friendly message based on the `ResponseDescription`
///
/// - Returns: Formatted user-friendly message based on the `ResponseDescription`
static func createMessage(fromResponse response: ResponseInfo) -> String {
var message = "The API returned an unexpected response: "
message += "[\(response.statusCode) \(HTTPURLResponse.localizedString(forStatusCode: response.statusCode).capitalized)"

if let requestId = response.requestId {
message += " | \(requestId)] "
}
else {
message += "]"
}

if let code = response.code {
message += " \(code)"
}

if let shortMessage = response.message {
message += " - \(shortMessage)"
}

return message
}
}
14 changes: 14 additions & 0 deletions Sources/Box/Errors/BoxNetworkError.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import Foundation

/// Describes network related errors.
public class BoxNetworkError: BoxSDKError {

/// Initializer
///
/// - Parameters:
/// - message: Error message
/// - error: The underlying error which caused this error, if any.
public init(message: String, timestamp: Date? = nil, error: Error? = nil) {
super.init(message: message, timestamp: timestamp, error: error, name: "BoxNetworkError")
}
}
47 changes: 47 additions & 0 deletions Sources/Box/Errors/BoxSDKError.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import Foundation

/// Describes general errors
public class BoxSDKError: Error {
/// The error message
public let message: String
/// The timestamp of the error
public let timestamp: Date
/// The underlying error which caused this error
public let error: Error?
/// The name of the error
public let name: String

public init(message: String, timestamp: Date? = nil, error: Error? = nil, name: String = "BoxSDKError") {
self.message = message
self.timestamp = timestamp ?? Date()
self.error = error
self.name = name
}

/// Gets a dictionary representing the BoxSDKError.
///
/// - Returns: A dictionary representing the BoxSDKError.
public func getDictionary() -> [String: Any] {
var dict = [String: Any]()
dict["name"] = name
dict["timestamp"] = Utils.Dates.dateTimeToString(dateTime: timestamp)
dict["message"] = message.description
dict["error"] = error?.localizedDescription
return dict
}

}

/// Extension for `CustomStringConvertible` conformance
extension BoxSDKError: CustomStringConvertible {
/// Provides error JSON string if found.
public var description: String {
guard
let encodedData = try? JSONSerialization.data(withJSONObject: getDictionary(), options: [.prettyPrinted, .sortedKeys]),
let JSONString = String(data: encodedData, encoding: .utf8)
else {
return "<Unparsed Error>"
}
return JSONString.replacingOccurrences(of: "\\", with: "")
}
}
Loading

0 comments on commit d12bbb7

Please sign in to comment.