Install EventSource via Xcode Package Dependency
mainIn Xcode, navigate to File > Swift Packages > Add Package Dependency and use the following URL:
https://github.com/Recouse/EventSource
https://github.com/Recouse/EventSourcerepository·main·Indexed 41 days ago
https://github.com/recouse/eventsourceA concurrency-safe Swift package for Server-Sent Events (SSE) that utilizes async/await and AsyncSequence to handle real-time updates from persistent HTTP connections. Supports standard SSE and a data-only mode optimized for streaming APIs like OpenAI.
In Xcode, navigate to File > Swift Packages > Add Package Dependency and use the following URL:
https://github.com/Recouse/EventSource
https://github.com/Recouse/EventSourceTo connect to an SSE endpoint, create an instance of EventSource, initiate a dataTask(for:) with a URLRequest, and iterate over the events using an AsyncSequence via dataTask.events().
Note: To explicitly close the connection, call task.cancel() on the parent Task. Note that if you cancel the task, the .closed event will not be emitted.
import EventSource
let task = Task {
let eventSource = EventSource()
let dataTask = eventSource.dataTask(for: urlRequest)
for await event in dataTask.events() {
switch event {
case .open:
print("Connection was opened.")
case .error(let error):
print("Received an error:", error.localizedDescription)
case .event(let event):
print("Received an event", event.data ?? "")
case .closed:
print("Connection was closed.")
}
}
}EventSource using Xcode Package Dependency or Swift Package Manager. After installation, import the module in your Swift files using import EventSource.import EventSourceAdd the package to your Package.swift dependencies and include it in your target's dependencies:
// In dependencies
.package(url: "https://github.com/Recouse/EventSource.git"),
// In your target
.target(name: "<target>", dependencies: [
.product(name: "EventSource", package: "EventSource"),
]),.package(url: "https://github.com/Recouse/EventSource.git"),
.target(name: "<target>", dependencies: [
.product(name: "EventSource", package: "EventSource"),
]),For APIs that primarily stream data (like OpenAI's completions API), initialize EventSource with mode: .dataOnly. This mode is optimized for handling streams where you only care about the data payload within the event.
Task {
var urlRequest = URLRequest(url: URL(string: "https://api.openai.com/v1/chat/completions")!)
urlRequest.allHTTPHeaderFields = [
"Content-Type": "application/json",
"Authorization": "Bearer \(accessToken)"
]
urlRequest.httpMethod = "POST"
urlRequest.httpBody = """
{
"model": "gpt-4o-mini",
"messages": [
{"role": "user", "content": "Why is the sky blue?"}
],
"stream": true
}
""".data(using: .utf8)!
let eventSource = EventSource(mode: .dataOnly)
let dataTask = eventSource.dataTask(for: urlRequest)
var response: String = ""
for await event in dataTask.events() {
switch event {
case .event(let event):
if let data = event.data?.data(using: .utf8) {
let chunk = try? JSONDecoder().decode(ChatCompletionChunk.self, from: data)
let string = chunk?.choices.first?.delta.content ?? ""
response += string
}
default:
break
}
}
print(response)
}EventSource is compatible with the following platforms: