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



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: "")!
    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


import NetworkAgent

class Repository {

    typealias Callback<T> = (T) -> ()
    static let shared: Repository = Repository()
    private let provider: NetworkAgentProvider<Api> = .init(plugins: [])
    func login(email: String, password: String) -> <Session, 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) -> <Book, Error> {
        return provider.request(.book(id: id))


import Foundation
import Combine

class LoginViewModel: ObservableObject {
    @Published var email: String = ""
    @Published var password: String = ""
    private var cancellable: Set<AnyCancellable> = .init()
    private var repository = Repository.shared
    func login(completion: @escaping Callback<Session>) {
        self.isLoading = true
        repository.login(email: email, password: password)
            .sink(onSuccess: completion)
            .store(in: &cancellable)


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)