From 721e732dc91170ca6adb650fa756e5b5fa7fdf2d Mon Sep 17 00:00:00 2001 From: Guilherme Souza Date: Tue, 21 Oct 2025 15:53:35 -0300 Subject: [PATCH 1/2] feat(functions): make FunctionsClient and actor --- Sources/Functions/FunctionsClient.swift | 57 +++++++++---------- .../xcshareddata/xcschemes/Functions.xcscheme | 10 ++++ .../FunctionsTests/FunctionsClientTests.swift | 34 +++++------ Tests/SupabaseTests/SupabaseClientTests.swift | 7 ++- 4 files changed, 58 insertions(+), 50 deletions(-) diff --git a/Sources/Functions/FunctionsClient.swift b/Sources/Functions/FunctionsClient.swift index f0037d106..d323aae26 100644 --- a/Sources/Functions/FunctionsClient.swift +++ b/Sources/Functions/FunctionsClient.swift @@ -1,4 +1,3 @@ -import ConcurrencyExtras import Foundation import HTTPTypes @@ -9,11 +8,12 @@ import HTTPTypes let version = Helpers.version /// An actor representing a client for invoking functions. -public final class FunctionsClient: Sendable { +public actor FunctionsClient { /// Fetch handler used to make requests. - public typealias FetchHandler = @Sendable (_ request: URLRequest) async throws -> ( - Data, URLResponse - ) + public typealias FetchHandler = + @Sendable (_ request: URLRequest) async throws -> ( + Data, URLResponse + ) /// Request idle timeout: 150s (If an Edge Function doesn't send a response before the timeout, 504 Gateway Timeout will be returned) /// @@ -26,19 +26,12 @@ public final class FunctionsClient: Sendable { /// The Region to invoke the functions in. let region: FunctionRegion? - struct MutableState { - /// Headers to be included in the requests. - var headers = HTTPFields() - } + /// Headers to be included in the requests. + var headers = HTTPFields() private let http: any HTTPClientType - private let mutableState = LockIsolated(MutableState()) private let sessionConfiguration: URLSessionConfiguration - var headers: HTTPFields { - mutableState.headers - } - /// Initializes a new instance of `FunctionsClient`. /// /// - Parameters: @@ -48,7 +41,7 @@ public final class FunctionsClient: Sendable { /// - logger: SupabaseLogger instance to use. /// - fetch: The fetch handler used to make requests. (Default: URLSession.shared.data(for:)) @_disfavoredOverload - public convenience init( + public init( url: URL, headers: [String: String] = [:], region: FunctionRegion? = nil, @@ -65,7 +58,7 @@ public final class FunctionsClient: Sendable { ) } - convenience init( + init( url: URL, headers: [String: String] = [:], region: FunctionRegion? = nil, @@ -101,11 +94,9 @@ public final class FunctionsClient: Sendable { self.http = http self.sessionConfiguration = sessionConfiguration - mutableState.withValue { - $0.headers = HTTPFields(headers) - if $0.headers[.xClientInfo] == nil { - $0.headers[.xClientInfo] = "functions-swift/\(version)" - } + self.headers = HTTPFields(headers) + if self.headers[.xClientInfo] == nil { + self.headers[.xClientInfo] = "functions-swift/\(version)" } } @@ -113,12 +104,10 @@ public final class FunctionsClient: Sendable { /// /// - Parameter token: The new JWT token sent in the authorization header. public func setAuth(token: String?) { - mutableState.withValue { - if let token { - $0.headers[.authorization] = "Bearer \(token)" - } else { - $0.headers[.authorization] = nil - } + if let token { + headers[.authorization] = "Bearer \(token)" + } else { + headers[.authorization] = nil } } @@ -136,7 +125,8 @@ public final class FunctionsClient: Sendable { decode: (Data, HTTPURLResponse) throws -> Response ) async throws -> Response { let response = try await rawInvoke( - functionName: functionName, invokeOptions: options + functionName: functionName, + invokeOptions: options ) return try decode(response.data, response.underlyingResponse) } @@ -208,7 +198,10 @@ public final class FunctionsClient: Sendable { let delegate = StreamResponseDelegate(continuation: continuation) let session = URLSession( - configuration: sessionConfiguration, delegate: delegate, delegateQueue: nil) + configuration: sessionConfiguration, + delegate: delegate, + delegateQueue: nil + ) let urlRequest = buildRequest(functionName: functionName, options: invokeOptions).urlRequest @@ -233,7 +226,7 @@ public final class FunctionsClient: Sendable { url: url.appendingPathComponent(functionName), method: FunctionInvokeOptions.httpMethod(options.method) ?? .post, query: query, - headers: mutableState.headers.merging(with: options.headers), + headers: headers.merging(with: options.headers), body: options.body, timeoutInterval: FunctionsClient.requestIdleTimeout ) @@ -264,7 +257,9 @@ final class StreamResponseDelegate: NSObject, URLSessionDataDelegate, Sendable { } func urlSession( - _: URLSession, dataTask _: URLSessionDataTask, didReceive response: URLResponse, + _: URLSession, + dataTask _: URLSessionDataTask, + didReceive response: URLResponse, completionHandler: @escaping (URLSession.ResponseDisposition) -> Void ) { defer { diff --git a/Supabase.xcworkspace/xcshareddata/xcschemes/Functions.xcscheme b/Supabase.xcworkspace/xcshareddata/xcschemes/Functions.xcscheme index 91fc09e07..5ff3d456a 100644 --- a/Supabase.xcworkspace/xcshareddata/xcschemes/Functions.xcscheme +++ b/Supabase.xcworkspace/xcshareddata/xcschemes/Functions.xcscheme @@ -28,6 +28,16 @@ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" shouldUseLaunchSchemeArgsEnv = "YES"> + + + + Date: Tue, 21 Oct 2025 15:55:21 -0300 Subject: [PATCH 2/2] drop disfavoredOverload --- Sources/Functions/FunctionsClient.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/Sources/Functions/FunctionsClient.swift b/Sources/Functions/FunctionsClient.swift index d323aae26..00590bc6e 100644 --- a/Sources/Functions/FunctionsClient.swift +++ b/Sources/Functions/FunctionsClient.swift @@ -40,7 +40,6 @@ public actor FunctionsClient { /// - region: The Region to invoke the functions in. /// - logger: SupabaseLogger instance to use. /// - fetch: The fetch handler used to make requests. (Default: URLSession.shared.data(for:)) - @_disfavoredOverload public init( url: URL, headers: [String: String] = [:],