HTTPSCallable.swift 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. // Copyright 2022 Google LLC
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. import Foundation
  15. private import FirebaseCoreInternal
  16. /// A `HTTPSCallableResult` contains the result of calling a `HTTPSCallable`.
  17. @objc(FIRHTTPSCallableResult)
  18. open class HTTPSCallableResult: NSObject {
  19. /// The data that was returned from the Callable HTTPS trigger.
  20. ///
  21. /// The data is in the form of native objects. For example, if your trigger returned an
  22. /// array, this object would be an `Array<Any>`. If your trigger returned a JavaScript object with
  23. /// keys and values, this object would be an instance of `[String: Any]`.
  24. @objc public let data: Any
  25. init(data: Any) {
  26. self.data = data
  27. }
  28. }
  29. /// A `HTTPSCallable` is a reference to a particular Callable HTTPS trigger in Cloud Functions.
  30. @objc(FIRHTTPSCallable)
  31. public final class HTTPSCallable: NSObject, Sendable {
  32. // MARK: - Private Properties
  33. // The functions client to use for making calls.
  34. private let functions: Functions
  35. private let url: URL
  36. private let options: HTTPSCallableOptions?
  37. private let _timeoutInterval: UnfairLock<TimeInterval> = .init(70)
  38. // MARK: - Public Properties
  39. /// The timeout to use when calling the function. Defaults to 70 seconds.
  40. @objc public var timeoutInterval: TimeInterval {
  41. get { _timeoutInterval.value() }
  42. set {
  43. _timeoutInterval.withLock { timeoutInterval in
  44. timeoutInterval = newValue
  45. }
  46. }
  47. }
  48. init(functions: Functions, url: URL, options: HTTPSCallableOptions? = nil) {
  49. self.functions = functions
  50. self.url = url
  51. self.options = options
  52. }
  53. /// Executes this Callable HTTPS trigger asynchronously.
  54. ///
  55. /// The data passed into the trigger can be any of the following types:
  56. /// - `nil` or `NSNull`
  57. /// - `String`
  58. /// - `NSNumber`, or any Swift numeric type bridgeable to `NSNumber`
  59. /// - `[Any]`, where the contained objects are also one of these types.
  60. /// - `[String: Any]` where the values are also one of these types.
  61. ///
  62. /// The request to the Cloud Functions backend made by this method automatically includes a
  63. /// Firebase Installations ID token to identify the app instance. If a user is logged in with
  64. /// Firebase Auth, an auth ID token for the user is also automatically included.
  65. ///
  66. /// Firebase Cloud Messaging sends data to the Firebase backend periodically to collect
  67. /// information
  68. /// regarding the app instance. To stop this, see `Messaging.deleteData()`. It
  69. /// resumes with a new FCM Token the next time you call this method.
  70. ///
  71. /// - Parameters:
  72. /// - data: Parameters to pass to the trigger.
  73. /// - completion: The block to call when the HTTPS request has completed.
  74. @available(swift 1000.0) // Objective-C only API
  75. @objc(callWithObject:completion:) public func call(_ data: Any? = nil,
  76. completion: @escaping @MainActor (HTTPSCallableResult?,
  77. Error?)
  78. -> Void) {
  79. call(SendableWrapper(value: data as Any), completion: completion)
  80. }
  81. /// Executes this Callable HTTPS trigger asynchronously.
  82. ///
  83. /// The data passed into the trigger can be any of the following types:
  84. /// - `nil` or `NSNull`
  85. /// - `String`
  86. /// - `NSNumber`, or any Swift numeric type bridgeable to `NSNumber`
  87. /// - `[Any]`, where the contained objects are also one of these types.
  88. /// - `[String: Any]` where the values are also one of these types.
  89. ///
  90. /// The request to the Cloud Functions backend made by this method automatically includes a
  91. /// Firebase Installations ID token to identify the app instance. If a user is logged in with
  92. /// Firebase Auth, an auth ID token for the user is also automatically included.
  93. ///
  94. /// Firebase Cloud Messaging sends data to the Firebase backend periodically to collect
  95. /// information
  96. /// regarding the app instance. To stop this, see `Messaging.deleteData()`. It
  97. /// resumes with a new FCM Token the next time you call this method.
  98. ///
  99. /// - Parameters:
  100. /// - data: Parameters to pass to the trigger.
  101. /// - completion: The block to call when the HTTPS request has completed.
  102. @nonobjc public func call(_ data: sending Any? = nil,
  103. completion: @escaping @MainActor (HTTPSCallableResult?,
  104. Error?)
  105. -> Void) {
  106. let data = (data as? SendableWrapper)?.value ?? data
  107. Task {
  108. do {
  109. let result = try await call(data)
  110. await completion(result, nil)
  111. } catch {
  112. await completion(nil, error)
  113. }
  114. }
  115. }
  116. /// Executes this Callable HTTPS trigger asynchronously. This API should only be used from
  117. /// Objective-C.
  118. ///
  119. /// The request to the Cloud Functions backend made by this method automatically includes a
  120. /// Firebase Installations ID token to identify the app instance. If a user is logged in with
  121. /// Firebase Auth, an auth ID token for the user is also automatically included.
  122. ///
  123. /// Firebase Cloud Messaging sends data to the Firebase backend periodically to collect
  124. /// information
  125. /// regarding the app instance. To stop this, see `Messaging.deleteData()`. It
  126. /// resumes with a new FCM Token the next time you call this method.
  127. ///
  128. /// - Parameter completion: The block to call when the HTTPS request has completed.
  129. @objc(callWithCompletion:) public func __call(completion: @escaping @MainActor (HTTPSCallableResult?,
  130. Error?) -> Void) {
  131. call(nil, completion: completion)
  132. }
  133. /// Executes this Callable HTTPS trigger asynchronously.
  134. ///
  135. /// The request to the Cloud Functions backend made by this method automatically includes a
  136. /// FCM token to identify the app instance. If a user is logged in with Firebase
  137. /// Auth, an auth ID token for the user is also automatically included.
  138. ///
  139. /// Firebase Cloud Messaging sends data to the Firebase backend periodically to collect
  140. /// information
  141. /// regarding the app instance. To stop this, see `Messaging.deleteData()`. It
  142. /// resumes with a new FCM Token the next time you call this method.
  143. ///
  144. /// - Parameter data: Parameters to pass to the trigger.
  145. /// - Throws: An error if the Cloud Functions invocation failed.
  146. /// - Returns: The result of the call.
  147. public func call(_ data: Any? = nil) async throws -> sending HTTPSCallableResult {
  148. try await functions
  149. .callFunction(at: url, withObject: data, options: options, timeout: timeoutInterval)
  150. }
  151. @available(macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0, *)
  152. func stream(_ data: SendableWrapper? = nil) -> AsyncThrowingStream<JSONStreamResponse, Error> {
  153. functions.stream(at: url, data: data, options: options, timeout: timeoutInterval)
  154. }
  155. }