NetworkAgent
This package is meant to make http request of an easy way inspiren in the architecture of Moya package. This package is 100% free of dependencies and works with Combine api + Codable
Example
Api.swift
import NetworkAgent
enum Api {
    case login(email: String, password: String)
    case books(query: [String: Any])
    case book(id: Int)
}
extension Api: NetworkAgentEndpoint {
    var baseURL: URL {
        return URL(string: "https://some_url.com/api")!
    }
    
    var path: String {
        switch self {
        case .login: return "/login"
        case .books: return "/books"
        case let .book(id): return "/books/\(id)"
        }
    }
    
    var method: HTTPMethod {
        return .get
    }
    
    var task: HTTPTask {
        switch self {
            case let .login(email, password): return .requestAttributes(attributes: ["email:" email, "password": password], encoding: .json)
            case let .books(query): return .requestAttributes(attributes: query, encoding: .url)
            case .book: return .requestPlain
        }
    }
}
Repository.swift
import NetworkAgent
class Repository {
    typealias Callback<T> = (T) -> ()
    static let shared: Repository = Repository()
    private let provider: NetworkAgentProvider = .init(plugins: [])
    
    func login(email: String, password: String) -> Error> {
        return provider.request(.login(email: email, password: password))
    }
    
    func books(query: [String: Any]) -> <[Book], Error> {
        return provider.request(.books(query: query))
    }
    
    func book(id: int) -> Error> {
        return provider.request(.book(id: id))
    }
}   
LoginViewModel.swift
import Foundation import Combine class LoginViewModel: ObservableObject { @Published var email: String = "" @Published var password: String = "" private var cancellable: Set= .init() private var repository = Repository.shared func login(completion: @escaping Callback ) { self.isLoading = true repository.login(email: email, password: password) .sink(onSuccess: completion) .store(in: &cancellable) } } 
Plugins
To make a custom plugin is as easy to implement the protocol NetworkAgentPlugin every function of the protocol is optional.
public protocol NetworkAgentPlugin {
    func onRequest(_ request: URLRequest, with configuration: RequestConfiguration)
    func onResponse(_ response: HTTPURLResponse, with payload: Data)
    func onResponse(_ response: HTTPURLResponse?, with payload: Data?, receiving error: NetworkAgent.NetworkError, from endpoint: NetworkAgentEndpoint)
}