Connect-Swift is a small library (<200KB!) that provides support for using generated, type-safe, and idiomatic Swift APIs to communicate with your app's servers using Protocol Buffers (Protobuf). It works with the Connect, gRPC, and gRPC-Web protocols.
Imagine a world where
you don't have to handwrite Codable
models for REST/JSON endpoints
and you can instead get right to building features by calling a generated
API method that is guaranteed to match the server's modeling. Furthermore,
imagine never having to worry about serialization again, and being able to
easily write tests using generated mocks that conform to the same protocol
that the real implementations do.
All of this is possible with Connect-Swift.
Given a simple Protobuf schema, Connect-Swift generates idiomatic Swift protocol interfaces and client implementations:
eliza.connect.swift
public protocol Eliza_V1_ChatServiceClientInterface {
func say(request: Eliza_V1_SayRequest, headers: Headers)
async -> ResponseMessage<Eliza_V1_SayResponse>
}
public final class Eliza_V1_ChatServiceClient: Eliza_V1_ChatServiceClientInterface {
private let client: ProtocolClientInterface
public init(client: ProtocolClientInterface) {
self.client = client
}
public func say(request: Eliza_V1_SayRequest, headers: Headers = [:])
async -> ResponseMessage<Eliza_V1_SayResponse>
{
return await self.client.unary(path: "buf.connect.demo.eliza.v1.ElizaService/Say", request: request, headers: headers)
}
}
This code can then be integrated with just a few lines:
final class MessagingViewModel: ObservableObject {
private let elizaClient: Eliza_V1_ChatServiceClientInterface
init(elizaClient: Eliza_V1_ChatServiceClientInterface) {
self.elizaClient = elizaClient
}
@Published private(set) var messages: [Message] {...}
func send(_ userSentence: String) async {
let request = Eliza_V1_SayRequest.with { $0.sentence = userSentence }
let response = await self.elizaClient.say(request: request, headers: [:])
if let elizaSentence = response.message?.sentence {
self.messages.append(Message(sentence: userSentence, author: .user))
self.messages.append(Message(sentence: elizaSentence, author: .eliza))
}
}
}
That’s it! You no longer need to manually define Swift response models,
add Codable
conformances, type out URL(string: ...)
initializers,
or even create protocol interfaces to wrap service classes - all this is taken
care of by Connect-Swift, and the underlying network transport is
handled automatically.
Testing also becomes a breeze with generated mocks which conform to the same protocol interfaces as the production clients:
eliza.mock.swift
open class Eliza_V1_ChatServiceClientMock: Eliza_V1_ChatServiceClientInterface {
public var mockAsyncSay = { (_: Eliza_V1_SayRequest) -> ResponseMessage<Eliza_V1_Response> in .init(message: .init()) }
open func say(request: Eliza_V1_SayRequest, headers: Headers = [:])
async -> ResponseMessage<Eliza_V1_SayResponse>
{
return self.mockAsyncSay(request)
}
}
func testMessagingViewModel() async {
let client = Eliza_V1_ChatServiceClientMock()
client.mockAsyncSay = { request in
XCTAssertEqual(request.sentence, "hello!")
return ResponseMessage(message: .with { $0.sentence = "hi, i'm eliza!" })
}
let viewModel = MessagingViewModel(elizaClient: client)
await viewModel.send("hello!")
XCTAssertEqual(viewModel.messages.count, 2)
XCTAssertEqual(viewModel.messages[0].message, "hello!")
XCTAssertEqual(viewModel.messages[0].author, .user)
XCTAssertEqual(viewModel.messages[1].message, "hi, i'm eliza!")
XCTAssertEqual(viewModel.messages[1].author, .eliza)
}
Head over to our quick start tutorial to get started. It only takes ~10 minutes to complete a working SwiftUI chat app that uses Connect-Swift!
Comprehensive documentation for everything, including interceptors, mocking/testing, streaming, and error handling is available on the connect.build website.
Example apps are available in the Examples
directory and can be opened and built using Xcode. They demonstrate:
We'd love your help making Connect better!
Extensive instructions for building the library and generator plugins locally,
running tests, and contributing to the repository are available in our
CONTRIBUTING.md
guide. Please check it out
for details.
This project is in beta, and we may make a few changes as we gather feedback from early adopters. Join us on Slack!
Offered under the Apache 2 license.
link |
Stars: 44 |
Last commit: Yesterday |
HTTPMetrics
to unary interceptors by @rebello95 in https://github.com/bufbuild/connect-swift/pull/109streamResultFunc
to streamResultFunction
by @rebello95 in https://github.com/bufbuild/connect-swift/pull/107sha256.txt
by @rebello95 in https://github.com/bufbuild/connect-swift/pull/114Full Changelog: https://github.com/bufbuild/connect-swift/compare/0.4.0...0.5.0
Swiftpack is being maintained by Petr Pavlik | @ptrpavlik | @swiftpackco | API | Analytics