From b0fb1d167c51381d353ed233d7ab810107279be8 Mon Sep 17 00:00:00 2001 From: Tom Andersen Date: Wed, 27 Apr 2022 15:24:33 -0400 Subject: [PATCH 1/5] Add TransactionOptions --- common/api-review/firestore-lite.api.md | 751 ++++++------ common/api-review/firestore.api.md | 1055 +++++++++-------- packages/firestore/lite/index.ts | 2 + packages/firestore/src/api.ts | 2 + packages/firestore/src/api/transaction.ts | 21 +- .../firestore/src/api/transaction_options.ts | 18 + .../firestore/src/core/firestore_client.ts | 5 +- .../firestore/src/core/transaction_options.ts | 39 + .../firestore/src/core/transaction_runner.ts | 7 +- .../firestore/src/lite-api/transaction.ts | 15 +- .../src/lite-api/transaction_options.ts | 24 + .../api_internal/transaction.test.ts | 262 ++-- 12 files changed, 1169 insertions(+), 1032 deletions(-) create mode 100644 packages/firestore/src/api/transaction_options.ts create mode 100644 packages/firestore/src/core/transaction_options.ts create mode 100644 packages/firestore/src/lite-api/transaction_options.ts diff --git a/common/api-review/firestore-lite.api.md b/common/api-review/firestore-lite.api.md index f026ffc2840..a96f3ada5cb 100644 --- a/common/api-review/firestore-lite.api.md +++ b/common/api-review/firestore-lite.api.md @@ -1,373 +1,378 @@ -## API Report File for "@firebase/firestore-lite" - -> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). - -```ts - -import { EmulatorMockTokenOptions } from '@firebase/util'; -import { FirebaseApp } from '@firebase/app'; -import { FirebaseError } from '@firebase/util'; -import { LogLevelString as LogLevel } from '@firebase/logger'; - -// @public -export function addDoc(reference: CollectionReference, data: WithFieldValue): Promise>; - -// @public -export type AddPrefixToKeys> = { - [K in keyof T & string as `${Prefix}.${K}`]+?: T[K]; -}; - -// @public -export function arrayRemove(...elements: unknown[]): FieldValue; - -// @public -export function arrayUnion(...elements: unknown[]): FieldValue; - -// @public -export class Bytes { - static fromBase64String(base64: string): Bytes; - static fromUint8Array(array: Uint8Array): Bytes; - isEqual(other: Bytes): boolean; - toBase64(): string; - toString(): string; - toUint8Array(): Uint8Array; -} - -// @public -export type ChildUpdateFields = V extends Record ? AddPrefixToKeys> : never; - -// @public -export function collection(firestore: Firestore, path: string, ...pathSegments: string[]): CollectionReference; - -// @public -export function collection(reference: CollectionReference, path: string, ...pathSegments: string[]): CollectionReference; - -// @public -export function collection(reference: DocumentReference, path: string, ...pathSegments: string[]): CollectionReference; - -// @public -export function collectionGroup(firestore: Firestore, collectionId: string): Query; - -// @public -export class CollectionReference extends Query { - get id(): string; - get parent(): DocumentReference | null; - get path(): string; - readonly type = "collection"; - withConverter(converter: FirestoreDataConverter): CollectionReference; - withConverter(converter: null): CollectionReference; -} - -// @public -export function connectFirestoreEmulator(firestore: Firestore, host: string, port: number, options?: { - mockUserToken?: EmulatorMockTokenOptions | string; -}): void; - -// @public -export function deleteDoc(reference: DocumentReference): Promise; - -// @public -export function deleteField(): FieldValue; - -// @public -export function doc(firestore: Firestore, path: string, ...pathSegments: string[]): DocumentReference; - -// @public -export function doc(reference: CollectionReference, path?: string, ...pathSegments: string[]): DocumentReference; - -// @public -export function doc(reference: DocumentReference, path: string, ...pathSegments: string[]): DocumentReference; - -// @public -export interface DocumentData { - [field: string]: any; -} - -// @public -export function documentId(): FieldPath; - -// @public -export class DocumentReference { - readonly converter: FirestoreDataConverter | null; - readonly firestore: Firestore; - get id(): string; - get parent(): CollectionReference; - get path(): string; - readonly type = "document"; - withConverter(converter: FirestoreDataConverter): DocumentReference; - withConverter(converter: null): DocumentReference; -} - -// @public -export class DocumentSnapshot { - protected constructor(); - data(): T | undefined; - exists(): this is QueryDocumentSnapshot; - get(fieldPath: string | FieldPath): any; - get id(): string; - get ref(): DocumentReference; -} - -export { EmulatorMockTokenOptions } - -// @public -export function endAt(snapshot: DocumentSnapshot): QueryConstraint; - -// @public -export function endAt(...fieldValues: unknown[]): QueryConstraint; - -// @public -export function endBefore(snapshot: DocumentSnapshot): QueryConstraint; - -// @public -export function endBefore(...fieldValues: unknown[]): QueryConstraint; - -// @public -export class FieldPath { - constructor(...fieldNames: string[]); - isEqual(other: FieldPath): boolean; -} - -// @public -export abstract class FieldValue { - abstract isEqual(other: FieldValue): boolean; -} - -// @public -export class Firestore { - get app(): FirebaseApp; - toJSON(): object; - type: 'firestore-lite' | 'firestore'; -} - -// @public -export interface FirestoreDataConverter { - fromFirestore(snapshot: QueryDocumentSnapshot): T; - toFirestore(modelObject: WithFieldValue): DocumentData; - toFirestore(modelObject: PartialWithFieldValue, options: SetOptions): DocumentData; -} - -// @public -export class FirestoreError extends FirebaseError { - readonly code: FirestoreErrorCode; - readonly message: string; - readonly stack?: string; -} - -// @public -export type FirestoreErrorCode = 'cancelled' | 'unknown' | 'invalid-argument' | 'deadline-exceeded' | 'not-found' | 'already-exists' | 'permission-denied' | 'resource-exhausted' | 'failed-precondition' | 'aborted' | 'out-of-range' | 'unimplemented' | 'internal' | 'unavailable' | 'data-loss' | 'unauthenticated'; - -// @public -export class GeoPoint { - constructor(latitude: number, longitude: number); - isEqual(other: GeoPoint): boolean; - get latitude(): number; - get longitude(): number; - toJSON(): { - latitude: number; - longitude: number; - }; -} - -// @public -export function getDoc(reference: DocumentReference): Promise>; - -// @public -export function getDocs(query: Query): Promise>; - -// @public -export function getFirestore(app?: FirebaseApp): Firestore; - -// @public -export function increment(n: number): FieldValue; - -// @public -export function initializeFirestore(app: FirebaseApp, settings: Settings): Firestore; - -// @public -export function limit(limit: number): QueryConstraint; - -// @public -export function limitToLast(limit: number): QueryConstraint; - -export { LogLevel } - -// @public -export type NestedUpdateFields> = UnionToIntersection<{ - [K in keyof T & string]: ChildUpdateFields; -}[keyof T & string]>; - -// @public -export function orderBy(fieldPath: string | FieldPath, directionStr?: OrderByDirection): QueryConstraint; - -// @public -export type OrderByDirection = 'desc' | 'asc'; - -// @public -export type PartialWithFieldValue = Partial | (T extends Primitive ? T : T extends {} ? { - [K in keyof T]?: PartialWithFieldValue | FieldValue; -} : never); - -// @public -export type Primitive = string | number | boolean | undefined | null; - -// @public -export class Query { - protected constructor(); - readonly converter: FirestoreDataConverter | null; - readonly firestore: Firestore; - readonly type: 'query' | 'collection'; - withConverter(converter: null): Query; - withConverter(converter: FirestoreDataConverter): Query; -} - -// @public -export function query(query: Query, ...queryConstraints: QueryConstraint[]): Query; - -// @public -export abstract class QueryConstraint { - abstract readonly type: QueryConstraintType; -} - -// @public -export type QueryConstraintType = 'where' | 'orderBy' | 'limit' | 'limitToLast' | 'startAt' | 'startAfter' | 'endAt' | 'endBefore'; - -// @public -export class QueryDocumentSnapshot extends DocumentSnapshot { - // @override - data(): T; -} - -// @public -export function queryEqual(left: Query, right: Query): boolean; - -// @public -export class QuerySnapshot { - get docs(): Array>; - get empty(): boolean; - forEach(callback: (result: QueryDocumentSnapshot) => void, thisArg?: unknown): void; - readonly query: Query; - get size(): number; -} - -// @public -export function refEqual(left: DocumentReference | CollectionReference, right: DocumentReference | CollectionReference): boolean; - -// @public -export function runTransaction(firestore: Firestore, updateFunction: (transaction: Transaction) => Promise): Promise; - -// @public -export function serverTimestamp(): FieldValue; - -// @public -export function setDoc(reference: DocumentReference, data: WithFieldValue): Promise; - -// @public -export function setDoc(reference: DocumentReference, data: PartialWithFieldValue, options: SetOptions): Promise; - -// @public -export function setLogLevel(logLevel: LogLevel): void; - -// @public -export type SetOptions = { - readonly merge?: boolean; -} | { - readonly mergeFields?: Array; -}; - -// @public -export interface Settings { - host?: string; - ignoreUndefinedProperties?: boolean; - ssl?: boolean; -} - -// @public -export function snapshotEqual(left: DocumentSnapshot | QuerySnapshot, right: DocumentSnapshot | QuerySnapshot): boolean; - -// @public -export function startAfter(snapshot: DocumentSnapshot): QueryConstraint; - -// @public -export function startAfter(...fieldValues: unknown[]): QueryConstraint; - -// @public -export function startAt(snapshot: DocumentSnapshot): QueryConstraint; - -// @public -export function startAt(...fieldValues: unknown[]): QueryConstraint; - -// @public -export function terminate(firestore: Firestore): Promise; - -// @public -export class Timestamp { - constructor( - seconds: number, - nanoseconds: number); - static fromDate(date: Date): Timestamp; - static fromMillis(milliseconds: number): Timestamp; - isEqual(other: Timestamp): boolean; - readonly nanoseconds: number; - static now(): Timestamp; - readonly seconds: number; - toDate(): Date; - toJSON(): { - seconds: number; - nanoseconds: number; - }; - toMillis(): number; - toString(): string; - valueOf(): string; -} - -// @public -export class Transaction { - delete(documentRef: DocumentReference): this; - get(documentRef: DocumentReference): Promise>; - set(documentRef: DocumentReference, data: WithFieldValue): this; - set(documentRef: DocumentReference, data: PartialWithFieldValue, options: SetOptions): this; - update(documentRef: DocumentReference, data: UpdateData): this; - update(documentRef: DocumentReference, field: string | FieldPath, value: unknown, ...moreFieldsAndValues: unknown[]): this; -} - -// @public -export type UnionToIntersection = (U extends unknown ? (k: U) => void : never) extends (k: infer I) => void ? I : never; - -// @public -export type UpdateData = T extends Primitive ? T : T extends {} ? { - [K in keyof T]?: UpdateData | FieldValue; -} & NestedUpdateFields : Partial; - -// @public -export function updateDoc(reference: DocumentReference, data: UpdateData): Promise; - -// @public -export function updateDoc(reference: DocumentReference, field: string | FieldPath, value: unknown, ...moreFieldsAndValues: unknown[]): Promise; - -// @public -export function where(fieldPath: string | FieldPath, opStr: WhereFilterOp, value: unknown): QueryConstraint; - -// @public -export type WhereFilterOp = '<' | '<=' | '==' | '!=' | '>=' | '>' | 'array-contains' | 'in' | 'array-contains-any' | 'not-in'; - -// @public -export type WithFieldValue = T | (T extends Primitive ? T : T extends {} ? { - [K in keyof T]: WithFieldValue | FieldValue; -} : never); - -// @public -export class WriteBatch { - commit(): Promise; - delete(documentRef: DocumentReference): WriteBatch; - set(documentRef: DocumentReference, data: WithFieldValue): WriteBatch; - set(documentRef: DocumentReference, data: PartialWithFieldValue, options: SetOptions): WriteBatch; - update(documentRef: DocumentReference, data: UpdateData): WriteBatch; - update(documentRef: DocumentReference, field: string | FieldPath, value: unknown, ...moreFieldsAndValues: unknown[]): WriteBatch; -} - -// @public -export function writeBatch(firestore: Firestore): WriteBatch; - - -``` +## API Report File for "@firebase/firestore-lite" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts + +import { EmulatorMockTokenOptions } from '@firebase/util'; +import { FirebaseApp } from '@firebase/app'; +import { FirebaseError } from '@firebase/util'; +import { LogLevelString as LogLevel } from '@firebase/logger'; + +// @public +export function addDoc(reference: CollectionReference, data: WithFieldValue): Promise>; + +// @public +export type AddPrefixToKeys> = { + [K in keyof T & string as `${Prefix}.${K}`]+?: T[K]; +}; + +// @public +export function arrayRemove(...elements: unknown[]): FieldValue; + +// @public +export function arrayUnion(...elements: unknown[]): FieldValue; + +// @public +export class Bytes { + static fromBase64String(base64: string): Bytes; + static fromUint8Array(array: Uint8Array): Bytes; + isEqual(other: Bytes): boolean; + toBase64(): string; + toString(): string; + toUint8Array(): Uint8Array; +} + +// @public +export type ChildUpdateFields = V extends Record ? AddPrefixToKeys> : never; + +// @public +export function collection(firestore: Firestore, path: string, ...pathSegments: string[]): CollectionReference; + +// @public +export function collection(reference: CollectionReference, path: string, ...pathSegments: string[]): CollectionReference; + +// @public +export function collection(reference: DocumentReference, path: string, ...pathSegments: string[]): CollectionReference; + +// @public +export function collectionGroup(firestore: Firestore, collectionId: string): Query; + +// @public +export class CollectionReference extends Query { + get id(): string; + get parent(): DocumentReference | null; + get path(): string; + readonly type = "collection"; + withConverter(converter: FirestoreDataConverter): CollectionReference; + withConverter(converter: null): CollectionReference; +} + +// @public +export function connectFirestoreEmulator(firestore: Firestore, host: string, port: number, options?: { + mockUserToken?: EmulatorMockTokenOptions | string; +}): void; + +// @public +export function deleteDoc(reference: DocumentReference): Promise; + +// @public +export function deleteField(): FieldValue; + +// @public +export function doc(firestore: Firestore, path: string, ...pathSegments: string[]): DocumentReference; + +// @public +export function doc(reference: CollectionReference, path?: string, ...pathSegments: string[]): DocumentReference; + +// @public +export function doc(reference: DocumentReference, path: string, ...pathSegments: string[]): DocumentReference; + +// @public +export interface DocumentData { + [field: string]: any; +} + +// @public +export function documentId(): FieldPath; + +// @public +export class DocumentReference { + readonly converter: FirestoreDataConverter | null; + readonly firestore: Firestore; + get id(): string; + get parent(): CollectionReference; + get path(): string; + readonly type = "document"; + withConverter(converter: FirestoreDataConverter): DocumentReference; + withConverter(converter: null): DocumentReference; +} + +// @public +export class DocumentSnapshot { + protected constructor(); + data(): T | undefined; + exists(): this is QueryDocumentSnapshot; + get(fieldPath: string | FieldPath): any; + get id(): string; + get ref(): DocumentReference; +} + +export { EmulatorMockTokenOptions } + +// @public +export function endAt(snapshot: DocumentSnapshot): QueryConstraint; + +// @public +export function endAt(...fieldValues: unknown[]): QueryConstraint; + +// @public +export function endBefore(snapshot: DocumentSnapshot): QueryConstraint; + +// @public +export function endBefore(...fieldValues: unknown[]): QueryConstraint; + +// @public +export class FieldPath { + constructor(...fieldNames: string[]); + isEqual(other: FieldPath): boolean; +} + +// @public +export abstract class FieldValue { + abstract isEqual(other: FieldValue): boolean; +} + +// @public +export class Firestore { + get app(): FirebaseApp; + toJSON(): object; + type: 'firestore-lite' | 'firestore'; +} + +// @public +export interface FirestoreDataConverter { + fromFirestore(snapshot: QueryDocumentSnapshot): T; + toFirestore(modelObject: WithFieldValue): DocumentData; + toFirestore(modelObject: PartialWithFieldValue, options: SetOptions): DocumentData; +} + +// @public +export class FirestoreError extends FirebaseError { + readonly code: FirestoreErrorCode; + readonly message: string; + readonly stack?: string; +} + +// @public +export type FirestoreErrorCode = 'cancelled' | 'unknown' | 'invalid-argument' | 'deadline-exceeded' | 'not-found' | 'already-exists' | 'permission-denied' | 'resource-exhausted' | 'failed-precondition' | 'aborted' | 'out-of-range' | 'unimplemented' | 'internal' | 'unavailable' | 'data-loss' | 'unauthenticated'; + +// @public +export class GeoPoint { + constructor(latitude: number, longitude: number); + isEqual(other: GeoPoint): boolean; + get latitude(): number; + get longitude(): number; + toJSON(): { + latitude: number; + longitude: number; + }; +} + +// @public +export function getDoc(reference: DocumentReference): Promise>; + +// @public +export function getDocs(query: Query): Promise>; + +// @public +export function getFirestore(app?: FirebaseApp): Firestore; + +// @public +export function increment(n: number): FieldValue; + +// @public +export function initializeFirestore(app: FirebaseApp, settings: Settings): Firestore; + +// @public +export function limit(limit: number): QueryConstraint; + +// @public +export function limitToLast(limit: number): QueryConstraint; + +export { LogLevel } + +// @public +export type NestedUpdateFields> = UnionToIntersection<{ + [K in keyof T & string]: ChildUpdateFields; +}[keyof T & string]>; + +// @public +export function orderBy(fieldPath: string | FieldPath, directionStr?: OrderByDirection): QueryConstraint; + +// @public +export type OrderByDirection = 'desc' | 'asc'; + +// @public +export type PartialWithFieldValue = Partial | (T extends Primitive ? T : T extends {} ? { + [K in keyof T]?: PartialWithFieldValue | FieldValue; +} : never); + +// @public +export type Primitive = string | number | boolean | undefined | null; + +// @public +export class Query { + protected constructor(); + readonly converter: FirestoreDataConverter | null; + readonly firestore: Firestore; + readonly type: 'query' | 'collection'; + withConverter(converter: null): Query; + withConverter(converter: FirestoreDataConverter): Query; +} + +// @public +export function query(query: Query, ...queryConstraints: QueryConstraint[]): Query; + +// @public +export abstract class QueryConstraint { + abstract readonly type: QueryConstraintType; +} + +// @public +export type QueryConstraintType = 'where' | 'orderBy' | 'limit' | 'limitToLast' | 'startAt' | 'startAfter' | 'endAt' | 'endBefore'; + +// @public +export class QueryDocumentSnapshot extends DocumentSnapshot { + // @override + data(): T; +} + +// @public +export function queryEqual(left: Query, right: Query): boolean; + +// @public +export class QuerySnapshot { + get docs(): Array>; + get empty(): boolean; + forEach(callback: (result: QueryDocumentSnapshot) => void, thisArg?: unknown): void; + readonly query: Query; + get size(): number; +} + +// @public +export function refEqual(left: DocumentReference | CollectionReference, right: DocumentReference | CollectionReference): boolean; + +// @public +export function runTransaction(firestore: Firestore, updateFunction: (transaction: Transaction) => Promise, options?: TransactionOptions): Promise; + +// @public +export function serverTimestamp(): FieldValue; + +// @public +export function setDoc(reference: DocumentReference, data: WithFieldValue): Promise; + +// @public +export function setDoc(reference: DocumentReference, data: PartialWithFieldValue, options: SetOptions): Promise; + +// @public +export function setLogLevel(logLevel: LogLevel): void; + +// @public +export type SetOptions = { + readonly merge?: boolean; +} | { + readonly mergeFields?: Array; +}; + +// @public +export interface Settings { + host?: string; + ignoreUndefinedProperties?: boolean; + ssl?: boolean; +} + +// @public +export function snapshotEqual(left: DocumentSnapshot | QuerySnapshot, right: DocumentSnapshot | QuerySnapshot): boolean; + +// @public +export function startAfter(snapshot: DocumentSnapshot): QueryConstraint; + +// @public +export function startAfter(...fieldValues: unknown[]): QueryConstraint; + +// @public +export function startAt(snapshot: DocumentSnapshot): QueryConstraint; + +// @public +export function startAt(...fieldValues: unknown[]): QueryConstraint; + +// @public +export function terminate(firestore: Firestore): Promise; + +// @public +export class Timestamp { + constructor( + seconds: number, + nanoseconds: number); + static fromDate(date: Date): Timestamp; + static fromMillis(milliseconds: number): Timestamp; + isEqual(other: Timestamp): boolean; + readonly nanoseconds: number; + static now(): Timestamp; + readonly seconds: number; + toDate(): Date; + toJSON(): { + seconds: number; + nanoseconds: number; + }; + toMillis(): number; + toString(): string; + valueOf(): string; +} + +// @public +export class Transaction { + delete(documentRef: DocumentReference): this; + get(documentRef: DocumentReference): Promise>; + set(documentRef: DocumentReference, data: WithFieldValue): this; + set(documentRef: DocumentReference, data: PartialWithFieldValue, options: SetOptions): this; + update(documentRef: DocumentReference, data: UpdateData): this; + update(documentRef: DocumentReference, field: string | FieldPath, value: unknown, ...moreFieldsAndValues: unknown[]): this; +} + +// @public +export interface TransactionOptions { + readonly maxAttempts?: number; +} + +// @public +export type UnionToIntersection = (U extends unknown ? (k: U) => void : never) extends (k: infer I) => void ? I : never; + +// @public +export type UpdateData = T extends Primitive ? T : T extends {} ? { + [K in keyof T]?: UpdateData | FieldValue; +} & NestedUpdateFields : Partial; + +// @public +export function updateDoc(reference: DocumentReference, data: UpdateData): Promise; + +// @public +export function updateDoc(reference: DocumentReference, field: string | FieldPath, value: unknown, ...moreFieldsAndValues: unknown[]): Promise; + +// @public +export function where(fieldPath: string | FieldPath, opStr: WhereFilterOp, value: unknown): QueryConstraint; + +// @public +export type WhereFilterOp = '<' | '<=' | '==' | '!=' | '>=' | '>' | 'array-contains' | 'in' | 'array-contains-any' | 'not-in'; + +// @public +export type WithFieldValue = T | (T extends Primitive ? T : T extends {} ? { + [K in keyof T]: WithFieldValue | FieldValue; +} : never); + +// @public +export class WriteBatch { + commit(): Promise; + delete(documentRef: DocumentReference): WriteBatch; + set(documentRef: DocumentReference, data: WithFieldValue): WriteBatch; + set(documentRef: DocumentReference, data: PartialWithFieldValue, options: SetOptions): WriteBatch; + update(documentRef: DocumentReference, data: UpdateData): WriteBatch; + update(documentRef: DocumentReference, field: string | FieldPath, value: unknown, ...moreFieldsAndValues: unknown[]): WriteBatch; +} + +// @public +export function writeBatch(firestore: Firestore): WriteBatch; + + +``` diff --git a/common/api-review/firestore.api.md b/common/api-review/firestore.api.md index 39828bda9ff..db36b60482c 100644 --- a/common/api-review/firestore.api.md +++ b/common/api-review/firestore.api.md @@ -1,525 +1,530 @@ -## API Report File for "@firebase/firestore" - -> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). - -```ts - -import { EmulatorMockTokenOptions } from '@firebase/util'; -import { FirebaseApp } from '@firebase/app'; -import { FirebaseError } from '@firebase/util'; -import { LogLevelString as LogLevel } from '@firebase/logger'; - -// @public -export function addDoc(reference: CollectionReference, data: WithFieldValue): Promise>; - -// @public -export type AddPrefixToKeys> = { - [K in keyof T & string as `${Prefix}.${K}`]+?: T[K]; -}; - -// @public -export function arrayRemove(...elements: unknown[]): FieldValue; - -// @public -export function arrayUnion(...elements: unknown[]): FieldValue; - -// @public -export class Bytes { - static fromBase64String(base64: string): Bytes; - static fromUint8Array(array: Uint8Array): Bytes; - isEqual(other: Bytes): boolean; - toBase64(): string; - toString(): string; - toUint8Array(): Uint8Array; -} - -// @public -export const CACHE_SIZE_UNLIMITED = -1; - -// @public -export type ChildUpdateFields = V extends Record ? AddPrefixToKeys> : never; - -// @public -export function clearIndexedDbPersistence(firestore: Firestore): Promise; - -// @public -export function collection(firestore: Firestore, path: string, ...pathSegments: string[]): CollectionReference; - -// @public -export function collection(reference: CollectionReference, path: string, ...pathSegments: string[]): CollectionReference; - -// @public -export function collection(reference: DocumentReference, path: string, ...pathSegments: string[]): CollectionReference; - -// @public -export function collectionGroup(firestore: Firestore, collectionId: string): Query; - -// @public -export class CollectionReference extends Query { - get id(): string; - get parent(): DocumentReference | null; - get path(): string; - readonly type = "collection"; - withConverter(converter: FirestoreDataConverter): CollectionReference; - withConverter(converter: null): CollectionReference; -} - -// @public -export function connectFirestoreEmulator(firestore: Firestore, host: string, port: number, options?: { - mockUserToken?: EmulatorMockTokenOptions | string; -}): void; - -// @public -export function deleteDoc(reference: DocumentReference): Promise; - -// @public -export function deleteField(): FieldValue; - -// @public -export function disableNetwork(firestore: Firestore): Promise; - -// @public -export function doc(firestore: Firestore, path: string, ...pathSegments: string[]): DocumentReference; - -// @public -export function doc(reference: CollectionReference, path?: string, ...pathSegments: string[]): DocumentReference; - -// @public -export function doc(reference: DocumentReference, path: string, ...pathSegments: string[]): DocumentReference; - -// @public -export interface DocumentChange { - readonly doc: QueryDocumentSnapshot; - readonly newIndex: number; - readonly oldIndex: number; - readonly type: DocumentChangeType; -} - -// @public -export type DocumentChangeType = 'added' | 'removed' | 'modified'; - -// @public -export interface DocumentData { - [field: string]: any; -} - -// @public -export function documentId(): FieldPath; - -// @public -export class DocumentReference { - readonly converter: FirestoreDataConverter | null; - readonly firestore: Firestore; - get id(): string; - get parent(): CollectionReference; - get path(): string; - readonly type = "document"; - withConverter(converter: FirestoreDataConverter): DocumentReference; - withConverter(converter: null): DocumentReference; -} - -// @public -export class DocumentSnapshot { - protected constructor(); - data(options?: SnapshotOptions): T | undefined; - exists(): this is QueryDocumentSnapshot; - get(fieldPath: string | FieldPath, options?: SnapshotOptions): any; - get id(): string; - readonly metadata: SnapshotMetadata; - get ref(): DocumentReference; -} - -export { EmulatorMockTokenOptions } - -// @public -export function enableIndexedDbPersistence(firestore: Firestore, persistenceSettings?: PersistenceSettings): Promise; - -// @public -export function enableMultiTabIndexedDbPersistence(firestore: Firestore): Promise; - -// @public -export function enableNetwork(firestore: Firestore): Promise; - -// @public -export function endAt(snapshot: DocumentSnapshot): QueryConstraint; - -// @public -export function endAt(...fieldValues: unknown[]): QueryConstraint; - -// @public -export function endBefore(snapshot: DocumentSnapshot): QueryConstraint; - -// @public -export function endBefore(...fieldValues: unknown[]): QueryConstraint; - -// @public -export class FieldPath { - constructor(...fieldNames: string[]); - isEqual(other: FieldPath): boolean; -} - -// @public -export abstract class FieldValue { - abstract isEqual(other: FieldValue): boolean; -} - -// @public -export class Firestore { - get app(): FirebaseApp; - toJSON(): object; - type: 'firestore-lite' | 'firestore'; -} - -// @public -export interface FirestoreDataConverter { - fromFirestore(snapshot: QueryDocumentSnapshot, options?: SnapshotOptions): T; - toFirestore(modelObject: WithFieldValue): DocumentData; - toFirestore(modelObject: PartialWithFieldValue, options: SetOptions): DocumentData; -} - -// @public -export class FirestoreError extends FirebaseError { - readonly code: FirestoreErrorCode; - readonly message: string; - readonly stack?: string; -} - -// @public -export type FirestoreErrorCode = 'cancelled' | 'unknown' | 'invalid-argument' | 'deadline-exceeded' | 'not-found' | 'already-exists' | 'permission-denied' | 'resource-exhausted' | 'failed-precondition' | 'aborted' | 'out-of-range' | 'unimplemented' | 'internal' | 'unavailable' | 'data-loss' | 'unauthenticated'; - -// @public -export interface FirestoreSettings { - cacheSizeBytes?: number; - experimentalAutoDetectLongPolling?: boolean; - experimentalForceLongPolling?: boolean; - host?: string; - ignoreUndefinedProperties?: boolean; - ssl?: boolean; -} - -// @public -export class GeoPoint { - constructor(latitude: number, longitude: number); - isEqual(other: GeoPoint): boolean; - get latitude(): number; - get longitude(): number; - toJSON(): { - latitude: number; - longitude: number; - }; -} - -// @public -export function getDoc(reference: DocumentReference): Promise>; - -// @public -export function getDocFromCache(reference: DocumentReference): Promise>; - -// @public -export function getDocFromServer(reference: DocumentReference): Promise>; - -// @public -export function getDocs(query: Query): Promise>; - -// @public -export function getDocsFromCache(query: Query): Promise>; - -// @public -export function getDocsFromServer(query: Query): Promise>; - -// @public -export function getFirestore(app?: FirebaseApp): Firestore; - -// @public -export function increment(n: number): FieldValue; - -// @public -export function initializeFirestore(app: FirebaseApp, settings: FirestoreSettings): Firestore; - -// @public -export function limit(limit: number): QueryConstraint; - -// @public -export function limitToLast(limit: number): QueryConstraint; - -// @public -export function loadBundle(firestore: Firestore, bundleData: ReadableStream | ArrayBuffer | string): LoadBundleTask; - -// @public -export class LoadBundleTask implements PromiseLike { - catch(onRejected: (a: Error) => R | PromiseLike): Promise; - onProgress(next?: (progress: LoadBundleTaskProgress) => unknown, error?: (err: Error) => unknown, complete?: () => void): void; - then(onFulfilled?: (a: LoadBundleTaskProgress) => T | PromiseLike, onRejected?: (a: Error) => R | PromiseLike): Promise; -} - -// @public -export interface LoadBundleTaskProgress { - bytesLoaded: number; - documentsLoaded: number; - taskState: TaskState; - totalBytes: number; - totalDocuments: number; -} - -export { LogLevel } - -// @public -export function namedQuery(firestore: Firestore, name: string): Promise; - -// @public -export type NestedUpdateFields> = UnionToIntersection<{ - [K in keyof T & string]: ChildUpdateFields; -}[keyof T & string]>; - -// @public -export function onSnapshot(reference: DocumentReference, observer: { - next?: (snapshot: DocumentSnapshot) => void; - error?: (error: FirestoreError) => void; - complete?: () => void; -}): Unsubscribe; - -// @public -export function onSnapshot(reference: DocumentReference, options: SnapshotListenOptions, observer: { - next?: (snapshot: DocumentSnapshot) => void; - error?: (error: FirestoreError) => void; - complete?: () => void; -}): Unsubscribe; - -// @public -export function onSnapshot(reference: DocumentReference, onNext: (snapshot: DocumentSnapshot) => void, onError?: (error: FirestoreError) => void, onCompletion?: () => void): Unsubscribe; - -// @public -export function onSnapshot(reference: DocumentReference, options: SnapshotListenOptions, onNext: (snapshot: DocumentSnapshot) => void, onError?: (error: FirestoreError) => void, onCompletion?: () => void): Unsubscribe; - -// @public -export function onSnapshot(query: Query, observer: { - next?: (snapshot: QuerySnapshot) => void; - error?: (error: FirestoreError) => void; - complete?: () => void; -}): Unsubscribe; - -// @public -export function onSnapshot(query: Query, options: SnapshotListenOptions, observer: { - next?: (snapshot: QuerySnapshot) => void; - error?: (error: FirestoreError) => void; - complete?: () => void; -}): Unsubscribe; - -// @public -export function onSnapshot(query: Query, onNext: (snapshot: QuerySnapshot) => void, onError?: (error: FirestoreError) => void, onCompletion?: () => void): Unsubscribe; - -// @public -export function onSnapshot(query: Query, options: SnapshotListenOptions, onNext: (snapshot: QuerySnapshot) => void, onError?: (error: FirestoreError) => void, onCompletion?: () => void): Unsubscribe; - -// @public -export function onSnapshotsInSync(firestore: Firestore, observer: { - next?: (value: void) => void; - error?: (error: FirestoreError) => void; - complete?: () => void; -}): Unsubscribe; - -// @public -export function onSnapshotsInSync(firestore: Firestore, onSync: () => void): Unsubscribe; - -// @public -export function orderBy(fieldPath: string | FieldPath, directionStr?: OrderByDirection): QueryConstraint; - -// @public -export type OrderByDirection = 'desc' | 'asc'; - -// @public -export type PartialWithFieldValue = Partial | (T extends Primitive ? T : T extends {} ? { - [K in keyof T]?: PartialWithFieldValue | FieldValue; -} : never); - -// @public -export interface PersistenceSettings { - forceOwnership?: boolean; -} - -// @public -export type Primitive = string | number | boolean | undefined | null; - -// @public -export class Query { - protected constructor(); - readonly converter: FirestoreDataConverter | null; - readonly firestore: Firestore; - readonly type: 'query' | 'collection'; - withConverter(converter: null): Query; - withConverter(converter: FirestoreDataConverter): Query; -} - -// @public -export function query(query: Query, ...queryConstraints: QueryConstraint[]): Query; - -// @public -export abstract class QueryConstraint { - abstract readonly type: QueryConstraintType; -} - -// @public -export type QueryConstraintType = 'where' | 'orderBy' | 'limit' | 'limitToLast' | 'startAt' | 'startAfter' | 'endAt' | 'endBefore'; - -// @public -export class QueryDocumentSnapshot extends DocumentSnapshot { - // @override - data(options?: SnapshotOptions): T; -} - -// @public -export function queryEqual(left: Query, right: Query): boolean; - -// @public -export class QuerySnapshot { - docChanges(options?: SnapshotListenOptions): Array>; - get docs(): Array>; - get empty(): boolean; - forEach(callback: (result: QueryDocumentSnapshot) => void, thisArg?: unknown): void; - readonly metadata: SnapshotMetadata; - readonly query: Query; - get size(): number; -} - -// @public -export function refEqual(left: DocumentReference | CollectionReference, right: DocumentReference | CollectionReference): boolean; - -// @public -export function runTransaction(firestore: Firestore, updateFunction: (transaction: Transaction) => Promise): Promise; - -// @public -export function serverTimestamp(): FieldValue; - -// @public -export function setDoc(reference: DocumentReference, data: WithFieldValue): Promise; - -// @public -export function setDoc(reference: DocumentReference, data: PartialWithFieldValue, options: SetOptions): Promise; - -// @public -export function setLogLevel(logLevel: LogLevel): void; - -// @public -export type SetOptions = { - readonly merge?: boolean; -} | { - readonly mergeFields?: Array; -}; - -// @public -export function snapshotEqual(left: DocumentSnapshot | QuerySnapshot, right: DocumentSnapshot | QuerySnapshot): boolean; - -// @public -export interface SnapshotListenOptions { - readonly includeMetadataChanges?: boolean; -} - -// @public -export class SnapshotMetadata { - readonly fromCache: boolean; - readonly hasPendingWrites: boolean; - isEqual(other: SnapshotMetadata): boolean; -} - -// @public -export interface SnapshotOptions { - readonly serverTimestamps?: 'estimate' | 'previous' | 'none'; -} - -// @public -export function startAfter(snapshot: DocumentSnapshot): QueryConstraint; - -// @public -export function startAfter(...fieldValues: unknown[]): QueryConstraint; - -// @public -export function startAt(snapshot: DocumentSnapshot): QueryConstraint; - -// @public -export function startAt(...fieldValues: unknown[]): QueryConstraint; - -// @public -export type TaskState = 'Error' | 'Running' | 'Success'; - -// @public -export function terminate(firestore: Firestore): Promise; - -// @public -export class Timestamp { - constructor( - seconds: number, - nanoseconds: number); - static fromDate(date: Date): Timestamp; - static fromMillis(milliseconds: number): Timestamp; - isEqual(other: Timestamp): boolean; - readonly nanoseconds: number; - static now(): Timestamp; - readonly seconds: number; - toDate(): Date; - toJSON(): { - seconds: number; - nanoseconds: number; - }; - toMillis(): number; - toString(): string; - valueOf(): string; -} - -// @public -export class Transaction { - delete(documentRef: DocumentReference): this; - get(documentRef: DocumentReference): Promise>; - set(documentRef: DocumentReference, data: WithFieldValue): this; - set(documentRef: DocumentReference, data: PartialWithFieldValue, options: SetOptions): this; - update(documentRef: DocumentReference, data: UpdateData): this; - update(documentRef: DocumentReference, field: string | FieldPath, value: unknown, ...moreFieldsAndValues: unknown[]): this; -} - -// @public -export type UnionToIntersection = (U extends unknown ? (k: U) => void : never) extends (k: infer I) => void ? I : never; - -// @public -export interface Unsubscribe { - (): void; -} - -// @public -export type UpdateData = T extends Primitive ? T : T extends {} ? { - [K in keyof T]?: UpdateData | FieldValue; -} & NestedUpdateFields : Partial; - -// @public -export function updateDoc(reference: DocumentReference, data: UpdateData): Promise; - -// @public -export function updateDoc(reference: DocumentReference, field: string | FieldPath, value: unknown, ...moreFieldsAndValues: unknown[]): Promise; - -// @public -export function waitForPendingWrites(firestore: Firestore): Promise; - -// @public -export function where(fieldPath: string | FieldPath, opStr: WhereFilterOp, value: unknown): QueryConstraint; - -// @public -export type WhereFilterOp = '<' | '<=' | '==' | '!=' | '>=' | '>' | 'array-contains' | 'in' | 'array-contains-any' | 'not-in'; - -// @public -export type WithFieldValue = T | (T extends Primitive ? T : T extends {} ? { - [K in keyof T]: WithFieldValue | FieldValue; -} : never); - -// @public -export class WriteBatch { - commit(): Promise; - delete(documentRef: DocumentReference): WriteBatch; - set(documentRef: DocumentReference, data: WithFieldValue): WriteBatch; - set(documentRef: DocumentReference, data: PartialWithFieldValue, options: SetOptions): WriteBatch; - update(documentRef: DocumentReference, data: UpdateData): WriteBatch; - update(documentRef: DocumentReference, field: string | FieldPath, value: unknown, ...moreFieldsAndValues: unknown[]): WriteBatch; -} - -// @public -export function writeBatch(firestore: Firestore): WriteBatch; - - -``` +## API Report File for "@firebase/firestore" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts + +import { EmulatorMockTokenOptions } from '@firebase/util'; +import { FirebaseApp } from '@firebase/app'; +import { FirebaseError } from '@firebase/util'; +import { LogLevelString as LogLevel } from '@firebase/logger'; + +// @public +export function addDoc(reference: CollectionReference, data: WithFieldValue): Promise>; + +// @public +export type AddPrefixToKeys> = { + [K in keyof T & string as `${Prefix}.${K}`]+?: T[K]; +}; + +// @public +export function arrayRemove(...elements: unknown[]): FieldValue; + +// @public +export function arrayUnion(...elements: unknown[]): FieldValue; + +// @public +export class Bytes { + static fromBase64String(base64: string): Bytes; + static fromUint8Array(array: Uint8Array): Bytes; + isEqual(other: Bytes): boolean; + toBase64(): string; + toString(): string; + toUint8Array(): Uint8Array; +} + +// @public +export const CACHE_SIZE_UNLIMITED = -1; + +// @public +export type ChildUpdateFields = V extends Record ? AddPrefixToKeys> : never; + +// @public +export function clearIndexedDbPersistence(firestore: Firestore): Promise; + +// @public +export function collection(firestore: Firestore, path: string, ...pathSegments: string[]): CollectionReference; + +// @public +export function collection(reference: CollectionReference, path: string, ...pathSegments: string[]): CollectionReference; + +// @public +export function collection(reference: DocumentReference, path: string, ...pathSegments: string[]): CollectionReference; + +// @public +export function collectionGroup(firestore: Firestore, collectionId: string): Query; + +// @public +export class CollectionReference extends Query { + get id(): string; + get parent(): DocumentReference | null; + get path(): string; + readonly type = "collection"; + withConverter(converter: FirestoreDataConverter): CollectionReference; + withConverter(converter: null): CollectionReference; +} + +// @public +export function connectFirestoreEmulator(firestore: Firestore, host: string, port: number, options?: { + mockUserToken?: EmulatorMockTokenOptions | string; +}): void; + +// @public +export function deleteDoc(reference: DocumentReference): Promise; + +// @public +export function deleteField(): FieldValue; + +// @public +export function disableNetwork(firestore: Firestore): Promise; + +// @public +export function doc(firestore: Firestore, path: string, ...pathSegments: string[]): DocumentReference; + +// @public +export function doc(reference: CollectionReference, path?: string, ...pathSegments: string[]): DocumentReference; + +// @public +export function doc(reference: DocumentReference, path: string, ...pathSegments: string[]): DocumentReference; + +// @public +export interface DocumentChange { + readonly doc: QueryDocumentSnapshot; + readonly newIndex: number; + readonly oldIndex: number; + readonly type: DocumentChangeType; +} + +// @public +export type DocumentChangeType = 'added' | 'removed' | 'modified'; + +// @public +export interface DocumentData { + [field: string]: any; +} + +// @public +export function documentId(): FieldPath; + +// @public +export class DocumentReference { + readonly converter: FirestoreDataConverter | null; + readonly firestore: Firestore; + get id(): string; + get parent(): CollectionReference; + get path(): string; + readonly type = "document"; + withConverter(converter: FirestoreDataConverter): DocumentReference; + withConverter(converter: null): DocumentReference; +} + +// @public +export class DocumentSnapshot { + protected constructor(); + data(options?: SnapshotOptions): T | undefined; + exists(): this is QueryDocumentSnapshot; + get(fieldPath: string | FieldPath, options?: SnapshotOptions): any; + get id(): string; + readonly metadata: SnapshotMetadata; + get ref(): DocumentReference; +} + +export { EmulatorMockTokenOptions } + +// @public +export function enableIndexedDbPersistence(firestore: Firestore, persistenceSettings?: PersistenceSettings): Promise; + +// @public +export function enableMultiTabIndexedDbPersistence(firestore: Firestore): Promise; + +// @public +export function enableNetwork(firestore: Firestore): Promise; + +// @public +export function endAt(snapshot: DocumentSnapshot): QueryConstraint; + +// @public +export function endAt(...fieldValues: unknown[]): QueryConstraint; + +// @public +export function endBefore(snapshot: DocumentSnapshot): QueryConstraint; + +// @public +export function endBefore(...fieldValues: unknown[]): QueryConstraint; + +// @public +export class FieldPath { + constructor(...fieldNames: string[]); + isEqual(other: FieldPath): boolean; +} + +// @public +export abstract class FieldValue { + abstract isEqual(other: FieldValue): boolean; +} + +// @public +export class Firestore { + get app(): FirebaseApp; + toJSON(): object; + type: 'firestore-lite' | 'firestore'; +} + +// @public +export interface FirestoreDataConverter { + fromFirestore(snapshot: QueryDocumentSnapshot, options?: SnapshotOptions): T; + toFirestore(modelObject: WithFieldValue): DocumentData; + toFirestore(modelObject: PartialWithFieldValue, options: SetOptions): DocumentData; +} + +// @public +export class FirestoreError extends FirebaseError { + readonly code: FirestoreErrorCode; + readonly message: string; + readonly stack?: string; +} + +// @public +export type FirestoreErrorCode = 'cancelled' | 'unknown' | 'invalid-argument' | 'deadline-exceeded' | 'not-found' | 'already-exists' | 'permission-denied' | 'resource-exhausted' | 'failed-precondition' | 'aborted' | 'out-of-range' | 'unimplemented' | 'internal' | 'unavailable' | 'data-loss' | 'unauthenticated'; + +// @public +export interface FirestoreSettings { + cacheSizeBytes?: number; + experimentalAutoDetectLongPolling?: boolean; + experimentalForceLongPolling?: boolean; + host?: string; + ignoreUndefinedProperties?: boolean; + ssl?: boolean; +} + +// @public +export class GeoPoint { + constructor(latitude: number, longitude: number); + isEqual(other: GeoPoint): boolean; + get latitude(): number; + get longitude(): number; + toJSON(): { + latitude: number; + longitude: number; + }; +} + +// @public +export function getDoc(reference: DocumentReference): Promise>; + +// @public +export function getDocFromCache(reference: DocumentReference): Promise>; + +// @public +export function getDocFromServer(reference: DocumentReference): Promise>; + +// @public +export function getDocs(query: Query): Promise>; + +// @public +export function getDocsFromCache(query: Query): Promise>; + +// @public +export function getDocsFromServer(query: Query): Promise>; + +// @public +export function getFirestore(app?: FirebaseApp): Firestore; + +// @public +export function increment(n: number): FieldValue; + +// @public +export function initializeFirestore(app: FirebaseApp, settings: FirestoreSettings): Firestore; + +// @public +export function limit(limit: number): QueryConstraint; + +// @public +export function limitToLast(limit: number): QueryConstraint; + +// @public +export function loadBundle(firestore: Firestore, bundleData: ReadableStream | ArrayBuffer | string): LoadBundleTask; + +// @public +export class LoadBundleTask implements PromiseLike { + catch(onRejected: (a: Error) => R | PromiseLike): Promise; + onProgress(next?: (progress: LoadBundleTaskProgress) => unknown, error?: (err: Error) => unknown, complete?: () => void): void; + then(onFulfilled?: (a: LoadBundleTaskProgress) => T | PromiseLike, onRejected?: (a: Error) => R | PromiseLike): Promise; +} + +// @public +export interface LoadBundleTaskProgress { + bytesLoaded: number; + documentsLoaded: number; + taskState: TaskState; + totalBytes: number; + totalDocuments: number; +} + +export { LogLevel } + +// @public +export function namedQuery(firestore: Firestore, name: string): Promise; + +// @public +export type NestedUpdateFields> = UnionToIntersection<{ + [K in keyof T & string]: ChildUpdateFields; +}[keyof T & string]>; + +// @public +export function onSnapshot(reference: DocumentReference, observer: { + next?: (snapshot: DocumentSnapshot) => void; + error?: (error: FirestoreError) => void; + complete?: () => void; +}): Unsubscribe; + +// @public +export function onSnapshot(reference: DocumentReference, options: SnapshotListenOptions, observer: { + next?: (snapshot: DocumentSnapshot) => void; + error?: (error: FirestoreError) => void; + complete?: () => void; +}): Unsubscribe; + +// @public +export function onSnapshot(reference: DocumentReference, onNext: (snapshot: DocumentSnapshot) => void, onError?: (error: FirestoreError) => void, onCompletion?: () => void): Unsubscribe; + +// @public +export function onSnapshot(reference: DocumentReference, options: SnapshotListenOptions, onNext: (snapshot: DocumentSnapshot) => void, onError?: (error: FirestoreError) => void, onCompletion?: () => void): Unsubscribe; + +// @public +export function onSnapshot(query: Query, observer: { + next?: (snapshot: QuerySnapshot) => void; + error?: (error: FirestoreError) => void; + complete?: () => void; +}): Unsubscribe; + +// @public +export function onSnapshot(query: Query, options: SnapshotListenOptions, observer: { + next?: (snapshot: QuerySnapshot) => void; + error?: (error: FirestoreError) => void; + complete?: () => void; +}): Unsubscribe; + +// @public +export function onSnapshot(query: Query, onNext: (snapshot: QuerySnapshot) => void, onError?: (error: FirestoreError) => void, onCompletion?: () => void): Unsubscribe; + +// @public +export function onSnapshot(query: Query, options: SnapshotListenOptions, onNext: (snapshot: QuerySnapshot) => void, onError?: (error: FirestoreError) => void, onCompletion?: () => void): Unsubscribe; + +// @public +export function onSnapshotsInSync(firestore: Firestore, observer: { + next?: (value: void) => void; + error?: (error: FirestoreError) => void; + complete?: () => void; +}): Unsubscribe; + +// @public +export function onSnapshotsInSync(firestore: Firestore, onSync: () => void): Unsubscribe; + +// @public +export function orderBy(fieldPath: string | FieldPath, directionStr?: OrderByDirection): QueryConstraint; + +// @public +export type OrderByDirection = 'desc' | 'asc'; + +// @public +export type PartialWithFieldValue = Partial | (T extends Primitive ? T : T extends {} ? { + [K in keyof T]?: PartialWithFieldValue | FieldValue; +} : never); + +// @public +export interface PersistenceSettings { + forceOwnership?: boolean; +} + +// @public +export type Primitive = string | number | boolean | undefined | null; + +// @public +export class Query { + protected constructor(); + readonly converter: FirestoreDataConverter | null; + readonly firestore: Firestore; + readonly type: 'query' | 'collection'; + withConverter(converter: null): Query; + withConverter(converter: FirestoreDataConverter): Query; +} + +// @public +export function query(query: Query, ...queryConstraints: QueryConstraint[]): Query; + +// @public +export abstract class QueryConstraint { + abstract readonly type: QueryConstraintType; +} + +// @public +export type QueryConstraintType = 'where' | 'orderBy' | 'limit' | 'limitToLast' | 'startAt' | 'startAfter' | 'endAt' | 'endBefore'; + +// @public +export class QueryDocumentSnapshot extends DocumentSnapshot { + // @override + data(options?: SnapshotOptions): T; +} + +// @public +export function queryEqual(left: Query, right: Query): boolean; + +// @public +export class QuerySnapshot { + docChanges(options?: SnapshotListenOptions): Array>; + get docs(): Array>; + get empty(): boolean; + forEach(callback: (result: QueryDocumentSnapshot) => void, thisArg?: unknown): void; + readonly metadata: SnapshotMetadata; + readonly query: Query; + get size(): number; +} + +// @public +export function refEqual(left: DocumentReference | CollectionReference, right: DocumentReference | CollectionReference): boolean; + +// @public +export function runTransaction(firestore: Firestore, updateFunction: (transaction: Transaction) => Promise, options?: TransactionOptions): Promise; + +// @public +export function serverTimestamp(): FieldValue; + +// @public +export function setDoc(reference: DocumentReference, data: WithFieldValue): Promise; + +// @public +export function setDoc(reference: DocumentReference, data: PartialWithFieldValue, options: SetOptions): Promise; + +// @public +export function setLogLevel(logLevel: LogLevel): void; + +// @public +export type SetOptions = { + readonly merge?: boolean; +} | { + readonly mergeFields?: Array; +}; + +// @public +export function snapshotEqual(left: DocumentSnapshot | QuerySnapshot, right: DocumentSnapshot | QuerySnapshot): boolean; + +// @public +export interface SnapshotListenOptions { + readonly includeMetadataChanges?: boolean; +} + +// @public +export class SnapshotMetadata { + readonly fromCache: boolean; + readonly hasPendingWrites: boolean; + isEqual(other: SnapshotMetadata): boolean; +} + +// @public +export interface SnapshotOptions { + readonly serverTimestamps?: 'estimate' | 'previous' | 'none'; +} + +// @public +export function startAfter(snapshot: DocumentSnapshot): QueryConstraint; + +// @public +export function startAfter(...fieldValues: unknown[]): QueryConstraint; + +// @public +export function startAt(snapshot: DocumentSnapshot): QueryConstraint; + +// @public +export function startAt(...fieldValues: unknown[]): QueryConstraint; + +// @public +export type TaskState = 'Error' | 'Running' | 'Success'; + +// @public +export function terminate(firestore: Firestore): Promise; + +// @public +export class Timestamp { + constructor( + seconds: number, + nanoseconds: number); + static fromDate(date: Date): Timestamp; + static fromMillis(milliseconds: number): Timestamp; + isEqual(other: Timestamp): boolean; + readonly nanoseconds: number; + static now(): Timestamp; + readonly seconds: number; + toDate(): Date; + toJSON(): { + seconds: number; + nanoseconds: number; + }; + toMillis(): number; + toString(): string; + valueOf(): string; +} + +// @public +export class Transaction { + delete(documentRef: DocumentReference): this; + get(documentRef: DocumentReference): Promise>; + set(documentRef: DocumentReference, data: WithFieldValue): this; + set(documentRef: DocumentReference, data: PartialWithFieldValue, options: SetOptions): this; + update(documentRef: DocumentReference, data: UpdateData): this; + update(documentRef: DocumentReference, field: string | FieldPath, value: unknown, ...moreFieldsAndValues: unknown[]): this; +} + +// @public +export interface TransactionOptions { + readonly maxAttempts?: number; +} + +// @public +export type UnionToIntersection = (U extends unknown ? (k: U) => void : never) extends (k: infer I) => void ? I : never; + +// @public +export interface Unsubscribe { + (): void; +} + +// @public +export type UpdateData = T extends Primitive ? T : T extends {} ? { + [K in keyof T]?: UpdateData | FieldValue; +} & NestedUpdateFields : Partial; + +// @public +export function updateDoc(reference: DocumentReference, data: UpdateData): Promise; + +// @public +export function updateDoc(reference: DocumentReference, field: string | FieldPath, value: unknown, ...moreFieldsAndValues: unknown[]): Promise; + +// @public +export function waitForPendingWrites(firestore: Firestore): Promise; + +// @public +export function where(fieldPath: string | FieldPath, opStr: WhereFilterOp, value: unknown): QueryConstraint; + +// @public +export type WhereFilterOp = '<' | '<=' | '==' | '!=' | '>=' | '>' | 'array-contains' | 'in' | 'array-contains-any' | 'not-in'; + +// @public +export type WithFieldValue = T | (T extends Primitive ? T : T extends {} ? { + [K in keyof T]: WithFieldValue | FieldValue; +} : never); + +// @public +export class WriteBatch { + commit(): Promise; + delete(documentRef: DocumentReference): WriteBatch; + set(documentRef: DocumentReference, data: WithFieldValue): WriteBatch; + set(documentRef: DocumentReference, data: PartialWithFieldValue, options: SetOptions): WriteBatch; + update(documentRef: DocumentReference, data: UpdateData): WriteBatch; + update(documentRef: DocumentReference, field: string | FieldPath, value: unknown, ...moreFieldsAndValues: unknown[]): WriteBatch; +} + +// @public +export function writeBatch(firestore: Firestore): WriteBatch; + + +``` diff --git a/packages/firestore/lite/index.ts b/packages/firestore/lite/index.ts index 42e1554c92e..ad7ec7d8294 100644 --- a/packages/firestore/lite/index.ts +++ b/packages/firestore/lite/index.ts @@ -111,6 +111,8 @@ export { export { WriteBatch, writeBatch } from '../src/lite-api/write_batch'; +export { TransactionOptions } from '../src/lite-api/transaction_options'; + export { Transaction, runTransaction } from '../src/lite-api/transaction'; export { setLogLevel, LogLevelString as LogLevel } from '../src/util/log'; diff --git a/packages/firestore/src/api.ts b/packages/firestore/src/api.ts index 810289c0d14..8e774dbfb30 100644 --- a/packages/firestore/src/api.ts +++ b/packages/firestore/src/api.ts @@ -89,6 +89,8 @@ export { export { Unsubscribe, SnapshotListenOptions } from './api/reference_impl'; +export { TransactionOptions } from './api/transaction_options'; + export { runTransaction, Transaction } from './api/transaction'; export { diff --git a/packages/firestore/src/api/transaction.ts b/packages/firestore/src/api/transaction.ts index 798f95cf4fa..ee5377b2fe8 100644 --- a/packages/firestore/src/api/transaction.ts +++ b/packages/firestore/src/api/transaction.ts @@ -17,6 +17,11 @@ import { firestoreClientTransaction } from '../core/firestore_client'; import { Transaction as InternalTransaction } from '../core/transaction'; +import { + TransactionOptions as TranasactionOptionsInternal, + DEFAULT_TRANSACTION_OPTIONS, + validateTransactionOptions +} from '../core/transaction_options'; import { DocumentReference } from '../lite-api/reference'; import { Transaction as LiteTransaction } from '../lite-api/transaction'; import { validateReference } from '../lite-api/write_batch'; @@ -25,6 +30,7 @@ import { cast } from '../util/input_validation'; import { ensureFirestoreConfigured, Firestore } from './database'; import { ExpUserDataWriter } from './reference_impl'; import { DocumentSnapshot, SnapshotMetadata } from './snapshot'; +import { TransactionOptions } from './transaction_options'; /** * A reference to a transaction. @@ -92,11 +98,20 @@ export class Transaction extends LiteTransaction { */ export function runTransaction( firestore: Firestore, - updateFunction: (transaction: Transaction) => Promise + updateFunction: (transaction: Transaction) => Promise, + options?: TransactionOptions ): Promise { firestore = cast(firestore, Firestore); + const optionsWithDefaults: TranasactionOptionsInternal = { + ...DEFAULT_TRANSACTION_OPTIONS, + ...options + }; + validateTransactionOptions(optionsWithDefaults); const client = ensureFirestoreConfigured(firestore); - return firestoreClientTransaction(client, internalTransaction => - updateFunction(new Transaction(firestore, internalTransaction)) + return firestoreClientTransaction( + client, + internalTransaction => + updateFunction(new Transaction(firestore, internalTransaction)), + optionsWithDefaults ); } diff --git a/packages/firestore/src/api/transaction_options.ts b/packages/firestore/src/api/transaction_options.ts new file mode 100644 index 00000000000..e369259918a --- /dev/null +++ b/packages/firestore/src/api/transaction_options.ts @@ -0,0 +1,18 @@ +/** + * @license + * Copyright 2022 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. + */ + +export { TransactionOptions } from '../lite-api/transaction_options'; diff --git a/packages/firestore/src/core/firestore_client.ts b/packages/firestore/src/core/firestore_client.ts index 858b40929ad..7175737c59b 100644 --- a/packages/firestore/src/core/firestore_client.ts +++ b/packages/firestore/src/core/firestore_client.ts @@ -82,6 +82,7 @@ import { syncEngineWrite } from './sync_engine_impl'; import { Transaction } from './transaction'; +import { TransactionOptions } from './transaction_options'; import { TransactionRunner } from './transaction_runner'; import { View } from './view'; import { ViewSnapshot } from './view_snapshot'; @@ -483,7 +484,8 @@ export function firestoreClientAddSnapshotsInSyncListener( */ export function firestoreClientTransaction( client: FirestoreClient, - updateFunction: (transaction: Transaction) => Promise + updateFunction: (transaction: Transaction) => Promise, + options: TransactionOptions ): Promise { const deferred = new Deferred(); client.asyncQueue.enqueueAndForget(async () => { @@ -491,6 +493,7 @@ export function firestoreClientTransaction( new TransactionRunner( client.asyncQueue, datastore, + options, updateFunction, deferred ).run(); diff --git a/packages/firestore/src/core/transaction_options.ts b/packages/firestore/src/core/transaction_options.ts new file mode 100644 index 00000000000..f5bc4501d81 --- /dev/null +++ b/packages/firestore/src/core/transaction_options.ts @@ -0,0 +1,39 @@ +/** + * @license + * Copyright 2022 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 { Code, FirestoreError } from '../util/error'; + +export const DEFAULT_TRANSACTION_OPTIONS: TransactionOptions = { + maxAttempts: 5 +}; + +/** + * Options to customize transaction behavior. + */ +export declare interface TransactionOptions { + /** maximum number of attempts to commit, after which transaction fails. Default is 5. */ + readonly maxAttempts: number; +} + +export function validateTransactionOptions(options: TransactionOptions): void { + if (options.maxAttempts < 1) { + throw new FirestoreError( + Code.INVALID_ARGUMENT, + 'Max attempts must be at least 1' + ); + } +} diff --git a/packages/firestore/src/core/transaction_runner.ts b/packages/firestore/src/core/transaction_runner.ts index a9e17327aa7..d46f581b768 100644 --- a/packages/firestore/src/core/transaction_runner.ts +++ b/packages/firestore/src/core/transaction_runner.ts @@ -24,23 +24,24 @@ import { Deferred } from '../util/promise'; import { isNullOrUndefined } from '../util/types'; import { Transaction } from './transaction'; - -export const DEFAULT_MAX_ATTEMPTS_COUNT = 5; +import { TransactionOptions } from './transaction_options'; /** * TransactionRunner encapsulates the logic needed to run and retry transactions * with backoff. */ export class TransactionRunner { - private attemptsRemaining = DEFAULT_MAX_ATTEMPTS_COUNT; + private attemptsRemaining: number; private backoff: ExponentialBackoff; constructor( private readonly asyncQueue: AsyncQueue, private readonly datastore: Datastore, + private readonly options: TransactionOptions, private readonly updateFunction: (transaction: Transaction) => Promise, private readonly deferred: Deferred ) { + this.attemptsRemaining = options.maxAttempts; this.backoff = new ExponentialBackoff( this.asyncQueue, TimerId.TransactionRetry diff --git a/packages/firestore/src/lite-api/transaction.ts b/packages/firestore/src/lite-api/transaction.ts index 38297e8528f..af602582c5f 100644 --- a/packages/firestore/src/lite-api/transaction.ts +++ b/packages/firestore/src/lite-api/transaction.ts @@ -18,6 +18,11 @@ import { getModularInstance } from '@firebase/util'; import { Transaction as InternalTransaction } from '../core/transaction'; +import { + DEFAULT_TRANSACTION_OPTIONS, + TransactionOptions as TranasactionOptionsInternal, + validateTransactionOptions +} from '../core/transaction_options'; import { TransactionRunner } from '../core/transaction_runner'; import { fail } from '../util/assert'; import { newAsyncQueue } from '../util/async_queue_impl'; @@ -39,6 +44,7 @@ import { LiteUserDataWriter } from './reference_impl'; import { DocumentSnapshot } from './snapshot'; +import { TransactionOptions } from './transaction_options'; import { newUserDataReader, parseSetData, @@ -266,14 +272,21 @@ export class Transaction { */ export function runTransaction( firestore: Firestore, - updateFunction: (transaction: Transaction) => Promise + updateFunction: (transaction: Transaction) => Promise, + options?: TransactionOptions ): Promise { firestore = cast(firestore, Firestore); const datastore = getDatastore(firestore); + const optionsWithDefaults: TranasactionOptionsInternal = { + ...DEFAULT_TRANSACTION_OPTIONS, + ...options + }; + validateTransactionOptions(optionsWithDefaults); const deferred = new Deferred(); new TransactionRunner( newAsyncQueue(), datastore, + optionsWithDefaults, internalTransaction => updateFunction(new Transaction(firestore, internalTransaction)), deferred diff --git a/packages/firestore/src/lite-api/transaction_options.ts b/packages/firestore/src/lite-api/transaction_options.ts new file mode 100644 index 00000000000..49d2bcd5be2 --- /dev/null +++ b/packages/firestore/src/lite-api/transaction_options.ts @@ -0,0 +1,24 @@ +/** + * @license + * Copyright 2022 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. + */ + +/** + * Options to customize transaction behavior. + */ +export declare interface TransactionOptions { + /** maximum number of attempts to commit, after which transaction fails. Default is 5. */ + readonly maxAttempts?: number; +} diff --git a/packages/firestore/test/integration/api_internal/transaction.test.ts b/packages/firestore/test/integration/api_internal/transaction.test.ts index f8665094b6b..99a677b715f 100644 --- a/packages/firestore/test/integration/api_internal/transaction.test.ts +++ b/packages/firestore/test/integration/api_internal/transaction.test.ts @@ -17,24 +17,24 @@ import { expect } from 'chai'; -import { DEFAULT_MAX_ATTEMPTS_COUNT } from '../../../src/core/transaction_runner'; +import { DEFAULT_TRANSACTION_OPTIONS } from '../../../src/core/transaction_options'; import { TimerId } from '../../../src/util/async_queue'; import { Deferred } from '../../util/promise'; import { collection, doc, - FirestoreError, getDoc, runTransaction, - setDoc + setDoc, + TransactionOptions } from '../util/firebase_export'; import { apiDescribe, withTestDb } from '../util/helpers'; import { asyncQueue } from '../util/internal_helpers'; -apiDescribe( +apiDescribe.only( 'Database transactions (with internal API)', (persistence: boolean) => { - it('increment transactionally', () => { + it('should increment transactionally', async () => { // A set of concurrent transactions. const transactionPromises: Array> = []; const readPromises: Array> = []; @@ -42,55 +42,45 @@ apiDescribe( const barrier = new Deferred(); let started = 0; - return withTestDb(persistence, db => { + await withTestDb(persistence, async db => { asyncQueue(db).skipDelaysForTimerId(TimerId.TransactionRetry); const docRef = doc(collection(db, 'counters')); - return setDoc(docRef, { - count: 5 - }) - .then(() => { - // Make 3 transactions that will all increment. - for (let i = 0; i < 3; i++) { - const resolveRead = new Deferred(); - readPromises.push(resolveRead.promise); - transactionPromises.push( - runTransaction(db, transaction => { - return transaction.get(docRef).then(snapshot => { - expect(snapshot).to.exist; - started = started + 1; - resolveRead.resolve(); - return barrier.promise.then(() => { - transaction.set(docRef, { - count: snapshot.data()!['count'] + 1 - }); - }); - }); - }) - ); - } + await setDoc(docRef, { count: 5 }); + // Make 3 transactions that will all increment. + for (let i = 0; i < 3; i++) { + const resolveRead = new Deferred(); + readPromises.push(resolveRead.promise); + transactionPromises.push( + runTransaction(db, async transaction => { + const snapshot = await transaction.get(docRef); + expect(snapshot).to.exist; + started += 1; + resolveRead.resolve(); + await barrier.promise; + transaction.set(docRef, { + count: snapshot.data()!['count'] + 1 + }); + }) + ); + } - // Let all of the transactions fetch the old value and stop once. - return Promise.all(readPromises); - }) - .then(() => { - // Let all of the transactions continue and wait for them to - // finish. - expect(started).to.equal(3); - barrier.resolve(); - return Promise.all(transactionPromises); - }) - .then(() => { - // Now all transaction should be completed, so check the result. - return getDoc(docRef); - }) - .then(snapshot => { - expect(snapshot).to.exist; - expect(snapshot.data()!['count']).to.equal(8); - }); + // Let all of the transactions fetch the old value and stop once. + await Promise.all(readPromises); + + // Let all of the transactions continue and wait for them to + // finish. + expect(started).to.equal(3); + barrier.resolve(); + await Promise.all(transactionPromises); + + // Now all transaction should be completed, so check the result. + const snapshot = await getDoc(docRef); + expect(snapshot).to.exist; + expect(snapshot.data()!['count']).to.equal(8); }); }); - it('update transactionally', () => { + it('should update transactionally', async () => { // A set of concurrent transactions. const transactionPromises: Array> = []; const readPromises: Array> = []; @@ -98,96 +88,116 @@ apiDescribe( const barrier = new Deferred(); let counter = 0; - return withTestDb(persistence, db => { + await withTestDb(persistence, async db => { asyncQueue(db).skipDelaysForTimerId(TimerId.TransactionRetry); const docRef = doc(collection(db, 'counters')); - return setDoc(docRef, { + await setDoc(docRef, { count: 5, other: 'yes' - }) - .then(() => { - // Make 3 transactions that will all increment. - for (let i = 0; i < 3; i++) { - const resolveRead = new Deferred(); - readPromises.push(resolveRead.promise); - transactionPromises.push( - runTransaction(db, transaction => { - return transaction.get(docRef).then(snapshot => { - expect(snapshot).to.exist; - counter = counter + 1; - resolveRead.resolve(); - return barrier.promise.then(() => { - transaction.update(docRef, { - count: snapshot.data()!['count'] + 1 - }); - }); - }); - }) - ); - } + }); + // Make 3 transactions that will all increment. + for (let i = 0; i < 3; i++) { + const resolveRead = new Deferred(); + readPromises.push(resolveRead.promise); + transactionPromises.push( + runTransaction(db, async transaction => { + const snapshot = await transaction.get(docRef); + expect(snapshot).to.exist; + counter += 1; + resolveRead.resolve(); + await barrier.promise; + await transaction.update(docRef, { + count: snapshot.data()!['count'] + 1 + }); + }) + ); + } - // Let all of the transactions fetch the old value and stop once. - return Promise.all(readPromises); - }) - .then(() => { - // Let all of the transactions continue and wait for them to - // finish. There should be 3 initial transaction runs. - expect(counter).to.equal(3); - barrier.resolve(); - return Promise.all(transactionPromises); - }) - .then(() => { - // Now all transaction should be completed, so check the result. - // There should be a maximum of 3 retries: once for the 2nd update, - // and twice for the 3rd update. - expect(counter).to.be.lessThan(7); - return getDoc(docRef); - }) - .then(snapshot => { - expect(snapshot).to.exist; - expect(snapshot.data()!['count']).to.equal(8); - expect(snapshot.data()!['other']).to.equal('yes'); - }); + // Let all of the transactions fetch the old value and stop once. + await Promise.all(readPromises); + + // Let all of the transactions continue and wait for them to + // finish. There should be 3 initial transaction runs. + expect(counter).to.equal(3); + barrier.resolve(); + await Promise.all(transactionPromises); + + // Now all transaction should be completed, so check the result. + // There should be a maximum of 3 retries: once for the 2nd update, + // and twice for the 3rd update. + expect(counter).to.be.lessThan(7); + const snapshot = await getDoc(docRef); + expect(snapshot).to.exist; + expect(snapshot.data()!['count']).to.equal(8); + expect(snapshot.data()!['other']).to.equal('yes'); }); }); - it('handle reading a doc twice with different versions', () => { - return withTestDb(persistence, db => { + + it('should fail transaction (maxAttempts: default) when reading a doc twice with different versions', async () => { + await withTestDb(persistence, async db => { asyncQueue(db).skipDelaysForTimerId(TimerId.TransactionRetry); const docRef = doc(collection(db, 'counters')); let counter = 0; - return setDoc(docRef, { - count: 15 - }) - .then(() => { - return runTransaction(db, transaction => { - counter++; - // Get the docRef once. - return ( - transaction - .get(docRef) - // Do a write outside of the transaction. Because the transaction - // will retry, set the document to a different value each time. - .then(() => setDoc(docRef, { count: 1234 + counter })) - // Get the docRef again in the transaction with the new - // version. - .then(() => transaction.get(docRef)) - // Now try to update the docRef from within the transaction. - // This should fail, because we read 15 earlier. - .then(() => transaction.set(docRef, { count: 16 })) - ); - }); - }) - .then(() => expect.fail('transaction should fail')) - .catch((err: FirestoreError) => { - expect(err).to.exist; - expect(err.code).to.equal('aborted'); - }) - .then(() => getDoc(docRef)) - .then(snapshot => { - expect(snapshot.data()!['count']).to.equal(1234 + counter); - expect(counter).to.equal(DEFAULT_MAX_ATTEMPTS_COUNT); + await setDoc(docRef, { count: 15 }); + try { + await runTransaction(db, async transaction => { + counter++; + // Get the docRef once. + await transaction.get(docRef); + // Do a write outside of the transaction. Because the transaction + // will retry, set the document to a different value each time. + await setDoc(docRef, {count: 1234 + counter}); + // Get the docRef again in the transaction with the new + // version. + await transaction.get(docRef); + // Now try to update the docRef from within the transaction. + // This should fail, because we read 15 earlier. + await transaction.set(docRef, {count: 16}); }); + expect.fail('transaction should fail'); + } catch (err) { + expect(err).to.exist; + expect(err.code).to.equal('aborted'); + } + const snapshot = await getDoc(docRef); + expect(snapshot.data()!['count']).to.equal(1234 + counter); + expect(counter).to.equal(DEFAULT_TRANSACTION_OPTIONS.maxAttempts); + }); + }); + + it('should fail transaction (maxAttempts: 1) when reading a doc twice with different versions', async () => { + await withTestDb(persistence, async db => { + asyncQueue(db).skipDelaysForTimerId(TimerId.TransactionRetry); + const docRef = doc(collection(db, 'counters')); + const options: TransactionOptions = { + maxAttempts: 1 + }; + let counter = 0; + await setDoc(docRef, { count: 15 }); + try { + await runTransaction(db, async transaction => { + counter++; + // Get the docRef once. + await transaction.get(docRef); + // Do a write outside of the transaction. Because the transaction + // will retry, set the document to a different value each time. + await setDoc(docRef, {count: 1234 + counter}); + // Get the docRef again in the transaction with the new + // version. + await transaction.get(docRef); + // Now try to update the docRef from within the transaction. + // This should fail, because we read 15 earlier. + await transaction.set(docRef, {count: 16}); + }, options); + expect.fail('transaction should fail'); + } catch (err) { + expect(err).to.exist; + expect(err.code).to.equal('aborted'); + } + const snapshot = await getDoc(docRef); + expect(snapshot.data()!['count']).to.equal(1234 + counter); + expect(counter).to.equal(options.maxAttempts); }); }); } From b4c2c193a68a48cdfa1909b475bc0cc24f313773 Mon Sep 17 00:00:00 2001 From: Tom Andersen Date: Thu, 28 Apr 2022 09:46:34 -0400 Subject: [PATCH 2/5] Fix whitespace --- .../api_internal/transaction.test.ts | 37 ++++++++++--------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/packages/firestore/test/integration/api_internal/transaction.test.ts b/packages/firestore/test/integration/api_internal/transaction.test.ts index 99a677b715f..50a0dcef626 100644 --- a/packages/firestore/test/integration/api_internal/transaction.test.ts +++ b/packages/firestore/test/integration/api_internal/transaction.test.ts @@ -133,7 +133,6 @@ apiDescribe.only( }); }); - it('should fail transaction (maxAttempts: default) when reading a doc twice with different versions', async () => { await withTestDb(persistence, async db => { asyncQueue(db).skipDelaysForTimerId(TimerId.TransactionRetry); @@ -147,13 +146,13 @@ apiDescribe.only( await transaction.get(docRef); // Do a write outside of the transaction. Because the transaction // will retry, set the document to a different value each time. - await setDoc(docRef, {count: 1234 + counter}); + await setDoc(docRef, { count: 1234 + counter }); // Get the docRef again in the transaction with the new // version. await transaction.get(docRef); // Now try to update the docRef from within the transaction. // This should fail, because we read 15 earlier. - await transaction.set(docRef, {count: 16}); + await transaction.set(docRef, { count: 16 }); }); expect.fail('transaction should fail'); } catch (err) { @@ -176,20 +175,24 @@ apiDescribe.only( let counter = 0; await setDoc(docRef, { count: 15 }); try { - await runTransaction(db, async transaction => { - counter++; - // Get the docRef once. - await transaction.get(docRef); - // Do a write outside of the transaction. Because the transaction - // will retry, set the document to a different value each time. - await setDoc(docRef, {count: 1234 + counter}); - // Get the docRef again in the transaction with the new - // version. - await transaction.get(docRef); - // Now try to update the docRef from within the transaction. - // This should fail, because we read 15 earlier. - await transaction.set(docRef, {count: 16}); - }, options); + await runTransaction( + db, + async transaction => { + counter++; + // Get the docRef once. + await transaction.get(docRef); + // Do a write outside of the transaction. Because the transaction + // will retry, set the document to a different value each time. + await setDoc(docRef, { count: 1234 + counter }); + // Get the docRef again in the transaction with the new + // version. + await transaction.get(docRef); + // Now try to update the docRef from within the transaction. + // This should fail, because we read 15 earlier. + await transaction.set(docRef, { count: 16 }); + }, + options + ); expect.fail('transaction should fail'); } catch (err) { expect(err).to.exist; From d53d8c4a9e97a94092c006129d9d303a2252d303 Mon Sep 17 00:00:00 2001 From: Tom Andersen Date: Fri, 29 Apr 2022 15:45:54 -0400 Subject: [PATCH 3/5] Fix whitespace --- common/api-review/firestore-lite.api.md | 756 ++++++------ common/api-review/firestore.api.md | 1060 ++++++++--------- .../firestore/src/core/transaction_options.ts | 2 +- .../api_internal/transaction.test.ts | 2 +- 4 files changed, 910 insertions(+), 910 deletions(-) diff --git a/common/api-review/firestore-lite.api.md b/common/api-review/firestore-lite.api.md index a96f3ada5cb..477962a737f 100644 --- a/common/api-review/firestore-lite.api.md +++ b/common/api-review/firestore-lite.api.md @@ -1,378 +1,378 @@ -## API Report File for "@firebase/firestore-lite" - -> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). - -```ts - -import { EmulatorMockTokenOptions } from '@firebase/util'; -import { FirebaseApp } from '@firebase/app'; -import { FirebaseError } from '@firebase/util'; -import { LogLevelString as LogLevel } from '@firebase/logger'; - -// @public -export function addDoc(reference: CollectionReference, data: WithFieldValue): Promise>; - -// @public -export type AddPrefixToKeys> = { - [K in keyof T & string as `${Prefix}.${K}`]+?: T[K]; -}; - -// @public -export function arrayRemove(...elements: unknown[]): FieldValue; - -// @public -export function arrayUnion(...elements: unknown[]): FieldValue; - -// @public -export class Bytes { - static fromBase64String(base64: string): Bytes; - static fromUint8Array(array: Uint8Array): Bytes; - isEqual(other: Bytes): boolean; - toBase64(): string; - toString(): string; - toUint8Array(): Uint8Array; -} - -// @public -export type ChildUpdateFields = V extends Record ? AddPrefixToKeys> : never; - -// @public -export function collection(firestore: Firestore, path: string, ...pathSegments: string[]): CollectionReference; - -// @public -export function collection(reference: CollectionReference, path: string, ...pathSegments: string[]): CollectionReference; - -// @public -export function collection(reference: DocumentReference, path: string, ...pathSegments: string[]): CollectionReference; - -// @public -export function collectionGroup(firestore: Firestore, collectionId: string): Query; - -// @public -export class CollectionReference extends Query { - get id(): string; - get parent(): DocumentReference | null; - get path(): string; - readonly type = "collection"; - withConverter(converter: FirestoreDataConverter): CollectionReference; - withConverter(converter: null): CollectionReference; -} - -// @public -export function connectFirestoreEmulator(firestore: Firestore, host: string, port: number, options?: { - mockUserToken?: EmulatorMockTokenOptions | string; -}): void; - -// @public -export function deleteDoc(reference: DocumentReference): Promise; - -// @public -export function deleteField(): FieldValue; - -// @public -export function doc(firestore: Firestore, path: string, ...pathSegments: string[]): DocumentReference; - -// @public -export function doc(reference: CollectionReference, path?: string, ...pathSegments: string[]): DocumentReference; - -// @public -export function doc(reference: DocumentReference, path: string, ...pathSegments: string[]): DocumentReference; - -// @public -export interface DocumentData { - [field: string]: any; -} - -// @public -export function documentId(): FieldPath; - -// @public -export class DocumentReference { - readonly converter: FirestoreDataConverter | null; - readonly firestore: Firestore; - get id(): string; - get parent(): CollectionReference; - get path(): string; - readonly type = "document"; - withConverter(converter: FirestoreDataConverter): DocumentReference; - withConverter(converter: null): DocumentReference; -} - -// @public -export class DocumentSnapshot { - protected constructor(); - data(): T | undefined; - exists(): this is QueryDocumentSnapshot; - get(fieldPath: string | FieldPath): any; - get id(): string; - get ref(): DocumentReference; -} - -export { EmulatorMockTokenOptions } - -// @public -export function endAt(snapshot: DocumentSnapshot): QueryConstraint; - -// @public -export function endAt(...fieldValues: unknown[]): QueryConstraint; - -// @public -export function endBefore(snapshot: DocumentSnapshot): QueryConstraint; - -// @public -export function endBefore(...fieldValues: unknown[]): QueryConstraint; - -// @public -export class FieldPath { - constructor(...fieldNames: string[]); - isEqual(other: FieldPath): boolean; -} - -// @public -export abstract class FieldValue { - abstract isEqual(other: FieldValue): boolean; -} - -// @public -export class Firestore { - get app(): FirebaseApp; - toJSON(): object; - type: 'firestore-lite' | 'firestore'; -} - -// @public -export interface FirestoreDataConverter { - fromFirestore(snapshot: QueryDocumentSnapshot): T; - toFirestore(modelObject: WithFieldValue): DocumentData; - toFirestore(modelObject: PartialWithFieldValue, options: SetOptions): DocumentData; -} - -// @public -export class FirestoreError extends FirebaseError { - readonly code: FirestoreErrorCode; - readonly message: string; - readonly stack?: string; -} - -// @public -export type FirestoreErrorCode = 'cancelled' | 'unknown' | 'invalid-argument' | 'deadline-exceeded' | 'not-found' | 'already-exists' | 'permission-denied' | 'resource-exhausted' | 'failed-precondition' | 'aborted' | 'out-of-range' | 'unimplemented' | 'internal' | 'unavailable' | 'data-loss' | 'unauthenticated'; - -// @public -export class GeoPoint { - constructor(latitude: number, longitude: number); - isEqual(other: GeoPoint): boolean; - get latitude(): number; - get longitude(): number; - toJSON(): { - latitude: number; - longitude: number; - }; -} - -// @public -export function getDoc(reference: DocumentReference): Promise>; - -// @public -export function getDocs(query: Query): Promise>; - -// @public -export function getFirestore(app?: FirebaseApp): Firestore; - -// @public -export function increment(n: number): FieldValue; - -// @public -export function initializeFirestore(app: FirebaseApp, settings: Settings): Firestore; - -// @public -export function limit(limit: number): QueryConstraint; - -// @public -export function limitToLast(limit: number): QueryConstraint; - -export { LogLevel } - -// @public -export type NestedUpdateFields> = UnionToIntersection<{ - [K in keyof T & string]: ChildUpdateFields; -}[keyof T & string]>; - -// @public -export function orderBy(fieldPath: string | FieldPath, directionStr?: OrderByDirection): QueryConstraint; - -// @public -export type OrderByDirection = 'desc' | 'asc'; - -// @public -export type PartialWithFieldValue = Partial | (T extends Primitive ? T : T extends {} ? { - [K in keyof T]?: PartialWithFieldValue | FieldValue; -} : never); - -// @public -export type Primitive = string | number | boolean | undefined | null; - -// @public -export class Query { - protected constructor(); - readonly converter: FirestoreDataConverter | null; - readonly firestore: Firestore; - readonly type: 'query' | 'collection'; - withConverter(converter: null): Query; - withConverter(converter: FirestoreDataConverter): Query; -} - -// @public -export function query(query: Query, ...queryConstraints: QueryConstraint[]): Query; - -// @public -export abstract class QueryConstraint { - abstract readonly type: QueryConstraintType; -} - -// @public -export type QueryConstraintType = 'where' | 'orderBy' | 'limit' | 'limitToLast' | 'startAt' | 'startAfter' | 'endAt' | 'endBefore'; - -// @public -export class QueryDocumentSnapshot extends DocumentSnapshot { - // @override - data(): T; -} - -// @public -export function queryEqual(left: Query, right: Query): boolean; - -// @public -export class QuerySnapshot { - get docs(): Array>; - get empty(): boolean; - forEach(callback: (result: QueryDocumentSnapshot) => void, thisArg?: unknown): void; - readonly query: Query; - get size(): number; -} - -// @public -export function refEqual(left: DocumentReference | CollectionReference, right: DocumentReference | CollectionReference): boolean; - -// @public -export function runTransaction(firestore: Firestore, updateFunction: (transaction: Transaction) => Promise, options?: TransactionOptions): Promise; - -// @public -export function serverTimestamp(): FieldValue; - -// @public -export function setDoc(reference: DocumentReference, data: WithFieldValue): Promise; - -// @public -export function setDoc(reference: DocumentReference, data: PartialWithFieldValue, options: SetOptions): Promise; - -// @public -export function setLogLevel(logLevel: LogLevel): void; - -// @public -export type SetOptions = { - readonly merge?: boolean; -} | { - readonly mergeFields?: Array; -}; - -// @public -export interface Settings { - host?: string; - ignoreUndefinedProperties?: boolean; - ssl?: boolean; -} - -// @public -export function snapshotEqual(left: DocumentSnapshot | QuerySnapshot, right: DocumentSnapshot | QuerySnapshot): boolean; - -// @public -export function startAfter(snapshot: DocumentSnapshot): QueryConstraint; - -// @public -export function startAfter(...fieldValues: unknown[]): QueryConstraint; - -// @public -export function startAt(snapshot: DocumentSnapshot): QueryConstraint; - -// @public -export function startAt(...fieldValues: unknown[]): QueryConstraint; - -// @public -export function terminate(firestore: Firestore): Promise; - -// @public -export class Timestamp { - constructor( - seconds: number, - nanoseconds: number); - static fromDate(date: Date): Timestamp; - static fromMillis(milliseconds: number): Timestamp; - isEqual(other: Timestamp): boolean; - readonly nanoseconds: number; - static now(): Timestamp; - readonly seconds: number; - toDate(): Date; - toJSON(): { - seconds: number; - nanoseconds: number; - }; - toMillis(): number; - toString(): string; - valueOf(): string; -} - -// @public -export class Transaction { - delete(documentRef: DocumentReference): this; - get(documentRef: DocumentReference): Promise>; - set(documentRef: DocumentReference, data: WithFieldValue): this; - set(documentRef: DocumentReference, data: PartialWithFieldValue, options: SetOptions): this; - update(documentRef: DocumentReference, data: UpdateData): this; - update(documentRef: DocumentReference, field: string | FieldPath, value: unknown, ...moreFieldsAndValues: unknown[]): this; -} - -// @public -export interface TransactionOptions { - readonly maxAttempts?: number; -} - -// @public -export type UnionToIntersection = (U extends unknown ? (k: U) => void : never) extends (k: infer I) => void ? I : never; - -// @public -export type UpdateData = T extends Primitive ? T : T extends {} ? { - [K in keyof T]?: UpdateData | FieldValue; -} & NestedUpdateFields : Partial; - -// @public -export function updateDoc(reference: DocumentReference, data: UpdateData): Promise; - -// @public -export function updateDoc(reference: DocumentReference, field: string | FieldPath, value: unknown, ...moreFieldsAndValues: unknown[]): Promise; - -// @public -export function where(fieldPath: string | FieldPath, opStr: WhereFilterOp, value: unknown): QueryConstraint; - -// @public -export type WhereFilterOp = '<' | '<=' | '==' | '!=' | '>=' | '>' | 'array-contains' | 'in' | 'array-contains-any' | 'not-in'; - -// @public -export type WithFieldValue = T | (T extends Primitive ? T : T extends {} ? { - [K in keyof T]: WithFieldValue | FieldValue; -} : never); - -// @public -export class WriteBatch { - commit(): Promise; - delete(documentRef: DocumentReference): WriteBatch; - set(documentRef: DocumentReference, data: WithFieldValue): WriteBatch; - set(documentRef: DocumentReference, data: PartialWithFieldValue, options: SetOptions): WriteBatch; - update(documentRef: DocumentReference, data: UpdateData): WriteBatch; - update(documentRef: DocumentReference, field: string | FieldPath, value: unknown, ...moreFieldsAndValues: unknown[]): WriteBatch; -} - -// @public -export function writeBatch(firestore: Firestore): WriteBatch; - - -``` +## API Report File for "@firebase/firestore-lite" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts + +import { EmulatorMockTokenOptions } from '@firebase/util'; +import { FirebaseApp } from '@firebase/app'; +import { FirebaseError } from '@firebase/util'; +import { LogLevelString as LogLevel } from '@firebase/logger'; + +// @public +export function addDoc(reference: CollectionReference, data: WithFieldValue): Promise>; + +// @public +export type AddPrefixToKeys> = { + [K in keyof T & string as `${Prefix}.${K}`]+?: T[K]; +}; + +// @public +export function arrayRemove(...elements: unknown[]): FieldValue; + +// @public +export function arrayUnion(...elements: unknown[]): FieldValue; + +// @public +export class Bytes { + static fromBase64String(base64: string): Bytes; + static fromUint8Array(array: Uint8Array): Bytes; + isEqual(other: Bytes): boolean; + toBase64(): string; + toString(): string; + toUint8Array(): Uint8Array; +} + +// @public +export type ChildUpdateFields = V extends Record ? AddPrefixToKeys> : never; + +// @public +export function collection(firestore: Firestore, path: string, ...pathSegments: string[]): CollectionReference; + +// @public +export function collection(reference: CollectionReference, path: string, ...pathSegments: string[]): CollectionReference; + +// @public +export function collection(reference: DocumentReference, path: string, ...pathSegments: string[]): CollectionReference; + +// @public +export function collectionGroup(firestore: Firestore, collectionId: string): Query; + +// @public +export class CollectionReference extends Query { + get id(): string; + get parent(): DocumentReference | null; + get path(): string; + readonly type = "collection"; + withConverter(converter: FirestoreDataConverter): CollectionReference; + withConverter(converter: null): CollectionReference; +} + +// @public +export function connectFirestoreEmulator(firestore: Firestore, host: string, port: number, options?: { + mockUserToken?: EmulatorMockTokenOptions | string; +}): void; + +// @public +export function deleteDoc(reference: DocumentReference): Promise; + +// @public +export function deleteField(): FieldValue; + +// @public +export function doc(firestore: Firestore, path: string, ...pathSegments: string[]): DocumentReference; + +// @public +export function doc(reference: CollectionReference, path?: string, ...pathSegments: string[]): DocumentReference; + +// @public +export function doc(reference: DocumentReference, path: string, ...pathSegments: string[]): DocumentReference; + +// @public +export interface DocumentData { + [field: string]: any; +} + +// @public +export function documentId(): FieldPath; + +// @public +export class DocumentReference { + readonly converter: FirestoreDataConverter | null; + readonly firestore: Firestore; + get id(): string; + get parent(): CollectionReference; + get path(): string; + readonly type = "document"; + withConverter(converter: FirestoreDataConverter): DocumentReference; + withConverter(converter: null): DocumentReference; +} + +// @public +export class DocumentSnapshot { + protected constructor(); + data(): T | undefined; + exists(): this is QueryDocumentSnapshot; + get(fieldPath: string | FieldPath): any; + get id(): string; + get ref(): DocumentReference; +} + +export { EmulatorMockTokenOptions } + +// @public +export function endAt(snapshot: DocumentSnapshot): QueryConstraint; + +// @public +export function endAt(...fieldValues: unknown[]): QueryConstraint; + +// @public +export function endBefore(snapshot: DocumentSnapshot): QueryConstraint; + +// @public +export function endBefore(...fieldValues: unknown[]): QueryConstraint; + +// @public +export class FieldPath { + constructor(...fieldNames: string[]); + isEqual(other: FieldPath): boolean; +} + +// @public +export abstract class FieldValue { + abstract isEqual(other: FieldValue): boolean; +} + +// @public +export class Firestore { + get app(): FirebaseApp; + toJSON(): object; + type: 'firestore-lite' | 'firestore'; +} + +// @public +export interface FirestoreDataConverter { + fromFirestore(snapshot: QueryDocumentSnapshot): T; + toFirestore(modelObject: WithFieldValue): DocumentData; + toFirestore(modelObject: PartialWithFieldValue, options: SetOptions): DocumentData; +} + +// @public +export class FirestoreError extends FirebaseError { + readonly code: FirestoreErrorCode; + readonly message: string; + readonly stack?: string; +} + +// @public +export type FirestoreErrorCode = 'cancelled' | 'unknown' | 'invalid-argument' | 'deadline-exceeded' | 'not-found' | 'already-exists' | 'permission-denied' | 'resource-exhausted' | 'failed-precondition' | 'aborted' | 'out-of-range' | 'unimplemented' | 'internal' | 'unavailable' | 'data-loss' | 'unauthenticated'; + +// @public +export class GeoPoint { + constructor(latitude: number, longitude: number); + isEqual(other: GeoPoint): boolean; + get latitude(): number; + get longitude(): number; + toJSON(): { + latitude: number; + longitude: number; + }; +} + +// @public +export function getDoc(reference: DocumentReference): Promise>; + +// @public +export function getDocs(query: Query): Promise>; + +// @public +export function getFirestore(app?: FirebaseApp): Firestore; + +// @public +export function increment(n: number): FieldValue; + +// @public +export function initializeFirestore(app: FirebaseApp, settings: Settings): Firestore; + +// @public +export function limit(limit: number): QueryConstraint; + +// @public +export function limitToLast(limit: number): QueryConstraint; + +export { LogLevel } + +// @public +export type NestedUpdateFields> = UnionToIntersection<{ + [K in keyof T & string]: ChildUpdateFields; +}[keyof T & string]>; + +// @public +export function orderBy(fieldPath: string | FieldPath, directionStr?: OrderByDirection): QueryConstraint; + +// @public +export type OrderByDirection = 'desc' | 'asc'; + +// @public +export type PartialWithFieldValue = Partial | (T extends Primitive ? T : T extends {} ? { + [K in keyof T]?: PartialWithFieldValue | FieldValue; +} : never); + +// @public +export type Primitive = string | number | boolean | undefined | null; + +// @public +export class Query { + protected constructor(); + readonly converter: FirestoreDataConverter | null; + readonly firestore: Firestore; + readonly type: 'query' | 'collection'; + withConverter(converter: null): Query; + withConverter(converter: FirestoreDataConverter): Query; +} + +// @public +export function query(query: Query, ...queryConstraints: QueryConstraint[]): Query; + +// @public +export abstract class QueryConstraint { + abstract readonly type: QueryConstraintType; +} + +// @public +export type QueryConstraintType = 'where' | 'orderBy' | 'limit' | 'limitToLast' | 'startAt' | 'startAfter' | 'endAt' | 'endBefore'; + +// @public +export class QueryDocumentSnapshot extends DocumentSnapshot { + // @override + data(): T; +} + +// @public +export function queryEqual(left: Query, right: Query): boolean; + +// @public +export class QuerySnapshot { + get docs(): Array>; + get empty(): boolean; + forEach(callback: (result: QueryDocumentSnapshot) => void, thisArg?: unknown): void; + readonly query: Query; + get size(): number; +} + +// @public +export function refEqual(left: DocumentReference | CollectionReference, right: DocumentReference | CollectionReference): boolean; + +// @public +export function runTransaction(firestore: Firestore, updateFunction: (transaction: Transaction) => Promise, options?: TransactionOptions): Promise; + +// @public +export function serverTimestamp(): FieldValue; + +// @public +export function setDoc(reference: DocumentReference, data: WithFieldValue): Promise; + +// @public +export function setDoc(reference: DocumentReference, data: PartialWithFieldValue, options: SetOptions): Promise; + +// @public +export function setLogLevel(logLevel: LogLevel): void; + +// @public +export type SetOptions = { + readonly merge?: boolean; +} | { + readonly mergeFields?: Array; +}; + +// @public +export interface Settings { + host?: string; + ignoreUndefinedProperties?: boolean; + ssl?: boolean; +} + +// @public +export function snapshotEqual(left: DocumentSnapshot | QuerySnapshot, right: DocumentSnapshot | QuerySnapshot): boolean; + +// @public +export function startAfter(snapshot: DocumentSnapshot): QueryConstraint; + +// @public +export function startAfter(...fieldValues: unknown[]): QueryConstraint; + +// @public +export function startAt(snapshot: DocumentSnapshot): QueryConstraint; + +// @public +export function startAt(...fieldValues: unknown[]): QueryConstraint; + +// @public +export function terminate(firestore: Firestore): Promise; + +// @public +export class Timestamp { + constructor( + seconds: number, + nanoseconds: number); + static fromDate(date: Date): Timestamp; + static fromMillis(milliseconds: number): Timestamp; + isEqual(other: Timestamp): boolean; + readonly nanoseconds: number; + static now(): Timestamp; + readonly seconds: number; + toDate(): Date; + toJSON(): { + seconds: number; + nanoseconds: number; + }; + toMillis(): number; + toString(): string; + valueOf(): string; +} + +// @public +export class Transaction { + delete(documentRef: DocumentReference): this; + get(documentRef: DocumentReference): Promise>; + set(documentRef: DocumentReference, data: WithFieldValue): this; + set(documentRef: DocumentReference, data: PartialWithFieldValue, options: SetOptions): this; + update(documentRef: DocumentReference, data: UpdateData): this; + update(documentRef: DocumentReference, field: string | FieldPath, value: unknown, ...moreFieldsAndValues: unknown[]): this; +} + +// @public +export interface TransactionOptions { + readonly maxAttempts?: number; +} + +// @public +export type UnionToIntersection = (U extends unknown ? (k: U) => void : never) extends (k: infer I) => void ? I : never; + +// @public +export type UpdateData = T extends Primitive ? T : T extends {} ? { + [K in keyof T]?: UpdateData | FieldValue; +} & NestedUpdateFields : Partial; + +// @public +export function updateDoc(reference: DocumentReference, data: UpdateData): Promise; + +// @public +export function updateDoc(reference: DocumentReference, field: string | FieldPath, value: unknown, ...moreFieldsAndValues: unknown[]): Promise; + +// @public +export function where(fieldPath: string | FieldPath, opStr: WhereFilterOp, value: unknown): QueryConstraint; + +// @public +export type WhereFilterOp = '<' | '<=' | '==' | '!=' | '>=' | '>' | 'array-contains' | 'in' | 'array-contains-any' | 'not-in'; + +// @public +export type WithFieldValue = T | (T extends Primitive ? T : T extends {} ? { + [K in keyof T]: WithFieldValue | FieldValue; +} : never); + +// @public +export class WriteBatch { + commit(): Promise; + delete(documentRef: DocumentReference): WriteBatch; + set(documentRef: DocumentReference, data: WithFieldValue): WriteBatch; + set(documentRef: DocumentReference, data: PartialWithFieldValue, options: SetOptions): WriteBatch; + update(documentRef: DocumentReference, data: UpdateData): WriteBatch; + update(documentRef: DocumentReference, field: string | FieldPath, value: unknown, ...moreFieldsAndValues: unknown[]): WriteBatch; +} + +// @public +export function writeBatch(firestore: Firestore): WriteBatch; + + +``` diff --git a/common/api-review/firestore.api.md b/common/api-review/firestore.api.md index db36b60482c..80a772e4db7 100644 --- a/common/api-review/firestore.api.md +++ b/common/api-review/firestore.api.md @@ -1,530 +1,530 @@ -## API Report File for "@firebase/firestore" - -> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). - -```ts - -import { EmulatorMockTokenOptions } from '@firebase/util'; -import { FirebaseApp } from '@firebase/app'; -import { FirebaseError } from '@firebase/util'; -import { LogLevelString as LogLevel } from '@firebase/logger'; - -// @public -export function addDoc(reference: CollectionReference, data: WithFieldValue): Promise>; - -// @public -export type AddPrefixToKeys> = { - [K in keyof T & string as `${Prefix}.${K}`]+?: T[K]; -}; - -// @public -export function arrayRemove(...elements: unknown[]): FieldValue; - -// @public -export function arrayUnion(...elements: unknown[]): FieldValue; - -// @public -export class Bytes { - static fromBase64String(base64: string): Bytes; - static fromUint8Array(array: Uint8Array): Bytes; - isEqual(other: Bytes): boolean; - toBase64(): string; - toString(): string; - toUint8Array(): Uint8Array; -} - -// @public -export const CACHE_SIZE_UNLIMITED = -1; - -// @public -export type ChildUpdateFields = V extends Record ? AddPrefixToKeys> : never; - -// @public -export function clearIndexedDbPersistence(firestore: Firestore): Promise; - -// @public -export function collection(firestore: Firestore, path: string, ...pathSegments: string[]): CollectionReference; - -// @public -export function collection(reference: CollectionReference, path: string, ...pathSegments: string[]): CollectionReference; - -// @public -export function collection(reference: DocumentReference, path: string, ...pathSegments: string[]): CollectionReference; - -// @public -export function collectionGroup(firestore: Firestore, collectionId: string): Query; - -// @public -export class CollectionReference extends Query { - get id(): string; - get parent(): DocumentReference | null; - get path(): string; - readonly type = "collection"; - withConverter(converter: FirestoreDataConverter): CollectionReference; - withConverter(converter: null): CollectionReference; -} - -// @public -export function connectFirestoreEmulator(firestore: Firestore, host: string, port: number, options?: { - mockUserToken?: EmulatorMockTokenOptions | string; -}): void; - -// @public -export function deleteDoc(reference: DocumentReference): Promise; - -// @public -export function deleteField(): FieldValue; - -// @public -export function disableNetwork(firestore: Firestore): Promise; - -// @public -export function doc(firestore: Firestore, path: string, ...pathSegments: string[]): DocumentReference; - -// @public -export function doc(reference: CollectionReference, path?: string, ...pathSegments: string[]): DocumentReference; - -// @public -export function doc(reference: DocumentReference, path: string, ...pathSegments: string[]): DocumentReference; - -// @public -export interface DocumentChange { - readonly doc: QueryDocumentSnapshot; - readonly newIndex: number; - readonly oldIndex: number; - readonly type: DocumentChangeType; -} - -// @public -export type DocumentChangeType = 'added' | 'removed' | 'modified'; - -// @public -export interface DocumentData { - [field: string]: any; -} - -// @public -export function documentId(): FieldPath; - -// @public -export class DocumentReference { - readonly converter: FirestoreDataConverter | null; - readonly firestore: Firestore; - get id(): string; - get parent(): CollectionReference; - get path(): string; - readonly type = "document"; - withConverter(converter: FirestoreDataConverter): DocumentReference; - withConverter(converter: null): DocumentReference; -} - -// @public -export class DocumentSnapshot { - protected constructor(); - data(options?: SnapshotOptions): T | undefined; - exists(): this is QueryDocumentSnapshot; - get(fieldPath: string | FieldPath, options?: SnapshotOptions): any; - get id(): string; - readonly metadata: SnapshotMetadata; - get ref(): DocumentReference; -} - -export { EmulatorMockTokenOptions } - -// @public -export function enableIndexedDbPersistence(firestore: Firestore, persistenceSettings?: PersistenceSettings): Promise; - -// @public -export function enableMultiTabIndexedDbPersistence(firestore: Firestore): Promise; - -// @public -export function enableNetwork(firestore: Firestore): Promise; - -// @public -export function endAt(snapshot: DocumentSnapshot): QueryConstraint; - -// @public -export function endAt(...fieldValues: unknown[]): QueryConstraint; - -// @public -export function endBefore(snapshot: DocumentSnapshot): QueryConstraint; - -// @public -export function endBefore(...fieldValues: unknown[]): QueryConstraint; - -// @public -export class FieldPath { - constructor(...fieldNames: string[]); - isEqual(other: FieldPath): boolean; -} - -// @public -export abstract class FieldValue { - abstract isEqual(other: FieldValue): boolean; -} - -// @public -export class Firestore { - get app(): FirebaseApp; - toJSON(): object; - type: 'firestore-lite' | 'firestore'; -} - -// @public -export interface FirestoreDataConverter { - fromFirestore(snapshot: QueryDocumentSnapshot, options?: SnapshotOptions): T; - toFirestore(modelObject: WithFieldValue): DocumentData; - toFirestore(modelObject: PartialWithFieldValue, options: SetOptions): DocumentData; -} - -// @public -export class FirestoreError extends FirebaseError { - readonly code: FirestoreErrorCode; - readonly message: string; - readonly stack?: string; -} - -// @public -export type FirestoreErrorCode = 'cancelled' | 'unknown' | 'invalid-argument' | 'deadline-exceeded' | 'not-found' | 'already-exists' | 'permission-denied' | 'resource-exhausted' | 'failed-precondition' | 'aborted' | 'out-of-range' | 'unimplemented' | 'internal' | 'unavailable' | 'data-loss' | 'unauthenticated'; - -// @public -export interface FirestoreSettings { - cacheSizeBytes?: number; - experimentalAutoDetectLongPolling?: boolean; - experimentalForceLongPolling?: boolean; - host?: string; - ignoreUndefinedProperties?: boolean; - ssl?: boolean; -} - -// @public -export class GeoPoint { - constructor(latitude: number, longitude: number); - isEqual(other: GeoPoint): boolean; - get latitude(): number; - get longitude(): number; - toJSON(): { - latitude: number; - longitude: number; - }; -} - -// @public -export function getDoc(reference: DocumentReference): Promise>; - -// @public -export function getDocFromCache(reference: DocumentReference): Promise>; - -// @public -export function getDocFromServer(reference: DocumentReference): Promise>; - -// @public -export function getDocs(query: Query): Promise>; - -// @public -export function getDocsFromCache(query: Query): Promise>; - -// @public -export function getDocsFromServer(query: Query): Promise>; - -// @public -export function getFirestore(app?: FirebaseApp): Firestore; - -// @public -export function increment(n: number): FieldValue; - -// @public -export function initializeFirestore(app: FirebaseApp, settings: FirestoreSettings): Firestore; - -// @public -export function limit(limit: number): QueryConstraint; - -// @public -export function limitToLast(limit: number): QueryConstraint; - -// @public -export function loadBundle(firestore: Firestore, bundleData: ReadableStream | ArrayBuffer | string): LoadBundleTask; - -// @public -export class LoadBundleTask implements PromiseLike { - catch(onRejected: (a: Error) => R | PromiseLike): Promise; - onProgress(next?: (progress: LoadBundleTaskProgress) => unknown, error?: (err: Error) => unknown, complete?: () => void): void; - then(onFulfilled?: (a: LoadBundleTaskProgress) => T | PromiseLike, onRejected?: (a: Error) => R | PromiseLike): Promise; -} - -// @public -export interface LoadBundleTaskProgress { - bytesLoaded: number; - documentsLoaded: number; - taskState: TaskState; - totalBytes: number; - totalDocuments: number; -} - -export { LogLevel } - -// @public -export function namedQuery(firestore: Firestore, name: string): Promise; - -// @public -export type NestedUpdateFields> = UnionToIntersection<{ - [K in keyof T & string]: ChildUpdateFields; -}[keyof T & string]>; - -// @public -export function onSnapshot(reference: DocumentReference, observer: { - next?: (snapshot: DocumentSnapshot) => void; - error?: (error: FirestoreError) => void; - complete?: () => void; -}): Unsubscribe; - -// @public -export function onSnapshot(reference: DocumentReference, options: SnapshotListenOptions, observer: { - next?: (snapshot: DocumentSnapshot) => void; - error?: (error: FirestoreError) => void; - complete?: () => void; -}): Unsubscribe; - -// @public -export function onSnapshot(reference: DocumentReference, onNext: (snapshot: DocumentSnapshot) => void, onError?: (error: FirestoreError) => void, onCompletion?: () => void): Unsubscribe; - -// @public -export function onSnapshot(reference: DocumentReference, options: SnapshotListenOptions, onNext: (snapshot: DocumentSnapshot) => void, onError?: (error: FirestoreError) => void, onCompletion?: () => void): Unsubscribe; - -// @public -export function onSnapshot(query: Query, observer: { - next?: (snapshot: QuerySnapshot) => void; - error?: (error: FirestoreError) => void; - complete?: () => void; -}): Unsubscribe; - -// @public -export function onSnapshot(query: Query, options: SnapshotListenOptions, observer: { - next?: (snapshot: QuerySnapshot) => void; - error?: (error: FirestoreError) => void; - complete?: () => void; -}): Unsubscribe; - -// @public -export function onSnapshot(query: Query, onNext: (snapshot: QuerySnapshot) => void, onError?: (error: FirestoreError) => void, onCompletion?: () => void): Unsubscribe; - -// @public -export function onSnapshot(query: Query, options: SnapshotListenOptions, onNext: (snapshot: QuerySnapshot) => void, onError?: (error: FirestoreError) => void, onCompletion?: () => void): Unsubscribe; - -// @public -export function onSnapshotsInSync(firestore: Firestore, observer: { - next?: (value: void) => void; - error?: (error: FirestoreError) => void; - complete?: () => void; -}): Unsubscribe; - -// @public -export function onSnapshotsInSync(firestore: Firestore, onSync: () => void): Unsubscribe; - -// @public -export function orderBy(fieldPath: string | FieldPath, directionStr?: OrderByDirection): QueryConstraint; - -// @public -export type OrderByDirection = 'desc' | 'asc'; - -// @public -export type PartialWithFieldValue = Partial | (T extends Primitive ? T : T extends {} ? { - [K in keyof T]?: PartialWithFieldValue | FieldValue; -} : never); - -// @public -export interface PersistenceSettings { - forceOwnership?: boolean; -} - -// @public -export type Primitive = string | number | boolean | undefined | null; - -// @public -export class Query { - protected constructor(); - readonly converter: FirestoreDataConverter | null; - readonly firestore: Firestore; - readonly type: 'query' | 'collection'; - withConverter(converter: null): Query; - withConverter(converter: FirestoreDataConverter): Query; -} - -// @public -export function query(query: Query, ...queryConstraints: QueryConstraint[]): Query; - -// @public -export abstract class QueryConstraint { - abstract readonly type: QueryConstraintType; -} - -// @public -export type QueryConstraintType = 'where' | 'orderBy' | 'limit' | 'limitToLast' | 'startAt' | 'startAfter' | 'endAt' | 'endBefore'; - -// @public -export class QueryDocumentSnapshot extends DocumentSnapshot { - // @override - data(options?: SnapshotOptions): T; -} - -// @public -export function queryEqual(left: Query, right: Query): boolean; - -// @public -export class QuerySnapshot { - docChanges(options?: SnapshotListenOptions): Array>; - get docs(): Array>; - get empty(): boolean; - forEach(callback: (result: QueryDocumentSnapshot) => void, thisArg?: unknown): void; - readonly metadata: SnapshotMetadata; - readonly query: Query; - get size(): number; -} - -// @public -export function refEqual(left: DocumentReference | CollectionReference, right: DocumentReference | CollectionReference): boolean; - -// @public -export function runTransaction(firestore: Firestore, updateFunction: (transaction: Transaction) => Promise, options?: TransactionOptions): Promise; - -// @public -export function serverTimestamp(): FieldValue; - -// @public -export function setDoc(reference: DocumentReference, data: WithFieldValue): Promise; - -// @public -export function setDoc(reference: DocumentReference, data: PartialWithFieldValue, options: SetOptions): Promise; - -// @public -export function setLogLevel(logLevel: LogLevel): void; - -// @public -export type SetOptions = { - readonly merge?: boolean; -} | { - readonly mergeFields?: Array; -}; - -// @public -export function snapshotEqual(left: DocumentSnapshot | QuerySnapshot, right: DocumentSnapshot | QuerySnapshot): boolean; - -// @public -export interface SnapshotListenOptions { - readonly includeMetadataChanges?: boolean; -} - -// @public -export class SnapshotMetadata { - readonly fromCache: boolean; - readonly hasPendingWrites: boolean; - isEqual(other: SnapshotMetadata): boolean; -} - -// @public -export interface SnapshotOptions { - readonly serverTimestamps?: 'estimate' | 'previous' | 'none'; -} - -// @public -export function startAfter(snapshot: DocumentSnapshot): QueryConstraint; - -// @public -export function startAfter(...fieldValues: unknown[]): QueryConstraint; - -// @public -export function startAt(snapshot: DocumentSnapshot): QueryConstraint; - -// @public -export function startAt(...fieldValues: unknown[]): QueryConstraint; - -// @public -export type TaskState = 'Error' | 'Running' | 'Success'; - -// @public -export function terminate(firestore: Firestore): Promise; - -// @public -export class Timestamp { - constructor( - seconds: number, - nanoseconds: number); - static fromDate(date: Date): Timestamp; - static fromMillis(milliseconds: number): Timestamp; - isEqual(other: Timestamp): boolean; - readonly nanoseconds: number; - static now(): Timestamp; - readonly seconds: number; - toDate(): Date; - toJSON(): { - seconds: number; - nanoseconds: number; - }; - toMillis(): number; - toString(): string; - valueOf(): string; -} - -// @public -export class Transaction { - delete(documentRef: DocumentReference): this; - get(documentRef: DocumentReference): Promise>; - set(documentRef: DocumentReference, data: WithFieldValue): this; - set(documentRef: DocumentReference, data: PartialWithFieldValue, options: SetOptions): this; - update(documentRef: DocumentReference, data: UpdateData): this; - update(documentRef: DocumentReference, field: string | FieldPath, value: unknown, ...moreFieldsAndValues: unknown[]): this; -} - -// @public -export interface TransactionOptions { - readonly maxAttempts?: number; -} - -// @public -export type UnionToIntersection = (U extends unknown ? (k: U) => void : never) extends (k: infer I) => void ? I : never; - -// @public -export interface Unsubscribe { - (): void; -} - -// @public -export type UpdateData = T extends Primitive ? T : T extends {} ? { - [K in keyof T]?: UpdateData | FieldValue; -} & NestedUpdateFields : Partial; - -// @public -export function updateDoc(reference: DocumentReference, data: UpdateData): Promise; - -// @public -export function updateDoc(reference: DocumentReference, field: string | FieldPath, value: unknown, ...moreFieldsAndValues: unknown[]): Promise; - -// @public -export function waitForPendingWrites(firestore: Firestore): Promise; - -// @public -export function where(fieldPath: string | FieldPath, opStr: WhereFilterOp, value: unknown): QueryConstraint; - -// @public -export type WhereFilterOp = '<' | '<=' | '==' | '!=' | '>=' | '>' | 'array-contains' | 'in' | 'array-contains-any' | 'not-in'; - -// @public -export type WithFieldValue = T | (T extends Primitive ? T : T extends {} ? { - [K in keyof T]: WithFieldValue | FieldValue; -} : never); - -// @public -export class WriteBatch { - commit(): Promise; - delete(documentRef: DocumentReference): WriteBatch; - set(documentRef: DocumentReference, data: WithFieldValue): WriteBatch; - set(documentRef: DocumentReference, data: PartialWithFieldValue, options: SetOptions): WriteBatch; - update(documentRef: DocumentReference, data: UpdateData): WriteBatch; - update(documentRef: DocumentReference, field: string | FieldPath, value: unknown, ...moreFieldsAndValues: unknown[]): WriteBatch; -} - -// @public -export function writeBatch(firestore: Firestore): WriteBatch; - - -``` +## API Report File for "@firebase/firestore" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts + +import { EmulatorMockTokenOptions } from '@firebase/util'; +import { FirebaseApp } from '@firebase/app'; +import { FirebaseError } from '@firebase/util'; +import { LogLevelString as LogLevel } from '@firebase/logger'; + +// @public +export function addDoc(reference: CollectionReference, data: WithFieldValue): Promise>; + +// @public +export type AddPrefixToKeys> = { + [K in keyof T & string as `${Prefix}.${K}`]+?: T[K]; +}; + +// @public +export function arrayRemove(...elements: unknown[]): FieldValue; + +// @public +export function arrayUnion(...elements: unknown[]): FieldValue; + +// @public +export class Bytes { + static fromBase64String(base64: string): Bytes; + static fromUint8Array(array: Uint8Array): Bytes; + isEqual(other: Bytes): boolean; + toBase64(): string; + toString(): string; + toUint8Array(): Uint8Array; +} + +// @public +export const CACHE_SIZE_UNLIMITED = -1; + +// @public +export type ChildUpdateFields = V extends Record ? AddPrefixToKeys> : never; + +// @public +export function clearIndexedDbPersistence(firestore: Firestore): Promise; + +// @public +export function collection(firestore: Firestore, path: string, ...pathSegments: string[]): CollectionReference; + +// @public +export function collection(reference: CollectionReference, path: string, ...pathSegments: string[]): CollectionReference; + +// @public +export function collection(reference: DocumentReference, path: string, ...pathSegments: string[]): CollectionReference; + +// @public +export function collectionGroup(firestore: Firestore, collectionId: string): Query; + +// @public +export class CollectionReference extends Query { + get id(): string; + get parent(): DocumentReference | null; + get path(): string; + readonly type = "collection"; + withConverter(converter: FirestoreDataConverter): CollectionReference; + withConverter(converter: null): CollectionReference; +} + +// @public +export function connectFirestoreEmulator(firestore: Firestore, host: string, port: number, options?: { + mockUserToken?: EmulatorMockTokenOptions | string; +}): void; + +// @public +export function deleteDoc(reference: DocumentReference): Promise; + +// @public +export function deleteField(): FieldValue; + +// @public +export function disableNetwork(firestore: Firestore): Promise; + +// @public +export function doc(firestore: Firestore, path: string, ...pathSegments: string[]): DocumentReference; + +// @public +export function doc(reference: CollectionReference, path?: string, ...pathSegments: string[]): DocumentReference; + +// @public +export function doc(reference: DocumentReference, path: string, ...pathSegments: string[]): DocumentReference; + +// @public +export interface DocumentChange { + readonly doc: QueryDocumentSnapshot; + readonly newIndex: number; + readonly oldIndex: number; + readonly type: DocumentChangeType; +} + +// @public +export type DocumentChangeType = 'added' | 'removed' | 'modified'; + +// @public +export interface DocumentData { + [field: string]: any; +} + +// @public +export function documentId(): FieldPath; + +// @public +export class DocumentReference { + readonly converter: FirestoreDataConverter | null; + readonly firestore: Firestore; + get id(): string; + get parent(): CollectionReference; + get path(): string; + readonly type = "document"; + withConverter(converter: FirestoreDataConverter): DocumentReference; + withConverter(converter: null): DocumentReference; +} + +// @public +export class DocumentSnapshot { + protected constructor(); + data(options?: SnapshotOptions): T | undefined; + exists(): this is QueryDocumentSnapshot; + get(fieldPath: string | FieldPath, options?: SnapshotOptions): any; + get id(): string; + readonly metadata: SnapshotMetadata; + get ref(): DocumentReference; +} + +export { EmulatorMockTokenOptions } + +// @public +export function enableIndexedDbPersistence(firestore: Firestore, persistenceSettings?: PersistenceSettings): Promise; + +// @public +export function enableMultiTabIndexedDbPersistence(firestore: Firestore): Promise; + +// @public +export function enableNetwork(firestore: Firestore): Promise; + +// @public +export function endAt(snapshot: DocumentSnapshot): QueryConstraint; + +// @public +export function endAt(...fieldValues: unknown[]): QueryConstraint; + +// @public +export function endBefore(snapshot: DocumentSnapshot): QueryConstraint; + +// @public +export function endBefore(...fieldValues: unknown[]): QueryConstraint; + +// @public +export class FieldPath { + constructor(...fieldNames: string[]); + isEqual(other: FieldPath): boolean; +} + +// @public +export abstract class FieldValue { + abstract isEqual(other: FieldValue): boolean; +} + +// @public +export class Firestore { + get app(): FirebaseApp; + toJSON(): object; + type: 'firestore-lite' | 'firestore'; +} + +// @public +export interface FirestoreDataConverter { + fromFirestore(snapshot: QueryDocumentSnapshot, options?: SnapshotOptions): T; + toFirestore(modelObject: WithFieldValue): DocumentData; + toFirestore(modelObject: PartialWithFieldValue, options: SetOptions): DocumentData; +} + +// @public +export class FirestoreError extends FirebaseError { + readonly code: FirestoreErrorCode; + readonly message: string; + readonly stack?: string; +} + +// @public +export type FirestoreErrorCode = 'cancelled' | 'unknown' | 'invalid-argument' | 'deadline-exceeded' | 'not-found' | 'already-exists' | 'permission-denied' | 'resource-exhausted' | 'failed-precondition' | 'aborted' | 'out-of-range' | 'unimplemented' | 'internal' | 'unavailable' | 'data-loss' | 'unauthenticated'; + +// @public +export interface FirestoreSettings { + cacheSizeBytes?: number; + experimentalAutoDetectLongPolling?: boolean; + experimentalForceLongPolling?: boolean; + host?: string; + ignoreUndefinedProperties?: boolean; + ssl?: boolean; +} + +// @public +export class GeoPoint { + constructor(latitude: number, longitude: number); + isEqual(other: GeoPoint): boolean; + get latitude(): number; + get longitude(): number; + toJSON(): { + latitude: number; + longitude: number; + }; +} + +// @public +export function getDoc(reference: DocumentReference): Promise>; + +// @public +export function getDocFromCache(reference: DocumentReference): Promise>; + +// @public +export function getDocFromServer(reference: DocumentReference): Promise>; + +// @public +export function getDocs(query: Query): Promise>; + +// @public +export function getDocsFromCache(query: Query): Promise>; + +// @public +export function getDocsFromServer(query: Query): Promise>; + +// @public +export function getFirestore(app?: FirebaseApp): Firestore; + +// @public +export function increment(n: number): FieldValue; + +// @public +export function initializeFirestore(app: FirebaseApp, settings: FirestoreSettings): Firestore; + +// @public +export function limit(limit: number): QueryConstraint; + +// @public +export function limitToLast(limit: number): QueryConstraint; + +// @public +export function loadBundle(firestore: Firestore, bundleData: ReadableStream | ArrayBuffer | string): LoadBundleTask; + +// @public +export class LoadBundleTask implements PromiseLike { + catch(onRejected: (a: Error) => R | PromiseLike): Promise; + onProgress(next?: (progress: LoadBundleTaskProgress) => unknown, error?: (err: Error) => unknown, complete?: () => void): void; + then(onFulfilled?: (a: LoadBundleTaskProgress) => T | PromiseLike, onRejected?: (a: Error) => R | PromiseLike): Promise; +} + +// @public +export interface LoadBundleTaskProgress { + bytesLoaded: number; + documentsLoaded: number; + taskState: TaskState; + totalBytes: number; + totalDocuments: number; +} + +export { LogLevel } + +// @public +export function namedQuery(firestore: Firestore, name: string): Promise; + +// @public +export type NestedUpdateFields> = UnionToIntersection<{ + [K in keyof T & string]: ChildUpdateFields; +}[keyof T & string]>; + +// @public +export function onSnapshot(reference: DocumentReference, observer: { + next?: (snapshot: DocumentSnapshot) => void; + error?: (error: FirestoreError) => void; + complete?: () => void; +}): Unsubscribe; + +// @public +export function onSnapshot(reference: DocumentReference, options: SnapshotListenOptions, observer: { + next?: (snapshot: DocumentSnapshot) => void; + error?: (error: FirestoreError) => void; + complete?: () => void; +}): Unsubscribe; + +// @public +export function onSnapshot(reference: DocumentReference, onNext: (snapshot: DocumentSnapshot) => void, onError?: (error: FirestoreError) => void, onCompletion?: () => void): Unsubscribe; + +// @public +export function onSnapshot(reference: DocumentReference, options: SnapshotListenOptions, onNext: (snapshot: DocumentSnapshot) => void, onError?: (error: FirestoreError) => void, onCompletion?: () => void): Unsubscribe; + +// @public +export function onSnapshot(query: Query, observer: { + next?: (snapshot: QuerySnapshot) => void; + error?: (error: FirestoreError) => void; + complete?: () => void; +}): Unsubscribe; + +// @public +export function onSnapshot(query: Query, options: SnapshotListenOptions, observer: { + next?: (snapshot: QuerySnapshot) => void; + error?: (error: FirestoreError) => void; + complete?: () => void; +}): Unsubscribe; + +// @public +export function onSnapshot(query: Query, onNext: (snapshot: QuerySnapshot) => void, onError?: (error: FirestoreError) => void, onCompletion?: () => void): Unsubscribe; + +// @public +export function onSnapshot(query: Query, options: SnapshotListenOptions, onNext: (snapshot: QuerySnapshot) => void, onError?: (error: FirestoreError) => void, onCompletion?: () => void): Unsubscribe; + +// @public +export function onSnapshotsInSync(firestore: Firestore, observer: { + next?: (value: void) => void; + error?: (error: FirestoreError) => void; + complete?: () => void; +}): Unsubscribe; + +// @public +export function onSnapshotsInSync(firestore: Firestore, onSync: () => void): Unsubscribe; + +// @public +export function orderBy(fieldPath: string | FieldPath, directionStr?: OrderByDirection): QueryConstraint; + +// @public +export type OrderByDirection = 'desc' | 'asc'; + +// @public +export type PartialWithFieldValue = Partial | (T extends Primitive ? T : T extends {} ? { + [K in keyof T]?: PartialWithFieldValue | FieldValue; +} : never); + +// @public +export interface PersistenceSettings { + forceOwnership?: boolean; +} + +// @public +export type Primitive = string | number | boolean | undefined | null; + +// @public +export class Query { + protected constructor(); + readonly converter: FirestoreDataConverter | null; + readonly firestore: Firestore; + readonly type: 'query' | 'collection'; + withConverter(converter: null): Query; + withConverter(converter: FirestoreDataConverter): Query; +} + +// @public +export function query(query: Query, ...queryConstraints: QueryConstraint[]): Query; + +// @public +export abstract class QueryConstraint { + abstract readonly type: QueryConstraintType; +} + +// @public +export type QueryConstraintType = 'where' | 'orderBy' | 'limit' | 'limitToLast' | 'startAt' | 'startAfter' | 'endAt' | 'endBefore'; + +// @public +export class QueryDocumentSnapshot extends DocumentSnapshot { + // @override + data(options?: SnapshotOptions): T; +} + +// @public +export function queryEqual(left: Query, right: Query): boolean; + +// @public +export class QuerySnapshot { + docChanges(options?: SnapshotListenOptions): Array>; + get docs(): Array>; + get empty(): boolean; + forEach(callback: (result: QueryDocumentSnapshot) => void, thisArg?: unknown): void; + readonly metadata: SnapshotMetadata; + readonly query: Query; + get size(): number; +} + +// @public +export function refEqual(left: DocumentReference | CollectionReference, right: DocumentReference | CollectionReference): boolean; + +// @public +export function runTransaction(firestore: Firestore, updateFunction: (transaction: Transaction) => Promise, options?: TransactionOptions): Promise; + +// @public +export function serverTimestamp(): FieldValue; + +// @public +export function setDoc(reference: DocumentReference, data: WithFieldValue): Promise; + +// @public +export function setDoc(reference: DocumentReference, data: PartialWithFieldValue, options: SetOptions): Promise; + +// @public +export function setLogLevel(logLevel: LogLevel): void; + +// @public +export type SetOptions = { + readonly merge?: boolean; +} | { + readonly mergeFields?: Array; +}; + +// @public +export function snapshotEqual(left: DocumentSnapshot | QuerySnapshot, right: DocumentSnapshot | QuerySnapshot): boolean; + +// @public +export interface SnapshotListenOptions { + readonly includeMetadataChanges?: boolean; +} + +// @public +export class SnapshotMetadata { + readonly fromCache: boolean; + readonly hasPendingWrites: boolean; + isEqual(other: SnapshotMetadata): boolean; +} + +// @public +export interface SnapshotOptions { + readonly serverTimestamps?: 'estimate' | 'previous' | 'none'; +} + +// @public +export function startAfter(snapshot: DocumentSnapshot): QueryConstraint; + +// @public +export function startAfter(...fieldValues: unknown[]): QueryConstraint; + +// @public +export function startAt(snapshot: DocumentSnapshot): QueryConstraint; + +// @public +export function startAt(...fieldValues: unknown[]): QueryConstraint; + +// @public +export type TaskState = 'Error' | 'Running' | 'Success'; + +// @public +export function terminate(firestore: Firestore): Promise; + +// @public +export class Timestamp { + constructor( + seconds: number, + nanoseconds: number); + static fromDate(date: Date): Timestamp; + static fromMillis(milliseconds: number): Timestamp; + isEqual(other: Timestamp): boolean; + readonly nanoseconds: number; + static now(): Timestamp; + readonly seconds: number; + toDate(): Date; + toJSON(): { + seconds: number; + nanoseconds: number; + }; + toMillis(): number; + toString(): string; + valueOf(): string; +} + +// @public +export class Transaction { + delete(documentRef: DocumentReference): this; + get(documentRef: DocumentReference): Promise>; + set(documentRef: DocumentReference, data: WithFieldValue): this; + set(documentRef: DocumentReference, data: PartialWithFieldValue, options: SetOptions): this; + update(documentRef: DocumentReference, data: UpdateData): this; + update(documentRef: DocumentReference, field: string | FieldPath, value: unknown, ...moreFieldsAndValues: unknown[]): this; +} + +// @public +export interface TransactionOptions { + readonly maxAttempts?: number; +} + +// @public +export type UnionToIntersection = (U extends unknown ? (k: U) => void : never) extends (k: infer I) => void ? I : never; + +// @public +export interface Unsubscribe { + (): void; +} + +// @public +export type UpdateData = T extends Primitive ? T : T extends {} ? { + [K in keyof T]?: UpdateData | FieldValue; +} & NestedUpdateFields : Partial; + +// @public +export function updateDoc(reference: DocumentReference, data: UpdateData): Promise; + +// @public +export function updateDoc(reference: DocumentReference, field: string | FieldPath, value: unknown, ...moreFieldsAndValues: unknown[]): Promise; + +// @public +export function waitForPendingWrites(firestore: Firestore): Promise; + +// @public +export function where(fieldPath: string | FieldPath, opStr: WhereFilterOp, value: unknown): QueryConstraint; + +// @public +export type WhereFilterOp = '<' | '<=' | '==' | '!=' | '>=' | '>' | 'array-contains' | 'in' | 'array-contains-any' | 'not-in'; + +// @public +export type WithFieldValue = T | (T extends Primitive ? T : T extends {} ? { + [K in keyof T]: WithFieldValue | FieldValue; +} : never); + +// @public +export class WriteBatch { + commit(): Promise; + delete(documentRef: DocumentReference): WriteBatch; + set(documentRef: DocumentReference, data: WithFieldValue): WriteBatch; + set(documentRef: DocumentReference, data: PartialWithFieldValue, options: SetOptions): WriteBatch; + update(documentRef: DocumentReference, data: UpdateData): WriteBatch; + update(documentRef: DocumentReference, field: string | FieldPath, value: unknown, ...moreFieldsAndValues: unknown[]): WriteBatch; +} + +// @public +export function writeBatch(firestore: Firestore): WriteBatch; + + +``` diff --git a/packages/firestore/src/core/transaction_options.ts b/packages/firestore/src/core/transaction_options.ts index f5bc4501d81..a1d5b5a40ae 100644 --- a/packages/firestore/src/core/transaction_options.ts +++ b/packages/firestore/src/core/transaction_options.ts @@ -25,7 +25,7 @@ export const DEFAULT_TRANSACTION_OPTIONS: TransactionOptions = { * Options to customize transaction behavior. */ export declare interface TransactionOptions { - /** maximum number of attempts to commit, after which transaction fails. Default is 5. */ + /** Maximum number of attempts to commit, after which transaction fails. Default is 5. */ readonly maxAttempts: number; } diff --git a/packages/firestore/test/integration/api_internal/transaction.test.ts b/packages/firestore/test/integration/api_internal/transaction.test.ts index 50a0dcef626..7eab6d7d53d 100644 --- a/packages/firestore/test/integration/api_internal/transaction.test.ts +++ b/packages/firestore/test/integration/api_internal/transaction.test.ts @@ -31,7 +31,7 @@ import { import { apiDescribe, withTestDb } from '../util/helpers'; import { asyncQueue } from '../util/internal_helpers'; -apiDescribe.only( +apiDescribe( 'Database transactions (with internal API)', (persistence: boolean) => { it('should increment transactionally', async () => { From 6ff1128245115fd92e80a0432adcdc3d848c6c88 Mon Sep 17 00:00:00 2001 From: Tom Andersen Date: Fri, 29 Apr 2022 18:19:43 -0400 Subject: [PATCH 4/5] Add changeset --- .changeset/lazy-nails-guess.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/lazy-nails-guess.md diff --git a/.changeset/lazy-nails-guess.md b/.changeset/lazy-nails-guess.md new file mode 100644 index 00000000000..0a02ef47b05 --- /dev/null +++ b/.changeset/lazy-nails-guess.md @@ -0,0 +1,5 @@ +--- +'@firebase/firestore': patch +--- + +Add TransactionOptions to runTransaction From d09ddb4f862697705f8ab1412b6ea03a72e9ca1d Mon Sep 17 00:00:00 2001 From: Tom Andersen Date: Wed, 4 May 2022 14:01:49 -0400 Subject: [PATCH 5/5] Update comments --- .changeset/lazy-nails-guess.md | 2 +- packages/firestore/src/lite-api/transaction_options.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.changeset/lazy-nails-guess.md b/.changeset/lazy-nails-guess.md index 0a02ef47b05..9a7e7ae82e4 100644 --- a/.changeset/lazy-nails-guess.md +++ b/.changeset/lazy-nails-guess.md @@ -2,4 +2,4 @@ '@firebase/firestore': patch --- -Add TransactionOptions to runTransaction +Add `TransactionOptions` param to `runTransaction` method diff --git a/packages/firestore/src/lite-api/transaction_options.ts b/packages/firestore/src/lite-api/transaction_options.ts index 49d2bcd5be2..d31b9127fc3 100644 --- a/packages/firestore/src/lite-api/transaction_options.ts +++ b/packages/firestore/src/lite-api/transaction_options.ts @@ -19,6 +19,6 @@ * Options to customize transaction behavior. */ export declare interface TransactionOptions { - /** maximum number of attempts to commit, after which transaction fails. Default is 5. */ + /** Maximum number of attempts to commit, after which transaction fails. Default is 5. */ readonly maxAttempts?: number; }