Code Monkey home page Code Monkey logo

moyasugar's Introduction

MoyaSugar

Swift CI CocoaPods

Syntactic sugar for Moya.

Why?

Moya is an elegant network abstraction layer which abstracts API endpoints gracefully with enum. However, it would become massive when the application is getting larger. Whenever you add an endpoint, you should write code at least 5 places: enum case, method, path, parameters and parameterEncoding property. It makes you scroll down again and again. Besides, if you would like to set different HTTP header fields, you should customize endpointClosure of MoyaProvider.

If you're as lazy as I am, MoyaSugar is for you.

At a Glance

Forget about method, path, parameters, parameterEncoding and endpointClosure. Use route, params, httpHeaderFields instead.

extension MyService: SugarTargetType {
  var route: Route {
    return .get("/me")
  }

  var params: Parameters? {
    return JSONEncoding() => [
      "username": "devxoul",
      "password": "****",
    ]
  }

  var headers: [String: String]? {
    return ["Accept": "application/json"]
  }
}

Use MoyaSugarProvider instead of MoyaProvider.

let provider = MoyaSugarProvider<MyService>()
let provider = RxMoyaSugarProvider<MyService>() // If you're using Moya/RxSwift

Complete Example

import Moya
import Moyasugar

enum GitHubAPI {
  case url(String)
  case userRepos(owner: String)
  case createIssue(owner: String, repo: String, title: String, body: String?)
  case editIssue(owner: String, repo: String, number: Int, title: String?, body: String?)
}

extension GitHubAPI : SugarTargetType {

  /// method + path
  var route: Route {
    switch self {
    case .url(let urlString):
      return .get(urlString)

    case .userRepos(let owner):
      return .get("/users/\(owner)/repos")

    case .createIssue(let owner, let repo, _, _):
      return .post("/repos/\(owner)/\(repo)/issues")

    case .editIssue(let owner, let repo, let number, _, _):
      return .patch("/repos/\(owner)/\(repo)/issues/\(number)")
    }
  }

  // override default url building behavior
  var url: URL {
    switch self {
    case .url(let urlString):
      return URL(string: urlString)!
    default:
      return self.defaultURL
    }
  }

  /// encoding + parameters
  var params: Parameters? {
    switch self {
    case .url:
      return nil

    case .userRepos:
      return nil

    case .createIssue(_, _, let title, let body):
      return JSONEncoding() => [
        "title": title,
        "body": body,
      ]

    case .editIssue(_, _, _, let title, let body):
      // Use `URLEncoding()` as default when not specified
      return [
        "title": title,
        "body": body,
      ]
    }
  }

  var headers: [String: String]? {
    return [
      "Accept": "application/json"
    ]
  }

}

APIs

  • ๐Ÿ”— protocol SugarTargetType

    - extension GitHubAPI: TargetType
    + extension GitHubAPI: SugarTargetType
  • ๐Ÿ”— var route: Route

    Returns Route which contains HTTP method and URL path information.

    - var method: Method { get }
    - var path: String { get }
    + var route: Route { get }

    Example:

    var route: Route {
      return .get("/me")
    }
  • ๐Ÿ”— var url: URL

    Returns the request URL. It retuens defaultURL as default, which is the combination of baseURL and path. Implement this property to return custom url. See #6 for detail.

  • ๐Ÿ”— var params: Parameters?

    Returns Parameters which contains parameter encoding and values.

    - var parameters: [String: Any]? { get }
    + var params: Parameters? { get }

    Example:

    var params: Parameters? {
      return JSONEncoding() => [
        "username": "devxoul",
        "password": "****",
      ]
    }

    Note: If the MoyaSugarProvider is initialized with an endpointClosure parameter, HTTP header fields of endpointClosure will be used. This is how to extend the target's HTTP header fields in endpointClosure:

    let endpointClosure: (GitHubAPI) -> Endpoint<GitHubAPI> = { target in
      let defaultEndpoint = MoyaProvider.defaultEndpointMapping(for: target)
      return defaultEndpoint
        .adding(newHTTPHeaderFields: ["Authorization": "MySecretToken"])
    }

Requirements

Same with Moya

Installation

  • Using CocoaPods:

    pod 'MoyaSugar'
    pod 'MoyaSugar/RxSwift' # Use with RxSwift

MoyaSugar currently doesn't cupport Carthage.

Contributing

$ TEST=1 swift package generate-xcodeproj
$ open MoyaSugar.xcodeproj

License

MoyaSugar is under MIT license. See the LICENSE file for more info.

moyasugar's People

Contributors

basthomas avatar cjndubisi avatar devxoul avatar kdawgwilk avatar marvin-yorke avatar ohkanghoon avatar wanbok avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

moyasugar's Issues

MoyaSugar behaves differently when `route` contains an empty `path`

I'm designing a simple SugarTargetType to download files from arbitrary urls:

/* ... */

var baseURL: URL {
  switch self {
  case .download(let url): return url
  }
}
  
var route: Route {
  return .get("")
}

/* ... */

Moya's previous behaviour was to always append the path to the baseURL. They changed this behaviour in Moya 8.0.4 (see: Moya/Moya#1053) to avoid appending an extraneous / at the end of the url.

It seems to me that the code can easily be modified to respect the new Moya behaviour.
The change would happen at https://github.com/devxoul/MoyaSugar/blob/master/Sources/SugarTargetType.swift#L56

var defaultURL: URL {
  return self.baseURL.appendingPathComponent(self.path)
}

would become

var defaultURL: URL {
  return self.path.isEmpty ? self.baseURL : self.baseURL.appendingPathComponent(self.path)
}

I would do a pull request but I am unable to compile the project on my computer.

Build errors with new release Moya 9.0.0

Are there any plans to migrate to the latest Moya release according to this guide ? Otherwise you should fix podspec file by replacing Moya dependency version 'Moya', '>= 8.0.0' to 'Moya', '~> 8.0.0'

Implementation of SugarTargetType

Hi,

I need to put several http headers with my project, that's why I want to use your abstraction of Moya and have something like this :

enum BikeTrackTestRx {
    case userLogIn(mail: String, password: String)
    case userCreate(mail: String, password: String)
}
extension BikeTrackTestRx: SugarTargetType {
    var url: URL {return URL(string: "https://api.herokuapp.com")!}
    
    var route: Route {
        switch self {
            case .userLogIn(_):
                return .post("/authenticate")
            case .userCreate(_):
                return .post("/signup")
        }
    }
    
    var params: Parameters? {
        switch self {
        case .userLogIn(let mail, let password):
            return JSONEncoding.default => [
                "mail": "\(mail)",
                "password": "\(password)"
            ]
        case .userCreate(let mail, let password):
            return JSONEncoding.default => [
                "mail": "\(mail)",
                "password": "\(password)"
            ]
        }
    }
    
    var task: Task {
        return .request
    }
    
    var sampleData: Data {
        switch self {
        case .userLogIn(_):
            return "{\"username\": \"toto\", \"password\": \"titi\"}".data(using: .utf8)!
        case .userCreate(_):
            return "{\"username\": \"toto\", \"password\": \"titi\"}".data(using: .utf8)!
        }
    }

    var httpHeaderFields: [String: String]? {
        switch self {
        case .userLogIn(_):
                return ["Authorization": "MyKey",
                        "token": "randomToken"]
        default:
            return ["Authorization": "MyKey"]
        }
    }
    
}

But i got an error : Type 'BikeTrackTestRx' does not conform to protocol 'TargetType'

Maybe I don't have the good version of Moya, so there is my podfile :

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '10.0'
use_frameworks!

target 'Biketrack' do
       pod 'RxCocoa', '~> 3.0.0'
       pod 'Moya-ModelMapper/RxSwift', '~> 4.1.0'
       pod 'MoyaSugar/RxSwift', '~> 0.4'
       pod 'RxOptional'
end

Thanks in advance ๐Ÿ˜ƒ

Add additional parameters to params

I have two fields, most of the requests are required, but I don't want to repeat these two fields in all params. Is there any way to solve them?
Sorry, my English is not very good, use Google translate, if you can solve it, thank you very much

Optional parameters

  var params: Parameters? {
    switch self {
    case .cars(let offset, let sort): //here offset and sort are optionals
      if offset != nil && sort != nil { return ["offset":offset!, "sort": sort!] }
      else if offset != nil { return ["offset":offset!] }
      else if sort != nil { return ["sort": sort!] }
      else { return nil }
    }
  }

I'm trying to get this variations:

/Cars
/Cars?offset=1
/Cars?sort=price
/Cars?offset=1&sort=price

Is there any way to simplify this ?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.