/* * Copyright 2018 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. */ #ifndef FIREBASE_FIRESTORE_SRC_INCLUDE_FIREBASE_FIRESTORE_H_ #define FIREBASE_FIRESTORE_SRC_INCLUDE_FIREBASE_FIRESTORE_H_ #include #include #include "firebase/internal/common.h" #include "firebase/app.h" #include "firebase/future.h" #include "firebase/log.h" // Include *all* the public headers to make sure including just "firestore.h" is // sufficient for users. #include "firebase/firestore/aggregate_query.h" #include "firebase/firestore/aggregate_query_snapshot.h" #include "firebase/firestore/aggregate_source.h" #include "firebase/firestore/collection_reference.h" #include "firebase/firestore/document_change.h" #include "firebase/firestore/document_reference.h" #include "firebase/firestore/document_snapshot.h" #include "firebase/firestore/field_path.h" #include "firebase/firestore/field_value.h" #include "firebase/firestore/filter.h" #include "firebase/firestore/firestore_errors.h" #include "firebase/firestore/geo_point.h" #include "firebase/firestore/listener_registration.h" #include "firebase/firestore/load_bundle_task_progress.h" #include "firebase/firestore/map_field_value.h" #include "firebase/firestore/metadata_changes.h" #include "firebase/firestore/query.h" #include "firebase/firestore/query_snapshot.h" #include "firebase/firestore/set_options.h" #include "firebase/firestore/settings.h" #include "firebase/firestore/snapshot_metadata.h" #include "firebase/firestore/source.h" #include "firebase/firestore/timestamp.h" #include "firebase/firestore/transaction.h" #include "firebase/firestore/transaction_options.h" #include "firebase/firestore/write_batch.h" namespace firebase { /** * @brief Cloud Firestore API. * * Cloud Firestore is a flexible, scalable database for mobile, web, and server * development from Firebase and Google Cloud Platform. */ namespace firestore { class FirestoreInternal; namespace csharp { class ApiHeaders; class TransactionManager; } // namespace csharp /** The default name for "unset" database ID in resource names. */ static const char* kDefaultDatabase = "(default)"; /** * @brief Entry point for the Firebase Firestore C++ SDK. * * To use the SDK, call firebase::firestore::Firestore::GetInstance() to obtain * an instance of Firestore, then use Collection() or Document() to obtain * references to child paths within the database. From there, you can set data * via CollectionReference::Add() and DocumentReference::Set(), or get data via * CollectionReference::Get() and DocumentReference::Get(), attach listeners, * and more. * * @note Firestore classes are not meant to be subclassed except for use in test * mocks. Subclassing is not supported in production code and new SDK releases * may break code that does so. */ class Firestore { public: /** * @brief Returns an instance of Firestore corresponding to the given App * with default database ID. * * Firebase Firestore uses firebase::App to communicate with Firebase * Authentication to authenticate users to the Firestore server backend. * * If you call GetInstance() multiple times with the same App, you will get * the same instance of Firestore. * * @param[in] app Your instance of firebase::App. Firebase Firestore will use * this to communicate with Firebase Authentication. * @param[out] init_result_out If provided, the initialization result will be * written here. Will be set to firebase::kInitResultSuccess if initialization * succeeded, or firebase::kInitResultFailedMissingDependency on Android if * Google Play services is not available on the current device. * * @return An instance of Firestore corresponding to the given App with * default database ID. */ static Firestore* GetInstance(::firebase::App* app, InitResult* init_result_out = nullptr); /** * @brief Returns an instance of Firestore corresponding to the default App * with default database ID. * * Firebase Firestore uses the default App to communicate with Firebase * Authentication to authenticate users to the Firestore server backend. * * If you call GetInstance() multiple times, you will get the same instance. * * @param[out] init_result_out If provided, the initialization result will be * written here. Will be set to firebase::kInitResultSuccess if initialization * succeeded, or firebase::kInitResultFailedMissingDependency on Android if * Google Play services is not available on the current device. * * @return An instance of Firestore corresponding to the default App * with default database ID. */ static Firestore* GetInstance(InitResult* init_result_out = nullptr); /** * @brief Returns an instance of Firestore corresponding to the given App with * the given database ID. * * Firebase Firestore uses firebase::App to communicate with Firebase * Authentication to authenticate users to the Firestore server backend. * * If you call GetInstance() multiple times with the same App, you will get * the same instance of Firestore. * * @param[in] app Your instance of firebase::App. Firebase Firestore will use * this to communicate with Firebase Authentication. * @param[in] db_name Name of the database. Firebase Firestore will use * this to communicate with Firebase Authentication. * @param[out] init_result_out If provided, the initialization result will be * written here. Will be set to firebase::kInitResultSuccess if initialization * succeeded, or firebase::kInitResultFailedMissingDependency on Android if * Google Play services is not available on the current device. * * @return An instance of Firestore corresponding to the given App with * the given database ID. */ static Firestore* GetInstance(::firebase::App* app, const char* db_name, InitResult* init_result_out = nullptr); /** * @brief Returns an instance of Firestore corresponding to the default App * with the given database ID. * * Firebase Firestore uses firebase::App to communicate with Firebase * Authentication to authenticate users to the Firestore server backend. * * If you call GetInstance() multiple times with the same App, you will get * the same instance of Firestore. * * @param[in] db_name Name of the database. Firebase Firestore will use * this to communicate with Firebase Authentication. * @param[out] init_result_out If provided, the initialization result will be * written here. Will be set to firebase::kInitResultSuccess if initialization * succeeded, or firebase::kInitResultFailedMissingDependency on Android if * Google Play services is not available on the current device. * * @return An instance of Firestore corresponding to the default App with * the given database ID. */ static Firestore* GetInstance(const char* db_name, InitResult* init_result_out = nullptr); /** * @brief Destructor for the Firestore object. * * When deleted, this instance will be removed from the cache of Firestore * objects. If you call GetInstance() in the future with the same App, a new * Firestore instance will be created. */ virtual ~Firestore(); /** * Deleted copy constructor; Firestore must be created with * Firestore::GetInstance(). */ Firestore(const Firestore& src) = delete; /** * Deleted copy assignment operator; Firestore must be created with * Firestore::GetInstance(). */ Firestore& operator=(const Firestore& src) = delete; /** * @brief Returns the firebase::App that this Firestore was created with. * * @return The firebase::App this Firestore was created with. */ virtual const App* app() const; /** * @brief Returns the firebase::App that this Firestore was created with. * * @return The firebase::App this Firestore was created with. */ virtual App* app(); /** * @brief Returns a CollectionReference instance that refers to the * collection at the specified path within the database. * * @param[in] collection_path A slash-separated path to a collection. * * @return The CollectionReference instance. */ virtual CollectionReference Collection(const char* collection_path) const; /** * @brief Returns a CollectionReference instance that refers to the * collection at the specified path within the database. * * @param[in] collection_path A slash-separated path to a collection. * * @return The CollectionReference instance. */ virtual CollectionReference Collection( const std::string& collection_path) const; /** * @brief Returns a DocumentReference instance that refers to the document at * the specified path within the database. * * @param[in] document_path A slash-separated path to a document. * @return The DocumentReference instance. */ virtual DocumentReference Document(const char* document_path) const; /** * @brief Returns a DocumentReference instance that refers to the document at * the specified path within the database. * * @param[in] document_path A slash-separated path to a document. * * @return The DocumentReference instance. */ virtual DocumentReference Document(const std::string& document_path) const; /** * @brief Returns a Query instance that includes all documents in the * database that are contained in a collection or subcollection with the * given collection_id. * * @param[in] collection_id Identifies the collections to query over. Every * collection or subcollection with this ID as the last segment of its path * will be included. Cannot contain a slash. * * @return The Query instance. */ virtual Query CollectionGroup(const char* collection_id) const; /** * @brief Returns a Query instance that includes all documents in the * database that are contained in a collection or subcollection with the * given collection_id. * * @param[in] collection_id Identifies the collections to query over. Every * collection or subcollection with this ID as the last segment of its path * will be included. Cannot contain a slash. * * @return The Query instance. */ virtual Query CollectionGroup(const std::string& collection_id) const; /** Returns the settings used by this Firestore object. */ virtual Settings settings() const; /** Sets any custom settings used to configure this Firestore object. */ virtual void set_settings(Settings settings); /** * Creates a write batch, used for performing multiple writes as a single * atomic operation. * * Unlike transactions, write batches are persisted offline and therefore are * preferable when you don't need to condition your writes on read data. * * @return The created WriteBatch object. */ virtual WriteBatch batch() const; /** * Executes the given update and then attempts to commit the changes applied * within the transaction. If any document read within the transaction has * changed, the update function will be retried. If it fails to commit after * 5 attempts, the transaction will fail. * * @param update function or lambda to execute within the transaction context. * The string reference parameter can be used to set the error message. * * @return A Future that will be resolved when the transaction finishes. */ virtual Future RunTransaction( std::function update); /** * Executes the given update and then attempts to commit the changes applied * within the transaction. If any document read within the transaction has * changed, the update function will be retried. If it fails to commit after * the `max_attempts` specified in the given `TransactionOptions`, the * transaction will fail. * * @param options The transaction options for controlling execution. * @param update function or lambda to execute within the transaction context. * The string reference parameter can be used to set the error message. * * @return A Future that will be resolved when the transaction finishes. */ virtual Future RunTransaction( TransactionOptions options, std::function update); /** * Sets the log verbosity of all Firestore instances. * * The default verbosity level is `kLogLevelInfo`. * * @param[in] log_level The desired verbosity. */ static void set_log_level(LogLevel log_level); /** * Disables network access for this instance. While the network is disabled, * any snapshot listeners or Get() calls will return results from cache, and * any write operations will be queued until network usage is re-enabled via a * call to EnableNetwork(). * * If the network was already disabled, calling `DisableNetwork()` again is * a no-op. */ virtual Future DisableNetwork(); /** * Re-enables network usage for this instance after a prior call to * DisableNetwork(). * * If the network is currently enabled, calling `EnableNetwork()` is a no-op. */ virtual Future EnableNetwork(); /** * Terminates this `Firestore` instance. * * After calling `Terminate()`, only the `ClearPersistence()` method may be * used. Calling any other methods will result in an error. * * To restart after termination, simply create a new instance of `Firestore` * with `Firestore::GetInstance()`. * * `Terminate()` does not cancel any pending writes and any tasks that are * awaiting a response from the server will not be resolved. The next time you * start this instance, it will resume attempting to send these writes to the * server. * * Note: under normal circumstances, calling `Terminate()` is not required. * This method is useful only when you want to force this instance to release * all of its resources or in combination with `ClearPersistence()` to ensure * that all local state is destroyed between test runs. * * @return A `Future` that is resolved when the instance has been successfully * terminated. */ virtual Future Terminate(); /** * Waits until all currently pending writes for the active user have been * acknowledged by the backend. * * The returned future is resolved immediately without error if there are no * outstanding writes. Otherwise, the future is resolved when all previously * issued writes (including those written in a previous app session) have been * acknowledged by the backend. The future does not wait for writes that were * added after the method is called. If you wish to wait for additional * writes, you have to call `WaitForPendingWrites` again. * * Any outstanding `WaitForPendingWrites` futures are resolved with an * error during user change. */ virtual Future WaitForPendingWrites(); /** * Clears the persistent storage. This includes pending writes and cached * documents. * * Must be called while the Firestore instance is not started (after the app * is shut down or when the app is first initialized). On startup, this method * must be called before other methods (other than `settings()` and * `set_settings()`). If the Firestore instance is still running, the function * will complete with an error code of `FailedPrecondition`. * * Note: `ClearPersistence()` is primarily intended to help write * reliable tests that use Firestore. It uses the most efficient mechanism * possible for dropping existing data but does not attempt to securely * overwrite or otherwise make cached data unrecoverable. For applications * that are sensitive to the disclosure of cache data in between user sessions * we strongly recommend not to enable persistence in the first place. */ virtual Future ClearPersistence(); /** * Attaches a listener for a snapshots-in-sync event. Server-generated * updates and local changes can affect multiple snapshot listeners. * The snapshots-in-sync event indicates that all listeners affected by * a given change have fired. * * NOTE: The snapshots-in-sync event only indicates that listeners are * in sync with each other, but does not relate to whether those * snapshots are in sync with the server. Use `SnapshotMetadata` in the * individual listeners to determine if a snapshot is from the cache or * the server. * * @param callback A callback to be called every time all snapshot * listeners are in sync with each other. * @return A `ListenerRegistration` object that can be used to remove the * listener. */ virtual ListenerRegistration AddSnapshotsInSyncListener( std::function callback); /** * Loads a Firestore bundle into the local cache. * * @param bundle A string containing the bundle to be loaded. * @return A `Future` that is resolved when the loading is either completed * or aborted due to an error. */ virtual Future LoadBundle(const std::string& bundle); /** * Loads a Firestore bundle into the local cache, with the provided callback * executed for progress updates. * * @param bundle A string containing the bundle to be loaded. * @param progress_callback A callback that is called with progress * updates, and completion or error updates. * @return A `Future` that is resolved when the loading is either completed * or aborted due to an error. */ virtual Future LoadBundle( const std::string& bundle, std::function progress_callback); /** * Reads a Firestore `Query` from the local cache, identified by the given * name. * * Named queries are packaged into bundles on the server side (along with the * resulting documents) and loaded into local cache using `LoadBundle`. Once * in the local cache, you can use this method to extract a query by name. * * If a query cannot be found, the returned future will complete with its * `error()` set to a non-zero error code. * * @param query_name The name of the query to read from saved bundles. */ virtual Future NamedQuery(const std::string& query_name); protected: /** * Default constructor, to be used only for mocking `Firestore`. */ Firestore() = default; private: friend class FieldValueInternal; friend class FirestoreInternal; friend class Wrapper; friend struct ConverterImpl; friend class FirestoreIntegrationTest; friend class IncludesTest; template friend struct CleanupFn; friend class csharp::ApiHeaders; friend class csharp::TransactionManager; explicit Firestore(::firebase::App* app, const std::string& database_id = kDefaultDatabase); explicit Firestore(FirestoreInternal* internal); static Firestore* CreateFirestore(::firebase::App* app, FirestoreInternal* internal, InitResult* init_result_out); static Firestore* AddFirestoreToCache(Firestore* firestore, InitResult* init_result_out); static void SetClientLanguage(const std::string& language_token); // Delete the internal_ data. void DeleteInternal(); mutable FirestoreInternal* internal_ = nullptr; }; } // namespace firestore } // namespace firebase #endif // FIREBASE_FIRESTORE_SRC_INCLUDE_FIREBASE_FIRESTORE_H_