@google-cloud/firestore
Version:
Firestore Client Library for Node.js
1,226 lines (1,150 loc) • 128 kB
TypeScript
/*!
* Copyright 2020 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.
*/
// We deliberately use `any` in the external API to not impose type-checking
// on end users.
/* eslint-disable @typescript-eslint/no-explicit-any */
// Declare a global (ambient) namespace
// (used when not using import statement, but just script include).
declare namespace FirebaseFirestore {
/** Alias for `any` but used where a Firestore field value would be provided. */
export type DocumentFieldValue = any;
/**
* Document data (for use with `DocumentReference.set()`) consists of fields
* mapped to values.
*/
export type DocumentData = {[field: string]: DocumentFieldValue};
/**
* Similar to Typescript's `Partial<T>`, but allows nested fields to be
* omitted and FieldValues to be passed in as property values.
*/
export type PartialWithFieldValue<T> =
| Partial<T>
| (T extends Primitive
? T
: T extends {}
? {
[K in keyof T]?: T[K] extends Function
? T[K]
: PartialWithFieldValue<T[K]> | FieldValue;
}
: never);
/**
* Allows FieldValues to be passed in as a property value while maintaining
* type safety.
*/
export type WithFieldValue<T> =
| T
| (T extends Primitive
? T
: T extends {}
? {
[K in keyof T]: T[K] extends Function
? T[K]
: WithFieldValue<T[K]> | FieldValue;
}
: never);
/**
* Update data (for use with [update]{@link DocumentReference#update})
* that contains paths mapped to values. Fields that contain dots reference
* nested fields within the document. FieldValues can be passed in
* as property values.
*
* You can update a top-level field in your document by using the field name
* as a key (e.g. `foo`). The provided value completely replaces the contents
* for this field.
*
* You can also update a nested field directly by using its field path as a
* key (e.g. `foo.bar`). This nested field update replaces the contents at
* `bar` but does not modify other data under `foo`.
*/
export type UpdateData<T> = T extends Primitive
? T
: T extends {}
? {
// If `string extends K`, this is an index signature like
// `{[key: string]: { foo: bool }}`. In the generated UpdateData
// indexed properties can match their type or any child types.
[K in keyof T]?: string extends K
? PartialWithFieldValue<ChildTypes<T[K]>>
: UpdateData<T[K]> | FieldValue;
} & NestedUpdateFields<T>
: Partial<T>;
/**
* For the given type, return a union type of T
* and the types of all child properties of T.
*/
export type ChildTypes<T> =
T extends Record<string, unknown>
?
| {
[K in keyof T & string]: ChildTypes<T[K]>;
}[keyof T & string]
| T
: T;
/** Primitive types. */
export type Primitive = string | number | boolean | undefined | null;
/**
* For each field (e.g. 'bar'), find all nested keys (e.g. {'bar.baz': T1,
* 'bar.qux': T2}). Intersect them together to make a single map containing
* all possible keys that are all marked as optional
*/
export type NestedUpdateFields<T extends Record<string, unknown>> =
UnionToIntersection<
{
// If `string extends K`, this is an index signature like
// `{[key: string]: { foo: bool }}`. We map these properties to
// `never`, which prevents prefixing a nested key with `[string]`.
// We don't want to generate a field like `[string].foo: bool`.
[K in keyof T & string]: string extends K
? never
: ChildUpdateFields<K, T[K]>;
}[keyof T & string] // Also include the generated prefix-string keys.
>;
/**
* Helper for calculating the nested fields for a given type T1. This is needed
* to distribute union types such as `undefined | {...}` (happens for optional
* props) or `{a: A} | {b: B}`.
*
* In this use case, `V` is used to distribute the union types of `T[K]` on
* `Record`, since `T[K]` is evaluated as an expression and not distributed.
*
* See https://www.typescriptlang.org/docs/handbook/advanced-types.html#distributive-conditional-types
*/
export type ChildUpdateFields<K extends string, V> =
// Only allow nesting for map values
V extends Record<string, unknown>
? // Recurse into the map and add the prefix in front of each key
// (for example prefix 'bar.' to create: 'bar.baz' and 'bar.qux').
AddPrefixToKeys<K, UpdateData<V>>
: // UpdateData is always a map of values.
never;
/**
* Returns a new map where every key is prefixed with the outer key appended
* to a dot.
*/
export type AddPrefixToKeys<
Prefix extends string,
T extends Record<string, unknown>,
> =
// Remap K => Prefix.K. See https://www.typescriptlang.org/docs/handbook/2/mapped-types.html#key-remapping-via-as
// `string extends K : ...` is used to detect index signatures
// like `{[key: string]: bool}`. We map these properties to type `any`
// because a field path like `foo.[string]` will match `foo.bar` or a
// sub-path `foo.bar.baz`. Because it matches a sub-path, we have to
// make this type a union to including all types of the sub-path properties.
// This is a significant downside to using index signatures in types for `T`
// for `UpdateData<T>`.
{
[K in keyof T & string as `${Prefix}.${K}`]+?: string extends K
? ChildTypes<T[K]>
: T[K];
};
/**
* Given a union type `U = T1 | T2 | ...`, returns an intersected type
* `(T1 & T2 & ...)`.
*
* Uses distributive conditional types and inference from conditional types.
* This works because multiple candidates for the same type variable in
* contra-variant positions causes an intersection type to be inferred.
* https://www.typescriptlang.org/docs/handbook/advanced-types.html#type-inference-in-conditional-types
* https://stackoverflow.com/questions/50374908/transform-union-type-to-intersection-type
*/
export type UnionToIntersection<U> = (
U extends unknown ? (k: U) => void : never
) extends (k: infer I) => void
? I
: never;
/**
* Sets or disables the log function for all active Firestore instances.
*
* @param logger A log function that takes a message (such as `console.log`) or
* `null` to turn off logging.
*/
function setLogFunction(logger: ((msg: string) => void) | null): void;
/**
* Converter used by `withConverter()` to transform user objects of type
* `AppModelType` into Firestore data of type `DbModelType`.
*
* Using the converter allows you to specify generic type arguments when
* storing and retrieving objects from Firestore.
*
* In this context, an "AppModel" is a class that is used in an application to
* package together related information and functionality. Such a class could,
* for example, have properties with complex, nested data types, properties
* used for memoization, properties of types not supported by Firestore (such
* as `symbol` and `bigint`), and helper functions that perform compound
* operations. Such classes are not suitable and/or possible to store into a
* Firestore database. Instead, instances of such classes need to be converted
* to "plain old JavaScript objects" (POJOs) with exclusively primitive
* properties, potentially nested inside other POJOs or arrays of POJOs. In
* this context, this type is referred to as the "DbModel" and would be an
* object suitable for persisting into Firestore. For convenience,
* applications can implement `FirestoreDataConverter` and register the
* converter with Firestore objects, such as `DocumentReference` or `Query`,
* to automatically convert `AppModel` to `DbModel` when storing into
* Firestore, and convert `DbModel` to `AppModel` when retrieving from
* Firestore.
*
* @example
*
* Simple Example
*
* const numberConverter = {
* toFirestore(value: WithFieldValue<number>) {
* return { value };
* },
* fromFirestore(snapshot: QueryDocumentSnapshot) {
* return snapshot.data().value as number;
* }
* };
*
* async function simpleDemo(db: Firestore): Promise<void> {
* const documentRef = db.doc('values/value123').withConverter(numberConverter);
*
* // converters are used with `setDoc`, `addDoc`, and `getDoc`
* await documentRef.set(42);
* const snapshot1 = await documentRef.get();
* assertEqual(snapshot1.data(), 42);
*
* // converters are not used when writing data with `updateDoc`
* await documentRef.update({ value: 999 });
* const snapshot2 = await documentRef.get();
* assertEqual(snapshot2.data(), 999);
* }
*
* Advanced Example
*
* // The Post class is a model that is used by our application.
* // This class may have properties and methods that are specific
* // to our application execution, which do not need to be persisted
* // to Firestore.
* class Post {
* constructor(
* readonly title: string,
* readonly author: string,
* readonly lastUpdatedMillis: number
* ) {}
* toString(): string {
* return `${this.title} by ${this.author}`;
* }
* }
*
* // The PostDbModel represents how we want our posts to be stored
* // in Firestore. This DbModel has different properties (`ttl`,
* // `aut`, and `lut`) from the Post class we use in our application.
* interface PostDbModel {
* ttl: string;
* aut: { firstName: string; lastName: string };
* lut: Timestamp;
* }
*
* // The `PostConverter` implements `FirestoreDataConverter` and specifies
* // how the Firestore SDK can convert `Post` objects to `PostDbModel`
* // objects and vice versa.
* class PostConverter implements FirestoreDataConverter<Post, PostDbModel> {
* toFirestore(post: WithFieldValue<Post>): WithFieldValue<PostDbModel> {
* return {
* ttl: post.title,
* aut: this._autFromAuthor(post.author),
* lut: this._lutFromLastUpdatedMillis(post.lastUpdatedMillis)
* };
* }
*
* fromFirestore(snapshot: QueryDocumentSnapshot): Post {
* const data = snapshot.data() as PostDbModel;
* const author = `${data.aut.firstName} ${data.aut.lastName}`;
* return new Post(data.ttl, author, data.lut.toMillis());
* }
*
* _autFromAuthor(
* author: string | FieldValue
* ): { firstName: string; lastName: string } | FieldValue {
* if (typeof author !== 'string') {
* // `author` is a FieldValue, so just return it.
* return author;
* }
* const [firstName, lastName] = author.split(' ');
* return {firstName, lastName};
* }
*
* _lutFromLastUpdatedMillis(
* lastUpdatedMillis: number | FieldValue
* ): Timestamp | FieldValue {
* if (typeof lastUpdatedMillis !== 'number') {
* // `lastUpdatedMillis` must be a FieldValue, so just return it.
* return lastUpdatedMillis;
* }
* return Timestamp.fromMillis(lastUpdatedMillis);
* }
* }
*
* async function advancedDemo(db: Firestore): Promise<void> {
* // Create a `DocumentReference` with a `FirestoreDataConverter`.
* const documentRef = db.doc('posts/post123').withConverter(new PostConverter());
*
* // The `data` argument specified to `DocumentReference.set()` is type
* // checked by the TypeScript compiler to be compatible with `Post`. Since
* // the `data` argument is typed as `WithFieldValue<Post>` rather than just
* // `Post`, this allows properties of the `data` argument to also be special
* // Firestore values that perform server-side mutations, such as
* // `FieldValue.arrayRemove()`, `FieldValue.delete()`, and
* // `FieldValue.serverTimestamp()`.
* await documentRef.set({
* title: 'My Life',
* author: 'Foo Bar',
* lastUpdatedMillis: FieldValue.serverTimestamp()
* });
*
* // The TypeScript compiler will fail to compile if the `data` argument
* // to `DocumentReference.set()` is _not_ compatible with
* // `WithFieldValue<Post>`. This type checking prevents the caller from
* // specifying objects with incorrect properties or property values.
* // @ts-expect-error "Argument of type { ttl: string; } is not assignable
* // to parameter of type WithFieldValue<Post>"
* await documentRef.set(documentRef, { ttl: 'The Title' });
*
* // When retrieving a document with `DocumentReference.get()` the
* // `DocumentSnapshot` object's `data()` method returns a `Post`, rather
* // than a generic object, which would have been returned if the
* // `DocumentReference` did _not_ have a `FirestoreDataConverter`
* // attached to it.
* const snapshot1: DocumentSnapshot<Post> = await documentRef.get();
* const post1: Post = snapshot1.data()!;
* if (post1) {
* assertEqual(post1.title, 'My Life');
* assertEqual(post1.author, 'Foo Bar');
* }
*
* // The `data` argument specified to `DocumentReference.update()` is type
* // checked by the TypeScript compiler to be compatible with
* // `PostDbModel`. Note that unlike `DocumentReference.set()`, whose
* // `data` argument must be compatible with `Post`, the `data` argument
* // to `update()` must be compatible with `PostDbModel`. Similar to
* // `set()`, since the `data` argument is typed as
* // `WithFieldValue<PostDbModel>` rather than just `PostDbModel`, this
* // allows properties of the `data` argument to also be those special
* // Firestore values, like `FieldValue.arrayRemove()`,
* // `FieldValue.delete()`, and `FieldValue.serverTimestamp()`.
* await documentRef.update({
* 'aut.firstName': 'NewFirstName',
* lut: FieldValue.serverTimestamp()
* });
*
* // The TypeScript compiler will fail to compile if the `data` argument
* // to `DocumentReference.update()` is _not_ compatible with
* // `WithFieldValue<PostDbModel>`. This type checking prevents the caller
* // from specifying objects with incorrect properties or property values.
* // @ts-expect-error "Argument of type { title: string; } is not
* // assignable to parameter of type WithFieldValue<PostDbModel>"
* await documentRef.update({ title: 'New Title' });
* const snapshot2: DocumentSnapshot<Post> = await documentRef.get();
* const post2: Post = snapshot2.data()!;
* if (post2) {
* assertEqual(post2.title, 'My Life');
* assertEqual(post2.author, 'NewFirstName Bar');
* }
* }
*/
export interface FirestoreDataConverter<
AppModelType,
DbModelType extends DocumentData = DocumentData,
> {
/**
* Called by the Firestore SDK to convert a custom model object of type
* `AppModelType` into a plain Javascript object (suitable for writing
* directly to the Firestore database) of type `DbModelType`.
*
* To use set() with `merge` and `mergeFields`,
* toFirestore() must be defined with `Partial<T>`.
*
* The `WithFieldValue<T>` type extends `T` to also allow FieldValues such
* as `FieldValue.delete()` to be used as property values.
*/
toFirestore(
modelObject: WithFieldValue<AppModelType>,
): WithFieldValue<DbModelType>;
/**
* Called by the Firestore SDK to convert a custom model object of type
* `AppModelType` into a plain Javascript object (suitable for writing
* directly to the Firestore database) of type `DbModelType`.
*
* To use set() with `merge` and `mergeFields`,
* toFirestore() must be defined with `Partial<T>`.
*
* The `PartialWithFieldValue<T>` type extends `Partial<T>` to allow
* FieldValues such as `FieldValue.delete()` to be used as property values.
* It also supports nested `Partial` by allowing nested fields to be
* omitted.
*/
toFirestore(
modelObject: PartialWithFieldValue<AppModelType>,
options: SetOptions,
): PartialWithFieldValue<DbModelType>;
/**
* Called by the Firestore SDK to convert Firestore data into an object of
* type `AppModelType`. You can access your data by calling:
* `snapshot.data()`.
*
* Generally, the data returned from `snapshot.data()` can be cast to
* `DbModelType`; however, this is not guaranteed because Firestore does not
* enforce a schema on the database. For example, writes from a previous
* version of the application or writes from another client that did not use
* a type converter could have written data with different properties and/or
* property types. The implementation will need to choose whether to
* gracefully recover from non-conforming data or throw an error.
*/
fromFirestore(snapshot: QueryDocumentSnapshot): AppModelType;
}
/**
* Settings used to directly configure a `Firestore` instance.
*/
export interface Settings {
/**
* The project ID from the Google Developer's Console, e.g.
* 'grape-spaceship-123'. We will also check the environment variable
* GCLOUD_PROJECT for your project ID. Can be omitted in environments that
* support {@link https://cloud.google.com/docs/authentication Application
* Default Credentials}
*/
projectId?: string;
/**
* The database name. If omitted, the default database will be used.
*/
databaseId?: string;
/** The hostname to connect to. */
host?: string;
/** The port to connect to. */
port?: number;
/**
* Local file containing the Service Account credentials as downloaded from
* the Google Developers Console. Can be omitted in environments that
* support {@link https://cloud.google.com/docs/authentication Application
* Default Credentials}. To configure Firestore with custom credentials, use
* the `credentials` property to provide the `client_email` and
* `private_key` of your service account.
*/
keyFilename?: string;
/**
* The 'client_email' and 'private_key' properties of the service account
* to use with your Firestore project. Can be omitted in environments that
* support {@link https://cloud.google.com/docs/authentication Application
* Default Credentials}. If your credentials are stored in a JSON file, you
* can specify a `keyFilename` instead.
*/
credentials?: {client_email?: string; private_key?: string};
/** Whether to use SSL when connecting. */
ssl?: boolean;
/**
* The maximum number of idle GRPC channels to keep. A smaller number of idle
* channels reduces memory usage but increases request latency for clients
* with fluctuating request rates. If set to 0, shuts down all GRPC channels
* when the client becomes idle. Defaults to 1.
*/
maxIdleChannels?: number;
/**
* Whether to use `BigInt` for integer types when deserializing Firestore
* Documents. Regardless of magnitude, all integer values are returned as
* `BigInt` to match the precision of the Firestore backend. Floating point
* numbers continue to use JavaScript's `number` type.
*/
useBigInt?: boolean;
/**
* Whether to skip nested properties that are set to `undefined` during
* object serialization. If set to `true`, these properties are skipped
* and not written to Firestore. If set `false` or omitted, the SDK throws
* an exception when it encounters properties of type `undefined`.
*/
ignoreUndefinedProperties?: boolean;
/**
* Whether to force the use of HTTP/1.1 REST transport until a method that requires gRPC
* is called. When a method requires gRPC, this Firestore client will load dependent gRPC
* libraries and then use gRPC transport for communication from that point forward.
* Currently the only operation that requires gRPC is creating a snapshot listener with
* the method `DocumentReference<T>.onSnapshot()`, `CollectionReference<T>.onSnapshot()`,
* or `Query<T>.onSnapshot()`.
*/
preferRest?: boolean;
/**
* Settings related to telemetry collection by this client.
* @beta
*/
openTelemetry?: FirestoreOpenTelemetryOptions;
[key: string]: any; // Accept other properties, such as GRPC settings.
}
/**
* Options to configure telemetry collection.
* This is a 'beta' interface and may change in backwards incompatible ways.
* @beta
*/
export interface FirestoreOpenTelemetryOptions {
/**
* The OpenTelemetry TracerProvider instance that the SDK should use to
* create trace spans. If not provided, the SDK will use the Global TracerProvider.
*
* Even if a Global TracerProvider has been registered, users can still
* disable this client's span creation by passing in a "no-op" tracer provider
* here, or by setting the `FIRESTORE_ENABLE_TRACING` environment variable to `OFF` or `FALSE`.
*/
tracerProvider?: any;
}
/** Options to configure a read-only transaction. */
export interface ReadOnlyTransactionOptions {
/** Set to true to indicate a read-only transaction. */
readOnly: true;
/**
* If specified, documents are read at the given time. This may not be more
* than 60 seconds in the past from when the request is processed by the
* server.
*/
readTime?: Timestamp;
}
/** Options to configure a read-write transaction. */
export interface ReadWriteTransactionOptions {
/** Set to false or omit to indicate a read-write transaction. */
readOnly?: false;
/**
* The maximum number of attempts for this transaction. Defaults to 5.
*/
maxAttempts?: number;
}
/**
* `Firestore` represents a Firestore Database and is the entry point for all
* Firestore operations.
*/
export class Firestore {
/**
* @param settings Configuration object. See [Firestore Documentation]
* {@link https://firebase.google.com/docs/firestore/}
*/
public constructor(settings?: Settings);
/**
* Specifies custom settings to be used to configure the `Firestore`
* instance. Can only be invoked once and before any other Firestore
* method.
*
* If settings are provided via both `settings()` and the `Firestore`
* constructor, both settings objects are merged and any settings provided
* via `settings()` take precedence.
*
* @param {object} settings The settings to use for all Firestore
* operations.
*/
settings(settings: Settings): void;
/**
* Returns the Database ID for this Firestore instance.
*/
get databaseId(): string;
/**
* Gets a `CollectionReference` instance that refers to the collection at
* the specified path.
*
* @param collectionPath A slash-separated path to a collection.
* @return The `CollectionReference` instance.
*/
collection(collectionPath: string): CollectionReference;
/**
* Gets a `DocumentReference` instance that refers to the document at the
* specified path.
*
* @param documentPath A slash-separated path to a document.
* @return The `DocumentReference` instance.
*/
doc(documentPath: string): DocumentReference;
/**
* Creates and returns a new Query that includes all documents in the
* database that are contained in a collection or subcollection with the
* given collectionId.
*
* @param collectionId 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 created `CollectionGroup`.
*/
collectionGroup(collectionId: string): CollectionGroup;
/**
* Retrieves multiple documents from Firestore.
*
* The first argument is required and must be of type `DocumentReference`
* followed by any additional `DocumentReference` documents. If used, the
* optional `ReadOptions` must be the last argument.
*
* @param {Array.<DocumentReference|ReadOptions>} documentRefsOrReadOptions
* The `DocumentReferences` to receive, followed by an optional field
* mask.
* @return A Promise that resolves with an array of resulting document
* snapshots.
*/
getAll(
...documentRefsOrReadOptions: Array<DocumentReference | ReadOptions>
): Promise<Array<DocumentSnapshot>>;
/**
* Recursively deletes all documents and subcollections at and under the
* specified level.
*
* If any delete fails, the promise is rejected with an error message
* containing the number of failed deletes and the stack trace of the last
* failed delete. The provided reference is deleted regardless of whether
* all deletes succeeded.
*
* `recursiveDelete()` uses a BulkWriter instance with default settings to
* perform the deletes. To customize throttling rates or add success/error
* callbacks, pass in a custom BulkWriter instance.
*
* @param ref The reference of a document or collection to delete.
* @param bulkWriter A custom BulkWriter instance used to perform the
* deletes.
* @return A promise that resolves when all deletes have been performed.
* The promise is rejected if any of the deletes fail.
*
* @example
* // Recursively delete a reference and log the references of failures.
* const bulkWriter = firestore.bulkWriter();
* bulkWriter
* .onWriteError((error) => {
* if (
* error.failedAttempts < MAX_RETRY_ATTEMPTS
* ) {
* return true;
* } else {
* console.log('Failed write at document: ', error.documentRef.path);
* return false;
* }
* });
* await firestore.recursiveDelete(docRef, bulkWriter);
*/
recursiveDelete(
ref: CollectionReference<any, any> | DocumentReference<any, any>,
bulkWriter?: BulkWriter,
): Promise<void>;
/**
* Terminates the Firestore client and closes all open streams.
*
* @return A Promise that resolves when the client is terminated.
*/
terminate(): Promise<void>;
/**
* Fetches the root collections that are associated with this Firestore
* database.
*
* @returns A Promise that resolves with an array of CollectionReferences.
*/
listCollections(): Promise<Array<CollectionReference>>;
/**
* Executes the given updateFunction and commits the changes applied within
* the transaction.
*
* You can use the transaction object passed to 'updateFunction' to read and
* modify Firestore documents under lock. You have to perform all reads
* before you perform any write.
*
* Transactions can be performed as read-only or read-write transactions. By
* default, transactions are executed in read-write mode.
*
* A read-write transaction obtains a pessimistic lock on all documents that
* are read during the transaction. These locks block other transactions,
* batched writes, and other non-transactional writes from changing that
* document. Any writes in a read-write transactions are committed once
* 'updateFunction' resolves, which also releases all locks.
*
* If a read-write transaction fails with contention, the transaction is
* retried up to five times. The `updateFunction` is invoked once for each
* attempt.
*
* Read-only transactions do not lock documents. They can be used to read
* documents at a consistent snapshot in time, which may be up to 60 seconds
* in the past. Read-only transactions are not retried.
*
* Transactions time out after 60 seconds if no documents are read.
* Transactions that are not committed within than 270 seconds are also
* aborted. Any remaining locks are released when a transaction times out.
*
* @param updateFunction The function to execute within the transaction
* context.
* @param transactionOptions Transaction options.
* @return If the transaction completed successfully or was explicitly
* aborted (by the updateFunction returning a failed Promise), the Promise
* returned by the updateFunction will be returned here. Else if the
* transaction failed, a rejected Promise with the corresponding failure
* error will be returned.
*/
runTransaction<T>(
updateFunction: (transaction: Transaction) => Promise<T>,
transactionOptions?:
| ReadWriteTransactionOptions
| ReadOnlyTransactionOptions,
): Promise<T>;
/**
* Creates a write batch, used for performing multiple writes as a single
* atomic operation.
*/
batch(): WriteBatch;
/**
* Creates a [BulkWriter]{@link BulkWriter}, used for performing
* multiple writes in parallel. Gradually ramps up writes as specified
* by the 500/50/5 rule.
*
* @see https://firebase.google.com/docs/firestore/best-practices#ramping_up_traffic
*
* @param options An options object used to configure the throttling
* behavior for the underlying BulkWriter.
*/
bulkWriter(options?: BulkWriterOptions): BulkWriter;
/**
* Creates a new `BundleBuilder` instance to package selected Firestore data into
* a bundle.
*
* @param bundleId The ID of the bundle. When loaded on clients, client SDKs use this ID
* and the timestamp associated with the bundle to tell if it has been loaded already.
* If not specified, a random identifier will be used.
*
*
* @example
* const bundle = firestore.bundle('data-bundle');
* const docSnapshot = await firestore.doc('abc/123').get();
* const querySnapshot = await firestore.collection('coll').get();
*
* const bundleBuffer = bundle.add(docSnapshot); // Add a document
* .add('coll-query', querySnapshot) // Add a named query.
* .build()
* // Save `bundleBuffer` to CDN or stream it to clients.
*/
bundle(bundleId?: string): BundleBuilder;
}
/**
* An immutable object representing a geo point in Firestore. The geo point
* is represented as latitude/longitude pair.
*
* Latitude values are in the range of [-90, 90].
* Longitude values are in the range of [-180, 180].
*/
export class GeoPoint {
/**
* Creates a new immutable GeoPoint object with the provided latitude and
* longitude values.
* @param latitude The latitude as number between -90 and 90.
* @param longitude The longitude as number between -180 and 180.
*/
constructor(latitude: number, longitude: number);
readonly latitude: number;
readonly longitude: number;
/**
* Returns true if this `GeoPoint` is equal to the provided one.
*
* @param other The `GeoPoint` to compare against.
* @return true if this `GeoPoint` is equal to the provided one.
*/
isEqual(other: GeoPoint): boolean;
}
/**
* A reference to a transaction.
* The `Transaction` object passed to a transaction's updateFunction provides
* the methods to read and write data within the transaction context. See
* `Firestore.runTransaction()`.
*/
export class Transaction {
private constructor();
/**
* Retrieves a query result. Holds a pessimistic lock on all returned
* documents.
*
* @param query A query to execute.
* @return A QuerySnapshot for the retrieved data.
*/
get<AppModelType, DbModelType extends DocumentData>(
query: Query<AppModelType, DbModelType>,
): Promise<QuerySnapshot<AppModelType, DbModelType>>;
/**
* Reads the document referenced by the provided `DocumentReference.`
* Holds a pessimistic lock on the returned document.
*
* @param documentRef A reference to the document to be read.
* @return A DocumentSnapshot for the read data.
*/
get<AppModelType, DbModelType extends DocumentData>(
documentRef: DocumentReference<AppModelType, DbModelType>,
): Promise<DocumentSnapshot<AppModelType, DbModelType>>;
/**
* Retrieves an aggregate query result. Holds a pessimistic lock on all
* documents that were matched by the underlying query.
*
* @param aggregateQuery An aggregate query to execute.
* @return An AggregateQuerySnapshot for the retrieved data.
*/
get<
AppModelType,
DbModelType extends DocumentData,
AggregateSpecType extends AggregateSpec,
>(
aggregateQuery: AggregateQuery<
AggregateSpecType,
AppModelType,
DbModelType
>,
): Promise<
AggregateQuerySnapshot<AggregateSpecType, AppModelType, DbModelType>
>;
/**
* Retrieves multiple documents from Firestore. Holds a pessimistic lock on
* all returned documents.
*
* The first argument is required and must be of type `DocumentReference`
* followed by any additional `DocumentReference` documents. If used, the
* optional `ReadOptions` must be the last argument.
*
* @param {Array.<DocumentReference|ReadOptions>} documentRefsOrReadOptions
* The `DocumentReferences` to receive, followed by an optional field
* mask.
* @return A Promise that resolves with an array of resulting document
* snapshots.
*/
getAll<AppModelType, DbModelType extends DocumentData>(
...documentRefsOrReadOptions: Array<
DocumentReference<AppModelType, DbModelType> | ReadOptions
>
): Promise<Array<DocumentSnapshot<AppModelType, DbModelType>>>;
/**
* Create the document referred to by the provided `DocumentReference`.
* The operation will fail the transaction if a document exists at the
* specified location.
*
* @param documentRef A reference to the document to be create.
* @param data The object data to serialize as the document.
* @throws Error If the provided input is not a valid Firestore document.
* @return This `Transaction` instance. Used for chaining method calls.
*/
create<AppModelType, DbModelType extends DocumentData>(
documentRef: DocumentReference<AppModelType, DbModelType>,
data: WithFieldValue<AppModelType>,
): Transaction;
/**
* Writes to the document referred to by the provided `DocumentReference`.
* If the document does not exist yet, it will be created. If you pass
* `SetOptions`, the provided data can be merged into the existing document.
*
* @param documentRef A reference to the document to be set.
* @param data An object of the fields and values for the document.
* @param options An object to configure the set behavior.
* @param options.merge - If true, set() merges the values specified in its
* data argument. Fields omitted from this set() call remain untouched. If
* your input sets any field to an empty map, all nested fields are
* overwritten.
* @param options.mergeFields - If provided, set() only replaces the
* specified field paths. Any field path that is not specified is ignored
* and remains untouched. If your input sets any field to an empty map, all
* nested fields are overwritten.
* @throws Error If the provided input is not a valid Firestore document.
* @return This `Transaction` instance. Used for chaining method calls.
*/
set<AppModelType, DbModelType extends DocumentData>(
documentRef: DocumentReference<AppModelType, DbModelType>,
data: PartialWithFieldValue<AppModelType>,
options: SetOptions,
): Transaction;
set<AppModelType, DbModelType extends DocumentData>(
documentRef: DocumentReference<AppModelType, DbModelType>,
data: WithFieldValue<AppModelType>,
): Transaction;
/**
* Updates fields in the document referred to by the provided
* `DocumentReference`. The update will fail if applied to a document that
* does not exist.
*
* Nested fields can be updated by providing dot-separated field path
* strings.
*
* @param documentRef A reference to the document to be updated.
* @param data An object containing the fields and values with which to
* update the document.
* @param precondition A Precondition to enforce on this update.
* @throws Error If the provided input is not valid Firestore data.
* @return This `Transaction` instance. Used for chaining method calls.
*/
update<AppModelType, DbModelType extends DocumentData>(
documentRef: DocumentReference<AppModelType, DbModelType>,
data: UpdateData<DbModelType>,
precondition?: Precondition,
): Transaction;
/**
* Updates fields in the document referred to by the provided
* `DocumentReference`. The update will fail if applied to a document that
* does not exist.
*
* Nested fields can be updated by providing dot-separated field path
* strings or by providing FieldPath objects.
*
* A `Precondition` restricting this update can be specified as the last
* argument.
*
* @param documentRef A reference to the document to be updated.
* @param field The first field to update.
* @param value The first value
* @param fieldsOrPrecondition An alternating list of field paths and values
* to update, optionally followed by a `Precondition` to enforce on this
* update.
* @throws Error If the provided input is not valid Firestore data.
* @return This `Transaction` instance. Used for chaining method calls.
*/
update(
documentRef: DocumentReference<any, any>,
field: string | FieldPath,
value: any,
...fieldsOrPrecondition: any[]
): Transaction;
/**
* Deletes the document referred to by the provided `DocumentReference`.
*
* @param documentRef A reference to the document to be deleted.
* @param precondition A Precondition to enforce for this delete.
* @return This `Transaction` instance. Used for chaining method calls.
*/
delete(
documentRef: DocumentReference<any, any>,
precondition?: Precondition,
): Transaction;
}
/**
* A Firestore BulkWriter than can be used to perform a large number of writes
* in parallel. Writes to the same document will be executed sequentially.
*
* @class
*/
export class BulkWriter {
private constructor();
/**
* Create a document with the provided data. This single operation will fail
* if a document exists at its location.
*
* @param documentRef A reference to the document to be
* created.
* @param data The object to serialize as the document.
* @throws Error If the provided input is not a valid Firestore document.
* @returns A promise that resolves with the result of the write. If the
* write fails, the promise is rejected with a
* [BulkWriterError]{@link BulkWriterError}.
*/
create<AppModelType, DbModelType extends DocumentData>(
documentRef: DocumentReference<AppModelType, DbModelType>,
data: WithFieldValue<AppModelType>,
): Promise<WriteResult>;
/**
* Delete a document from the database.
*
* @param documentRef A reference to the document to be
* deleted.
* @param precondition A precondition to enforce for this
* delete.
* @param precondition.lastUpdateTime If set, enforces that the
* document was last updated at lastUpdateTime. Fails the batch if the
* document doesn't exist or was last updated at a different time.
* @param precondition.exists If set, enforces that the target document
* must or must not exist.
* @returns A promise that resolves with the result of the delete. If the
* delete fails, the promise is rejected with a
* [BulkWriterError]{@link BulkWriterError}.
*/
delete(
documentRef: DocumentReference<any, any>,
precondition?: Precondition,
): Promise<WriteResult>;
/**
* Write to the document referred to by the provided
* [DocumentReference]{@link DocumentReference}. If the document does not
* exist yet, it will be created. If you pass
* [SetOptions]{@link SetOptions}., the provided data can be merged into the
* existing document.
*
* @param documentRef A reference to the document to be
* set.
* @param data The object to serialize as the document.
* @param options An object to configure the set behavior.
* @param options.merge - If true, set() merges the values specified in its
* data argument. Fields omitted from this set() call remain untouched. If
* your input sets any field to an empty map, all nested fields are
* overwritten.
* @param options.mergeFields - If provided, set() only replaces the
* specified field paths. Any field path that is not specified is ignored
* and remains untouched. If your input sets any field to an empty map, all
* nested fields are overwritten.
* @throws Error If the provided input is not a valid Firestore document.
* @returns A promise that resolves with the result of the write. If the
* write fails, the promise is rejected with a
* [BulkWriterError]{@link BulkWriterError}.
*/
set<AppModelType, DbModelType extends DocumentData>(
documentRef: DocumentReference<AppModelType, DbModelType>,
data: PartialWithFieldValue<AppModelType>,
options: SetOptions,
): Promise<WriteResult>;
set<AppModelType, DbModelType extends DocumentData>(
documentRef: DocumentReference<AppModelType, DbModelType>,
data: WithFieldValue<AppModelType>,
): Promise<WriteResult>;
/**
* Update fields of the document referred to by the provided
* [DocumentReference]{@link DocumentReference}. If the document doesn't yet
* exist, the update fails and the entire batch will be rejected.
*
* The update() method accepts either an object with field paths encoded as
* keys and field values encoded as values, or a variable number of
* arguments that alternate between field paths and field values. Nested
* fields can be updated by providing dot-separated field path strings or by
* providing FieldPath objects.
*
*
* A Precondition restricting this update can be specified as the last
* argument.
*
* @param documentRef A reference to the document to be updated.
* @param data An object containing the fields and values with which to
* update the document.
* @param precondition A Precondition to enforce on this update.
* @throws Error If the provided input is not valid Firestore data.
* @returns A promise that resolves with the result of the write. If the
* write fails, the promise is rejected with a
* [BulkWriterError]{@link BulkWriterError}.
*/
update<AppModelType, DbModelType extends DocumentData>(
documentRef: DocumentReference<AppModelType, DbModelType>,
data: UpdateData<DbModelType>,
precondition?: Precondition,
): Promise<WriteResult>;
/**
* Update fields of the document referred to by the provided
* [DocumentReference]{@link DocumentReference}. If the document doesn't yet
* exist, the update fails and the entire batch will be rejected.
*
* The update() method accepts either an object with field paths encoded as
* keys and field values encoded as values, or a variable number of
* arguments that alternate between field paths and field values. Nested
* fields can be updated by providing dot-separated field path strings or by
* providing FieldPath objects.
*
*
* A Precondition restricting this update can be specified as the last
* argument.
*
* @param documentRef A reference to the document to be updated.
* @param field The first field to update.
* @param value The first value
* @param fieldsOrPrecondition An alternating list of field paths and values
* to update, optionally followed a `Precondition` to enforce on this
* update.
* @throws Error If the provided input is not valid Firestore data;
* @returns A promise that resolves with the result of the write. If the
* write fails, the promise is rejected with a
* [BulkWriterError]{@link BulkWriterError}.
*/
update(
documentRef: DocumentReference<any, any>,
field: string | FieldPath,
value: any,
...fieldsOrPrecondition: any[]
): Promise<WriteResult>;
/**
* Attaches a listener that is run every time a BulkWriter operation
* successfully completes.
*
* @param callback A callback to be called every time a BulkWriter operation
* successfully completes.
*/
onWriteResult(
callback: (
documentRef: DocumentReference<any, any>,
result: WriteResult,
) => void,
): void;
/**
* Attaches an error handler listener that is run every time a BulkWriter
* operation fails.
*
* BulkWriter has a default error handler that retries UNAVAILABLE and
* ABORTED errors up to a maximum of 10 failed attempts. When an error
* handler is specified, the default error handler will be overwritten.
*
* @param shouldRetryCallback A callback to be called every time a BulkWriter
* operation fails. Returning `true` will retry the operation. Returning
* `false` will stop the retry loop.
*/
onWriteError(
shouldRetryCallback: (error: BulkWriterError) => boolean,
): void;
/**
* Commits all writes that have been enqueued up to this point in parallel.
*
* Returns a Promise that resolves when all currently queued operations have
* been committed. The Promise will never be rejected since the results for
* each individual operation are conveyed via their individual Promises.
*
* The Promise resolves immediately if there are no pending writes.
* Otherwise, the Promise waits for all previously issued writes, but it
* does not wait for writes that were added after the method is called. If
* you want to wait for additional writes, call `flush()` again.
*
* @return A promise that resolves when all enqueued writes
* up to this point have been committed.
*/
flush(): Promise<void>;
/**
* Commits all enqueued writes and marks the BulkWriter instance as closed.
*
* After calling `close()`, calling any method will throw an error. Any
* retries scheduled as part of an `onWriteError()` handler will be run
* before the `close()` promise resolves.
*
* Returns a Promise that resolves when all writes have been committed. The
* Promise will never be rejected. Calling this method will send all
* requests. The promise resolves immediately if there are no pending
* writes.
*
* @return A promise that resolves when all enqueued writes
* up to this point have been committed.
*/
close(): Promise<void>;
}
/**
* An options object to configure throttling on BulkWriter.
*/
export interface BulkWriterOptions {
/**
* Whether to disable or configure throttling. By default, throttling is
* enabled. This field can be set to either a boolean or a config
* object. Setting it to `true` will use default values. You can override
* the defaults by setting it to `false` to disable throttling, or by
* setting the config values to enable throttling with the provided values.
*
* @see https://firebase.google.com/docs/firestore/best-practices#ramping_up_traffic
*
* @param initialOpsPerSecond The initial maximum number of operations per
* second allowed by the throttler. If this field is not set, the default
* is 500 operations per second.
* @param maxOpsPerSecond The maximum number of operations per second
* allowed by the throttler. If this field is set, the throttler's allowed
* operations per second does not ramp up past the specified operations per
* second.
*/
readonly throttling?:
| boolean
| {initialOpsPerSecond?: number; maxOpsPerSecond?: number};
}
/**
* The error thrown when a BulkWriter operation fails.
*/
export class BulkWriterError extends Error {
/** The status code of the error. */
readonly code: GrpcStatus;
/** The error message of the error. */
readonly message: string;
/** The document reference the operation wa