/* * Copyright 2021 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import Foundation #if SWIFT_PACKAGE @_exported import FirebaseFirestoreInternalWrapper #else @_exported import FirebaseFirestoreInternal #endif // SWIFT_PACKAGE public extension DocumentReference { /// Fetches and decodes the document referenced by this `DocumentReference`. /// /// This allows users to retrieve a Firestore document and have it decoded to /// an instance of caller-specified type as follows: /// ```swift /// ref.getDocument(as: Book.self) { result in /// do { /// let book = try result.get() /// } catch { /// // Handle error /// } /// } /// ``` /// /// This method attempts to provide up-to-date data when possible by waiting /// for data from the server, but it may return cached data or fail if you are /// offline and the server cannot be reached. If `T` denotes an optional /// type, the method returns a successful status with a value of `nil` for /// non-existing documents. /// /// - Parameters: /// - as: A `Decodable` type to convert the document fields to. /// - serverTimestampBehavior: Configures how server timestamps that have /// not yet been set to their final value are returned from the snapshot. /// - decoder: The decoder to use to convert the document. Defaults to use /// the default decoder. /// - source: Indicates whether the results should be fetched from the cache only /// (`Source.cache`), the server only (`Source.server`), or to attempt the /// server and fall back to the cache (`Source.default`). /// - completion: The closure to call when the document snapshot has been /// fetched and decoded. func getDocument(as type: T.Type, with serverTimestampBehavior: ServerTimestampBehavior = .none, decoder: Firestore.Decoder = .init(), source: FirestoreSource = .default, completion: @escaping (Result) -> Void) { getDocument(source: source) { snapshot, error in guard let snapshot = snapshot else { /** * Force unwrapping here is fine since this logic corresponds to the auto-synthesized * async/await wrappers for Objective-C functions with callbacks taking an object and an error * parameter. The API should (and does) guarantee that either object or error is set, but never both. * For more details see: * https://github.com/firebase/firebase-ios-sdk/pull/9101#discussion_r809117034 */ completion(.failure(error!)) return } let result = Result { try snapshot.data(as: T.self, with: serverTimestampBehavior, decoder: decoder) } completion(result) } } /// Fetches and decodes the document referenced by this `DocumentReference`. /// /// This allows users to retrieve a Firestore document and have it decoded /// to an instance of caller-specified type as follows: /// ```swift /// do { /// let book = try await ref.getDocument(as: Book.self) /// } catch { /// // Handle error /// } /// ``` /// /// This method attempts to provide up-to-date data when possible by waiting /// for data from the server, but it may return cached data or fail if you /// are offline and the server cannot be reached. If `T` denotes /// an optional type, the method returns a successful status with a value /// of `nil` for non-existing documents. /// /// - Parameters: /// - as: A `Decodable` type to convert the document fields to. /// - serverTimestampBehavior: Configures how server timestamps that have /// not yet been set to their final value are returned from the /// snapshot. /// - decoder: The decoder to use to convert the document. Defaults to use /// the default decoder. /// - source: Indicates whether the results should be fetched from the cache only /// (`Source.cache`), the server only (`Source.server`), or to attempt the /// server and fall back to the cache (`Source.default`). /// - Returns: This instance of the supplied `Decodable` type `T`. @available(iOS 13, tvOS 13, macOS 10.15, macCatalyst 13, watchOS 7, *) func getDocument(as type: T.Type, with serverTimestampBehavior: ServerTimestampBehavior = .none, decoder: Firestore.Decoder = .init(), source: FirestoreSource = .default) async throws -> T { let snapshot = try await getDocument(source: source) return try snapshot.data(as: T.self, with: serverTimestampBehavior, decoder: decoder) } }