1
1
import Foundation
2
2
3
+ /// An actor representing a client for invoking functions.
3
4
public actor FunctionsClient {
5
+ /// Typealias for the fetch handler used to make requests.
4
6
public typealias FetchHandler = @Sendable ( _ request: URLRequest ) async throws -> (
5
7
Data , URLResponse
6
8
)
7
9
10
+ /// The base URL for the functions.
8
11
let url : URL
12
+ /// Headers to be included in the requests.
9
13
var headers : [ String : String ]
14
+ /// The fetch handler used to make requests.
10
15
let fetch : FetchHandler
11
16
17
+ /// Initializes a new instance of `FunctionsClient`.
18
+ ///
19
+ /// - Parameters:
20
+ /// - url: The base URL for the functions.
21
+ /// - headers: Headers to be included in the requests. (Default: empty dictionary)
22
+ /// - fetch: The fetch handler used to make requests. (Default: URLSession.shared.data(for:))
12
23
public init (
13
24
url: URL ,
14
25
headers: [ String : String ] = [ : ] ,
@@ -21,63 +32,70 @@ public actor FunctionsClient {
21
32
}
22
33
23
34
/// Updates the authorization header.
24
- /// - Parameter token: the new JWT token sent in the authorization header
35
+ ///
36
+ /// - Parameter token: The new JWT token sent in the authorization header.
25
37
public func setAuth( token: String ) {
26
38
headers [ " Authorization " ] = " Bearer \( token) "
27
39
}
28
40
29
- /// Invokes a function.
41
+ /// Invokes a function and decodes the response.
42
+ ///
30
43
/// - Parameters:
31
- /// - functionName: the name of the function to invoke.
44
+ /// - functionName: The name of the function to invoke.
45
+ /// - invokeOptions: Options for invoking the function. (Default: empty `FunctionInvokeOptions`)
46
+ /// - decode: A closure to decode the response data and HTTPURLResponse into a `Response` object.
47
+ /// - Returns: The decoded `Response` object.
32
48
public func invoke< Response> (
33
49
functionName: String ,
34
50
invokeOptions: FunctionInvokeOptions = . init( ) ,
35
51
decode: ( Data , HTTPURLResponse ) throws -> Response
36
52
) async throws -> Response {
37
53
let ( data, response) = try await rawInvoke (
38
- functionName: functionName,
39
- invokeOptions: invokeOptions
40
- )
54
+ functionName: functionName, invokeOptions: invokeOptions)
41
55
return try decode ( data, response)
42
56
}
43
57
44
- /// Invokes a function.
58
+ /// Invokes a function and decodes the response as a specific type.
59
+ ///
45
60
/// - Parameters:
46
- /// - functionName: the name of the function to invoke.
61
+ /// - functionName: The name of the function to invoke.
62
+ /// - invokeOptions: Options for invoking the function. (Default: empty `FunctionInvokeOptions`)
63
+ /// - decoder: The JSON decoder to use for decoding the response. (Default: `JSONDecoder()`)
64
+ /// - Returns: The decoded object of type `T`.
47
65
public func invoke< T: Decodable > (
48
66
functionName: String ,
49
67
invokeOptions: FunctionInvokeOptions = . init( ) ,
50
68
decoder: JSONDecoder = JSONDecoder ( )
51
69
) async throws -> T {
52
- try await invoke (
53
- functionName: functionName,
54
- invokeOptions: invokeOptions,
55
- decode: { data, _ in try decoder. decode ( T . self, from: data) }
56
- )
70
+ try await invoke ( functionName: functionName, invokeOptions: invokeOptions) { data, _ in
71
+ try decoder. decode ( T . self, from: data)
72
+ }
57
73
}
58
74
59
- /// Invokes a function.
75
+ /// Invokes a function without expecting a response.
76
+ ///
60
77
/// - Parameters:
61
- /// - functionName: the name of the function to invoke.
78
+ /// - functionName: The name of the function to invoke.
79
+ /// - invokeOptions: Options for invoking the function. (Default: empty `FunctionInvokeOptions`)
62
80
public func invoke(
63
81
functionName: String ,
64
82
invokeOptions: FunctionInvokeOptions = . init( )
65
83
) async throws {
66
- try await invoke (
67
- functionName: functionName,
68
- invokeOptions: invokeOptions,
69
- decode: { _, _ in ( ) }
70
- )
84
+ try await invoke ( functionName: functionName, invokeOptions: invokeOptions) { _, _ in ( ) }
71
85
}
72
86
73
87
private func rawInvoke(
74
88
functionName: String ,
75
89
invokeOptions: FunctionInvokeOptions
76
90
) async throws -> ( Data , HTTPURLResponse ) {
77
91
let url = self . url. appendingPathComponent ( functionName)
78
-
79
92
var urlRequest = URLRequest ( url: url)
80
- urlRequest. allHTTPHeaderFields = invokeOptions. headers. merging ( headers) { first, _ in first }
93
+
94
+ let headers = invokeOptions. headers. merging ( self . headers) { invokeOption, _ in invokeOption }
95
+ headers. forEach { key, value in
96
+ urlRequest. setValue ( value, forHTTPHeaderField: key)
97
+ }
98
+
81
99
urlRequest. httpMethod = " POST "
82
100
urlRequest. httpBody = invokeOptions. body
83
101
0 commit comments