vadymmarkov / Malibu

:surfer: Malibu is a networking library built on promises

Home Page:https://vadymmarkov.github.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Idea/suggestion: improve and extend Codable support

kevinrenskers opened this issue · comments

I've been playing around with the CodyFire network library recently and while it has some flaws (and doesn't use promises), it uses Codable throughout in nifty ways. For example, it uses strongly typed structs for both request parameters and the response, like this:

class API {
  func register(_ request: RegisterData) -> APIRequest<LoginResponse> {
    return APIRequest("user/register/", payload: request).method(.post).desiredStatusCode(.created)
  }

  func login(_ request: LoginRequest) -> APIRequest<LoginResponse> {
    return APIRequest("user/login/", payload: request).method(.post)
  }

  func logout() -> APIRequest<Nothing> {
    return APIRequest("user/logout/").method(.post).desiredStatusCode(.noContent)
  }
}

struct RegisterData: JSONPayload {
  let username: String
  let name: String
  let password: String
  let email: String
  let gender: String
}

struct LoginRequest: JSONPayload {
  let username: String
  let password: String
}

struct LoginResponse: Codable {
  var token: String
}

As you can see, the parameters are strongly typed, this works for query params, form params, multi-part upload, etc etc. And the response is also automatically decoded. I know that you can do that in Malibu 8.1.0 as well, but there you have to do it when you make the request, instead of declaring it upfront on the Request itself.

Another thing that would be great is to have Decodable support for errors as well, something that CodyFire also lacks sadly.

Compare to something like this:

enum Endpoint: RequestConvertible {
  case login(username: String, password: String)

  static var baseUrl: URLStringConvertible? = "http://127.0.0.1:8000/api"

  static var headers: [String: String] = [
    "Accept": "application/json",
  ]

  // Build requests
  var request: Request {
    switch self {
    case .login(let username, let password):
      return Request.post("user/login/", parameters: ["username": username, "password": password])
    }
  }
}

The username and password parameters are repeated multiple times and are sent stringly typed. And I have to do the response decoding my self on the call site.