Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: adds statusCode to serverError #7

Merged
merged 1 commit into from
Nov 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// swift-tools-version: 5.8
// swift-tools-version: 5.10
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,9 +138,9 @@ do {
let models = try await modelRetriever.openAI(apiKey: "your-api-key")
} catch let error as AIModelRetrieverError {
switch error {
case .serverError(let message):
case .serverError(let statusCode, let message):
// Handle server-side errors (e.g., invalid API key, rate limits)
print("Server Error: \(message)")
print("Server Error [\(statusCode)]: \(message)")
case .networkError(let error):
// Handle network-related errors (e.g., no internet connection)
print("Network Error: \(error.localizedDescription)")
Expand Down
9 changes: 7 additions & 2 deletions Sources/AIModelRetriever/AIModelRetriever.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,17 @@ public struct AIModelRetriever: Sendable {
do {
let (data, response) = try await URLSession.shared.data(for: request)

guard let httpResponse = response as? HTTPURLResponse else {
throw AIModelRetrieverError.serverError(statusCode: 0, message: response.description)
}

// Check for API errors first, as they might come with 200 status
if let errorResponse = try? JSONDecoder().decode(E.self, from: data) {
throw AIModelRetrieverError.serverError(errorResponse.errorMessage)
throw AIModelRetrieverError.serverError(statusCode: httpResponse.statusCode, message: errorResponse.errorMessage)
}

guard let httpResponse = response as? HTTPURLResponse, 200...299 ~= httpResponse.statusCode else {
throw AIModelRetrieverError.serverError(response.description)
throw AIModelRetrieverError.serverError(statusCode: httpResponse.statusCode, message: response.description)
}

return try JSONDecoder().decode(T.self, from: data)
Expand Down
34 changes: 12 additions & 22 deletions Sources/AIModelRetriever/AIModelRetrieverError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,35 +7,25 @@

import Foundation

/// An enum that represents errors that can occur during AI model retrieval.
/// An enum that represents errors that can occur during model retrieval.
public enum AIModelRetrieverError: Error, Sendable {
/// A case that represents a server-side error response.
/// An error that occurs during JSON decoding.
///
/// - Parameter message: The error message from the server.
case serverError(String)
/// - Parameter error: The underlying decoding error.
case decodingError(Error)

/// A case that represents a network-related error.
/// An error that occurs during network operations.
///
/// - Parameter error: The underlying network error.
case networkError(Error)

/// A case that represents a decoding error.
case decodingError(Error)
/// An error returned by the server.
///
/// - Parameters:
/// - statusCode: The HTTP status code returned by the server.
/// - message: The error message received from the server.
case serverError(statusCode: Int, message: String)

/// A case that represents a request has been canceled.
/// An error that occurs when the request is cancelled.
case cancelled

/// A localized message that describes the error.
public var errorDescription: String? {
switch self {
case .serverError(let error):
return error
case .networkError(let error):
return error.localizedDescription
case .decodingError(let error):
return error.localizedDescription
case .cancelled:
return "Request was cancelled"
}
}
}
4 changes: 2 additions & 2 deletions Sources/AIModelRetriever/Documentation.docc/Documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,9 @@ do {
let models = try await modelRetriever.openAI(apiKey: "your-api-key")
} catch let error as AIModelRetrieverError {
switch error {
case .serverError(let message):
case .serverError(let statusCode, let message):
// Handle server-side errors (e.g., invalid API key, rate limits)
print("Server Error: \(message)")
print("Server Error [\(statusCode)]: \(message)")
case .networkError(let error):
// Handle network-related errors (e.g., no internet connection)
print("Network Error: \(error.localizedDescription)")
Expand Down
8 changes: 5 additions & 3 deletions Tests/AIModelRetrieverTests/AIModelRetrieverTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ final class AIModelRetrieverTests: XCTestCase {
override func setUp() {
super.setUp()

URLProtocol.registerClass(URLProtocolMock.self)
retriever = AIModelRetriever()
URLProtocol.registerClass(URLProtocolMock.self)
}

override func tearDown() {
Expand Down Expand Up @@ -155,7 +155,8 @@ extension AIModelRetrieverTests {
XCTFail("Expected serverError to be thrown")
} catch let error as AIModelRetrieverError {
switch error {
case .serverError(let message):
case .serverError(let statusCode, let message):
XCTAssertEqual(statusCode, 401)
XCTAssertEqual(message, "Invalid API key provided")
default:
XCTFail("Expected serverError but got \(error)")
Expand All @@ -182,7 +183,8 @@ extension AIModelRetrieverTests {
XCTFail("Expected serverError to be thrown")
} catch let error as AIModelRetrieverError {
switch error {
case .serverError(let message):
case .serverError(let statusCode, let message):
XCTAssertEqual(statusCode, 200)
XCTAssertEqual(message, "An error occurred")
default:
XCTFail("Expected serverError but got \(error)")
Expand Down