Type safety App Store Connect API client in Swift 🚀
🐛 Wormhole invites you to the fastest trip to AppStore Connect.
This library is currently developing.
- ✅ Pure Swifty
- ✅ Type Safed
- ✅ Swift Package Manager Support
- 🚧 Linux Support
- ☠️ Available this summer
- Xcode 10
- libjwt(unstable version)
You need to install unstable version of libjwt.
$ brew tap giginet/libjwt https://github.com/giginet/libjwt.git
$ brew install giginet/libjwt/libjwt
$ mkdir MyExecutable
$ cd MyExecutable
$ swift package init --type executable
// swift-tools-version:4.2
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "MyExecutable",
dependencies: [
.package(url: "https://github.com/giginet/Wormhole.git", .from("0.1.0")),
],
targets: [
.target(
name: "MyExecutable",
dependencies: ["Wormhole"]),
]
)
$ swift run -Xcc -I/usr/local/include -Xlinker -L/usr/local/lib
You can find your issuerID, keyID or private key on App Store Connect.
import Foundation
import Wormhole
import Result
// Download your private key from App Store Connect
let client = try! Client(p8Path: URL(fileURLWithPath: "/path/to/private_key.p8"),
issuerID: UUID(uuidString: "b91d85c7-b7db-4451-8f3f-9a3c8af9a392")!,
keyID: "100000")
enum Role: String, Codable {
case developer = "DEVELOPER"
case marketing = "MARKETING"
}
struct User: AttributeType {
let firstName: String
let lastName: String
let email: String
let roles: [Role]
}
/// Define request model
struct GetUsersRequest: RequestType {
// You can use `SingleContainer<AttributeType>` or `CollectionContainer<AttributeType>`
typealias Response = CollectionContainer<User>
// HTTP method(get, post, patch or delete)
let method: HTTPMethod = .get
// API endpoint
let path = "/users"
// Request payload. You can use `.void` to send request without any payloads.
let payload: RequestPayload = .void
}
let request = GetUsersRequest()
client.send(request) { (result: Result<CollectionContainer<User>, ClientError>) in
switch result {
case .success(let container):
let firstUser: User = container.data.first!
print("Name: \(firstUser.firstName) \(firstUser.lastName)")
print("Email: \(firstUser.email)")
print("Roles: \(firstUser.roles)")
case .failure(let error):
print("Something went wrong")
print(String(describing: error))
}
}
// UUID of a target user
let uuid = UUID(uuidString: "588ec36e-ba74-11e8-8879-93c782f9ccb3")
// Define Request model
struct RoleModificationRequest: RequestType {
// Response should indicate a single user.
typealias Response = SingleContainer<User>
let method: HTTPMethod = .patch
var path: String {
return "/users/\(id.uuidString.lowercased())"
}
let id: UUID
let roles: [Role]
// Payload
var payload: RequestPayload {
return .init(id: id,
type: "users",
attributes: roles)
}
}
let request = RoleModificationRequest(id: uuid, roles: [.developer, .marketing])
client.send(request) { result in
switch result {
case .success(let container):
let modifiedUser: User = container.data
print("Name: \(modifiedUser.firstName) \(modifiedUser.lastName)")
print("Email: \(modifiedUser.email)")
print("Roles: \(modifiedUser.roles)")
case .failure(let error):
print("Something went wrong")
print(String(describing: error))
}
}
$ swift package generate-xcodeproj --xcconfig-overrides Config.xcconfig
$ open ./Wormhole.xcodeproj