supabase / supabase-swift

A Swift client for Supabase

Home Page:https://supabase.com/docs/reference/swift

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Ability to stream function responses

tmcgann-neotax opened this issue · comments

Feature request

Is your feature request related to a problem? Please describe.

Want to stream function responses. Use case: stream chat completions from AI provider.

Describe the solution you'd like

Would love to augment the FunctionsClient to be able to stream data from a function response. Rough example of solution:

/// Implement the StreamResponseHandler protocol to handle the streamed data.
/// You could append received data chunks to a buffer, process data as it arrives, 
/// or update the UI (updates would be dispatched on the main thread).
protocol StreamResponseHandler {
    func didReceive(data: Data)
    func didCompleteWithError(_ error: Error?)
}

class StreamDataTaskHandler: NSObject, URLSessionDataDelegate {
    let streamHandler: StreamResponseHandler

    init(streamHandler: StreamResponseHandler) {
        self.streamHandler = streamHandler
    }

    func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
        // Forward the received data to the stream handler
        streamHandler.didReceive(data: data)
    }

    func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
        // Notify the stream handler about completion or error
        streamHandler.didCompleteWithError(error)
    }
}

extension FunctionsClient {
    public func invokeWithStream(
        _ functionName: String,
        options: FunctionInvokeOptions = .init(),
        streamHandler: StreamResponseHandler
    ) async throws {
        // Setup URLSession with StreamDataTaskHandler as delegate
        let delegate = StreamDataTaskHandler(streamHandler: streamHandler)
        let session = URLSession(configuration: .default, delegate: delegate, delegateQueue: nil)
        
        // Rest of the setup similar to `rawInvoke`, but use the session with delegate
        let url = self.url.appendingPathComponent(functionName)
        var urlRequest = URLRequest(url: url)
        urlRequest.allHTTPHeaderFields = options.headers.merging(headers) { invoke, _ in invoke }
        urlRequest.httpMethod = (options.method ?? .post).rawValue
        urlRequest.httpBody = options.body
        
        // Start the data task
        let task = session.dataTask(with: urlRequest)
        task.resume()
        
        // Ensure to keep the session and delegate alive as long as needed
        // This may require storing references in the FunctionsClient or managing lifecycle appropriately
    }
}

Describe alternatives you've considered

Make the request to the function outside of supabase-swift.

Additional context

Open to alternatives, especially if this is somehow already supported and I missed it.

Going to recreate with my non-work github account. :)