@firebase/firestore
Version:
The Cloud Firestore component of the Firebase JS SDK.
1 lines • 2.45 MB
Source Map (JSON)
{"version":3,"file":"index.node.mjs","sources":["../src/auth/user.ts","../src/core/version.ts","../src/platform/node/format_json.ts","../src/util/log.ts","../src/util/assert.ts","../src/util/error.ts","../src/util/promise.ts","../src/api/credentials.ts","../src/platform/node/random_bytes.ts","../src/platform/node/text_serializer.ts","../src/util/misc.ts","../src/lite-api/timestamp.ts","../src/core/snapshot_version.ts","../src/model/path.ts","../src/model/document_key.ts","../src/model/field_index.ts","../src/local/persistence_transaction.ts","../src/local/local_store.ts","../src/local/persistence_promise.ts","../src/local/simple_db.ts","../src/local/index_backfiller.ts","../src/core/listen_sequence.ts","../src/local/encoded_resource_path.ts","../src/local/indexeddb_schema_legacy.ts","../src/local/indexeddb_sentinels.ts","../src/local/indexeddb_transaction.ts","../src/util/obj.ts","../src/util/sorted_map.ts","../src/util/sorted_set.ts","../src/model/field_mask.ts","../src/platform/node/base64.ts","../src/util/byte_string.ts","../src/model/normalize.ts","../src/model/server_timestamps.ts","../src/core/database_info.ts","../src/util/types.ts","../src/model/values.ts","../src/model/object_value.ts","../src/model/document.ts","../src/core/bound.ts","../src/core/order_by.ts","../src/core/filter.ts","../src/core/target.ts","../src/core/query.ts","../src/util/obj_map.ts","../src/model/collections.ts","../src/remote/number_serializer.ts","../src/model/transform_operation.ts","../src/model/mutation.ts","../src/model/mutation_batch.ts","../src/model/overlay.ts","../src/remote/existence_filter.ts","../src/remote/rpc_error.ts","../src/util/base64_decode_error.ts","../src/util/testing_hooks_spi.ts","../src/remote/bloom_filter.ts","../src/remote/remote_event.ts","../src/remote/watch_change.ts","../src/remote/serializer.ts","../src/local/target_data.ts","../src/local/local_serializer.ts","../src/local/indexeddb_bundle_cache.ts","../src/local/indexeddb_document_overlay_cache.ts","../src/local/indexeddb_globals_cache.ts","../src/index/firestore_index_value_writer.ts","../src/index/ordered_code_writer.ts","../src/index/index_byte_encoder.ts","../src/index/index_entry.ts","../src/model/target_index_matcher.ts","../src/util/logic_utils.ts","../src/local/memory_index_manager.ts","../src/local/indexeddb_index_manager.ts","../src/local/indexeddb_mutation_batch_impl.ts","../src/local/indexeddb_mutation_queue.ts","../src/core/target_id_generator.ts","../src/local/indexeddb_target_cache.ts","../src/local/lru_garbage_collector.ts","../src/local/lru_garbage_collector_impl.ts","../src/local/indexeddb_lru_delegate_impl.ts","../src/local/remote_document_change_buffer.ts","../src/local/indexeddb_remote_document_cache.ts","../src/local/indexeddb_schema.ts","../src/local/overlayed_document.ts","../src/local/local_documents_view.ts","../src/local/memory_bundle_cache.ts","../src/local/memory_document_overlay_cache.ts","../src/local/memory_globals_cache.ts","../src/local/reference_set.ts","../src/local/memory_mutation_queue.ts","../src/local/memory_remote_document_cache.ts","../src/local/memory_target_cache.ts","../src/local/memory_persistence.ts","../src/local/indexeddb_schema_converter.ts","../src/local/indexeddb_persistence.ts","../src/util/array.ts","../src/local/local_store_impl.ts","../src/local/query_context.ts","../src/local/query_engine.ts","../src/local/shared_client_state_schema.ts","../src/local/shared_client_state.ts","../src/remote/connectivity_monitor_noop.ts","../src/remote/stream_bridge.ts","../src/util/debug_uid.ts","../src/util/node_api.ts","../src/platform/node/grpc_connection.ts","../src/platform/node/load_protos.ts","../src/platform/node/connection.ts","../src/platform/node/dom.ts","../src/platform/node/serializer.ts","../src/remote/backoff.ts","../src/remote/persistent_stream.ts","../src/remote/datastore.ts","../src/remote/online_state_tracker.ts","../src/remote/remote_store.ts","../src/util/async_queue.ts","../src/model/document_set.ts","../src/core/view_snapshot.ts","../src/core/event_manager.ts","../src/local/local_view_changes.ts","../src/core/bundle_impl.ts","../src/core/view.ts","../src/core/sync_engine_impl.ts","../src/core/component_provider.ts","../src/util/byte_stream.ts","../src/util/input_validation.ts","../src/platform/node/byte_stream_reader.ts","../src/util/async_observer.ts","../src/util/bundle_reader.ts","../src/util/bundle_reader_impl.ts","../src/core/transaction.ts","../src/core/transaction_runner.ts","../src/core/firestore_client.ts","../src/api/long_polling_options.ts","../src/lite-api/components.ts","../src/lite-api/settings.ts","../src/lite-api/database.ts","../src/lite-api/reference.ts","../src/util/async_queue_impl.ts","../src/api/bundle.ts","../src/api/database.ts","../src/register.ts","../src/core/aggregate.ts","../src/lite-api/aggregate_types.ts","../src/lite-api/bytes.ts","../src/lite-api/field_path.ts","../src/lite-api/field_value.ts","../src/lite-api/geo_point.ts","../src/lite-api/vector_value.ts","../src/lite-api/user_data_reader.ts","../src/lite-api/snapshot.ts","../src/lite-api/query.ts","../src/lite-api/user_data_writer.ts","../src/lite-api/reference_impl.ts","../src/lite-api/aggregate.ts","../src/api/observer.ts","../src/api/snapshot.ts","../src/api/reference_impl.ts","../src/api/aggregate.ts","../src/api/cache_config.ts","../src/core/transaction_options.ts","../src/lite-api/write_batch.ts","../src/lite-api/transaction.ts","../src/api/transaction.ts","../src/lite-api/field_value_impl.ts","../src/api/write_batch.ts","../src/api/index_configuration.ts","../src/api/persistent_cache_index_manager.ts","../src/remote/internal_serializer.ts","../src/util/testing_hooks.ts","../src/index.node.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\n/**\n * Simple wrapper around a nullable UID. Mostly exists to make code more\n * readable.\n */\nexport class User {\n /** A user with a null UID. */\n static readonly UNAUTHENTICATED = new User(null);\n\n // TODO(mikelehen): Look into getting a proper uid-equivalent for\n // non-FirebaseAuth providers.\n static readonly GOOGLE_CREDENTIALS = new User('google-credentials-uid');\n static readonly FIRST_PARTY = new User('first-party-uid');\n static readonly MOCK_USER = new User('mock-user');\n\n constructor(readonly uid: string | null) {}\n\n isAuthenticated(): boolean {\n return this.uid != null;\n }\n\n /**\n * Returns a key representing this user, suitable for inclusion in a\n * dictionary.\n */\n toKey(): string {\n if (this.isAuthenticated()) {\n return 'uid:' + this.uid;\n } else {\n return 'anonymous-user';\n }\n }\n\n isEqual(otherUser: User): boolean {\n return otherUser.uid === this.uid;\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\n/** The semver (www.semver.org) version of the SDK. */\nimport { version } from '../../../firebase/package.json';\nexport let SDK_VERSION = version;\nexport function setSDKVersion(version: string): void {\n SDK_VERSION = version;\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 { inspect } from 'util';\n\n/** Formats an object as a JSON string, suitable for logging. */\nexport function formatJSON(value: unknown): string {\n // util.inspect() results in much more readable output than JSON.stringify()\n return inspect(value, { depth: 100 });\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 { Logger, LogLevel, LogLevelString } from '@firebase/logger';\n\nimport { SDK_VERSION } from '../core/version';\nimport { formatJSON } from '../platform/format_json';\n\nexport { LogLevel, LogLevelString };\n\nconst logClient = new Logger('@firebase/firestore');\n\n// Helper methods are needed because variables can't be exported as read/write\nexport function getLogLevel(): LogLevel {\n return logClient.logLevel;\n}\n\n/**\n * Sets the verbosity of Cloud Firestore logs (debug, error, or silent).\n *\n * @param logLevel - The verbosity you set for activity and error logging. Can\n * be any of the following values:\n *\n * <ul>\n * <li>`debug` for the most verbose logging level, primarily for\n * debugging.</li>\n * <li>`error` to log errors only.</li>\n * <li><code>`silent` to turn off logging.</li>\n * </ul>\n */\nexport function setLogLevel(logLevel: LogLevelString): void {\n logClient.setLogLevel(logLevel);\n}\n\nexport function logDebug(msg: string, ...obj: unknown[]): void {\n if (logClient.logLevel <= LogLevel.DEBUG) {\n const args = obj.map(argToString);\n logClient.debug(`Firestore (${SDK_VERSION}): ${msg}`, ...args);\n }\n}\n\nexport function logError(msg: string, ...obj: unknown[]): void {\n if (logClient.logLevel <= LogLevel.ERROR) {\n const args = obj.map(argToString);\n logClient.error(`Firestore (${SDK_VERSION}): ${msg}`, ...args);\n }\n}\n\n/**\n * @internal\n */\nexport function logWarn(msg: string, ...obj: unknown[]): void {\n if (logClient.logLevel <= LogLevel.WARN) {\n const args = obj.map(argToString);\n logClient.warn(`Firestore (${SDK_VERSION}): ${msg}`, ...args);\n }\n}\n\n/**\n * Converts an additional log parameter to a string representation.\n */\nfunction argToString(obj: unknown): string | unknown {\n if (typeof obj === 'string') {\n return obj;\n } else {\n try {\n return formatJSON(obj);\n } catch (e) {\n // Converting to JSON failed, just log the object directly\n return obj;\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 { SDK_VERSION } from '../core/version';\n\nimport { logError } from './log';\n\n/**\n * Unconditionally fails, throwing an Error with the given message.\n * Messages are stripped in production builds.\n *\n * Returns `never` and can be used in expressions:\n * @example\n * let futureVar = fail('not implemented yet');\n *\n * @param code generate a new unique value with `yarn assertion-id:generate`\n * Search for an existing value using `yarn assertion-id:find X`\n */\nexport function fail(\n code: number,\n message: string,\n context?: Record<string, unknown>\n): never;\n\n/**\n * Unconditionally fails, throwing an Error with the given message.\n * Messages are stripped in production builds.\n *\n * Returns `never` and can be used in expressions:\n * @example\n * let futureVar = fail('not implemented yet');\n *\n * @param id generate a new unique value with `yarn assertion-id:generate`\n * Search for an existing value using `yarn assertion-id:find X`\n */\nexport function fail(id: number, context?: Record<string, unknown>): never;\n\nexport function fail(\n id: number,\n messageOrContext?: string | Record<string, unknown>,\n context?: Record<string, unknown>\n): never {\n let message = 'Unexpected state';\n if (typeof messageOrContext === 'string') {\n message = messageOrContext;\n } else {\n context = messageOrContext;\n }\n _fail(id, message, context);\n}\n\nfunction _fail(\n id: number,\n failure: string,\n context?: Record<string, unknown>\n): never {\n // Log the failure in addition to throw an exception, just in case the\n // exception is swallowed.\n let message = `FIRESTORE (${SDK_VERSION}) INTERNAL ASSERTION FAILED: ${failure} (ID: ${id.toString(\n 16\n )})`;\n if (context !== undefined) {\n try {\n const stringContext = JSON.stringify(context);\n message += ' CONTEXT: ' + stringContext;\n } catch (e) {\n message += ' CONTEXT: ' + context;\n }\n }\n logError(message);\n\n // NOTE: We don't use FirestoreError here because these are internal failures\n // that cannot be handled by the user. (Also it would create a circular\n // dependency between the error and assert modules which doesn't work.)\n throw new Error(message);\n}\n\n/**\n * Fails if the given assertion condition is false, throwing an Error with the\n * given message if it did.\n *\n * Messages are stripped in production builds.\n *\n * @param id generate a new unique value with `yarn assertion-idgenerate`.\n * Search for an existing value using `yarn assertion-id:find X`\n */\nexport function hardAssert(\n assertion: boolean,\n id: number,\n message: string,\n context?: Record<string, unknown>\n): asserts assertion;\n\n/**\n * Fails if the given assertion condition is false, throwing an Error with the\n * given message if it did.\n *\n * Messages are stripped in production builds.\n *\n * @param id generate a new unique value with `yarn assertion-id:generate`.\n * Search for an existing value using `yarn assertion-id:find X`\n */\nexport function hardAssert(\n assertion: boolean,\n id: number,\n context?: Record<string, unknown>\n): asserts assertion;\n\nexport function hardAssert(\n assertion: boolean,\n id: number,\n messageOrContext?: string | Record<string, unknown>,\n context?: Record<string, unknown>\n): asserts assertion {\n let message = 'Unexpected state';\n if (typeof messageOrContext === 'string') {\n message = messageOrContext;\n } else {\n context = messageOrContext;\n }\n\n if (!assertion) {\n _fail(id, message, context);\n }\n}\n\n/**\n * Fails if the given assertion condition is false, throwing an Error with the\n * given message if it did.\n *\n * The code of callsites invoking this function are stripped out in production\n * builds. Any side-effects of code within the debugAssert() invocation will not\n * happen in this case.\n *\n * @internal\n */\nexport function debugAssert(\n assertion: boolean,\n message: string\n): asserts assertion {\n if (!assertion) {\n fail(0xdeb6, message);\n }\n}\n\n/**\n * Casts `obj` to `T`. In non-production builds, verifies that `obj` is an\n * instance of `T` before casting.\n */\nexport function debugCast<T>(\n obj: object,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n constructor: { new (...args: any[]): T }\n): T | never {\n debugAssert(\n obj instanceof constructor,\n `Expected type '${constructor.name}', but was '${obj.constructor.name}'`\n );\n return obj as T;\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 { FirebaseError } from '@firebase/util';\n\n/**\n * The set of Firestore status codes. The codes are the same at the ones\n * exposed by gRPC here:\n * https://github.com/grpc/grpc/blob/master/doc/statuscodes.md\n *\n * Possible values:\n * - 'cancelled': The operation was cancelled (typically by the caller).\n * - 'unknown': Unknown error or an error from a different error domain.\n * - 'invalid-argument': Client specified an invalid argument. Note that this\n * differs from 'failed-precondition'. 'invalid-argument' indicates\n * arguments that are problematic regardless of the state of the system\n * (e.g. an invalid field name).\n * - 'deadline-exceeded': Deadline expired before operation could complete.\n * For operations that change the state of the system, this error may be\n * returned even if the operation has completed successfully. For example,\n * a successful response from a server could have been delayed long enough\n * for the deadline to expire.\n * - 'not-found': Some requested document was not found.\n * - 'already-exists': Some document that we attempted to create already\n * exists.\n * - 'permission-denied': The caller does not have permission to execute the\n * specified operation.\n * - 'resource-exhausted': Some resource has been exhausted, perhaps a\n * per-user quota, or perhaps the entire file system is out of space.\n * - 'failed-precondition': Operation was rejected because the system is not\n * in a state required for the operation's execution.\n * - 'aborted': The operation was aborted, typically due to a concurrency\n * issue like transaction aborts, etc.\n * - 'out-of-range': Operation was attempted past the valid range.\n * - 'unimplemented': Operation is not implemented or not supported/enabled.\n * - 'internal': Internal errors. Means some invariants expected by\n * underlying system has been broken. If you see one of these errors,\n * something is very broken.\n * - 'unavailable': The service is currently unavailable. This is most likely\n * a transient condition and may be corrected by retrying with a backoff.\n * - 'data-loss': Unrecoverable data loss or corruption.\n * - 'unauthenticated': The request does not have valid authentication\n * credentials for the operation.\n */\nexport type FirestoreErrorCode =\n | 'cancelled'\n | 'unknown'\n | 'invalid-argument'\n | 'deadline-exceeded'\n | 'not-found'\n | 'already-exists'\n | 'permission-denied'\n | 'resource-exhausted'\n | 'failed-precondition'\n | 'aborted'\n | 'out-of-range'\n | 'unimplemented'\n | 'internal'\n | 'unavailable'\n | 'data-loss'\n | 'unauthenticated';\n\n/**\n * Error Codes describing the different ways Firestore can fail. These come\n * directly from GRPC.\n */\nexport type Code = FirestoreErrorCode;\n\nexport const Code = {\n // Causes are copied from:\n // https://github.com/grpc/grpc/blob/bceec94ea4fc5f0085d81235d8e1c06798dc341a/include/grpc%2B%2B/impl/codegen/status_code_enum.h\n /** Not an error; returned on success. */\n OK: 'ok' as FirestoreErrorCode,\n\n /** The operation was cancelled (typically by the caller). */\n CANCELLED: 'cancelled' as FirestoreErrorCode,\n\n /** Unknown error or an error from a different error domain. */\n UNKNOWN: 'unknown' as FirestoreErrorCode,\n\n /**\n * Client specified an invalid argument. Note that this differs from\n * FAILED_PRECONDITION. INVALID_ARGUMENT indicates arguments that are\n * problematic regardless of the state of the system (e.g., a malformed file\n * name).\n */\n INVALID_ARGUMENT: 'invalid-argument' as FirestoreErrorCode,\n\n /**\n * Deadline expired before operation could complete. For operations that\n * change the state of the system, this error may be returned even if the\n * operation has completed successfully. For example, a successful response\n * from a server could have been delayed long enough for the deadline to\n * expire.\n */\n DEADLINE_EXCEEDED: 'deadline-exceeded' as FirestoreErrorCode,\n\n /** Some requested entity (e.g., file or directory) was not found. */\n NOT_FOUND: 'not-found' as FirestoreErrorCode,\n\n /**\n * Some entity that we attempted to create (e.g., file or directory) already\n * exists.\n */\n ALREADY_EXISTS: 'already-exists' as FirestoreErrorCode,\n\n /**\n * The caller does not have permission to execute the specified operation.\n * PERMISSION_DENIED must not be used for rejections caused by exhausting\n * some resource (use RESOURCE_EXHAUSTED instead for those errors).\n * PERMISSION_DENIED must not be used if the caller cannot be identified\n * (use UNAUTHENTICATED instead for those errors).\n */\n PERMISSION_DENIED: 'permission-denied' as FirestoreErrorCode,\n\n /**\n * The request does not have valid authentication credentials for the\n * operation.\n */\n UNAUTHENTICATED: 'unauthenticated' as FirestoreErrorCode,\n\n /**\n * Some resource has been exhausted, perhaps a per-user quota, or perhaps the\n * entire file system is out of space.\n */\n RESOURCE_EXHAUSTED: 'resource-exhausted' as FirestoreErrorCode,\n\n /**\n * Operation was rejected because the system is not in a state required for\n * the operation's execution. For example, directory to be deleted may be\n * non-empty, an rmdir operation is applied to a non-directory, etc.\n *\n * A litmus test that may help a service implementor in deciding\n * between FAILED_PRECONDITION, ABORTED, and UNAVAILABLE:\n * (a) Use UNAVAILABLE if the client can retry just the failing call.\n * (b) Use ABORTED if the client should retry at a higher-level\n * (e.g., restarting a read-modify-write sequence).\n * (c) Use FAILED_PRECONDITION if the client should not retry until\n * the system state has been explicitly fixed. E.g., if an \"rmdir\"\n * fails because the directory is non-empty, FAILED_PRECONDITION\n * should be returned since the client should not retry unless\n * they have first fixed up the directory by deleting files from it.\n * (d) Use FAILED_PRECONDITION if the client performs conditional\n * REST Get/Update/Delete on a resource and the resource on the\n * server does not match the condition. E.g., conflicting\n * read-modify-write on the same resource.\n */\n FAILED_PRECONDITION: 'failed-precondition' as FirestoreErrorCode,\n\n /**\n * The operation was aborted, typically due to a concurrency issue like\n * sequencer check failures, transaction aborts, etc.\n *\n * See litmus test above for deciding between FAILED_PRECONDITION, ABORTED,\n * and UNAVAILABLE.\n */\n ABORTED: 'aborted' as FirestoreErrorCode,\n\n /**\n * Operation was attempted past the valid range. E.g., seeking or reading\n * past end of file.\n *\n * Unlike INVALID_ARGUMENT, this error indicates a problem that may be fixed\n * if the system state changes. For example, a 32-bit file system will\n * generate INVALID_ARGUMENT if asked to read at an offset that is not in the\n * range [0,2^32-1], but it will generate OUT_OF_RANGE if asked to read from\n * an offset past the current file size.\n *\n * There is a fair bit of overlap between FAILED_PRECONDITION and\n * OUT_OF_RANGE. We recommend using OUT_OF_RANGE (the more specific error)\n * when it applies so that callers who are iterating through a space can\n * easily look for an OUT_OF_RANGE error to detect when they are done.\n */\n OUT_OF_RANGE: 'out-of-range' as FirestoreErrorCode,\n\n /** Operation is not implemented or not supported/enabled in this service. */\n UNIMPLEMENTED: 'unimplemented' as FirestoreErrorCode,\n\n /**\n * Internal errors. Means some invariants expected by underlying System has\n * been broken. If you see one of these errors, Something is very broken.\n */\n INTERNAL: 'internal' as FirestoreErrorCode,\n\n /**\n * The service is currently unavailable. This is a most likely a transient\n * condition and may be corrected by retrying with a backoff.\n *\n * See litmus test above for deciding between FAILED_PRECONDITION, ABORTED,\n * and UNAVAILABLE.\n */\n UNAVAILABLE: 'unavailable' as FirestoreErrorCode,\n\n /** Unrecoverable data loss or corruption. */\n DATA_LOSS: 'data-loss' as FirestoreErrorCode\n};\n\n/** An error returned by a Firestore operation. */\nexport class FirestoreError extends FirebaseError {\n /** The stack of the error. */\n readonly stack?: string;\n\n /** @hideconstructor */\n constructor(\n /**\n * The backend error code associated with this error.\n */\n readonly code: FirestoreErrorCode,\n /**\n * A custom error description.\n */\n readonly message: string\n ) {\n super(code, message);\n\n // HACK: We write a toString property directly because Error is not a real\n // class and so inheritance does not work correctly. We could alternatively\n // do the same \"back-door inheritance\" trick that FirebaseError does.\n this.toString = () => `${this.name}: [code=${this.code}]: ${this.message}`;\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\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 { FirebaseApp, _isFirebaseServerApp } from '@firebase/app';\nimport {\n AppCheckInternalComponentName,\n AppCheckTokenListener,\n AppCheckTokenResult,\n FirebaseAppCheckInternal\n} from '@firebase/app-check-interop-types';\nimport {\n FirebaseAuthInternal,\n FirebaseAuthInternalName\n} from '@firebase/auth-interop-types';\nimport { Provider } from '@firebase/component';\n\nimport { User } from '../auth/user';\nimport { debugAssert, hardAssert } from '../util/assert';\nimport { AsyncQueue } from '../util/async_queue';\nimport { Code, FirestoreError } from '../util/error';\nimport { logDebug } from '../util/log';\nimport { Deferred } from '../util/promise';\n\n// TODO(mikelehen): This should be split into multiple files and probably\n// moved to an auth/ folder to match other platforms.\n\n/**\n * @internal\n */\nexport type AuthTokenFactory = () => string;\n\n/**\n * @internal\n */\nexport interface FirstPartyCredentialsSettings {\n // These are external types. Prevent minification.\n ['type']: 'firstParty';\n ['sessionIndex']: string;\n ['iamToken']: string | null;\n ['authTokenFactory']: AuthTokenFactory | null;\n}\n\nexport interface ProviderCredentialsSettings {\n // These are external types. Prevent minification.\n ['type']: 'provider';\n ['client']: CredentialsProvider<User>;\n}\n\n/** Settings for private credentials */\nexport type CredentialsSettings =\n | FirstPartyCredentialsSettings\n | ProviderCredentialsSettings;\n\nexport type TokenType = 'OAuth' | 'FirstParty' | 'AppCheck';\nexport interface Token {\n /** Type of token. */\n type: TokenType;\n\n /**\n * The user with which the token is associated (used for persisting user\n * state on disk, etc.).\n * This will be null for Tokens of the type 'AppCheck'.\n */\n user?: User;\n\n /** Header values to set for this token */\n headers: Map<string, string>;\n}\n\nexport class OAuthToken implements Token {\n type = 'OAuth' as TokenType;\n headers = new Map();\n\n constructor(value: string, public user: User) {\n this.headers.set('Authorization', `Bearer ${value}`);\n }\n}\n\n/**\n * A Listener for credential change events. The listener should fetch a new\n * token and may need to invalidate other state if the current user has also\n * changed.\n */\nexport type CredentialChangeListener<T> = (credential: T) => Promise<void>;\n\n/**\n * Provides methods for getting the uid and token for the current user and\n * listening for changes.\n */\nexport interface CredentialsProvider<T> {\n /**\n * Starts the credentials provider and specifies a listener to be notified of\n * credential changes (sign-in / sign-out, token changes). It is immediately\n * called once with the initial user.\n *\n * The change listener is invoked on the provided AsyncQueue.\n */\n start(\n asyncQueue: AsyncQueue,\n changeListener: CredentialChangeListener<T>\n ): void;\n\n /** Requests a token for the current user. */\n getToken(): Promise<Token | null>;\n\n /**\n * Marks the last retrieved token as invalid, making the next GetToken request\n * force-refresh the token.\n */\n invalidateToken(): void;\n\n shutdown(): void;\n}\n\n/**\n * A CredentialsProvider that always yields an empty token.\n * @internal\n */\nexport class EmptyAuthCredentialsProvider implements CredentialsProvider<User> {\n getToken(): Promise<Token | null> {\n return Promise.resolve<Token | null>(null);\n }\n\n invalidateToken(): void {}\n\n start(\n asyncQueue: AsyncQueue,\n changeListener: CredentialChangeListener<User>\n ): void {\n // Fire with initial user.\n asyncQueue.enqueueRetryable(() => changeListener(User.UNAUTHENTICATED));\n }\n\n shutdown(): void {}\n}\n\n/**\n * A CredentialsProvider that always returns a constant token. Used for\n * emulator token mocking.\n */\nexport class EmulatorAuthCredentialsProvider\n implements CredentialsProvider<User>\n{\n constructor(private token: Token) {}\n\n /**\n * Stores the listener registered with setChangeListener()\n * This isn't actually necessary since the UID never changes, but we use this\n * to verify the listen contract is adhered to in tests.\n */\n private changeListener: CredentialChangeListener<User> | null = null;\n\n getToken(): Promise<Token | null> {\n return Promise.resolve(this.token);\n }\n\n invalidateToken(): void {}\n\n start(\n asyncQueue: AsyncQueue,\n changeListener: CredentialChangeListener<User>\n ): void {\n debugAssert(\n !this.changeListener,\n 'Can only call setChangeListener() once.'\n );\n this.changeListener = changeListener;\n // Fire with initial user.\n asyncQueue.enqueueRetryable(() => changeListener(this.token.user!));\n }\n\n shutdown(): void {\n this.changeListener = null;\n }\n}\n\n/** Credential provider for the Lite SDK. */\nexport class LiteAuthCredentialsProvider implements CredentialsProvider<User> {\n private auth: FirebaseAuthInternal | null = null;\n\n constructor(authProvider: Provider<FirebaseAuthInternalName>) {\n authProvider.onInit(auth => {\n this.auth = auth;\n });\n }\n\n getToken(): Promise<Token | null> {\n if (!this.auth) {\n return Promise.resolve(null);\n }\n\n return this.auth.getToken().then(tokenData => {\n if (tokenData) {\n hardAssert(\n typeof tokenData.accessToken === 'string',\n 0xa539,\n 'Invalid tokenData returned from getToken()',\n { tokenData }\n );\n return new OAuthToken(\n tokenData.accessToken,\n new User(this.auth!.getUid())\n );\n } else {\n return null;\n }\n });\n }\n\n invalidateToken(): void {}\n\n start(\n asyncQueue: AsyncQueue,\n changeListener: CredentialChangeListener<User>\n ): void {}\n\n shutdown(): void {}\n}\n\nexport class FirebaseAuthCredentialsProvider\n implements CredentialsProvider<User>\n{\n /**\n * The auth token listener registered with FirebaseApp, retained here so we\n * can unregister it.\n */\n private tokenListener: (() => void) | undefined;\n\n /** Tracks the current User. */\n private currentUser: User = User.UNAUTHENTICATED;\n\n /**\n * Counter used to detect if the token changed while a getToken request was\n * outstanding.\n */\n private tokenCounter = 0;\n\n private forceRefresh = false;\n\n private auth: FirebaseAuthInternal | null = null;\n\n constructor(private authProvider: Provider<FirebaseAuthInternalName>) {}\n\n start(\n asyncQueue: AsyncQueue,\n changeListener: CredentialChangeListener<User>\n ): void {\n hardAssert(\n this.tokenListener === undefined,\n 0xa540,\n 'Token listener already added'\n );\n let lastTokenId = this.tokenCounter;\n\n // A change listener that prevents double-firing for the same token change.\n const guardedChangeListener: (user: User) => Promise<void> = user => {\n if (this.tokenCounter !== lastTokenId) {\n lastTokenId = this.tokenCounter;\n return changeListener(user);\n } else {\n return Promise.resolve();\n }\n };\n\n // A promise that can be waited on to block on the next token change.\n // This promise is re-created after each change.\n let nextToken = new Deferred<void>();\n\n this.tokenListener = () => {\n this.tokenCounter++;\n this.currentUser = this.getUser();\n nextToken.resolve();\n nextToken = new Deferred<void>();\n asyncQueue.enqueueRetryable(() =>\n guardedChangeListener(this.currentUser)\n );\n };\n\n const awaitNextToken: () => void = () => {\n const currentTokenAttempt = nextToken;\n asyncQueue.enqueueRetryable(async () => {\n await currentTokenAttempt.promise;\n await guardedChangeListener(this.currentUser);\n });\n };\n\n const registerAuth = (auth: FirebaseAuthInternal): void => {\n logDebug('FirebaseAuthCredentialsProvider', 'Auth detected');\n this.auth = auth;\n if (this.tokenListener) {\n this.auth.addAuthTokenListener(this.tokenListener);\n awaitNextToken();\n }\n };\n\n this.authProvider.onInit(auth => registerAuth(auth));\n\n // Our users can initialize Auth right after Firestore, so we give it\n // a chance to register itself with the component framework before we\n // determine whether to start up in unauthenticated mode.\n setTimeout(() => {\n if (!this.auth) {\n const auth = this.authProvider.getImmediate({ optional: true });\n if (auth) {\n registerAuth(auth);\n } else {\n // If auth is still not available, proceed with `null` user\n logDebug('FirebaseAuthCredentialsProvider', 'Auth not yet detected');\n nextToken.resolve();\n nextToken = new Deferred<void>();\n }\n }\n }, 0);\n\n awaitNextToken();\n }\n\n getToken(): Promise<Token | null> {\n debugAssert(\n this.tokenListener != null,\n 'FirebaseAuthCredentialsProvider not started.'\n );\n\n // Take note of the current value of the tokenCounter so that this method\n // can fail (with an ABORTED error) if there is a token change while the\n // request is outstanding.\n const initialTokenCounter = this.tokenCounter;\n const forceRefresh = this.forceRefresh;\n this.forceRefresh = false;\n\n if (!this.auth) {\n return Promise.resolve(null);\n }\n\n return this.auth.getToken(forceRefresh).then(tokenData => {\n // Cancel the request since the token changed while the request was\n // outstanding so the response is potentially for a previous user (which\n // user, we can't be sure).\n if (this.tokenCounter !== initialTokenCounter) {\n logDebug(\n 'FirebaseAuthCredentialsProvider',\n 'getToken aborted due to token change.'\n );\n return this.getToken();\n } else {\n if (tokenData) {\n hardAssert(\n typeof tokenData.accessToken === 'string',\n 0x7c5d,\n 'Invalid tokenData returned from getToken()',\n { tokenData }\n );\n return new OAuthToken(tokenData.accessToken, this.currentUser);\n } else {\n return null;\n }\n }\n });\n }\n\n invalidateToken(): void {\n this.forceRefresh = true;\n }\n\n shutdown(): void {\n if (this.auth && this.tokenListener) {\n this.auth.removeAuthTokenListener(this.tokenListener);\n }\n this.tokenListener = undefined;\n }\n\n // Auth.getUid() can return null even with a user logged in. It is because\n // getUid() is synchronous, but the auth code populating Uid is asynchronous.\n // This method should only be called in the AuthTokenListener callback\n // to guarantee to get the actual user.\n private getUser(): User {\n const currentUid = this.auth && this.auth.getUid();\n hardAssert(\n currentUid === null || typeof currentUid === 'string',\n 0x0807,\n 'Received invalid UID',\n { currentUid }\n );\n return new User(currentUid);\n }\n}\n\n/*\n * FirstPartyToken provides a fresh token each time its value\n * is requested, because if the token is too old, requests will be rejected.\n * Technically this may no longer be necessary since the SDK should gracefully\n * recover from unauthenticated errors (see b/33147818 for context), but it's\n * safer to keep the implementation as-is.\n */\nexport class FirstPartyToken implements Token {\n type = 'FirstParty' as TokenType;\n user = User.FIRST_PARTY;\n private _headers = new Map();\n\n constructor(\n private readonly sessionIndex: string,\n private readonly iamToken: string | null,\n private readonly authTokenFactory: AuthTokenFactory | null\n ) {}\n\n /**\n * Gets an authorization token, using a provided factory function, or return\n * null.\n */\n private getAuthToken(): string | null {\n if (this.authTokenFactory) {\n return this.authTokenFactory();\n } else {\n return null;\n }\n }\n\n get headers(): Map<string, string> {\n this._headers.set('X-Goog-AuthUser', this.sessionIndex);\n // Use array notation to prevent minification\n const authHeaderTokenValue = this.getAuthToken();\n if (authHeaderTokenValue) {\n this._headers.set('Authorization', authHeaderTokenValue);\n }\n if (this.iamToken) {\n this._headers.set('X-Goog-Iam-Authorization-Token', this.iamToken);\n }\n\n return this._headers;\n }\n}\n\n/*\n * Provides user credentials required for the Firestore JavaScript SDK\n * to authenticate the user, using technique that is only available\n * to applications hosted by Google.\n */\nexport class FirstPartyAuthCredentialsProvider\n implements CredentialsProvider<User>\n{\n constructor(\n private sessionIndex: string,\n private iamToken: string | null,\n private authTokenFactory: AuthTokenFactory | null\n ) {}\n\n getToken(): Promise<Token | null> {\n return Promise.resolve(\n new FirstPartyToken(\n this.sessionIndex,\n this.iamToken,\n this.authTokenFactory\n )\n );\n }\n\n start(\n asyncQueue: AsyncQueue,\n changeListener: CredentialChangeListener<User>\n ): void {\n // Fire with initial uid.\n asyncQueue.enqueueRetryable(() => changeListener(User.FIRST_PARTY));\n }\n\n shutdown(): void {}\n\n invalidateToken(): void {}\n}\n\nexport class AppCheckToken implements Token {\n type = 'AppCheck' as TokenType;\n headers = new Map();\n\n constructor(private value: string) {\n if (value && value.length > 0) {\n this.headers.set('x-firebase-appcheck', this.value);\n }\n }\n}\n\nexport class FirebaseAppCheckTokenProvider\n implements CredentialsProvider<string>\n{\n /**\n * The AppCheck token listener registered with FirebaseApp, retained here so\n * we can unregister it.\n */\n private tokenListener: AppCheckTokenListener | undefined;\n private forceRefresh = false;\n private appCheck: FirebaseAppCheckInternal | null = null;\n private latestAppCheckToken: string | null = null;\n private serverAppAppCheckToken: string | null = null;\n\n constructor(\n app: FirebaseApp,\n private appCheckProvider: Provider<AppCheckInternalComponentName>\n ) {\n if (_isFirebaseServerApp(app) && app.settings.appCheckToken) {\n this.serverAppAppCheckToken = app.settings.appCheckToken;\n }\n }\n\n start(\n asyncQueue: AsyncQueue,\n changeListener: CredentialChangeListener<string>\n ): void {\n hardAssert(\n this.tokenListener === undefined,\n 0x0db8,\n 'Token listener already added'\n );\n\n const onTokenChanged: (\n tokenResult: AppCheckTokenResult\n ) => Promise<void> = tokenResult => {\n if (tokenResult.error != null) {\n logDebug(\n 'FirebaseAppCheckTokenProvider',\n `Error getting App Check token; using placeholder token instead. Error: ${tokenResult.error.message}`\n );\n }\n const tokenUpdated = tokenResult.token !== this.latestAppCheckToken;\n this.latestAppCheckToken = tokenResult.token;\n logDebug(\n 'FirebaseAppCheckTokenProvider',\n `Received ${tokenUpdated ? 'new' : 'existing'} token.`\n );\n return tokenUpdated\n ? changeListener(tokenResult.token)\n : Promise.resolve();\n };\n\n this.tokenListener = (tokenResult: AppCheckTokenResult) => {\n asyncQueue.enqueueRetryable(() => onTokenChanged(tokenResult));\n };\n\n const registerAppCheck = (appCheck: FirebaseAppCheckInternal): void => {\n logDebug('FirebaseAppCheckTokenProvider', 'AppCheck detected');\n this.appCheck = appCheck;\n if (this.tokenListener) {\n this.appCheck.addTokenListener(this.tokenListener);\n }\n };\n\n this.appCheckProvider.onInit(appCheck => registerAppCheck(appCheck));\n\n // Our users can initialize AppCheck after Firestore, so we give it\n // a chance to register itself with the component framework.\n setTimeout(() => {\n if (!this.appCheck) {\n const appCheck = this.appCheckProvider.getImmediate({ optional: true });\n if (appCheck) {\n registerAppCheck(appCheck);\n } else {\n // If AppCheck is still not available, proceed without it.\n logDebug(\n 'FirebaseAppCheckTokenProvider',\n 'AppCheck not yet detected'\n );\n }\n }\n }, 0);\n }\n\n getToken(): Promise<Token | null> {\n if (this.serverAppAppCheckToken) {\n return Promise.resolve(new AppCheckToken(this.serverAppAppCheckToken));\n }\n debugAssert(\n this.tokenListener != null,\n 'FirebaseAppCheckTokenProvider not started.'\n );\n\n const forceRefresh = this.forceRefresh;\n this.forceRefresh = false;\n\n if (!this.appCheck) {\n return Promise.resolve(null);\n }\n\n return this.appCheck.getToken(forceRefresh).then(tokenResult => {\n if (tokenResult) {\n hardAssert(\n typeof tokenResult.token === 'string',\n 0xae0e,\n 'Invalid tokenResult returned from getToken()',\n { tokenResult }\n );\n this.latestAppCheckToken = tokenResult.token;\n return new AppCheckToken(tokenResult.token);\n } else {\n return null;\n }\n });\n }\n\n invalidateToken(): void {\n this.forceRefresh = true;\n }\n\n shutdown(): void {\n if (this.appCheck && this.tokenListener) {\n this.appCheck.removeTokenListener(this.tokenListener);\n }\n this.tokenListener = undefined;\n }\n}\n\n/**\n * An AppCheck token provider that always yields an empty token.\n * @internal\n */\nexport class EmptyAppCheckTokenProvider implements CredentialsProvider<string> {\n getToken(): Promise<Token | null> {\n return Promise.resolve<Token | null>(new AppCheckToken(''));\n }\n\n invalidateToken(): void {}\n\n start(\n asyncQueue: AsyncQueue,\n changeListener: CredentialChangeListener<string>\n ): void {}\n\n shutdown(): void {}\n}\n\n/** AppCheck token provider for the Lite SDK. */\nexport class LiteAppCheckTokenProvider implements CredentialsProvider<string> {\n private appCheck: FirebaseAppCheckInternal | null = null;\n private serverAppAppCheckToken: string | null = null;\n\n constructor(\n app: FirebaseApp,\n private appCheckProvider: Provider<AppCheckInternalComponentName>\n ) {\n if (_isFirebaseServerApp(app) && app.settings.appCheckToken) {\n this.serverAppAppCheckToken = app.settings.appCheckToken;\n }\n appCheckProvider.onInit(appCheck => {\n this.appCheck = appCheck;\n });\n }\n\n getToken(): Promise<Token | null> {\n if (this.serverAppAppCheckToken) {\n return Promise.resolve(new AppCheckToken(this.serverAppAppCheckToken));\n }\n\n if (!this.appCheck) {\n return Promise.resolve(null);\n }\n\n return this.appCheck.getToken().then(tokenResult => {\n if (tokenResult) {\n hardAssert(\n typeof tokenResult.token === 'string',\n 0x0d8e,\n 'Invalid tokenResult returned from getToken()',\n { tokenResult }\n );\n return new AppCheckToken(tokenResult.token);\n } else {\n return null;\n }\n });\n }\n\n invalidateToken(): void {}\n\n start(\n asyncQueue: AsyncQueue,\n changeListener: CredentialChangeListener<string>\n ): void {}\n\n shutdown(): void {}\n}\n\n/**\n * Builds a CredentialsProvider depending on the type of\n * the credentials passed in.\n */\nexport function makeAuthCredentialsProvider(\n credentials?: CredentialsSettings\n): CredentialsProvider<User> {\n if (!credentials) {\n return new EmptyAuthCredentialsProvider();\n }\n switch (credentials['type']) {\n case 'firstParty':\n return new FirstPartyAuthCredentialsProvider(\n credentials['sessionIndex'] || '0',\n credentials['iamToken'] || null,\n credentials['authTokenFactory'] || null\n );\n\n case 'provider':\n return credentials['client'];\n\n default:\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n 'makeAuthCredentialsProvider failed due to invalid credential type'\n );\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 { randomBytes as generateRandomBytes } from 'crypto';\n\nimport { debugAssert } from '../../util/assert';\n\n/**\n * Generates `nBytes` of random bytes.\n