Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/devxoul/MoyaSugar

🍯 Syntactic sugar for Moya
https://github.com/devxoul/MoyaSugar

alamofire moya rxswift syntactic-sugar

Last synced: 3 months ago
JSON representation

🍯 Syntactic sugar for Moya

Awesome Lists containing this project

README

        

# MoyaSugar

![Swift](https://img.shields.io/badge/Swift-5.1-orange.svg)
[![CI](https://github.com/devxoul/MoyaSugar/workflows/CI/badge.svg)](https://github.com/devxoul/MoyaSugar/workflows/actions)
[![CocoaPods](http://img.shields.io/cocoapods/v/MoyaSugar.svg)](https://cocoapods.org/pods/MoyaSugar)

Syntactic sugar for Moya.

## Why?

[Moya](https://github.com/Moya/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.

```swift
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`.

```swift
let provider = MoyaSugarProvider()
let provider = RxMoyaSugarProvider() // If you're using Moya/RxSwift
```

## Complete Example

```swift
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`**

```diff
- extension GitHubAPI: TargetType
+ extension GitHubAPI: SugarTargetType
```

- 🔗 **`var route: Route`**

Returns `Route` which contains HTTP method and URL path information.

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

Example:

```swift
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](https://github.com/devxoul/MoyaSugar/pull/6) for detail.

- 🔗 **`var params: Parameters?`**

Returns `Parameters` which contains parameter encoding and values.

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

Example:

```swift
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`:

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

## Requirements

Same with [Moya](https://github.com/Moya/Moya)

## Installation

- **Using [CocoaPods](https://cocoapods.org)**:

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

> MoyaSugar currently doesn't cupport Carthage.

## Contributing

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

## License

**MoyaSugar** is under MIT license. See the [LICENSE](LICENSE) file for more info.