block-employee-directory-in.../EmployeeDirectory/Services/NetworkService.swift

73 lines
2.3 KiB
Swift

//
// NetworkService.swift
// EmployeeDirectory
//
// Created by Matt Bruce on 1/20/25.
//
import Foundation
public enum NetworkServiceError: Error {
/// The response from the server was invalid (e.g., non-200 status code or malformed URL).
case invalidResponse
/// The url giving is invalid or malformed
case invalidURL
/// The data received was invalid or could not be decoded.
case decodingError(DecodingError)
/// A network-related error occurred.
case networkError(URLError)
/// An unexpected, uncategorized error occurred.
case unknownError(Error)
}
public class NetworkService {
public static let shared = NetworkService() // Default shared instance
private let session: URLSession
/// Public initializer to allow customization
public init(session: URLSession = .shared) {
self.session = session
}
/// Fetches data from a URL and decodes it into a generic Decodable type.
/// - Parameters:
/// - endpoint: The url to fetch data from.
/// - type: The type to decode the data into.
/// - Throws: A `ServiceError` for network, decoding, or unexpected errors.
/// - Returns: The decoded object of the specified type.
public func fetchData<T: Decodable>(from endpoint: String, as type: T.Type) async throws -> T {
do {
//ensure a valid URL
guard let url = URL(string: endpoint) else {
throw NetworkServiceError.invalidURL
}
// Perform network request
let (data, response) = try await URLSession.shared.data(for: URLRequest(url: url))
// Validate HTTP response
guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else {
throw NetworkServiceError.invalidResponse
}
// Decode the response into the specified type
return try JSONDecoder().decode(T.self, from: data)
} catch let urlError as URLError {
throw NetworkServiceError.networkError(urlError)
} catch let decodingError as DecodingError {
throw NetworkServiceError.decodingError(decodingError)
} catch {
throw NetworkServiceError.unknownError(error)
}
}
}