UNPKG

@firebase/firestore

Version:

The Cloud Firestore component of the Firebase JS SDK.

318 lines (317 loc) • 14.2 kB
/** * @license * 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. */ import { ChangeType, ViewSnapshot } from '../core/view_snapshot'; import { FieldPath } from '../lite/field_path'; import { DocumentData, Query, SetOptions } from '../lite/reference'; import { DocumentSnapshot as LiteDocumentSnapshot, FirestoreDataConverter as LiteFirestoreDataConverter } from '../lite/snapshot'; import { UntypedFirestoreDataConverter } from '../lite/user_data_reader'; import { AbstractUserDataWriter } from '../lite/user_data_writer'; import { Document } from '../model/document'; import { DocumentKey } from '../model/document_key'; import { FirebaseFirestore } from './database'; import { SnapshotListenOptions } from './reference_impl'; /** * Converter used by `withConverter()` to transform user objects of type `T` * into Firestore data. * * Using the converter allows you to specify generic type arguments when * storing and retrieving objects from Firestore. * * @example * ```typescript * class Post { * constructor(readonly title: string, readonly author: string) {} * * toString(): string { * return this.title + ', by ' + this.author; * } * } * * const postConverter = { * toFirestore(post: Post): firebase.firestore.DocumentData { * return {title: post.title, author: post.author}; * }, * fromFirestore( * snapshot: firebase.firestore.QueryDocumentSnapshot, * options: firebase.firestore.SnapshotOptions * ): Post { * const data = snapshot.data(options)!; * return new Post(data.title, data.author); * } * }; * * const postSnap = await firebase.firestore() * .collection('posts') * .withConverter(postConverter) * .doc().get(); * const post = postSnap.data(); * if (post !== undefined) { * post.title; // string * post.toString(); // Should be defined * post.someNonExistentProperty; // TS error * } * ``` */ export interface FirestoreDataConverter<T> extends LiteFirestoreDataConverter<T> { /** * Called by the Firestore SDK to convert a custom model object of type `T` * into a plain JavaScript object (suitable for writing directly to the * Firestore database). To use `set()` with `merge` and `mergeFields`, * `toFirestore()` must be defined with `Partial<T>`. */ toFirestore(modelObject: T): DocumentData; /** * Called by the Firestore SDK to convert a custom model object of type `T` * into a plain JavaScript object (suitable for writing directly to the * Firestore database). Used with {@link (setDoc:1)}, {@link (WriteBatch.set:1)} * and {@link (Transaction.set:1)} with `merge:true` or `mergeFields`. */ toFirestore(modelObject: Partial<T>, options: SetOptions): DocumentData; /** * Called by the Firestore SDK to convert Firestore data into an object of * type T. You can access your data by calling: `snapshot.data(options)`. * * @param snapshot - A `QueryDocumentSnapshot` containing your data and metadata. * @param options - The `SnapshotOptions` from the initial call to `data()`. */ fromFirestore(snapshot: QueryDocumentSnapshot<DocumentData>, options?: SnapshotOptions): T; } /** * Options that configure how data is retrieved from a `DocumentSnapshot` (for * example the desired behavior for server timestamps that have not yet been set * to their final value). */ export interface SnapshotOptions { /** * If set, controls the return value for server timestamps that have not yet * been set to their final value. * * By specifying 'estimate', pending server timestamps return an estimate * based on the local clock. This estimate will differ from the final value * and cause these values to change once the server result becomes available. * * By specifying 'previous', pending timestamps will be ignored and return * their previous value instead. * * If omitted or set to 'none', `null` will be returned by default until the * server value becomes available. */ readonly serverTimestamps?: 'estimate' | 'previous' | 'none'; } /** * Metadata about a snapshot, describing the state of the snapshot. */ export declare class SnapshotMetadata { /** * True if the snapshot contains the result of local writes (for example * `set()` or `update()` calls) that have not yet been committed to the * backend. If your listener has opted into metadata updates (via * `SnapshotListenOptions`) you will receive another snapshot with * `hasPendingWrites` equal to false once the writes have been committed to * the backend. */ readonly hasPendingWrites: boolean; /** * True if the snapshot was created from cached data rather than guaranteed * up-to-date server data. If your listener has opted into metadata updates * (via `SnapshotListenOptions`) you will receive another snapshot with * `fromCache` set to false once the client has received up-to-date data from * the backend. */ readonly fromCache: boolean; /** @hideconstructor */ constructor(hasPendingWrites: boolean, fromCache: boolean); /** * Returns true if this `SnapshotMetadata` is equal to the provided one. * * @param other - The `SnapshotMetadata` to compare against. * @returns true if this `SnapshotMetadata` is equal to the provided one. */ isEqual(other: SnapshotMetadata): boolean; } /** * The type of a `DocumentChange` may be 'added', 'removed', or 'modified'. */ export declare type DocumentChangeType = 'added' | 'removed' | 'modified'; /** * A `DocumentChange` represents a change to the documents matching a query. * It contains the document affected and the type of change that occurred. */ export interface DocumentChange<T = DocumentData> { /** The type of change ('added', 'modified', or 'removed'). */ readonly type: DocumentChangeType; /** The document affected by this change. */ readonly doc: QueryDocumentSnapshot<T>; /** * The index of the changed document in the result set immediately prior to * this `DocumentChange` (i.e. supposing that all prior `DocumentChange` objects * have been applied). Is `-1` for 'added' events. */ readonly oldIndex: number; /** * The index of the changed document in the result set immediately after * this `DocumentChange` (i.e. supposing that all prior `DocumentChange` * objects and the current `DocumentChange` object have been applied). * Is -1 for 'removed' events. */ readonly newIndex: number; } /** * A `DocumentSnapshot` contains data read from a document in your Firestore * database. The data can be extracted with `.data()` or `.get(<field>)` to * get a specific field. * * For a `DocumentSnapshot` that points to a non-existing document, any data * access will return 'undefined'. You can use the `exists()` method to * explicitly verify a document's existence. */ export declare class DocumentSnapshot<T = DocumentData> extends LiteDocumentSnapshot<T> { readonly _firestore: FirebaseFirestore; private readonly _firestoreImpl; /** * Metadata about the `DocumentSnapshot`, including information about its * source and local modifications. */ readonly metadata: SnapshotMetadata; /** @hideconstructor protected */ constructor(_firestore: FirebaseFirestore, userDataWriter: AbstractUserDataWriter, key: DocumentKey, document: Document | null, metadata: SnapshotMetadata, converter: UntypedFirestoreDataConverter<T> | null); /** * Property of the `DocumentSnapshot` that signals whether or not the data * exists. True if the document exists. */ exists(): this is QueryDocumentSnapshot<T>; /** * Retrieves all fields in the document as an `Object`. Returns `undefined` if * the document doesn't exist. * * By default, `FieldValue.serverTimestamp()` values that have not yet been * set to their final value will be returned as `null`. You can override * this by passing an options object. * * @param options - An options object to configure how data is retrieved from * the snapshot (for example the desired behavior for server timestamps that * have not yet been set to their final value). * @returns An `Object` containing all fields in the document or `undefined` if * the document doesn't exist. */ data(options?: SnapshotOptions): T | undefined; /** * Retrieves the field specified by `fieldPath`. Returns `undefined` if the * document or field doesn't exist. * * By default, a `FieldValue.serverTimestamp()` that has not yet been set to * its final value will be returned as `null`. You can override this by * passing an options object. * * @param fieldPath - The path (for example 'foo' or 'foo.bar') to a specific * field. * @param options - An options object to configure how the field is retrieved * from the snapshot (for example the desired behavior for server timestamps * that have not yet been set to their final value). * @returns The data at the specified field location or undefined if no such * field exists in the document. */ get(fieldPath: string | FieldPath, options?: SnapshotOptions): any; } /** * A `QueryDocumentSnapshot` contains data read from a document in your * Firestore database as part of a query. The document is guaranteed to exist * and its data can be extracted with `.data()` or `.get(<field>)` to get a * specific field. * * A `QueryDocumentSnapshot` offers the same API surface as a * `DocumentSnapshot`. Since query results contain only existing documents, the * `exists` property will always be true and `data()` will never return * 'undefined'. */ export declare class QueryDocumentSnapshot<T = DocumentData> extends DocumentSnapshot<T> { /** * Retrieves all fields in the document as an `Object`. * * By default, `FieldValue.serverTimestamp()` values that have not yet been * set to their final value will be returned as `null`. You can override * this by passing an options object. * * @override * @param options - An options object to configure how data is retrieved from * the snapshot (for example the desired behavior for server timestamps that * have not yet been set to their final value). * @returns An `Object` containing all fields in the document. */ data(options?: SnapshotOptions): T; } /** * A `QuerySnapshot` contains zero or more `DocumentSnapshot` objects * representing the results of a query. The documents can be accessed as an * array via the `docs` property or enumerated using the `forEach` method. The * number of documents can be determined via the `empty` and `size` * properties. */ export declare class QuerySnapshot<T = DocumentData> { readonly _firestore: FirebaseFirestore; readonly _userDataWriter: AbstractUserDataWriter; readonly _snapshot: ViewSnapshot; /** * Metadata about this snapshot, concerning its source and if it has local * modifications. */ readonly metadata: SnapshotMetadata; /** * The query on which you called `get` or `onSnapshot` in order to get this * `QuerySnapshot`. */ readonly query: Query<T>; private _cachedChanges?; private _cachedChangesIncludeMetadataChanges?; /** @hideconstructor */ constructor(_firestore: FirebaseFirestore, _userDataWriter: AbstractUserDataWriter, query: Query<T>, _snapshot: ViewSnapshot); /** An array of all the documents in the `QuerySnapshot`. */ get docs(): Array<QueryDocumentSnapshot<T>>; /** The number of documents in the `QuerySnapshot`. */ get size(): number; /** True if there are no documents in the `QuerySnapshot`. */ get empty(): boolean; /** * Enumerates all of the documents in the `QuerySnapshot`. * * @param callback - A callback to be called with a `QueryDocumentSnapshot` for * each document in the snapshot. * @param thisArg - The `this` binding for the callback. */ forEach(callback: (result: QueryDocumentSnapshot<T>) => void, thisArg?: unknown): void; /** * Returns an array of the documents changes since the last snapshot. If this * is the first snapshot, all documents will be in the list as 'added' * changes. * * @param options - `SnapshotListenOptions` that control whether metadata-only * changes (i.e. only `DocumentSnapshot.metadata` changed) should trigger * snapshot events. */ docChanges(options?: SnapshotListenOptions): Array<DocumentChange<T>>; } /** Calculates the array of DocumentChanges for a given ViewSnapshot. */ export declare function changesFromSnapshot<T>(querySnapshot: QuerySnapshot<T>, includeMetadataChanges: boolean): Array<DocumentChange<T>>; export declare function resultChangeType(type: ChangeType): DocumentChangeType; /** * Returns true if the provided snapshots are equal. * * @param left - A snapshot to compare. * @param right - A snapshot to compare. * @returns true if the snapshots are equal. */ export declare function snapshotEqual<T>(left: DocumentSnapshot<T> | QuerySnapshot<T>, right: DocumentSnapshot<T> | QuerySnapshot<T>): boolean;