0x1998 - MANAGER
Düzenlenen Dosya: index.node.mjs.map
{"version":3,"file":"index.node.mjs","sources":["../../src/util/promise.ts","../../src/remote/backoff.ts","../../src/local/simple_db.ts","../../lite/register.ts","../../src/core/aggregate.ts","../../src/lite-api/aggregate_types.ts","../../src/lite-api/aggregate.ts","../../src/lite-api/write_batch.ts","../../src/core/transaction_options.ts","../../src/core/transaction.ts","../../src/core/transaction_runner.ts","../../src/util/async_queue.ts","../../src/util/async_queue_impl.ts","../../src/lite-api/transaction.ts","../../lite/index.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2017 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport interface Resolver<R> {\n (value: R | Promise<R>): void;\n}\n\nexport interface Rejecter {\n (reason?: Error): void;\n}\n\nexport class Deferred<R = void> {\n promise: Promise<R>;\n // Assigned synchronously in constructor by Promise constructor callback.\n resolve!: Resolver<R>;\n reject!: Rejecter;\n\n constructor() {\n this.promise = new Promise((resolve: Resolver<R>, reject: Rejecter) => {\n this.resolve = resolve;\n this.reject = reject;\n });\n }\n}\n\n/**\n * Takes an array of values and a function from a value to a Promise. The function is run on each\n * value sequentially, waiting for the previous promise to resolve before starting the next one.\n * The returned promise resolves once the function has been run on all values.\n */\nexport function sequence<T>(\n values: T[],\n fn: (value: T) => Promise<void>\n): Promise<void> {\n let p = Promise.resolve();\n for (const value of values) {\n p = p.then(() => fn(value));\n }\n return p;\n}\n","/**\n * @license\n * Copyright 2017 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { AsyncQueue, DelayedOperation, TimerId } from '../util/async_queue';\nimport { logDebug } from '../util/log';\n\nconst LOG_TAG = 'ExponentialBackoff';\n\n/**\n * Initial backoff time in milliseconds after an error.\n * Set to 1s according to https://cloud.google.com/apis/design/errors.\n */\nconst DEFAULT_BACKOFF_INITIAL_DELAY_MS = 1000;\n\nconst DEFAULT_BACKOFF_FACTOR = 1.5;\n\n/** Maximum backoff time in milliseconds */\nconst DEFAULT_BACKOFF_MAX_DELAY_MS = 60 * 1000;\n\n/**\n * A helper for running delayed tasks following an exponential backoff curve\n * between attempts.\n *\n * Each delay is made up of a \"base\" delay which follows the exponential\n * backoff curve, and a +/- 50% \"jitter\" that is calculated and added to the\n * base delay. This prevents clients from accidentally synchronizing their\n * delays causing spikes of load to the backend.\n */\nexport class ExponentialBackoff {\n private currentBaseMs: number = 0;\n private timerPromise: DelayedOperation<void> | null = null;\n /** The last backoff attempt, as epoch milliseconds. */\n private lastAttemptTime = Date.now();\n\n constructor(\n /**\n * The AsyncQueue to run backoff operations on.\n */\n private readonly queue: AsyncQueue,\n /**\n * The ID to use when scheduling backoff operations on the AsyncQueue.\n */\n private readonly timerId: TimerId,\n /**\n * The initial delay (used as the base delay on the first retry attempt).\n * Note that jitter will still be applied, so the actual delay could be as\n * little as 0.5*initialDelayMs.\n */\n private readonly initialDelayMs: number = DEFAULT_BACKOFF_INITIAL_DELAY_MS,\n /**\n * The multiplier to use to determine the extended base delay after each\n * attempt.\n */\n private readonly backoffFactor: number = DEFAULT_BACKOFF_FACTOR,\n /**\n * The maximum base delay after which no further backoff is performed.\n * Note that jitter will still be applied, so the actual delay could be as\n * much as 1.5*maxDelayMs.\n */\n private readonly maxDelayMs: number = DEFAULT_BACKOFF_MAX_DELAY_MS\n ) {\n this.reset();\n }\n\n /**\n * Resets the backoff delay.\n *\n * The very next backoffAndWait() will have no delay. If it is called again\n * (i.e. due to an error), initialDelayMs (plus jitter) will be used, and\n * subsequent ones will increase according to the backoffFactor.\n */\n reset(): void {\n this.currentBaseMs = 0;\n }\n\n /**\n * Resets the backoff delay to the maximum delay (e.g. for use after a\n * RESOURCE_EXHAUSTED error).\n */\n resetToMax(): void {\n this.currentBaseMs = this.maxDelayMs;\n }\n\n /**\n * Returns a promise that resolves after currentDelayMs, and increases the\n * delay for any subsequent attempts. If there was a pending backoff operation\n * already, it will be canceled.\n */\n backoffAndRun(op: () => Promise<void>): void {\n // Cancel any pending backoff operation.\n this.cancel();\n\n // First schedule using the current base (which may be 0 and should be\n // honored as such).\n const desiredDelayWithJitterMs = Math.floor(\n this.currentBaseMs + this.jitterDelayMs()\n );\n\n // Guard against lastAttemptTime being in the future due to a clock change.\n const delaySoFarMs = Math.max(0, Date.now() - this.lastAttemptTime);\n\n // Guard against the backoff delay already being past.\n const remainingDelayMs = Math.max(\n 0,\n desiredDelayWithJitterMs - delaySoFarMs\n );\n\n if (remainingDelayMs > 0) {\n logDebug(\n LOG_TAG,\n `Backing off for ${remainingDelayMs} ms ` +\n `(base delay: ${this.currentBaseMs} ms, ` +\n `delay with jitter: ${desiredDelayWithJitterMs} ms, ` +\n `last attempt: ${delaySoFarMs} ms ago)`\n );\n }\n\n this.timerPromise = this.queue.enqueueAfterDelay(\n this.timerId,\n remainingDelayMs,\n () => {\n this.lastAttemptTime = Date.now();\n return op();\n }\n );\n\n // Apply backoff factor to determine next delay and ensure it is within\n // bounds.\n this.currentBaseMs *= this.backoffFactor;\n if (this.currentBaseMs < this.initialDelayMs) {\n this.currentBaseMs = this.initialDelayMs;\n }\n if (this.currentBaseMs > this.maxDelayMs) {\n this.currentBaseMs = this.maxDelayMs;\n }\n }\n\n skipBackoff(): void {\n if (this.timerPromise !== null) {\n this.timerPromise.skipDelay();\n this.timerPromise = null;\n }\n }\n\n cancel(): void {\n if (this.timerPromise !== null) {\n this.timerPromise.cancel();\n this.timerPromise = null;\n }\n }\n\n /** Returns a random value in the range [-currentBaseMs/2, currentBaseMs/2] */\n private jitterDelayMs(): number {\n return (Math.random() - 0.5) * this.currentBaseMs;\n }\n}\n","/**\n * @license\n * Copyright 2017 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { getGlobal, getUA, isIndexedDBAvailable } from '@firebase/util';\n\nimport { debugAssert } from '../util/assert';\nimport { Code, FirestoreError } from '../util/error';\nimport { logDebug, logError } from '../util/log';\nimport { Deferred } from '../util/promise';\n\nimport { PersistencePromise } from './persistence_promise';\n\n// References to `indexedDB` are guarded by SimpleDb.isAvailable() and getGlobal()\n/* eslint-disable no-restricted-globals */\n\nconst LOG_TAG = 'SimpleDb';\n\n/**\n * The maximum number of retry attempts for an IndexedDb transaction that fails\n * with a DOMException.\n */\nconst TRANSACTION_RETRY_COUNT = 3;\n\n// The different modes supported by `SimpleDb.runTransaction()`\ntype SimpleDbTransactionMode = 'readonly' | 'readwrite';\n\nexport interface SimpleDbSchemaConverter {\n createOrUpgrade(\n db: IDBDatabase,\n txn: IDBTransaction,\n fromVersion: number,\n toVersion: number\n ): PersistencePromise<void>;\n}\n\n/**\n * Wraps an IDBTransaction and exposes a store() method to get a handle to a\n * specific object store.\n */\nexport class SimpleDbTransaction {\n private aborted = false;\n\n /**\n * A `Promise` that resolves with the result of the IndexedDb transaction.\n */\n private readonly completionDeferred = new Deferred<void>();\n\n static open(\n db: IDBDatabase,\n action: string,\n mode: IDBTransactionMode,\n objectStoreNames: string[]\n ): SimpleDbTransaction {\n try {\n return new SimpleDbTransaction(\n action,\n db.transaction(objectStoreNames, mode)\n );\n } catch (e) {\n throw new IndexedDbTransactionError(action, e as Error);\n }\n }\n\n constructor(\n private readonly action: string,\n private readonly transaction: IDBTransaction\n ) {\n this.transaction.oncomplete = () => {\n this.completionDeferred.resolve();\n };\n this.transaction.onabort = () => {\n if (transaction.error) {\n this.completionDeferred.reject(\n new IndexedDbTransactionError(action, transaction.error)\n );\n } else {\n this.completionDeferred.resolve();\n }\n };\n this.transaction.onerror = (event: Event) => {\n const error = checkForAndReportiOSError(\n (event.target as IDBRequest).error!\n );\n this.completionDeferred.reject(\n new IndexedDbTransactionError(action, error)\n );\n };\n }\n\n get completionPromise(): Promise<void> {\n return this.completionDeferred.promise;\n }\n\n abort(error?: Error): void {\n if (error) {\n this.completionDeferred.reject(error);\n }\n\n if (!this.aborted) {\n logDebug(\n LOG_TAG,\n 'Aborting transaction:',\n error ? error.message : 'Client-initiated abort'\n );\n this.aborted = true;\n this.transaction.abort();\n }\n }\n\n maybeCommit(): void {\n // If the browser supports V3 IndexedDB, we invoke commit() explicitly to\n // speed up index DB processing if the event loop remains blocks.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const maybeV3IndexedDb = this.transaction as any;\n if (!this.aborted && typeof maybeV3IndexedDb.commit === 'function') {\n maybeV3IndexedDb.commit();\n }\n }\n\n /**\n * Returns a SimpleDbStore<KeyType, ValueType> for the specified store. All\n * operations performed on the SimpleDbStore happen within the context of this\n * transaction and it cannot be used anymore once the transaction is\n * completed.\n *\n * Note that we can't actually enforce that the KeyType and ValueType are\n * correct, but they allow type safety through the rest of the consuming code.\n */\n store<KeyType extends IDBValidKey, ValueType extends unknown>(\n storeName: string\n ): SimpleDbStore<KeyType, ValueType> {\n const store = this.transaction.objectStore(storeName);\n debugAssert(!!store, 'Object store not part of transaction: ' + storeName);\n return new SimpleDbStore<KeyType, ValueType>(store);\n }\n}\n\n/**\n * Provides a wrapper around IndexedDb with a simplified interface that uses\n * Promise-like return values to chain operations. Real promises cannot be used\n * since .then() continuations are executed asynchronously (e.g. via\n * .setImmediate), which would cause IndexedDB to end the transaction.\n * See PersistencePromise for more details.\n */\nexport class SimpleDb {\n private db?: IDBDatabase;\n private lastClosedDbVersion: number | null = null;\n private versionchangelistener?: (event: IDBVersionChangeEvent) => void;\n\n /** Deletes the specified database. */\n static delete(name: string): Promise<void> {\n logDebug(LOG_TAG, 'Removing database:', name);\n const globals = getGlobal();\n return wrapRequest<void>(\n globals.indexedDB.deleteDatabase(name)\n ).toPromise();\n }\n\n /** Returns true if IndexedDB is available in the current environment. */\n static isAvailable(): boolean {\n if (!isIndexedDBAvailable()) {\n return false;\n }\n\n if (SimpleDb.isMockPersistence()) {\n return true;\n }\n\n // We extensively use indexed array values and compound keys,\n // which IE and Edge do not support. However, they still have indexedDB\n // defined on the window, so we need to check for them here and make sure\n // to return that persistence is not enabled for those browsers.\n // For tracking support of this feature, see here:\n // https://developer.microsoft.com/en-us/microsoft-edge/platform/status/indexeddbarraysandmultientrysupport/\n\n // Check the UA string to find out the browser.\n const ua = getUA();\n\n // IE 10\n // ua = 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)';\n\n // IE 11\n // ua = 'Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko';\n\n // Edge\n // ua = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML,\n // like Gecko) Chrome/39.0.2171.71 Safari/537.36 Edge/12.0';\n\n // iOS Safari: Disable for users running iOS version < 10.\n const iOSVersion = SimpleDb.getIOSVersion(ua);\n const isUnsupportedIOS = 0 < iOSVersion && iOSVersion < 10;\n\n // Android browser: Disable for users running version < 4.5.\n const androidVersion = getAndroidVersion(ua);\n const isUnsupportedAndroid = 0 < androidVersion && androidVersion < 4.5;\n\n if (\n ua.indexOf('MSIE ') > 0 ||\n ua.indexOf('Trident/') > 0 ||\n ua.indexOf('Edge/') > 0 ||\n isUnsupportedIOS ||\n isUnsupportedAndroid\n ) {\n return false;\n } else {\n return true;\n }\n }\n\n /**\n * Returns true if the backing IndexedDB store is the Node IndexedDBShim\n * (see https://github.com/axemclion/IndexedDBShim).\n */\n static isMockPersistence(): boolean {\n return (\n typeof process !== 'undefined' &&\n process.env?.USE_MOCK_PERSISTENCE === 'YES'\n );\n }\n\n /** Helper to get a typed SimpleDbStore from a transaction. */\n static getStore<KeyType extends IDBValidKey, ValueType extends unknown>(\n txn: SimpleDbTransaction,\n store: string\n ): SimpleDbStore<KeyType, ValueType> {\n return txn.store<KeyType, ValueType>(store);\n }\n\n // visible for testing\n /** Parse User Agent to determine iOS version. Returns -1 if not found. */\n static getIOSVersion(ua: string): number {\n const iOSVersionRegex = ua.match(/i(?:phone|pad|pod) os ([\\d_]+)/i);\n const version = iOSVersionRegex\n ? iOSVersionRegex[1].split('_').slice(0, 2).join('.')\n : '-1';\n return Number(version);\n }\n\n /*\n * Creates a new SimpleDb wrapper for IndexedDb database `name`.\n *\n * Note that `version` must not be a downgrade. IndexedDB does not support\n * downgrading the schema version. We currently do not support any way to do\n * versioning outside of IndexedDB's versioning mechanism, as only\n * version-upgrade transactions are allowed to do things like create\n * objectstores.\n */\n constructor(\n private readonly name: string,\n private readonly version: number,\n private readonly schemaConverter: SimpleDbSchemaConverter\n ) {\n debugAssert(\n SimpleDb.isAvailable(),\n 'IndexedDB not supported in current environment.'\n );\n\n const iOSVersion = SimpleDb.getIOSVersion(getUA());\n // NOTE: According to https://bugs.webkit.org/show_bug.cgi?id=197050, the\n // bug we're checking for should exist in iOS >= 12.2 and < 13, but for\n // whatever reason it's much harder to hit after 12.2 so we only proactively\n // log on 12.2.\n if (iOSVersion === 12.2) {\n logError(\n 'Firestore persistence suffers from a bug in iOS 12.2 ' +\n 'Safari that may cause your app to stop working. See ' +\n 'https://stackoverflow.com/q/56496296/110915 for details ' +\n 'and a potential workaround.'\n );\n }\n }\n\n /**\n * Opens the specified database, creating or upgrading it if necessary.\n */\n async ensureDb(action: string): Promise<IDBDatabase> {\n if (!this.db) {\n logDebug(LOG_TAG, 'Opening database:', this.name);\n this.db = await new Promise<IDBDatabase>((resolve, reject) => {\n // TODO(mikelehen): Investigate browser compatibility.\n // https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API/Using_IndexedDB\n // suggests IE9 and older WebKit browsers handle upgrade\n // differently. They expect setVersion, as described here:\n // https://developer.mozilla.org/en-US/docs/Web/API/IDBVersionChangeRequest/setVersion\n const request = indexedDB.open(this.name, this.version);\n\n request.onsuccess = (event: Event) => {\n const db = (event.target as IDBOpenDBRequest).result;\n resolve(db);\n };\n\n request.onblocked = () => {\n reject(\n new IndexedDbTransactionError(\n action,\n 'Cannot upgrade IndexedDB schema while another tab is open. ' +\n 'Close all tabs that access Firestore and reload this page to proceed.'\n )\n );\n };\n\n request.onerror = (event: Event) => {\n const error: DOMException = (event.target as IDBOpenDBRequest).error!;\n if (error.name === 'VersionError') {\n reject(\n new FirestoreError(\n Code.FAILED_PRECONDITION,\n 'A newer version of the Firestore SDK was previously used and so the persisted ' +\n 'data is not compatible with the version of the SDK you are now using. The SDK ' +\n 'will operate with persistence disabled. If you need persistence, please ' +\n 're-upgrade to a newer version of the SDK or else clear the persisted IndexedDB ' +\n 'data for your app to start fresh.'\n )\n );\n } else if (error.name === 'InvalidStateError') {\n reject(\n new FirestoreError(\n Code.FAILED_PRECONDITION,\n 'Unable to open an IndexedDB connection. This could be due to running in a ' +\n 'private browsing session on a browser whose private browsing sessions do not ' +\n 'support IndexedDB: ' +\n error\n )\n );\n } else {\n reject(new IndexedDbTransactionError(action, error));\n }\n };\n\n request.onupgradeneeded = (event: IDBVersionChangeEvent) => {\n logDebug(\n LOG_TAG,\n 'Database \"' + this.name + '\" requires upgrade from version:',\n event.oldVersion\n );\n const db = (event.target as IDBOpenDBRequest).result;\n this.schemaConverter\n .createOrUpgrade(\n db,\n request.transaction!,\n event.oldVersion,\n this.version\n )\n .next(() => {\n logDebug(\n LOG_TAG,\n 'Database upgrade to version ' + this.version + ' complete'\n );\n });\n };\n });\n }\n\n if (this.versionchangelistener) {\n this.db.onversionchange = event => this.versionchangelistener!(event);\n }\n\n return this.db;\n }\n\n setVersionChangeListener(\n versionChangeListener: (event: IDBVersionChangeEvent) => void\n ): void {\n this.versionchangelistener = versionChangeListener;\n if (this.db) {\n this.db.onversionchange = (event: IDBVersionChangeEvent) => {\n return versionChangeListener(event);\n };\n }\n }\n\n async runTransaction<T>(\n action: string,\n mode: SimpleDbTransactionMode,\n objectStores: string[],\n transactionFn: (transaction: SimpleDbTransaction) => PersistencePromise<T>\n ): Promise<T> {\n const readonly = mode === 'readonly';\n let attemptNumber = 0;\n\n while (true) {\n ++attemptNumber;\n\n try {\n this.db = await this.ensureDb(action);\n\n const transaction = SimpleDbTransaction.open(\n this.db,\n action,\n readonly ? 'readonly' : 'readwrite',\n objectStores\n );\n const transactionFnResult = transactionFn(transaction)\n .next(result => {\n transaction.maybeCommit();\n return result;\n })\n .catch(error => {\n // Abort the transaction if there was an error.\n transaction.abort(error);\n // We cannot actually recover, and calling `abort()` will cause the transaction's\n // completion promise to be rejected. This in turn means that we won't use\n // `transactionFnResult` below. We return a rejection here so that we don't add the\n // possibility of returning `void` to the type of `transactionFnResult`.\n return PersistencePromise.reject<T>(error);\n })\n .toPromise();\n\n // As noted above, errors are propagated by aborting the transaction. So\n // we swallow any error here to avoid the browser logging it as unhandled.\n transactionFnResult.catch(() => {});\n\n // Wait for the transaction to complete (i.e. IndexedDb's onsuccess event to\n // fire), but still return the original transactionFnResult back to the\n // caller.\n await transaction.completionPromise;\n return transactionFnResult;\n } catch (e) {\n const error = e as Error;\n // TODO(schmidt-sebastian): We could probably be smarter about this and\n // not retry exceptions that are likely unrecoverable (such as quota\n // exceeded errors).\n\n // Note: We cannot use an instanceof check for FirestoreException, since the\n // exception is wrapped in a generic error by our async/await handling.\n const retryable =\n error.name !== 'FirebaseError' &&\n attemptNumber < TRANSACTION_RETRY_COUNT;\n logDebug(\n LOG_TAG,\n 'Transaction failed with error:',\n error.message,\n 'Retrying:',\n retryable\n );\n\n this.close();\n\n if (!retryable) {\n return Promise.reject(error);\n }\n }\n }\n }\n\n close(): void {\n if (this.db) {\n this.db.close();\n }\n this.db = undefined;\n }\n}\n\n/** Parse User Agent to determine Android version. Returns -1 if not found. */\nexport function getAndroidVersion(ua: string): number {\n const androidVersionRegex = ua.match(/Android ([\\d.]+)/i);\n const version = androidVersionRegex\n ? androidVersionRegex[1].split('.').slice(0, 2).join('.')\n : '-1';\n return Number(version);\n}\n\n/**\n * A controller for iterating over a key range or index. It allows an iterate\n * callback to delete the currently-referenced object, or jump to a new key\n * within the key range or index.\n */\nexport class IterationController {\n private shouldStop = false;\n private nextKey: IDBValidKey | null = null;\n\n constructor(private dbCursor: IDBCursorWithValue) {}\n\n get isDone(): boolean {\n return this.shouldStop;\n }\n\n get skipToKey(): IDBValidKey | null {\n return this.nextKey;\n }\n\n set cursor(value: IDBCursorWithValue) {\n this.dbCursor = value;\n }\n\n /**\n * This function can be called to stop iteration at any point.\n */\n done(): void {\n this.shouldStop = true;\n }\n\n /**\n * This function can be called to skip to that next key, which could be\n * an index or a primary key.\n */\n skip(key: IDBValidKey): void {\n this.nextKey = key;\n }\n\n /**\n * Delete the current cursor value from the object store.\n *\n * NOTE: You CANNOT do this with a keysOnly query.\n */\n delete(): PersistencePromise<void> {\n return wrapRequest<void>(this.dbCursor.delete());\n }\n}\n\n/**\n * Callback used with iterate() method.\n */\nexport type IterateCallback<KeyType, ValueType> = (\n key: KeyType,\n value: ValueType,\n control: IterationController\n) => void | PersistencePromise<void>;\n\n/** Options available to the iterate() method. */\nexport interface IterateOptions {\n /** Index to iterate over (else primary keys will be iterated) */\n index?: string;\n\n /** IndexedDB Range to iterate over (else entire store will be iterated) */\n range?: IDBKeyRange;\n\n /** If true, values aren't read while iterating. */\n keysOnly?: boolean;\n\n /** If true, iterate over the store in reverse. */\n reverse?: boolean;\n}\n\n/** An error that wraps exceptions that thrown during IndexedDB execution. */\nexport class IndexedDbTransactionError extends FirestoreError {\n name = 'IndexedDbTransactionError';\n\n constructor(actionName: string, cause: Error | string) {\n super(\n Code.UNAVAILABLE,\n `IndexedDB transaction '${actionName}' failed: ${cause}`\n );\n }\n}\n\n/** Verifies whether `e` is an IndexedDbTransactionError. */\nexport function isIndexedDbTransactionError(e: Error): boolean {\n // Use name equality, as instanceof checks on errors don't work with errors\n // that wrap other errors.\n return e.name === 'IndexedDbTransactionError';\n}\n\n/**\n * A wrapper around an IDBObjectStore providing an API that:\n *\n * 1) Has generic KeyType / ValueType parameters to provide strongly-typed\n * methods for acting against the object store.\n * 2) Deals with IndexedDB's onsuccess / onerror event callbacks, making every\n * method return a PersistencePromise instead.\n * 3) Provides a higher-level API to avoid needing to do excessive wrapping of\n * intermediate IndexedDB types (IDBCursorWithValue, etc.)\n */\nexport class SimpleDbStore<\n KeyType extends IDBValidKey,\n ValueType extends unknown\n> {\n constructor(private store: IDBObjectStore) {}\n\n /**\n * Writes a value into the Object Store.\n *\n * @param key - Optional explicit key to use when writing the object, else the\n * key will be auto-assigned (e.g. via the defined keyPath for the store).\n * @param value - The object to write.\n */\n put(value: ValueType): PersistencePromise<void>;\n put(key: KeyType, value: ValueType): PersistencePromise<void>;\n put(\n keyOrValue: KeyType | ValueType,\n value?: ValueType\n ): PersistencePromise<void> {\n let request;\n if (value !== undefined) {\n logDebug(LOG_TAG, 'PUT', this.store.name, keyOrValue, value);\n request = this.store.put(value, keyOrValue as KeyType);\n } else {\n logDebug(LOG_TAG, 'PUT', this.store.name, '<auto-key>', keyOrValue);\n request = this.store.put(keyOrValue as ValueType);\n }\n return wrapRequest<void>(request);\n }\n\n /**\n * Adds a new value into an Object Store and returns the new key. Similar to\n * IndexedDb's `add()`, this method will fail on primary key collisions.\n *\n * @param value - The object to write.\n * @returns The key of the value to add.\n */\n add(value: ValueType): PersistencePromise<KeyType> {\n logDebug(LOG_TAG, 'ADD', this.store.name, value, value);\n const request = this.store.add(value as ValueType);\n return wrapRequest<KeyType>(request);\n }\n\n /**\n * Gets the object with the specified key from the specified store, or null\n * if no object exists with the specified key.\n *\n * @key The key of the object to get.\n * @returns The object with the specified key or null if no object exists.\n */\n get(key: KeyType): PersistencePromise<ValueType | null> {\n const request = this.store.get(key);\n // We're doing an unsafe cast to ValueType.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return wrapRequest<any>(request).next(result => {\n // Normalize nonexistence to null.\n if (result === undefined) {\n result = null;\n }\n logDebug(LOG_TAG, 'GET', this.store.name, key, result);\n return result;\n });\n }\n\n delete(key: KeyType | IDBKeyRange): PersistencePromise<void> {\n logDebug(LOG_TAG, 'DELETE', this.store.name, key);\n const request = this.store.delete(key);\n return wrapRequest<void>(request);\n }\n\n /**\n * If we ever need more of the count variants, we can add overloads. For now,\n * all we need is to count everything in a store.\n *\n * Returns the number of rows in the store.\n */\n count(): PersistencePromise<number> {\n logDebug(LOG_TAG, 'COUNT', this.store.name);\n const request = this.store.count();\n return wrapRequest<number>(request);\n }\n\n /** Loads all elements from the object store. */\n loadAll(): PersistencePromise<ValueType[]>;\n /** Loads all elements for the index range from the object store. */\n loadAll(range: IDBKeyRange): PersistencePromise<ValueType[]>;\n /** Loads all elements ordered by the given index. */\n loadAll(index: string): PersistencePromise<ValueType[]>;\n /**\n * Loads all elements from the object store that fall into the provided in the\n * index range for the given index.\n */\n loadAll(index: string, range: IDBKeyRange): PersistencePromise<ValueType[]>;\n loadAll(\n indexOrRange?: string | IDBKeyRange,\n range?: IDBKeyRange\n ): PersistencePromise<ValueType[]> {\n const iterateOptions = this.options(indexOrRange, range);\n // Use `getAll()` if the browser supports IndexedDB v3, as it is roughly\n // 20% faster.\n const store = iterateOptions.index\n ? this.store.index(iterateOptions.index)\n : this.store;\n if (typeof store.getAll === 'function') {\n const request = store.getAll(iterateOptions.range);\n return new PersistencePromise((resolve, reject) => {\n request.onerror = (event: Event) => {\n reject((event.target as IDBRequest).error!);\n };\n request.onsuccess = (event: Event) => {\n resolve((event.target as IDBRequest).result);\n };\n });\n } else {\n const cursor = this.cursor(iterateOptions);\n const results: ValueType[] = [];\n return this.iterateCursor(cursor, (key, value) => {\n results.push(value);\n }).next(() => {\n return results;\n });\n }\n }\n\n /**\n * Loads the first `count` elements from the provided index range. Loads all\n * elements if no limit is provided.\n */\n loadFirst(\n range: IDBKeyRange,\n count: number | null\n ): PersistencePromise<ValueType[]> {\n const request = this.store.getAll(\n range,\n count === null ? undefined : count\n );\n return new PersistencePromise((resolve, reject) => {\n request.onerror = (event: Event) => {\n reject((event.target as IDBRequest).error!);\n };\n request.onsuccess = (event: Event) => {\n resolve((event.target as IDBRequest).result);\n };\n });\n }\n\n deleteAll(): PersistencePromise<void>;\n deleteAll(range: IDBKeyRange): PersistencePromise<void>;\n deleteAll(index: string, range: IDBKeyRange): PersistencePromise<void>;\n deleteAll(\n indexOrRange?: string | IDBKeyRange,\n range?: IDBKeyRange\n ): PersistencePromise<void> {\n logDebug(LOG_TAG, 'DELETE ALL', this.store.name);\n const options = this.options(indexOrRange, range);\n options.keysOnly = false;\n const cursor = this.cursor(options);\n return this.iterateCursor(cursor, (key, value, control) => {\n // NOTE: Calling delete() on a cursor is documented as more efficient than\n // calling delete() on an object store with a single key\n // (https://developer.mozilla.org/en-US/docs/Web/API/IDBObjectStore/delete),\n // however, this requires us *not* to use a keysOnly cursor\n // (https://developer.mozilla.org/en-US/docs/Web/API/IDBCursor/delete). We\n // may want to compare the performance of each method.\n return control.delete();\n });\n }\n\n /**\n * Iterates over keys and values in an object store.\n *\n * @param options - Options specifying how to iterate the objects in the\n * store.\n * @param callback - will be called for each iterated object. Iteration can be\n * canceled at any point by calling the doneFn passed to the callback.\n * The callback can return a PersistencePromise if it performs async\n * operations but note that iteration will continue without waiting for them\n * to complete.\n * @returns A PersistencePromise that resolves once all PersistencePromises\n * returned by callbacks resolve.\n */\n iterate(\n callback: IterateCallback<KeyType, ValueType>\n ): PersistencePromise<void>;\n iterate(\n options: IterateOptions,\n callback: IterateCallback<KeyType, ValueType>\n ): PersistencePromise<void>;\n iterate(\n optionsOrCallback: IterateOptions | IterateCallback<KeyType, ValueType>,\n callback?: IterateCallback<KeyType, ValueType>\n ): PersistencePromise<void> {\n let options;\n if (!callback) {\n options = {};\n callback = optionsOrCallback as IterateCallback<KeyType, ValueType>;\n } else {\n options = optionsOrCallback as IterateOptions;\n }\n const cursor = this.cursor(options);\n return this.iterateCursor(cursor, callback);\n }\n\n /**\n * Iterates over a store, but waits for the given callback to complete for\n * each entry before iterating the next entry. This allows the callback to do\n * asynchronous work to determine if this iteration should continue.\n *\n * The provided callback should return `true` to continue iteration, and\n * `false` otherwise.\n */\n iterateSerial(\n callback: (k: KeyType, v: ValueType) => PersistencePromise<boolean>\n ): PersistencePromise<void> {\n const cursorRequest = this.cursor({});\n return new PersistencePromise((resolve, reject) => {\n cursorRequest.onerror = (event: Event) => {\n const error = checkForAndReportiOSError(\n (event.target as IDBRequest).error!\n );\n reject(error);\n };\n cursorRequest.onsuccess = (event: Event) => {\n const cursor: IDBCursorWithValue = (event.target as IDBRequest).result;\n if (!cursor) {\n resolve();\n return;\n }\n\n callback(cursor.primaryKey as KeyType, cursor.value).next(\n shouldContinue => {\n if (shouldContinue) {\n cursor.continue();\n } else {\n resolve();\n }\n }\n );\n };\n });\n }\n\n private iterateCursor(\n cursorRequest: IDBRequest,\n fn: IterateCallback<KeyType, ValueType>\n ): PersistencePromise<void> {\n const results: Array<PersistencePromise<void>> = [];\n return new PersistencePromise((resolve, reject) => {\n cursorRequest.onerror = (event: Event) => {\n reject((event.target as IDBRequest).error!);\n };\n cursorRequest.onsuccess = (event: Event) => {\n const cursor: IDBCursorWithValue = (event.target as IDBRequest).result;\n if (!cursor) {\n resolve();\n return;\n }\n const controller = new IterationController(cursor);\n const userResult = fn(\n cursor.primaryKey as KeyType,\n cursor.value,\n controller\n );\n if (userResult instanceof PersistencePromise) {\n const userPromise: PersistencePromise<void> = userResult.catch(\n err => {\n controller.done();\n return PersistencePromise.reject(err);\n }\n );\n results.push(userPromise);\n }\n if (controller.isDone) {\n resolve();\n } else if (controller.skipToKey === null) {\n cursor.continue();\n } else {\n cursor.continue(controller.skipToKey);\n }\n };\n }).next(() => PersistencePromise.waitFor(results));\n }\n\n private options(\n indexOrRange?: string | IDBKeyRange,\n range?: IDBKeyRange\n ): IterateOptions {\n let indexName: string | undefined = undefined;\n if (indexOrRange !== undefined) {\n if (typeof indexOrRange === 'string') {\n indexName = indexOrRange;\n } else {\n debugAssert(\n range === undefined,\n '3rd argument must not be defined if 2nd is a range.'\n );\n range = indexOrRange;\n }\n }\n return { index: indexName, range };\n }\n\n private cursor(options: IterateOptions): IDBRequest {\n let direction: IDBCursorDirection = 'next';\n if (options.reverse) {\n direction = 'prev';\n }\n if (options.index) {\n const index = this.store.index(options.index);\n if (options.keysOnly) {\n return index.openKeyCursor(options.range, direction);\n } else {\n return index.openCursor(options.range, direction);\n }\n } else {\n return this.store.openCursor(options.range, direction);\n }\n }\n}\n\n/**\n * Wraps an IDBRequest in a PersistencePromise, using the onsuccess / onerror\n * handlers to resolve / reject the PersistencePromise as appropriate.\n */\nfunction wrapRequest<R>(request: IDBRequest): PersistencePromise<R> {\n return new PersistencePromise<R>((resolve, reject) => {\n request.onsuccess = (event: Event) => {\n const result = (event.target as IDBRequest).result;\n resolve(result);\n };\n\n request.onerror = (event: Event) => {\n const error = checkForAndReportiOSError(\n (event.target as IDBRequest).error!\n );\n reject(error);\n };\n });\n}\n\n// Guard so we only report the error once.\nlet reportedIOSError = false;\nfunction checkForAndReportiOSError(error: DOMException): Error {\n const iOSVersion = SimpleDb.getIOSVersion(getUA());\n if (iOSVersion >= 12.2 && iOSVersion < 13) {\n const IOS_ERROR =\n 'An internal error was encountered in the Indexed Database server';\n if (error.message.indexOf(IOS_ERROR) >= 0) {\n // Wrap error in a more descriptive one.\n const newError = new FirestoreError(\n 'internal',\n `IOS_INDEXEDDB_BUG1: IndexedDb has thrown '${IOS_ERROR}'. This is likely ` +\n `due to an unavoidable bug in iOS. See https://stackoverflow.com/q/56496296/110915 ` +\n `for details and a potential workaround.`\n );\n if (!reportedIOSError) {\n reportedIOSError = true;\n // Throw a global exception outside of this promise chain, for the user to\n // potentially catch.\n setTimeout(() => {\n throw newError;\n }, 0);\n }\n return newError;\n }\n }\n return error;\n}\n","/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n _registerComponent,\n registerVersion,\n SDK_VERSION\n} from '@firebase/app';\nimport { Component, ComponentType } from '@firebase/component';\n\nimport { version } from '../package.json';\nimport {\n LiteAppCheckTokenProvider,\n LiteAuthCredentialsProvider\n} from '../src/api/credentials';\nimport { databaseIdFromApp } from '../src/core/database_info';\nimport { setSDKVersion } from '../src/core/version';\nimport { Firestore } from '../src/lite-api/database';\n\ndeclare module '@firebase/component' {\n interface NameServiceMapping {\n 'firestore/lite': Firestore;\n }\n}\n\nexport function registerFirestore(): void {\n setSDKVersion(`${SDK_VERSION}_lite`);\n _registerComponent(\n new Component(\n 'firestore/lite',\n (container, { instanceIdentifier: databaseId, options: settings }) => {\n const app = container.getProvider('app').getImmediate()!;\n const firestoreInstance = new Firestore(\n new LiteAuthCredentialsProvider(\n container.getProvider('auth-internal')\n ),\n new LiteAppCheckTokenProvider(\n app,\n container.getProvider('app-check-internal')\n ),\n databaseIdFromApp(app, databaseId),\n app\n );\n if (settings) {\n firestoreInstance._setSettings(settings);\n }\n return firestoreInstance;\n },\n 'PUBLIC' as ComponentType.PUBLIC\n ).setMultipleInstances(true)\n );\n // RUNTIME_ENV and BUILD_TARGET are replaced by real values during the compilation\n registerVersion('firestore-lite', version, '__RUNTIME_ENV__');\n registerVersion('firestore-lite', version, '__BUILD_TARGET__');\n}\n","/**\n * @license\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { FieldPath } from '../model/path';\n\n/**\n * Union type representing the aggregate type to be performed.\n */\nexport type AggregateType = 'count' | 'avg' | 'sum';\n\n/**\n * Represents an Aggregate to be performed over a query result set.\n */\nexport interface Aggregate {\n readonly fieldPath?: FieldPath;\n readonly alias: string;\n readonly aggregateType: AggregateType;\n}\n\n/**\n * Concrete implementation of the Aggregate type.\n */\nexport class AggregateImpl implements Aggregate {\n constructor(\n readonly alias: string,\n readonly aggregateType: AggregateType,\n readonly fieldPath?: FieldPath\n ) {}\n}\n","/**\n * @license\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { AggregateType } from '../core/aggregate';\nimport { ObjectValue } from '../model/object_value';\nimport { FieldPath as InternalFieldPath } from '../model/path';\nimport {\n ApiClientObjectMap,\n firestoreV1ApiClientInterfaces,\n Value\n} from '../protos/firestore_proto_api';\n\nimport { average, count, sum } from './aggregate';\nimport { DocumentData, Query } from './reference';\nimport { AbstractUserDataWriter } from './user_data_writer';\n\nexport { AggregateType };\n\n/**\n * Represents an aggregation that can be performed by Firestore.\n */\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nexport class AggregateField<T> {\n /** A type string to uniquely identify instances of this class. */\n readonly type = 'AggregateField';\n\n /** Indicates the aggregation operation of this AggregateField. */\n readonly aggregateType: AggregateType;\n\n /**\n * Create a new AggregateField<T>\n * @param aggregateType - Specifies the type of aggregation operation to perform.\n * @param _internalFieldPath - Optionally specifies the field that is aggregated.\n * @internal\n */\n constructor(\n aggregateType: AggregateType = 'count',\n readonly _internalFieldPath?: InternalFieldPath\n ) {\n this.aggregateType = aggregateType;\n }\n}\n\n/**\n * The union of all `AggregateField` types that are supported by Firestore.\n */\nexport type AggregateFieldType =\n | ReturnType<typeof sum>\n | ReturnType<typeof average>\n | ReturnType<typeof count>;\n\n/**\n * Specifies a set of aggregations and their aliases.\n */\nexport interface AggregateSpec {\n [field: string]: AggregateFieldType;\n}\n\n/**\n * A type whose keys are taken from an `AggregateSpec`, and whose values are the\n * result of the aggregation performed by the corresponding `AggregateField`\n * from the input `AggregateSpec`.\n */\nexport type AggregateSpecData<T extends AggregateSpec> = {\n [P in keyof T]: T[P] extends AggregateField<infer U> ? U : never;\n};\n\n/**\n * The results of executing an aggregation query.\n */\nexport class AggregateQuerySnapshot<\n AggregateSpecType extends AggregateSpec,\n AppModelType = DocumentData,\n DbModelType extends DocumentData = DocumentData\n> {\n /** A type string to uniquely identify instances of this class. */\n readonly type = 'AggregateQuerySnapshot';\n\n /**\n * The underlying query over which the aggregations recorded in this\n * `AggregateQuerySnapshot` were performed.\n */\n readonly query: Query<AppModelType, DbModelType>;\n\n /** @hideconstructor */\n constructor(\n query: Query<AppModelType, DbModelType>,\n private readonly _userDataWriter: AbstractUserDataWriter,\n private readonly _data: ApiClientObjectMap<Value>\n ) {\n this.query = query;\n }\n\n /**\n * Returns the results of the aggregations performed over the underlying\n * query.\n *\n * The keys of the returned object will be the same as those of the\n * `AggregateSpec` object specified to the aggregation method, and the values\n * will be the corresponding aggregation result.\n *\n * @returns The results of the aggregations performed over the underlying\n * query.\n */\n data(): AggregateSpecData<AggregateSpecType> {\n return this._userDataWriter.convertObjectMap(\n this._data\n ) as AggregateSpecData<AggregateSpecType>;\n }\n\n /**\n * @internal\n * @private\n *\n * Retrieves all fields in the snapshot as a proto value.\n *\n * @returns An `Object` containing all fields in the snapshot.\n */\n _fieldsProto(): { [key: string]: firestoreV1ApiClientInterfaces.Value } {\n // Wrap data in an ObjectValue to clone it.\n const dataClone = new ObjectValue({\n mapValue: { fields: this._data }\n }).clone();\n\n // Return the cloned value to prevent manipulation of the Snapshot's data\n return dataClone.value.mapValue.fields!;\n }\n}\n","/**\n * @license\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { deepEqual } from '@firebase/util';\n\nimport { AggregateImpl } from '../core/aggregate';\nimport { ApiClientObjectMap, Value } from '../protos/firestore_proto_api';\nimport { invokeRunAggregationQueryRpc } from '../remote/datastore';\nimport { cast } from '../util/input_validation';\nimport { mapToArray } from '../util/obj';\n\nimport {\n AggregateField,\n AggregateQuerySnapshot,\n AggregateSpec\n} from './aggregate_types';\nimport { getDatastore } from './components';\nimport { Firestore } from './database';\nimport { FieldPath } from './field_path';\nimport { DocumentData, Query, queryEqual } from './reference';\nimport { LiteUserDataWriter } from './reference_impl';\nimport { fieldPathFromArgument } from './user_data_reader';\n\n/**\n * Calculates the number of documents in the result set of the given query\n * without actually downloading the documents.\n *\n * Using this function to count the documents is efficient because only the\n * final count, not the documents' data, is downloaded. This function can\n * count the documents in cases where the result set is prohibitively large to\n * download entirely (thousands of documents).\n *\n * @param query - The query whose result set size is calculated.\n * @returns A Promise that will be resolved with the count; the count can be\n * retrieved from `snapshot.data().count`, where `snapshot` is the\n * `AggregateQuerySnapshot` to which the returned Promise resolves.\n */\nexport function getCount<AppModelType, DbModelType extends DocumentData>(\n query: Query<AppModelType, DbModelType>\n): Promise<\n AggregateQuerySnapshot<\n { count: AggregateField<number> },\n AppModelType,\n DbModelType\n >\n> {\n const countQuerySpec: { count: AggregateField<number> } = {\n count: count()\n };\n\n return getAggregate(query, countQuerySpec);\n}\n\n/**\n * Calculates the specified aggregations over the documents in the result\n * set of the given query without actually downloading the documents.\n *\n * Using this function to perform aggregations is efficient because only the\n * final aggregation values, not the documents' data, are downloaded. This\n * function can perform aggregations of the documents in cases where the result\n * set is prohibitively large to download entirely (thousands of documents).\n *\n * @param query - The query whose result set is aggregated over.\n * @param aggregateSpec - An `AggregateSpec` object that specifies the aggregates\n * to perform over the result set. The AggregateSpec specifies aliases for each\n * aggregate, which can be used to retrieve the aggregate result.\n * @example\n * ```typescript\n * const aggregateSnapshot = await getAggregate(query, {\n * countOfDocs: count(),\n * totalHours: sum('hours'),\n * averageScore: average('score')\n * });\n *\n * const countOfDocs: number = aggregateSnapshot.data().countOfDocs;\n * const totalHours: number = aggregateSnapshot.data().totalHours;\n * const averageScore: number | null = aggregateSnapshot.data().averageScore;\n * ```\n */\nexport function getAggregate<\n AggregateSpecType extends AggregateSpec,\n AppModelType,\n DbModelType extends DocumentData\n>(\n query: Query<AppModelType, DbModelType>,\n aggregateSpec: AggregateSpecType\n): Promise<\n AggregateQuerySnapshot<AggregateSpecType, AppModelType, DbModelType>\n> {\n const firestore = cast(query.firestore, Firestore);\n const datastore = getDatastore(firestore);\n\n const internalAggregates = mapToArray(aggregateSpec, (aggregate, alias) => {\n return new AggregateImpl(\n alias,\n aggregate.aggregateType,\n aggregate._internalFieldPath\n );\n });\n\n // Run the aggregation and convert the results\n return invokeRunAggregationQueryRpc(\n datastore,\n query._query,\n internalAggregates\n ).then(aggregateResult =>\n convertToAggregateQuerySnapshot(firestore, query, aggregateResult)\n );\n}\n\nfunction convertToAggregateQuerySnapshot<\n AggregateSpecType extends AggregateSpec,\n AppModelType,\n DbModelType extends DocumentData\n>(\n firestore: Firestore,\n query: Query<AppModelType, DbModelType>,\n aggregateResult: ApiClientObjectMap<Value>\n): AggregateQuerySnapshot<AggregateSpecType, AppModelType, DbModelType> {\n const userDataWriter = new LiteUserDataWriter(firestore);\n const querySnapshot = new AggregateQuerySnapshot<\n AggregateSpecType,\n AppModelType,\n DbModelType\n >(query, userDataWriter, aggregateResult);\n return querySnapshot;\n}\n\n/**\n * Create an AggregateField object that can be used to compute the sum of\n * a specified field over a range of documents in the result set of a query.\n * @param field - Specifies the field to sum across the result set.\n */\nexport function sum(field: string | FieldPath): AggregateField<number> {\n return new AggregateField('sum', fieldPathFromArgument('sum', field));\n}\n\n/**\n * Create an AggregateField object that can be used to compute the average of\n * a specified field over a range of documents in the result set of a query.\n * @param field - Specifies the field to average across the result set.\n */\nexport function average(\n field: string | FieldPath\n): AggregateField<number | null> {\n return new AggregateField('avg', fieldPathFromArgument('average', field));\n}\n\n/**\n * Create an AggregateField object that can be used to compute the count of\n * documents in the result set of a query.\n */\nexport function count(): AggregateField<number> {\n return new AggregateField('count');\n}\n\n/**\n * Compares two 'AggregateField` instances for equality.\n *\n * @param left - Compare this AggregateField to the `right`.\n * @param right - Compare this AggregateField to the `left`.\n */\nexport function aggregateFieldEqual(\n left: AggregateField<unknown>,\n right: AggregateField<unknown>\n): boolean {\n return (\n left instanceof AggregateField &&\n right instanceof AggregateField &&\n left.aggregateType === right.aggregateType &&\n left._internalFieldPath?.canonicalString() ===\n right._internalFieldPath?.canonicalString()\n );\n}\n\n/**\n * Compares two `AggregateQuerySnapshot` instances for equality.\n *\n * Two `AggregateQuerySnapshot` instances are considered \"equal\" if they have\n * underlying queries that compare equal, and the same data.\n *\n * @param left - The first `AggregateQuerySnapshot` to compare.\n * @param right - The second `AggregateQuerySnapshot` to compare.\n *\n * @returns `true` if the objects are \"equal\", as defined above, or `false`\n * otherwise.\n */\nexport function aggregateQuerySnapshotEqual<\n AggregateSpecType extends AggregateSpec,\n AppModelType,\n DbModelType extends DocumentData\n>(\n left: AggregateQuerySnapshot<AggregateSpecType, AppModelType, DbModelType>,\n right: AggregateQuerySnapshot<AggregateSpecType, AppModelType, DbModelType>\n): boolean {\n return (\n queryEqual(left.query, right.query) && deepEqual(left.data(), right.data())\n );\n}\n","/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Compat, getModularInstance } from '@firebase/util';\n\nimport { DeleteMutation, Mutation, Precondition } from '../model/mutation';\nimport { invokeCommitRpc } from '../remote/datastore';\nimport { Code, FirestoreError } from '../util/error';\nimport { cast } from '../util/input_validation';\n\nimport { getDatastore } from './components';\nimport { Firestore } from './database';\nimport { FieldPath } from './field_path';\nimport {\n DocumentData,\n DocumentReference,\n PartialWithFieldValue,\n SetOptions,\n UpdateData,\n WithFieldValue\n} from './reference';\nimport { applyFirestoreDataConverter } from './reference_impl';\nimport {\n newUserDataReader,\n parseSetData,\n parseUpdateData,\n parseUpdateVarargs,\n UserDataReader\n} from './user_data_reader';\n\n/**\n * A write batch, used to perform multiple writes as a single atomic unit.\n *\n * A `WriteBatch` object can be acquired by calling {@link writeBatch}. It\n * provides methods for adding writes to the write batch. None of the writes\n * will be committed (or visible locally) until {@link WriteBatch.commit} is\n * called.\n */\nexport class WriteBatch {\n // This is the lite version of the WriteBatch API used in the legacy SDK. The\n // class is a close copy but takes different input types.\n\n private readonly _dataReader: UserDataReader;\n private _mutations = [] as Mutation[];\n private _committed = false;\n\n /** @hideconstructor */\n constructor(\n private readonly _firestore: Firestore,\n private readonly _commitHandler: (m: Mutation[]) => Promise<void>\n ) {\n this._dataReader = newUserDataReader(_firestore);\n }\n\n /**\n * Writes to the document referred to by the provided {@link\n * DocumentReference}. If the document does not exist yet, it will be created.\n *\n * @param documentRef - A reference to the document to be set.\n * @param data - An object of the fields and values for the document.\n * @returns This `WriteBatch` instance. Used for chaining method calls.\n */\n set<AppModelType, DbModelType extends DocumentData>(\n documentRef: DocumentReference<AppModelType, DbModelType>,\n data: WithFieldValue<AppModelType>\n ): WriteBatch;\n /**\n * Writes to the document referred to by the provided {@link\n * DocumentReference}. If the document does not exist yet, it will be created.\n * If you provide `merge` or `mergeFields`, the provided data can be merged\n * into an existing document.\n *\n * @param documentRef - A reference to the document to be set.\n * @param data - An object of the fields and values for the document.\n * @param options - An object to configure the set behavior.\n * @throws Error - If the provided input is not a valid Firestore document.\n * @returns This `WriteBatch` instance. Used for chaining method calls.\n */\n set<AppModelType, DbModelType extends DocumentData>(\n documentRef: DocumentReference<AppModelType, DbModelType>,\n data: PartialWithFieldValue<AppModelType>,\n options: SetOptions\n ): WriteBatch;\n set<AppModelType, DbModelType extends DocumentData>(\n documentRef: DocumentReference<AppModelType, DbModelType>,\n data: WithFieldValue<AppModelType> | PartialWithFieldValue<AppModelType>,\n options?: SetOptions\n ): WriteBatch {\n this._verifyNotCommitted();\n const ref = validateReference(documentRef, this._firestore);\n\n const convertedValue = applyFirestoreDataConverter(\n ref.converter,\n data,\n options\n );\n const parsed = parseSetData(\n this._dataReader,\n 'WriteBatch.set',\n ref._key,\n convertedValue,\n ref.converter !== null,\n options\n );\n this._mutations.push(parsed.toMutation(ref._key, Precondition.none()));\n return this;\n }\n\n /**\n * Updates fields in the document referred to by the provided {@link\n * DocumentReference}. The update will fail if applied to a document that does\n * not exist.\n *\n * @param documentRef - A reference to the document to be updated.\n * @param data - An object containing the fields and values with which to\n * update the document. Fields can contain dots to reference nested fields\n * within the document.\n * @throws Error - If the provided input is not valid Firestore data.\n * @returns This `WriteBatch` instance. Used for chaining method calls.\n */\n update<AppModelType, DbModelType extends DocumentData>(\n documentRef: DocumentReference<AppModelType, DbModelType>,\n data: UpdateData<DbModelType>\n ): WriteBatch;\n /**\n * Updates fields in the document referred to by this {@link\n * DocumentReference}. The update will fail if applied to a document that does\n * not exist.\n *\n * Nested fields can be update by providing dot-separated field path strings\n * or by providing `FieldPath` objects.\n *\n * @param documentRef - A reference to the document to be updated.\n * @param field - The first field to update.\n * @param value - The first value.\n * @param moreFieldsAndValues - Additional key value pairs.\n * @throws Error - If the provided input is not valid Firestore data.\n * @returns This `WriteBatch` instance. Used for chaining method calls.\n */\n update<AppModelType, DbModelType extends DocumentData>(\n documentRef: DocumentReference<AppModelType, DbModelType>,\n field: string | FieldPath,\n value: unknown,\n ...moreFieldsAndValues: unknown[]\n ): WriteBatch;\n update<AppModelType, DbModelType extends DocumentData>(\n documentRef: DocumentReference<AppModelType, DbModelType>,\n fieldOrUpdateData: string | FieldPath | UpdateData<DbModelType>,\n value?: unknown,\n ...moreFieldsAndValues: unknown[]\n ): WriteBatch {\n this._verifyNotCommitted();\n const ref = validateReference(documentRef, this._firestore);\n\n // For Compat types, we have to \"extract\" the underlying types before\n // performing validation.\n fieldOrUpdateData = getModularInstance(fieldOrUpdateData);\n\n let parsed;\n if (\n typeof fieldOrUpdateData === 'string' ||\n fieldOrUpdateData instanceof FieldPath\n ) {\n parsed = parseUpdateVarargs(\n this._dataReader,\n 'WriteBatch.update',\n ref._key,\n fieldOrUpdateData,\n value,\n moreFieldsAndValues\n );\n } else {\n parsed = parseUpdateData(\n this._dataReader,\n 'WriteBatch.update',\n ref._key,\n fieldOrUpdateData\n );\n }\n\n this._mutations.push(\n parsed.toMutation(ref._key, Precondition.exists(true))\n );\n return this;\n }\n\n /**\n * Deletes the document referred to by the provided {@link DocumentReference}.\n *\n * @param documentRef - A reference to the document to be deleted.\n * @returns This `WriteBatch` instance. Used for chaining method calls.\n */\n delete<AppModelType, DbModelType extends DocumentData>(\n documentRef: DocumentReference<AppModelType, DbModelType>\n ): WriteBatch {\n this._verifyNotCommitted();\n const ref = validateReference(documentRef, this._firestore);\n this._mutations = this._mutations.concat(\n new DeleteMutation(ref._key, Precondition.none())\n );\n return this;\n }\n\n /**\n * Commits all of the writes in this write batch as a single atomic unit.\n *\n * The result of these writes will only be reflected in document reads that\n * occur after the returned promise resolves. If the client is offline, the\n * write fails. If you would like to see local modifications or buffer writes\n * until the client is online, use the full Firestore SDK.\n *\n * @returns A `Promise` resolved once all of the writes in the batch have been\n * successfully written to the backend as an atomic unit (note that it won't\n * resolve while you're offline).\n */\n commit(): Promise<void> {\n this._verifyNotCommitted();\n this._committed = true;\n if (this._mutations.length > 0) {\n return this._commitHandler(this._mutations);\n }\n\n return Promise.resolve();\n }\n\n private _verifyNotCommitted(): void {\n if (this._committed) {\n throw new FirestoreError(\n Code.FAILED_PRECONDITION,\n 'A write batch can no longer be used after commit() ' +\n 'has been called.'\n );\n }\n }\n}\n\nexport function validateReference<\n AppModelType,\n DbModelType extends DocumentData\n>(\n documentRef:\n | DocumentReference<AppModelType, DbModelType>\n | Compat<DocumentReference<AppModelType, DbModelType>>,\n firestore: Firestore\n): DocumentReference<AppModelType, DbModelType> {\n documentRef = getModularInstance(documentRef);\n\n if (documentRef.firestore !== firestore) {\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n 'Provided document reference is from a different Firestore instance.'\n );\n } else {\n return documentRef as DocumentReference<AppModelType, DbModelType>;\n }\n}\n\n/**\n * Creates a write batch, used for performing multiple writes as a single\n * atomic operation. The maximum number of writes allowed in a single WriteBatch\n * is 500.\n *\n * The result of these writes will only be reflected in document reads that\n * occur after the returned promise resolves. If the client is offline, the\n * write fails. If you would like to see local modifications or buffer writes\n * until the client is online, use the full Firestore SDK.\n *\n * @returns A `WriteBatch` that can be used to atomically execute multiple\n * writes.\n */\nexport function writeBatch(firestore: Firestore): WriteBatch {\n firestore = cast(firestore, Firestore);\n const datastore = getDatastore(firestore);\n return new WriteBatch(firestore, writes =>\n invokeCommitRpc(datastore, writes)\n );\n}\n","/**\n * @license\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Code, FirestoreError } from '../util/error';\n\nexport const DEFAULT_TRANSACTION_OPTIONS: TransactionOptions = {\n maxAttempts: 5\n};\n\n/**\n * Options to customize transaction behavior.\n */\nexport declare interface TransactionOptions {\n /** Maximum number of attempts to commit, after which transaction fails. Default is 5. */\n readonly maxAttempts: number;\n}\n\nexport function validateTransactionOptions(options: TransactionOptions): void {\n if (options.maxAttempts < 1) {\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n 'Max attempts must be at least 1'\n );\n }\n}\n","/**\n * @license\n * Copyright 2017 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ParsedSetData, ParsedUpdateData } from '../lite-api/user_data_reader';\nimport { Document } from '../model/document';\nimport { DocumentKey } from '../model/document_key';\nimport {\n DeleteMutation,\n Mutation,\n Precondition,\n VerifyMutation\n} from '../model/mutation';\nimport {\n Datastore,\n invokeBatchGetDocumentsRpc,\n invokeCommitRpc\n} from '../remote/datastore';\nimport { fail, debugAssert } from '../util/assert';\nimport { Code, FirestoreError } from '../util/error';\n\nimport { SnapshotVersion } from './snapshot_version';\n\n/**\n * Internal transaction object responsible for accumulating the mutations to\n * perform and the base versions for any documents read.\n */\nexport class Transaction {\n // The version of each document that was read during this transaction.\n private readVersions = new Map</* path */ string, SnapshotVersion>();\n private mutations: Mutation[] = [];\n private committed = false;\n\n /**\n * A deferred usage error that occurred previously in this transaction that\n * will cause the transaction to fail once it actually commits.\n */\n private lastTransactionError: FirestoreError | null = null;\n\n /**\n * Set of documents that have been written in the transaction.\n *\n * When there's more than one write to the same key in a transaction, any\n * writes after the first are handled differently.\n */\n private writtenDocs: Set</* path= */ string> = new Set();\n\n constructor(private datastore: Datastore) {}\n\n async lookup(keys: DocumentKey[]): Promise<Document[]> {\n this.ensureCommitNotCalled();\n\n if (this.mutations.length > 0) {\n this.lastTransactionError = new FirestoreError(\n Code.INVALID_ARGUMENT,\n 'Firestore transactions require all reads to be executed before all writes.'\n );\n throw this.lastTransactionError;\n }\n const docs = await invokeBatchGetDocumentsRpc(this.datastore, keys);\n docs.forEach(doc => this.recordVersion(doc));\n return docs;\n }\n\n set(key: DocumentKey, data: ParsedSetData): void {\n this.write(data.toMutation(key, this.precondition(key)));\n this.writtenDocs.add(key.toString());\n }\n\n update(key: DocumentKey, data: ParsedUpdateData): void {\n try {\n this.write(data.toMutation(key, this.preconditionForUpdate(key)));\n } catch (e) {\n this.lastTransactionError = e as FirestoreError | null;\n }\n this.writtenDocs.add(key.toString());\n }\n\n delete(key: DocumentKey): void {\n this.write(new DeleteMutation(key, this.precondition(key)));\n this.writtenDocs.add(key.toString());\n }\n\n async commit(): Promise<void> {\n this.ensureCommitNotCalled();\n\n if (this.lastTransactionError) {\n throw this.lastTransactionError;\n }\n const unwritten = this.readVersions;\n // For each mutation, note that the doc was written.\n this.mutations.forEach(mutation => {\n unwritten.delete(mutation.key.toString());\n });\n // For each document that was read but not written to, we want to perform\n // a `verify` operation.\n unwritten.forEach((_, path) => {\n const key = DocumentKey.fromPath(path);\n this.mutations.push(new VerifyMutation(key, this.precondition(key)));\n });\n await invokeCommitRpc(this.datastore, this.mutations);\n this.committed = true;\n }\n\n private recordVersion(doc: Document): void {\n let docVersion: SnapshotVersion;\n\n if (doc.isFoundDocument()) {\n docVersion = doc.version;\n } else if (doc.isNoDocument()) {\n // Represent a deleted doc using SnapshotVersion.min().\n docVersion = SnapshotVersion.min();\n } else {\n throw fail(0xc542, 'Document in a transaction was a ', {\n documentName: doc.constructor.name\n });\n }\n\n const existingVersion = this.readVersions.get(doc.key.toString());\n if (existingVersion) {\n if (!docVersion.isEqual(existingVersion)) {\n // This transaction will fail no matter what.\n throw new FirestoreError(\n Code.ABORTED,\n 'Document version changed between two reads.'\n );\n }\n } else {\n this.readVersions.set(doc.key.toString(), docVersion);\n }\n }\n\n /**\n * Returns the version of this document when it was read in this transaction,\n * as a precondition, or no precondition if it was not read.\n */\n private precondition(key: DocumentKey): Precondition {\n const version = this.readVersions.get(key.toString());\n if (!this.writtenDocs.has(key.toString()) && version) {\n if (version.isEqual(SnapshotVersion.min())) {\n return Precondition.exists(false);\n } else {\n return Precondition.updateTime(version);\n }\n } else {\n return Precondition.none();\n }\n }\n\n /**\n * Returns the precondition for a document if the operation is an update.\n */\n private preconditionForUpdate(key: DocumentKey): Precondition {\n const version = this.readVersions.get(key.toString());\n // The first time a document is written, we want to take into account the\n // read time and existence\n if (!this.writtenDocs.has(key.toString()) && version) {\n if (version.isEqual(SnapshotVersion.min())) {\n // The document doesn't exist, so fail the transaction.\n\n // This has to be validated locally because you can't send a\n // precondition that a document does not exist without changing the\n // semantics of the backend write to be an insert. This is the reverse\n // of what we want, since we want to assert that the document doesn't\n // exist but then send the update and have it fail. Since we can't\n // express that to the backend, we have to validate locally.\n\n // Note: this can change once we can send separate verify writes in the\n // transaction.\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n \"Can't update a document that doesn't exist.\"\n );\n }\n // Document exists, base precondition on document update time.\n return Precondition.updateTime(version);\n } else {\n // Document was not read, so we just use the preconditions for a blind\n // update.\n return Precondition.exists(true);\n }\n }\n\n private write(mutation: Mutation): void {\n this.ensureCommitNotCalled();\n this.mutations.push(mutation);\n }\n\n private ensureCommitNotCalled(): void {\n debugAssert(\n !this.committed,\n 'A transaction object cannot be used after its update callback has been invoked.'\n );\n }\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ExponentialBackoff } from '../remote/backoff';\nimport { Datastore } from '../remote/datastore';\nimport { isPermanentError } from '../remote/rpc_error';\nimport { AsyncQueue, TimerId } from '../util/async_queue';\nimport { FirestoreError } from '../util/error';\nimport { Deferred } from '../util/promise';\nimport { isNullOrUndefined } from '../util/types';\n\nimport { Transaction } from './transaction';\nimport { TransactionOptions } from './transaction_options';\n\n/**\n * TransactionRunner encapsulates the logic needed to run and retry transactions\n * with backoff.\n */\nexport class TransactionRunner<T> {\n private attemptsRemaining: number;\n private backoff: ExponentialBackoff;\n\n constructor(\n private readonly asyncQueue: AsyncQueue,\n private readonly datastore: Datastore,\n private readonly options: TransactionOptions,\n private readonly updateFunction: (transaction: Transaction) => Promise<T>,\n private readonly deferred: Deferred<T>\n ) {\n this.attemptsRemaining = options.maxAttempts;\n this.backoff = new ExponentialBackoff(\n this.asyncQueue,\n TimerId.TransactionRetry\n );\n }\n\n /** Runs the transaction and sets the result on deferred. */\n run(): void {\n this.attemptsRemaining -= 1;\n this.runWithBackOff();\n }\n\n private runWithBackOff(): void {\n this.backoff.backoffAndRun(async () => {\n const transaction = new Transaction(this.datastore);\n const userPromise = this.tryRunUpdateFunction(transaction);\n if (userPromise) {\n userPromise\n .then(result => {\n this.asyncQueue.enqueueAndForget(() => {\n return transaction\n .commit()\n .then(() => {\n this.deferred.resolve(result);\n })\n .catch(commitError => {\n this.handleTransactionError(commitError);\n });\n });\n })\n .catch(userPromiseError => {\n this.handleTransactionError(userPromiseError);\n });\n }\n });\n }\n\n private tryRunUpdateFunction(transaction: Transaction): Promise<T> | null {\n try {\n const userPromise = this.updateFunction(transaction);\n if (\n isNullOrUndefined(userPromise) ||\n !userPromise.catch ||\n !userPromise.then\n ) {\n this.deferred.reject(\n Error('Transaction callback must return a Promise')\n );\n return null;\n }\n return userPromise;\n } catch (error) {\n // Do not retry errors thrown by user provided updateFunction.\n this.deferred.reject(error as Error);\n return null;\n }\n }\n\n private handleTransactionError(error: Error): void {\n if (this.attemptsRemaining > 0 && this.isRetryableTransactionError(error)) {\n this.attemptsRemaining -= 1;\n this.asyncQueue.enqueueAndForget(() => {\n this.runWithBackOff();\n return Promise.resolve();\n });\n } else {\n this.deferred.reject(error);\n }\n }\n\n private isRetryableTransactionError(error: Error | undefined): boolean {\n if (error?.name === 'FirebaseError') {\n // In transactions, the backend will fail outdated reads with FAILED_PRECONDITION and\n // non-matching document versions with ABORTED. These errors should be retried.\n const code = (error as FirestoreError).code;\n return (\n code === 'aborted' ||\n code === 'failed-precondition' ||\n code === 'already-exists' ||\n !isPermanentError(code)\n );\n }\n return false;\n }\n}\n","/**\n * @license\n * Copyright 2017 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { isIndexedDbTransactionError } from '../local/simple_db';\n\nimport { Code, FirestoreError } from './error';\nimport { logError } from './log';\nimport { Deferred } from './promise';\n\nconst LOG_TAG = 'AsyncQueue';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype TimerHandle = any;\n\n/**\n * Wellknown \"timer\" IDs used when scheduling delayed operations on the\n * AsyncQueue. These IDs can then be used from tests to check for the presence\n * of operations or to run them early.\n *\n * The string values are used when encoding these timer IDs in JSON spec tests.\n */\nexport const enum TimerId {\n /** All can be used with runDelayedOperationsEarly() to run all timers. */\n All = 'all',\n\n /**\n * The following 5 timers are used in persistent_stream.ts for the listen and\n * write streams. The \"Idle\" timer is used to close the stream due to\n * inactivity. The \"ConnectionBackoff\" timer is used to restart a stream once\n * the appropriate backoff delay has elapsed. The health check is used to mark\n * a stream healthy if it has not received an error during its initial setup.\n */\n ListenStreamIdle = 'listen_stream_idle',\n ListenStreamConnectionBackoff = 'listen_stream_connection_backoff',\n WriteStreamIdle = 'write_stream_idle',\n WriteStreamConnectionBackoff = 'write_stream_connection_backoff',\n HealthCheckTimeout = 'health_check_timeout',\n\n /**\n * A timer used in online_state_tracker.ts to transition from\n * OnlineState.Unknown to Offline after a set timeout, rather than waiting\n * indefinitely for success or failure.\n */\n OnlineStateTimeout = 'online_state_timeout',\n\n /**\n * A timer used to update the client metadata in IndexedDb, which is used\n * to determine the primary leaseholder.\n */\n ClientMetadataRefresh = 'client_metadata_refresh',\n\n /** A timer used to periodically attempt LRU Garbage collection */\n LruGarbageCollection = 'lru_garbage_collection',\n\n /**\n * A timer used to retry transactions. Since there can be multiple concurrent\n * transactions, multiple of these may be in the queue at a given time.\n */\n TransactionRetry = 'transaction_retry',\n\n /**\n * A timer used to retry operations scheduled via retryable AsyncQueue\n * operations.\n */\n AsyncQueueRetry = 'async_queue_retry',\n\n /**\n * A timer used to periodically attempt index backfill.\n */\n IndexBackfill = 'index_backfill'\n}\n\n/**\n * Represents an operation scheduled to be run in the future on an AsyncQueue.\n *\n * It is created via DelayedOperation.createAndSchedule().\n *\n * Supports cancellation (via cancel()) and early execution (via skipDelay()).\n *\n * Note: We implement `PromiseLike` instead of `Promise`, as the `Promise` type\n * in newer versions of TypeScript defines `finally`, which is not available in\n * IE.\n */\nexport class DelayedOperation<T extends unknown> implements PromiseLike<T> {\n // handle for use with clearTimeout(), or null if the operation has been\n // executed or canceled already.\n private timerHandle: TimerHandle | null;\n\n private readonly deferred = new Deferred<T>();\n\n private constructor(\n private readonly asyncQueue: AsyncQueue,\n readonly timerId: TimerId,\n readonly targetTimeMs: number,\n private readonly op: () => Promise<T>,\n private readonly removalCallback: (op: DelayedOperation<T>) => void\n ) {\n // It's normal for the deferred promise to be canceled (due to cancellation)\n // and so we attach a dummy catch callback to avoid\n // 'UnhandledPromiseRejectionWarning' log spam.\n this.deferred.promise.catch(err => {});\n }\n\n get promise(): Promise<T> {\n return this.deferred.promise;\n }\n\n /**\n * Creates and returns a DelayedOperation that has been scheduled to be\n * executed on the provided asyncQueue after the provided delayMs.\n *\n * @param asyncQueue - The queue to schedule the operation on.\n * @param id - A Timer ID identifying the type of operation this is.\n * @param delayMs - The delay (ms) before the operation should be scheduled.\n * @param op - The operation to run.\n * @param removalCallback - A callback to be called synchronously once the\n * operation is executed or canceled, notifying the AsyncQueue to remove it\n * from its delayedOperations list.\n * PORTING NOTE: This exists to prevent making removeDelayedOperation() and\n * the DelayedOperation class public.\n */\n static createAndSchedule<R extends unknown>(\n asyncQueue: AsyncQueue,\n timerId: TimerId,\n delayMs: number,\n op: () => Promise<R>,\n removalCallback: (op: DelayedOperation<R>) => void\n ): DelayedOperation<R> {\n const targetTime = Date.now() + delayMs;\n const delayedOp = new DelayedOperation(\n asyncQueue,\n timerId,\n targetTime,\n op,\n removalCallback\n );\n delayedOp.start(delayMs);\n return delayedOp;\n }\n\n /**\n * Starts the timer. This is called immediately after construction by\n * createAndSchedule().\n */\n private start(delayMs: number): void {\n this.timerHandle = setTimeout(() => this.handleDelayElapsed(), delayMs);\n }\n\n /**\n * Queues the operation to run immediately (if it hasn't already been run or\n * canceled).\n */\n skipDelay(): void {\n return this.handleDelayElapsed();\n }\n\n /**\n * Cancels the operation if it hasn't already been executed or canceled. The\n * promise will be rejected.\n *\n * As long as the operation has not yet been run, calling cancel() provides a\n * guarantee that the operation will not be run.\n */\n cancel(reason?: string): void {\n if (this.timerHandle !== null) {\n this.clearTimeout();\n this.deferred.reject(\n new FirestoreError(\n Code.CANCELLED,\n 'Operation cancelled' + (reason ? ': ' + reason : '')\n )\n );\n }\n }\n\n then = this.deferred.promise.then.bind(this.deferred.promise);\n\n private handleDelayElapsed(): void {\n this.asyncQueue.enqueueAndForget(() => {\n if (this.timerHandle !== null) {\n this.clearTimeout();\n return this.op().then(result => {\n return this.deferred.resolve(result);\n });\n } else {\n return Promise.resolve();\n }\n });\n }\n\n private clearTimeout(): void {\n if (this.timerHandle !== null) {\n this.removalCallback(this);\n clearTimeout(this.timerHandle);\n this.timerHandle = null;\n }\n }\n}\n\nexport interface AsyncQueue {\n // Is this AsyncQueue being shut down? If true, this instance will not enqueue\n // any new operations, Promises from enqueue requests will not resolve.\n readonly isShuttingDown: boolean;\n\n /**\n * Adds a new operation to the queue without waiting for it to complete (i.e.\n * we ignore the Promise result).\n */\n enqueueAndForget<T extends unknown>(op: () => Promise<T>): void;\n\n /**\n * Regardless if the queue has initialized shutdown, adds a new operation to the\n * queue without waiting for it to complete (i.e. we ignore the Promise result).\n */\n enqueueAndForgetEvenWhileRestricted<T extends unknown>(\n op: () => Promise<T>\n ): void;\n\n /**\n * Initialize the shutdown of this queue. Once this method is called, the\n * only possible way to request running an operation is through\n * `enqueueEvenWhileRestricted()`.\n *\n * @param purgeExistingTasks - Whether already enqueued tasked should be\n * rejected (unless enqueued with `enqueueEvenWhileRestricted()`). Defaults\n * to false.\n */\n enterRestrictedMode(purgeExistingTasks?: boolean): void;\n\n /**\n * Adds a new operation to the queue. Returns a promise that will be resolved\n * when the promise returned by the new operation is (with its value).\n */\n enqueue<T extends unknown>(op: () => Promise<T>): Promise<T>;\n\n /**\n * Enqueue a retryable operation.\n *\n * A retryable operation is rescheduled with backoff if it fails with a\n * IndexedDbTransactionError (the error type used by SimpleDb). All\n * retryable operations are executed in order and only run if all prior\n * operations were retried successfully.\n */\n enqueueRetryable(op: () => Promise<void>): void;\n\n /**\n * Schedules an operation to be queued on the AsyncQueue once the specified\n * `delayMs` has elapsed. The returned DelayedOperation can be used to cancel\n * or fast-forward the operation prior to its running.\n */\n enqueueAfterDelay<T extends unknown>(\n timerId: TimerId,\n delayMs: number,\n op: () => Promise<T>\n ): DelayedOperation<T>;\n\n /**\n * Verifies there's an operation currently in-progress on the AsyncQueue.\n * Unfortunately we can't verify that the running code is in the promise chain\n * of that operation, so this isn't a foolproof check, but it should be enough\n * to catch some bugs.\n */\n verifyOperationInProgress(): void;\n}\n\n/**\n * Returns a FirestoreError that can be surfaced to the user if the provided\n * error is an IndexedDbTransactionError. Re-throws the error otherwise.\n */\nexport function wrapInUserErrorIfRecoverable(\n e: Error,\n msg: string\n): FirestoreError {\n logError(LOG_TAG, `${msg}: ${e}`);\n if (isIndexedDbTransactionError(e)) {\n return new FirestoreError(Code.UNAVAILABLE, `${msg}: ${e}`);\n } else {\n throw e;\n }\n}\n","/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { isIndexedDbTransactionError } from '../local/simple_db';\nimport { getDocument } from '../platform/dom';\nimport { ExponentialBackoff } from '../remote/backoff';\n\nimport { debugAssert, fail } from './assert';\nimport { AsyncQueue, DelayedOperation, TimerId } from './async_queue';\nimport { FirestoreError } from './error';\nimport { logDebug, logError } from './log';\nimport { Deferred } from './promise';\n\nconst LOG_TAG = 'AsyncQueue';\n\nexport class AsyncQueueImpl implements AsyncQueue {\n // The last promise in the queue.\n private tail: Promise<unknown>;\n\n // A list of retryable operations. Retryable operations are run in order and\n // retried with backoff.\n private retryableOps: Array<() => Promise<void>> = [];\n\n // Is this AsyncQueue being shut down? Once it is set to true, it will not\n // be changed again.\n private _isShuttingDown: boolean = false;\n\n // Operations scheduled to be queued in the future. Operations are\n // automatically removed after they are run or canceled.\n private delayedOperations: Array<DelayedOperation<unknown>> = [];\n\n // visible for testing\n failure: FirestoreError | null = null;\n\n // Flag set while there's an outstanding AsyncQueue operation, used for\n // assertion sanity-checks.\n private operationInProgress = false;\n\n // Enabled during shutdown on Safari to prevent future access to IndexedDB.\n private skipNonRestrictedTasks = false;\n\n // List of TimerIds to fast-forward delays for.\n private timerIdsToSkip: TimerId[] = [];\n\n // Backoff timer used to schedule retries for retryable operations\n private backoff = new ExponentialBackoff(this, TimerId.AsyncQueueRetry);\n\n // Visibility handler that triggers an immediate retry of all retryable\n // operations. Meant to speed up recovery when we regain file system access\n // after page comes into foreground.\n private visibilityHandler: () => void = () => {\n const document = getDocument();\n if (document) {\n logDebug(\n LOG_TAG,\n 'Visibility state changed to ' + document.visibilityState\n );\n }\n this.backoff.skipBackoff();\n };\n\n constructor(tail: Promise<unknown> = Promise.resolve()) {\n this.tail = tail;\n const document = getDocument();\n if (document && typeof document.addEventListener === 'function') {\n document.addEventListener('visibilitychange', this.visibilityHandler);\n }\n }\n\n get isShuttingDown(): boolean {\n return this._isShuttingDown;\n }\n\n /**\n * Adds a new operation to the queue without waiting for it to complete (i.e.\n * we ignore the Promise result).\n */\n enqueueAndForget<T extends unknown>(op: () => Promise<T>): void {\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n this.enqueue(op);\n }\n\n enqueueAndForgetEvenWhileRestricted<T extends unknown>(\n op: () => Promise<T>\n ): void {\n this.verifyNotFailed();\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n this.enqueueInternal(op);\n }\n\n enterRestrictedMode(purgeExistingTasks?: boolean): void {\n if (!this._isShuttingDown) {\n this._isShuttingDown = true;\n this.skipNonRestrictedTasks = purgeExistingTasks || false;\n const document = getDocument();\n if (document && typeof document.removeEventListener === 'function') {\n document.removeEventListener(\n 'visibilitychange',\n this.visibilityHandler\n );\n }\n }\n }\n\n enqueue<T extends unknown>(op: () => Promise<T>): Promise<T> {\n this.verifyNotFailed();\n if (this._isShuttingDown) {\n // Return a Promise which never resolves.\n return new Promise<T>(() => {});\n }\n\n // Create a deferred Promise that we can return to the callee. This\n // allows us to return a \"hanging Promise\" only to the callee and still\n // advance the queue even when the operation is not run.\n const task = new Deferred<T>();\n return this.enqueueInternal<unknown>(() => {\n if (this._isShuttingDown && this.skipNonRestrictedTasks) {\n // We do not resolve 'task'\n return Promise.resolve();\n }\n\n op().then(task.resolve, task.reject);\n return task.promise;\n }).then(() => task.promise);\n }\n\n enqueueRetryable(op: () => Promise<void>): void {\n this.enqueueAndForget(() => {\n this.retryableOps.push(op);\n return this.retryNextOp();\n });\n }\n\n /**\n * Runs the next operation from the retryable queue. If the operation fails,\n * reschedules with backoff.\n */\n private async retryNextOp(): Promise<void> {\n if (this.retryableOps.length === 0) {\n return;\n }\n\n try {\n await this.retryableOps[0]();\n this.retryableOps.shift();\n this.backoff.reset();\n } catch (e) {\n if (isIndexedDbTransactionError(e as Error)) {\n logDebug(LOG_TAG, 'Operation failed with retryable error: ' + e);\n } else {\n throw e; // Failure will be handled by AsyncQueue\n }\n }\n\n if (this.retryableOps.length > 0) {\n // If there are additional operations, we re-schedule `retryNextOp()`.\n // This is necessary to run retryable operations that failed during\n // their initial attempt since we don't know whether they are already\n // enqueued. If, for example, `op1`, `op2`, `op3` are enqueued and `op1`\n // needs to be re-run, we will run `op1`, `op1`, `op2` using the\n // already enqueued calls to `retryNextOp()`. `op3()` will then run in the\n // call scheduled here.\n // Since `backoffAndRun()` cancels an existing backoff and schedules a\n // new backoff on every call, there is only ever a single additional\n // operation in the queue.\n this.backoff.backoffAndRun(() => this.retryNextOp());\n }\n }\n\n private enqueueInternal<T extends unknown>(op: () => Promise<T>): Promise<T> {\n const newTail = this.tail.then(() => {\n this.operationInProgress = true;\n return op()\n .catch((error: FirestoreError) => {\n this.failure = error;\n this.operationInProgress = false;\n const message = getMessageOrStack(error);\n logError('INTERNAL UNHANDLED ERROR: ', message);\n\n // Re-throw the error so that this.tail becomes a rejected Promise and\n // all further attempts to chain (via .then) will just short-circuit\n // and return the rejected Promise.\n throw error;\n })\n .then(result => {\n this.operationInProgress = false;\n return result;\n });\n });\n this.tail = newTail;\n return newTail;\n }\n\n enqueueAfterDelay<T extends unknown>(\n timerId: TimerId,\n delayMs: number,\n op: () => Promise<T>\n ): DelayedOperation<T> {\n this.verifyNotFailed();\n\n debugAssert(\n delayMs >= 0,\n `Attempted to schedule an operation with a negative delay of ${delayMs}`\n );\n\n // Fast-forward delays for timerIds that have been overridden.\n if (this.timerIdsToSkip.indexOf(timerId) > -1) {\n delayMs = 0;\n }\n\n const delayedOp = DelayedOperation.createAndSchedule<T>(\n this,\n timerId,\n delayMs,\n op,\n removedOp =>\n this.removeDelayedOperation(removedOp as DelayedOperation<unknown>)\n );\n this.delayedOperations.push(delayedOp as DelayedOperation<unknown>);\n return delayedOp;\n }\n\n private verifyNotFailed(): void {\n if (this.failure) {\n fail(0xb815, 'AsyncQueue is already failed', {\n messageOrStack: getMessageOrStack(this.failure)\n });\n }\n }\n\n verifyOperationInProgress(): void {\n debugAssert(\n this.operationInProgress,\n 'verifyOpInProgress() called when no op in progress on this queue.'\n );\n }\n\n /**\n * Waits until all currently queued tasks are finished executing. Delayed\n * operations are not run.\n */\n async drain(): Promise<void> {\n // Operations in the queue prior to draining may have enqueued additional\n // operations. Keep draining the queue until the tail is no longer advanced,\n // which indicates that no more new operations were enqueued and that all\n // operations were executed.\n let currentTail: Promise<unknown>;\n do {\n currentTail = this.tail;\n await currentTail;\n } while (currentTail !== this.tail);\n }\n\n /**\n * For Tests: Determine if a delayed operation with a particular TimerId\n * exists.\n */\n containsDelayedOperation(timerId: TimerId): boolean {\n for (const op of this.delayedOperations) {\n if (op.timerId === timerId) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * For Tests: Runs some or all delayed operations early.\n *\n * @param lastTimerId - Delayed operations up to and including this TimerId\n * will be drained. Pass TimerId.All to run all delayed operations.\n * @returns a Promise that resolves once all operations have been run.\n */\n runAllDelayedOperationsUntil(lastTimerId: TimerId): Promise<void> {\n // Note that draining may generate more delayed ops, so we do that first.\n return this.drain().then(() => {\n // Run ops in the same order they'd run if they ran naturally.\n /* eslint-disable-next-line @typescript-eslint/no-floating-promises */\n this.delayedOperations.sort((a, b) => a.targetTimeMs - b.targetTimeMs);\n\n for (const op of this.delayedOperations) {\n op.skipDelay();\n if (lastTimerId !== TimerId.All && op.timerId === lastTimerId) {\n break;\n }\n }\n\n return this.drain();\n });\n }\n\n /**\n * For Tests: Skip all subsequent delays for a timer id.\n */\n skipDelaysForTimerId(timerId: TimerId): void {\n this.timerIdsToSkip.push(timerId);\n }\n\n /** Called once a DelayedOperation is run or canceled. */\n private removeDelayedOperation(op: DelayedOperation<unknown>): void {\n // NOTE: indexOf / slice are O(n), but delayedOperations is expected to be small.\n const index = this.delayedOperations.indexOf(op);\n debugAssert(index >= 0, 'Delayed operation not found.');\n /* eslint-disable-next-line @typescript-eslint/no-floating-promises */\n this.delayedOperations.splice(index, 1);\n }\n}\n\nexport function newAsyncQueue(): AsyncQueue {\n return new AsyncQueueImpl();\n}\n\n/**\n * Chrome includes Error.message in Error.stack. Other browsers do not.\n * This returns expected output of message + stack when available.\n * @param error - Error or FirestoreError\n */\nfunction getMessageOrStack(error: Error): string {\n let message = error.message || '';\n if (error.stack) {\n if (error.stack.includes(error.message)) {\n message = error.stack;\n } else {\n message = error.message + '\\n' + error.stack;\n }\n }\n return message;\n}\n","/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { getModularInstance } from '@firebase/util';\n\nimport { Transaction as InternalTransaction } from '../core/transaction';\nimport {\n DEFAULT_TRANSACTION_OPTIONS,\n TransactionOptions as TransactionOptionsInternal,\n validateTransactionOptions\n} from '../core/transaction_options';\nimport { TransactionRunner } from '../core/transaction_runner';\nimport { fail } from '../util/assert';\nimport { newAsyncQueue } from '../util/async_queue_impl';\nimport { cast } from '../util/input_validation';\nimport { Deferred } from '../util/promise';\n\nimport { getDatastore } from './components';\nimport { Firestore } from './database';\nimport { FieldPath } from './field_path';\nimport {\n DocumentData,\n DocumentReference,\n PartialWithFieldValue,\n SetOptions,\n UpdateData,\n WithFieldValue\n} from './reference';\nimport {\n applyFirestoreDataConverter,\n LiteUserDataWriter\n} from './reference_impl';\nimport { DocumentSnapshot } from './snapshot';\nimport { TransactionOptions } from './transaction_options';\nimport {\n newUserDataReader,\n parseSetData,\n parseUpdateData,\n parseUpdateVarargs,\n UserDataReader\n} from './user_data_reader';\nimport { validateReference } from './write_batch';\n\n// TODO(mrschmidt) Consider using `BaseTransaction` as the base class in the\n// legacy SDK.\n\n/**\n * A reference to a transaction.\n *\n * The `Transaction` object passed to a transaction's `updateFunction` provides\n * the methods to read and write data within the transaction context. See\n * {@link runTransaction}.\n */\nexport class Transaction {\n // This is the tree-shakeable version of the Transaction class used in the\n // legacy SDK. The class is a close copy but takes different input and output\n // types. The firestore-exp SDK further extends this class to return its API\n // type.\n\n private readonly _dataReader: UserDataReader;\n\n /** @hideconstructor */\n constructor(\n protected readonly _firestore: Firestore,\n private readonly _transaction: InternalTransaction\n ) {\n this._dataReader = newUserDataReader(_firestore);\n }\n\n /**\n * Reads the document referenced by the provided {@link DocumentReference}.\n *\n * @param documentRef - A reference to the document to be read.\n * @returns A `DocumentSnapshot` with the read data.\n */\n get<AppModelType, DbModelType extends DocumentData>(\n documentRef: DocumentReference<AppModelType, DbModelType>\n ): Promise<DocumentSnapshot<AppModelType, DbModelType>> {\n const ref = validateReference(documentRef, this._firestore);\n const userDataWriter = new LiteUserDataWriter(this._firestore);\n return this._transaction.lookup([ref._key]).then(docs => {\n if (!docs || docs.length !== 1) {\n return fail(0x5de9, 'Mismatch in docs returned from document lookup.');\n }\n const doc = docs[0];\n if (doc.isFoundDocument()) {\n return new DocumentSnapshot<AppModelType, DbModelType>(\n this._firestore,\n userDataWriter,\n doc.key,\n doc,\n ref.converter\n );\n } else if (doc.isNoDocument()) {\n return new DocumentSnapshot<AppModelType, DbModelType>(\n this._firestore,\n userDataWriter,\n ref._key,\n null,\n ref.converter\n );\n } else {\n throw fail(\n 0x4801,\n 'BatchGetDocumentsRequest returned unexpected document',\n {\n doc\n }\n );\n }\n });\n }\n\n /**\n * Writes to the document referred to by the provided {@link\n * DocumentReference}. If the document does not exist yet, it will be created.\n *\n * @param documentRef - A reference to the document to be set.\n * @param data - An object of the fields and values for the document.\n * @throws Error - If the provided input is not a valid Firestore document.\n * @returns This `Transaction` instance. Used for chaining method calls.\n */\n set<AppModelType, DbModelType extends DocumentData>(\n documentRef: DocumentReference<AppModelType, DbModelType>,\n data: WithFieldValue<AppModelType>\n ): this;\n /**\n * Writes to the document referred to by the provided {@link\n * DocumentReference}. If the document does not exist yet, it will be created.\n * If you provide `merge` or `mergeFields`, the provided data can be merged\n * into an existing document.\n *\n * @param documentRef - A reference to the document to be set.\n * @param data - An object of the fields and values for the document.\n * @param options - An object to configure the set behavior.\n * @throws Error - If the provided input is not a valid Firestore document.\n * @returns This `Transaction` instance. Used for chaining method calls.\n */\n set<AppModelType, DbModelType extends DocumentData>(\n documentRef: DocumentReference<AppModelType, DbModelType>,\n data: PartialWithFieldValue<AppModelType>,\n options: SetOptions\n ): this;\n set<AppModelType, DbModelType extends DocumentData>(\n documentRef: DocumentReference<AppModelType, DbModelType>,\n value: PartialWithFieldValue<AppModelType>,\n options?: SetOptions\n ): this {\n const ref = validateReference(documentRef, this._firestore);\n const convertedValue = applyFirestoreDataConverter(\n ref.converter,\n value,\n options\n );\n const parsed = parseSetData(\n this._dataReader,\n 'Transaction.set',\n ref._key,\n convertedValue,\n ref.converter !== null,\n options\n );\n this._transaction.set(ref._key, parsed);\n return this;\n }\n\n /**\n * Updates fields in the document referred to by the provided {@link\n * DocumentReference}. The update will fail if applied to a document that does\n * not exist.\n *\n * @param documentRef - A reference to the document to be updated.\n * @param data - An object containing the fields and values with which to\n * update the document. Fields can contain dots to reference nested fields\n * within the document.\n * @throws Error - If the provided input is not valid Firestore data.\n * @returns This `Transaction` instance. Used for chaining method calls.\n */\n update<AppModelType, DbModelType extends DocumentData>(\n documentRef: DocumentReference<AppModelType, DbModelType>,\n data: UpdateData<DbModelType>\n ): this;\n /**\n * Updates fields in the document referred to by the provided {@link\n * DocumentReference}. The update will fail if applied to a document that does\n * not exist.\n *\n * Nested fields can be updated by providing dot-separated field path\n * strings or by providing `FieldPath` objects.\n *\n * @param documentRef - A reference to the document to be updated.\n * @param field - The first field to update.\n * @param value - The first value.\n * @param moreFieldsAndValues - Additional key/value pairs.\n * @throws Error - If the provided input is not valid Firestore data.\n * @returns This `Transaction` instance. Used for chaining method calls.\n */\n update<AppModelType, DbModelType extends DocumentData>(\n documentRef: DocumentReference<AppModelType, DbModelType>,\n field: string | FieldPath,\n value: unknown,\n ...moreFieldsAndValues: unknown[]\n ): this;\n update<AppModelType, DbModelType extends DocumentData>(\n documentRef: DocumentReference<AppModelType, DbModelType>,\n fieldOrUpdateData: string | FieldPath | UpdateData<DbModelType>,\n value?: unknown,\n ...moreFieldsAndValues: unknown[]\n ): this {\n const ref = validateReference(documentRef, this._firestore);\n\n // For Compat types, we have to \"extract\" the underlying types before\n // performing validation.\n fieldOrUpdateData = getModularInstance(fieldOrUpdateData);\n\n let parsed;\n if (\n typeof fieldOrUpdateData === 'string' ||\n fieldOrUpdateData instanceof FieldPath\n ) {\n parsed = parseUpdateVarargs(\n this._dataReader,\n 'Transaction.update',\n ref._key,\n fieldOrUpdateData,\n value,\n moreFieldsAndValues\n );\n } else {\n parsed = parseUpdateData(\n this._dataReader,\n 'Transaction.update',\n ref._key,\n fieldOrUpdateData\n );\n }\n\n this._transaction.update(ref._key, parsed);\n return this;\n }\n\n /**\n * Deletes the document referred to by the provided {@link DocumentReference}.\n *\n * @param documentRef - A reference to the document to be deleted.\n * @returns This `Transaction` instance. Used for chaining method calls.\n */\n delete<AppModelType, DbModelType extends DocumentData>(\n documentRef: DocumentReference<AppModelType, DbModelType>\n ): this {\n const ref = validateReference(documentRef, this._firestore);\n this._transaction.delete(ref._key);\n return this;\n }\n}\n\n/**\n * Executes the given `updateFunction` and then attempts to commit the changes\n * applied within the transaction. If any document read within the transaction\n * has changed, Cloud Firestore retries the `updateFunction`. If it fails to\n * commit after 5 attempts, the transaction fails.\n *\n * The maximum number of writes allowed in a single transaction is 500.\n *\n * @param firestore - A reference to the Firestore database to run this\n * transaction against.\n * @param updateFunction - The function to execute within the transaction\n * context.\n * @param options - An options object to configure maximum number of attempts to\n * commit.\n * @returns If the transaction completed successfully or was explicitly aborted\n * (the `updateFunction` returned a failed promise), the promise returned by the\n * `updateFunction `is returned here. Otherwise, if the transaction failed, a\n * rejected promise with the corresponding failure error is returned.\n */\nexport function runTransaction<T>(\n firestore: Firestore,\n updateFunction: (transaction: Transaction) => Promise<T>,\n options?: TransactionOptions\n): Promise<T> {\n firestore = cast(firestore, Firestore);\n const datastore = getDatastore(firestore);\n const optionsWithDefaults: TransactionOptionsInternal = {\n ...DEFAULT_TRANSACTION_OPTIONS,\n ...options\n };\n validateTransactionOptions(optionsWithDefaults);\n const deferred = new Deferred<T>();\n new TransactionRunner<T>(\n newAsyncQueue(),\n datastore,\n optionsWithDefaults,\n internalTransaction =>\n updateFunction(new Transaction(firestore, internalTransaction)),\n deferred\n ).run();\n return deferred.promise;\n}\n","/**\n * Firestore Lite\n *\n * @remarks Firestore Lite is a small online-only SDK that allows read\n * and write access to your Firestore database. All operations connect\n * directly to the backend, and `onSnapshot()` APIs are not supported.\n * @packageDocumentation\n */\n\n/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { registerFirestore } from './register';\nregisterFirestore();\n\nexport {\n aggregateQuerySnapshotEqual,\n getCount,\n getAggregate,\n count,\n sum,\n average,\n aggregateFieldEqual\n} from '../src/lite-api/aggregate';\n\nexport {\n AggregateField,\n AggregateFieldType,\n AggregateSpec,\n AggregateSpecData,\n AggregateQuerySnapshot,\n AggregateType\n} from '../src/lite-api/aggregate_types';\n\nexport { FirestoreSettings as Settings } from '../src/lite-api/settings';\n\nexport {\n Firestore as Firestore,\n EmulatorMockTokenOptions,\n initializeFirestore,\n getFirestore,\n terminate,\n connectFirestoreEmulator\n} from '../src/lite-api/database';\n\nexport {\n DocumentData,\n UpdateData,\n WithFieldValue,\n PartialWithFieldValue,\n SetOptions,\n DocumentReference,\n Query,\n CollectionReference,\n collection,\n collectionGroup,\n doc,\n refEqual,\n queryEqual\n} from '../src/lite-api/reference';\n\nexport {\n and,\n endAt,\n endBefore,\n startAt,\n startAfter,\n limit,\n limitToLast,\n where,\n or,\n orderBy,\n query,\n QueryConstraint,\n QueryConstraintType,\n QueryCompositeFilterConstraint,\n QueryFilterConstraint,\n QueryFieldFilterConstraint,\n QueryOrderByConstraint,\n QueryLimitConstraint,\n QueryNonFilterConstraint,\n QueryStartAtConstraint,\n QueryEndAtConstraint,\n OrderByDirection,\n WhereFilterOp\n} from '../src/lite-api/query';\n\nexport {\n addDoc,\n deleteDoc,\n updateDoc,\n setDoc,\n getDoc,\n getDocs\n} from '../src/lite-api/reference_impl';\n\nexport {\n Primitive,\n NestedUpdateFields,\n ChildUpdateFields,\n AddPrefixToKeys,\n UnionToIntersection\n} from '../src/lite-api/types';\n\n// TODO(firestorelite): Add tests when Queries are usable\nexport { FieldPath, documentId } from '../src/lite-api/field_path';\n\n// TODO(firestorelite): Add tests when setDoc() is available\nexport { FieldValue } from '../src/lite-api/field_value';\n\nexport {\n increment,\n arrayRemove,\n arrayUnion,\n serverTimestamp,\n deleteField,\n vector\n} from '../src/lite-api/field_value_impl';\n\nexport {\n FirestoreDataConverter,\n DocumentSnapshot,\n QueryDocumentSnapshot,\n QuerySnapshot,\n snapshotEqual\n} from '../src/lite-api/snapshot';\n\nexport { VectorValue } from '../src/lite-api/vector_value';\n\nexport { WriteBatch, writeBatch } from '../src/lite-api/write_batch';\n\nexport { TransactionOptions } from '../src/lite-api/transaction_options';\n\nexport { Transaction, runTransaction } from '../src/lite-api/transaction';\n\nexport { setLogLevel, LogLevelString as LogLevel } from '../src/util/log';\n\nexport { Bytes } from '../src/lite-api/bytes';\n\nexport { GeoPoint } from '../src/lite-api/geo_point';\n\nexport { Timestamp } from '../src/lite-api/timestamp';\n\nexport { FirestoreErrorCode, FirestoreError } from '../src/util/error';\n"],"names":["LOG_TAG","Transaction"],"mappings":"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"}
geri dön