borchero / Squid

Declarative and Reactive Networking for Swift.

Home Page:https://squid.borchero.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Global error mapping

kevinrenskers opened this issue · comments

It would be nice to set a global error mapping. My API returns errors in a certain format, so I now have to add .mapError every time I make a request.

PasswordResetTokenRequest(email: email)
  .schedule(with: api)
  .receive(on: DispatchQueue.main)
  .mapError(CoreAPIError.fromError)
  .sink(
    // etc

CoreAPIError looks like this, in case you're wondering:

struct CoreAPIError: Decodable, Error, LocalizedError {
  let message: String?
  let errors: [String: [String]]?

  var errorDescription: String? {
    if let errors = errors {
      let values = errors.flatMap { $0.value }
      return values.joined(separator: "\n")
    }
    return message ?? "An error occured"
  }

  static func fromError(_ error: Squid.Error) -> CoreAPIError {
    if case .requestFailed(_, let data) = error, let coreError = try? JSONDecoder().decode(CoreAPIError.self, from: data) {
      return coreError
    }

    return CoreAPIError(message: error.localizedDescription, errors: nil)
  }
}

The problem is that I always have to remember to add this one line to every call site. It would be great if it would be possible to set this as a default, global thing that happens to all requests.

This is not too bad. Still have to remember to do it at the call site, but at least it's right there in the autocompletion popup when I type .schedule :)

extension Request {
  func scheduleAndMapError(with service: HttpService) -> AnyPublisher<Self.Result, CoreAPIError> {
    return schedule(with: service)
      .mapError(CoreAPIError.fromError)
      .eraseToAnyPublisher()
  }
}

I will include that feature into the HttpService protocol, definitely makes sense ;)

Thanks!