@firebase/firestore
Version:
The Cloud Firestore component of the Firebase JS SDK.
1,288 lines (1,232 loc) • 998 kB
JavaScript
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var app = require('@firebase/app');
var component = require('@firebase/component');
var logger = require('@firebase/logger');
var util = require('@firebase/util');
var bloomBlob = require('@firebase/webchannel-wrapper/bloom-blob');
var webchannelBlob = require('@firebase/webchannel-wrapper/webchannel-blob');
const F = "@firebase/firestore", M = "4.9.0";
/**
* @license
* Copyright 2017 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Simple wrapper around a nullable UID. Mostly exists to make code more
* readable.
*/
class User {
constructor(e) {
this.uid = e;
}
isAuthenticated() {
return null != this.uid;
}
/**
* Returns a key representing this user, suitable for inclusion in a
* dictionary.
*/ toKey() {
return this.isAuthenticated() ? "uid:" + this.uid : "anonymous-user";
}
isEqual(e) {
return e.uid === this.uid;
}
}
/** A user with a null UID. */ User.UNAUTHENTICATED = new User(null),
// TODO(mikelehen): Look into getting a proper uid-equivalent for
// non-FirebaseAuth providers.
User.GOOGLE_CREDENTIALS = new User("google-credentials-uid"), User.FIRST_PARTY = new User("first-party-uid"),
User.MOCK_USER = new User("mock-user");
/**
* @license
* Copyright 2017 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
let x = "12.0.0";
/**
* @license
* Copyright 2017 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const O = new logger.Logger("@firebase/firestore");
// Helper methods are needed because variables can't be exported as read/write
function __PRIVATE_getLogLevel() {
return O.logLevel;
}
/**
* Sets the verbosity of Cloud Firestore logs (debug, error, or silent).
*
* @param logLevel - The verbosity you set for activity and error logging. Can
* be any of the following values:
*
* <ul>
* <li>`debug` for the most verbose logging level, primarily for
* debugging.</li>
* <li>`error` to log errors only.</li>
* <li><code>`silent` to turn off logging.</li>
* </ul>
*/ function setLogLevel(e) {
O.setLogLevel(e);
}
function __PRIVATE_logDebug(e, ...t) {
if (O.logLevel <= logger.LogLevel.DEBUG) {
const n = t.map(__PRIVATE_argToString);
O.debug(`Firestore (${x}): ${e}`, ...n);
}
}
function __PRIVATE_logError(e, ...t) {
if (O.logLevel <= logger.LogLevel.ERROR) {
const n = t.map(__PRIVATE_argToString);
O.error(`Firestore (${x}): ${e}`, ...n);
}
}
/**
* @internal
*/ function __PRIVATE_logWarn(e, ...t) {
if (O.logLevel <= logger.LogLevel.WARN) {
const n = t.map(__PRIVATE_argToString);
O.warn(`Firestore (${x}): ${e}`, ...n);
}
}
/**
* Converts an additional log parameter to a string representation.
*/ function __PRIVATE_argToString(e) {
if ("string" == typeof e) return e;
try {
/**
* @license
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** Formats an object as a JSON string, suitable for logging. */
return function __PRIVATE_formatJSON(e) {
return JSON.stringify(e);
}(e);
} catch (t) {
// Converting to JSON failed, just log the object directly
return e;
}
}
/**
* @license
* Copyright 2017 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ function fail(e, t, n) {
let r = "Unexpected state";
"string" == typeof t ? r = t : n = t, __PRIVATE__fail(e, r, n);
}
function __PRIVATE__fail(e, t, n) {
// Log the failure in addition to throw an exception, just in case the
// exception is swallowed.
let r = `FIRESTORE (${x}) INTERNAL ASSERTION FAILED: ${t} (ID: ${e.toString(16)})`;
if (void 0 !== n) try {
r += " CONTEXT: " + JSON.stringify(n);
} catch (e) {
r += " CONTEXT: " + n;
}
// NOTE: We don't use FirestoreError here because these are internal failures
// that cannot be handled by the user. (Also it would create a circular
// dependency between the error and assert modules which doesn't work.)
throw __PRIVATE_logError(r), new Error(r);
}
function __PRIVATE_hardAssert(e, t, n, r) {
let i = "Unexpected state";
"string" == typeof n ? i = n : r = n, e || __PRIVATE__fail(t, i, r);
}
/**
* Fails if the given assertion condition is false, throwing an Error with the
* given message if it did.
*
* The code of callsites invoking this function are stripped out in production
* builds. Any side-effects of code within the debugAssert() invocation will not
* happen in this case.
*
* @internal
*/ function __PRIVATE_debugAssert(e, t) {
e || fail(57014, t);
}
/**
* Casts `obj` to `T`. In non-production builds, verifies that `obj` is an
* instance of `T` before casting.
*/ function __PRIVATE_debugCast(e,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
t) {
return e;
}
/**
* @license
* Copyright 2017 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ const N = {
// Causes are copied from:
// https://github.com/grpc/grpc/blob/bceec94ea4fc5f0085d81235d8e1c06798dc341a/include/grpc%2B%2B/impl/codegen/status_code_enum.h
/** Not an error; returned on success. */
OK: "ok",
/** The operation was cancelled (typically by the caller). */
CANCELLED: "cancelled",
/** Unknown error or an error from a different error domain. */
UNKNOWN: "unknown",
/**
* Client specified an invalid argument. Note that this differs from
* FAILED_PRECONDITION. INVALID_ARGUMENT indicates arguments that are
* problematic regardless of the state of the system (e.g., a malformed file
* name).
*/
INVALID_ARGUMENT: "invalid-argument",
/**
* Deadline expired before operation could complete. For operations that
* change the state of the system, this error may be returned even if the
* operation has completed successfully. For example, a successful response
* from a server could have been delayed long enough for the deadline to
* expire.
*/
DEADLINE_EXCEEDED: "deadline-exceeded",
/** Some requested entity (e.g., file or directory) was not found. */
NOT_FOUND: "not-found",
/**
* Some entity that we attempted to create (e.g., file or directory) already
* exists.
*/
ALREADY_EXISTS: "already-exists",
/**
* The caller does not have permission to execute the specified operation.
* PERMISSION_DENIED must not be used for rejections caused by exhausting
* some resource (use RESOURCE_EXHAUSTED instead for those errors).
* PERMISSION_DENIED must not be used if the caller cannot be identified
* (use UNAUTHENTICATED instead for those errors).
*/
PERMISSION_DENIED: "permission-denied",
/**
* The request does not have valid authentication credentials for the
* operation.
*/
UNAUTHENTICATED: "unauthenticated",
/**
* Some resource has been exhausted, perhaps a per-user quota, or perhaps the
* entire file system is out of space.
*/
RESOURCE_EXHAUSTED: "resource-exhausted",
/**
* Operation was rejected because the system is not in a state required for
* the operation's execution. For example, directory to be deleted may be
* non-empty, an rmdir operation is applied to a non-directory, etc.
*
* A litmus test that may help a service implementor in deciding
* between FAILED_PRECONDITION, ABORTED, and UNAVAILABLE:
* (a) Use UNAVAILABLE if the client can retry just the failing call.
* (b) Use ABORTED if the client should retry at a higher-level
* (e.g., restarting a read-modify-write sequence).
* (c) Use FAILED_PRECONDITION if the client should not retry until
* the system state has been explicitly fixed. E.g., if an "rmdir"
* fails because the directory is non-empty, FAILED_PRECONDITION
* should be returned since the client should not retry unless
* they have first fixed up the directory by deleting files from it.
* (d) Use FAILED_PRECONDITION if the client performs conditional
* REST Get/Update/Delete on a resource and the resource on the
* server does not match the condition. E.g., conflicting
* read-modify-write on the same resource.
*/
FAILED_PRECONDITION: "failed-precondition",
/**
* The operation was aborted, typically due to a concurrency issue like
* sequencer check failures, transaction aborts, etc.
*
* See litmus test above for deciding between FAILED_PRECONDITION, ABORTED,
* and UNAVAILABLE.
*/
ABORTED: "aborted",
/**
* Operation was attempted past the valid range. E.g., seeking or reading
* past end of file.
*
* Unlike INVALID_ARGUMENT, this error indicates a problem that may be fixed
* if the system state changes. For example, a 32-bit file system will
* generate INVALID_ARGUMENT if asked to read at an offset that is not in the
* range [0,2^32-1], but it will generate OUT_OF_RANGE if asked to read from
* an offset past the current file size.
*
* There is a fair bit of overlap between FAILED_PRECONDITION and
* OUT_OF_RANGE. We recommend using OUT_OF_RANGE (the more specific error)
* when it applies so that callers who are iterating through a space can
* easily look for an OUT_OF_RANGE error to detect when they are done.
*/
OUT_OF_RANGE: "out-of-range",
/** Operation is not implemented or not supported/enabled in this service. */
UNIMPLEMENTED: "unimplemented",
/**
* Internal errors. Means some invariants expected by underlying System has
* been broken. If you see one of these errors, Something is very broken.
*/
INTERNAL: "internal",
/**
* The service is currently unavailable. This is a most likely a transient
* condition and may be corrected by retrying with a backoff.
*
* See litmus test above for deciding between FAILED_PRECONDITION, ABORTED,
* and UNAVAILABLE.
*/
UNAVAILABLE: "unavailable",
/** Unrecoverable data loss or corruption. */
DATA_LOSS: "data-loss"
};
/** An error returned by a Firestore operation. */ class FirestoreError extends util.FirebaseError {
/** @hideconstructor */
constructor(
/**
* The backend error code associated with this error.
*/
e,
/**
* A custom error description.
*/
t) {
super(e, t), this.code = e, this.message = t,
// HACK: We write a toString property directly because Error is not a real
// class and so inheritance does not work correctly. We could alternatively
// do the same "back-door inheritance" trick that FirebaseError does.
this.toString = () => `${this.name}: [code=${this.code}]: ${this.message}`;
}
}
/**
* @license
* Copyright 2017 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ class __PRIVATE_Deferred {
constructor() {
this.promise = new Promise(((e, t) => {
this.resolve = e, this.reject = t;
}));
}
}
/**
* @license
* Copyright 2017 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ class __PRIVATE_OAuthToken {
constructor(e, t) {
this.user = t, this.type = "OAuth", this.headers = new Map, this.headers.set("Authorization", `Bearer ${e}`);
}
}
/**
* A CredentialsProvider that always yields an empty token.
* @internal
*/ class __PRIVATE_EmptyAuthCredentialsProvider {
getToken() {
return Promise.resolve(null);
}
invalidateToken() {}
start(e, t) {
// Fire with initial user.
e.enqueueRetryable((() => t(User.UNAUTHENTICATED)));
}
shutdown() {}
}
/**
* A CredentialsProvider that always returns a constant token. Used for
* emulator token mocking.
*/ class __PRIVATE_EmulatorAuthCredentialsProvider {
constructor(e) {
this.token = e,
/**
* Stores the listener registered with setChangeListener()
* This isn't actually necessary since the UID never changes, but we use this
* to verify the listen contract is adhered to in tests.
*/
this.changeListener = null;
}
getToken() {
return Promise.resolve(this.token);
}
invalidateToken() {}
start(e, t) {
this.changeListener = t,
// Fire with initial user.
e.enqueueRetryable((() => t(this.token.user)));
}
shutdown() {
this.changeListener = null;
}
}
class __PRIVATE_FirebaseAuthCredentialsProvider {
constructor(e) {
this.t = e,
/** Tracks the current User. */
this.currentUser = User.UNAUTHENTICATED,
/**
* Counter used to detect if the token changed while a getToken request was
* outstanding.
*/
this.i = 0, this.forceRefresh = !1, this.auth = null;
}
start(e, t) {
__PRIVATE_hardAssert(void 0 === this.o, 42304);
let n = this.i;
// A change listener that prevents double-firing for the same token change.
const __PRIVATE_guardedChangeListener = e => this.i !== n ? (n = this.i,
t(e)) : Promise.resolve();
// A promise that can be waited on to block on the next token change.
// This promise is re-created after each change.
let r = new __PRIVATE_Deferred;
this.o = () => {
this.i++, this.currentUser = this.u(), r.resolve(), r = new __PRIVATE_Deferred,
e.enqueueRetryable((() => __PRIVATE_guardedChangeListener(this.currentUser)));
};
const __PRIVATE_awaitNextToken = () => {
const t = r;
e.enqueueRetryable((async () => {
await t.promise, await __PRIVATE_guardedChangeListener(this.currentUser);
}));
}, __PRIVATE_registerAuth = e => {
__PRIVATE_logDebug("FirebaseAuthCredentialsProvider", "Auth detected"), this.auth = e,
this.o && (this.auth.addAuthTokenListener(this.o), __PRIVATE_awaitNextToken());
};
this.t.onInit((e => __PRIVATE_registerAuth(e))),
// Our users can initialize Auth right after Firestore, so we give it
// a chance to register itself with the component framework before we
// determine whether to start up in unauthenticated mode.
setTimeout((() => {
if (!this.auth) {
const e = this.t.getImmediate({
optional: !0
});
e ? __PRIVATE_registerAuth(e) : (
// If auth is still not available, proceed with `null` user
__PRIVATE_logDebug("FirebaseAuthCredentialsProvider", "Auth not yet detected"),
r.resolve(), r = new __PRIVATE_Deferred);
}
}), 0), __PRIVATE_awaitNextToken();
}
getToken() {
// Take note of the current value of the tokenCounter so that this method
// can fail (with an ABORTED error) if there is a token change while the
// request is outstanding.
const e = this.i, t = this.forceRefresh;
return this.forceRefresh = !1, this.auth ? this.auth.getToken(t).then((t =>
// Cancel the request since the token changed while the request was
// outstanding so the response is potentially for a previous user (which
// user, we can't be sure).
this.i !== e ? (__PRIVATE_logDebug("FirebaseAuthCredentialsProvider", "getToken aborted due to token change."),
this.getToken()) : t ? (__PRIVATE_hardAssert("string" == typeof t.accessToken, 31837, {
l: t
}), new __PRIVATE_OAuthToken(t.accessToken, this.currentUser)) : null)) : Promise.resolve(null);
}
invalidateToken() {
this.forceRefresh = !0;
}
shutdown() {
this.auth && this.o && this.auth.removeAuthTokenListener(this.o), this.o = void 0;
}
// Auth.getUid() can return null even with a user logged in. It is because
// getUid() is synchronous, but the auth code populating Uid is asynchronous.
// This method should only be called in the AuthTokenListener callback
// to guarantee to get the actual user.
u() {
const e = this.auth && this.auth.getUid();
return __PRIVATE_hardAssert(null === e || "string" == typeof e, 2055, {
h: e
}), new User(e);
}
}
/*
* FirstPartyToken provides a fresh token each time its value
* is requested, because if the token is too old, requests will be rejected.
* Technically this may no longer be necessary since the SDK should gracefully
* recover from unauthenticated errors (see b/33147818 for context), but it's
* safer to keep the implementation as-is.
*/ class __PRIVATE_FirstPartyToken {
constructor(e, t, n) {
this.P = e, this.T = t, this.I = n, this.type = "FirstParty", this.user = User.FIRST_PARTY,
this.A = new Map;
}
/**
* Gets an authorization token, using a provided factory function, or return
* null.
*/ R() {
return this.I ? this.I() : null;
}
get headers() {
this.A.set("X-Goog-AuthUser", this.P);
// Use array notation to prevent minification
const e = this.R();
return e && this.A.set("Authorization", e), this.T && this.A.set("X-Goog-Iam-Authorization-Token", this.T),
this.A;
}
}
/*
* Provides user credentials required for the Firestore JavaScript SDK
* to authenticate the user, using technique that is only available
* to applications hosted by Google.
*/ class __PRIVATE_FirstPartyAuthCredentialsProvider {
constructor(e, t, n) {
this.P = e, this.T = t, this.I = n;
}
getToken() {
return Promise.resolve(new __PRIVATE_FirstPartyToken(this.P, this.T, this.I));
}
start(e, t) {
// Fire with initial uid.
e.enqueueRetryable((() => t(User.FIRST_PARTY)));
}
shutdown() {}
invalidateToken() {}
}
class AppCheckToken {
constructor(e) {
this.value = e, this.type = "AppCheck", this.headers = new Map, e && e.length > 0 && this.headers.set("x-firebase-appcheck", this.value);
}
}
class __PRIVATE_FirebaseAppCheckTokenProvider {
constructor(t, n) {
this.V = n, this.forceRefresh = !1, this.appCheck = null, this.m = null, this.p = null,
app._isFirebaseServerApp(t) && t.settings.appCheckToken && (this.p = t.settings.appCheckToken);
}
start(e, t) {
__PRIVATE_hardAssert(void 0 === this.o, 3512);
const onTokenChanged = e => {
null != e.error && __PRIVATE_logDebug("FirebaseAppCheckTokenProvider", `Error getting App Check token; using placeholder token instead. Error: ${e.error.message}`);
const n = e.token !== this.m;
return this.m = e.token, __PRIVATE_logDebug("FirebaseAppCheckTokenProvider", `Received ${n ? "new" : "existing"} token.`),
n ? t(e.token) : Promise.resolve();
};
this.o = t => {
e.enqueueRetryable((() => onTokenChanged(t)));
};
const __PRIVATE_registerAppCheck = e => {
__PRIVATE_logDebug("FirebaseAppCheckTokenProvider", "AppCheck detected"), this.appCheck = e,
this.o && this.appCheck.addTokenListener(this.o);
};
this.V.onInit((e => __PRIVATE_registerAppCheck(e))),
// Our users can initialize AppCheck after Firestore, so we give it
// a chance to register itself with the component framework.
setTimeout((() => {
if (!this.appCheck) {
const e = this.V.getImmediate({
optional: !0
});
e ? __PRIVATE_registerAppCheck(e) :
// If AppCheck is still not available, proceed without it.
__PRIVATE_logDebug("FirebaseAppCheckTokenProvider", "AppCheck not yet detected");
}
}), 0);
}
getToken() {
if (this.p) return Promise.resolve(new AppCheckToken(this.p));
const e = this.forceRefresh;
return this.forceRefresh = !1, this.appCheck ? this.appCheck.getToken(e).then((e => e ? (__PRIVATE_hardAssert("string" == typeof e.token, 44558, {
tokenResult: e
}), this.m = e.token, new AppCheckToken(e.token)) : null)) : Promise.resolve(null);
}
invalidateToken() {
this.forceRefresh = !0;
}
shutdown() {
this.appCheck && this.o && this.appCheck.removeTokenListener(this.o), this.o = void 0;
}
}
/**
* An AppCheck token provider that always yields an empty token.
* @internal
*/ class __PRIVATE_EmptyAppCheckTokenProvider {
getToken() {
return Promise.resolve(new AppCheckToken(""));
}
invalidateToken() {}
start(e, t) {}
shutdown() {}
}
/**
* Builds a CredentialsProvider depending on the type of
* the credentials passed in.
*/
/**
* @license
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Generates `nBytes` of random bytes.
*
* If `nBytes < 0` , an error will be thrown.
*/
function __PRIVATE_randomBytes(e) {
// Polyfills for IE and WebWorker by using `self` and `msCrypto` when `crypto` is not available.
const t =
// eslint-disable-next-line @typescript-eslint/no-explicit-any
"undefined" != typeof self && (self.crypto || self.msCrypto), n = new Uint8Array(e);
if (t && "function" == typeof t.getRandomValues) t.getRandomValues(n); else
// Falls back to Math.random
for (let t = 0; t < e; t++) n[t] = Math.floor(256 * Math.random());
return n;
}
/**
* @license
* Copyright 2017 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* A utility class for generating unique alphanumeric IDs of a specified length.
*
* @internal
* Exported internally for testing purposes.
*/ class __PRIVATE_AutoId {
static newId() {
// Alphanumeric characters
const e = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", t = 62 * Math.floor(256 / 62);
// The largest byte value that is a multiple of `char.length`.
let n = "";
for (;n.length < 20; ) {
const r = __PRIVATE_randomBytes(40);
for (let i = 0; i < r.length; ++i)
// Only accept values that are [0, maxMultiple), this ensures they can
// be evenly mapped to indices of `chars` via a modulo operation.
n.length < 20 && r[i] < t && (n += e.charAt(r[i] % 62));
}
return n;
}
}
function __PRIVATE_primitiveComparator(e, t) {
return e < t ? -1 : e > t ? 1 : 0;
}
/** Compare strings in UTF-8 encoded byte order */ function __PRIVATE_compareUtf8Strings(e, t) {
// Find the first differing character (a.k.a. "UTF-16 code unit") in the two strings and,
// if found, use that character to determine the relative ordering of the two strings as a
// whole. Comparing UTF-16 strings in UTF-8 byte order can be done simply and efficiently by
// comparing the UTF-16 code units (chars). This serendipitously works because of the way UTF-8
// and UTF-16 happen to represent Unicode code points.
// After finding the first pair of differing characters, there are two cases:
// Case 1: Both characters are non-surrogates (code points less than or equal to 0xFFFF) or
// both are surrogates from a surrogate pair (that collectively represent code points greater
// than 0xFFFF). In this case their numeric order as UTF-16 code units is the same as the
// lexicographical order of their corresponding UTF-8 byte sequences. A direct comparison is
// sufficient.
// Case 2: One character is a surrogate and the other is not. In this case the surrogate-
// containing string is always ordered after the non-surrogate. This is because surrogates are
// used to represent code points greater than 0xFFFF which have 4-byte UTF-8 representations
// and are lexicographically greater than the 1, 2, or 3-byte representations of code points
// less than or equal to 0xFFFF.
// An example of why Case 2 is required is comparing the following two Unicode code points:
// |-----------------------|------------|---------------------|-----------------|
// | Name | Code Point | UTF-8 Encoding | UTF-16 Encoding |
// |-----------------------|------------|---------------------|-----------------|
// | Replacement Character | U+FFFD | 0xEF 0xBF 0xBD | 0xFFFD |
// | Grinning Face | U+1F600 | 0xF0 0x9F 0x98 0x80 | 0xD83D 0xDE00 |
// |-----------------------|------------|---------------------|-----------------|
// A lexicographical comparison of the UTF-8 encodings of these code points would order
// "Replacement Character" _before_ "Grinning Face" because 0xEF is less than 0xF0. However, a
// direct comparison of the UTF-16 code units, as would be done in case 1, would erroneously
// produce the _opposite_ ordering, because 0xFFFD is _greater than_ 0xD83D. As it turns out,
// this relative ordering holds for all comparisons of UTF-16 code points requiring a surrogate
// pair with those that do not.
const n = Math.min(e.length, t.length);
for (let r = 0; r < n; r++) {
const n = e.charAt(r), i = t.charAt(r);
if (n !== i) return __PRIVATE_isSurrogate(n) === __PRIVATE_isSurrogate(i) ? __PRIVATE_primitiveComparator(n, i) : __PRIVATE_isSurrogate(n) ? 1 : -1;
}
// Use the lengths of the strings to determine the overall comparison result since either the
// strings were equal or one is a prefix of the other.
return __PRIVATE_primitiveComparator(e.length, t.length);
}
const B = 55296, L = 57343;
function __PRIVATE_isSurrogate(e) {
const t = e.charCodeAt(0);
return t >= B && t <= L;
}
/** Helper to compare arrays using isEqual(). */ function __PRIVATE_arrayEquals(e, t, n) {
return e.length === t.length && e.every(((e, r) => n(e, t[r])));
}
/**
* Returns the immediate lexicographically-following string. This is useful to
* construct an inclusive range for indexeddb iterators.
*/ function __PRIVATE_immediateSuccessor(e) {
// Return the input string, with an additional NUL byte appended.
return e + "\0";
}
/**
* @license
* Copyright 2017 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ const k = "__name__";
/**
* Path represents an ordered sequence of string segments.
*/ class BasePath {
constructor(e, t, n) {
void 0 === t ? t = 0 : t > e.length && fail(637, {
offset: t,
range: e.length
}), void 0 === n ? n = e.length - t : n > e.length - t && fail(1746, {
length: n,
range: e.length - t
}), this.segments = e, this.offset = t, this.len = n;
}
get length() {
return this.len;
}
isEqual(e) {
return 0 === BasePath.comparator(this, e);
}
child(e) {
const t = this.segments.slice(this.offset, this.limit());
return e instanceof BasePath ? e.forEach((e => {
t.push(e);
})) : t.push(e), this.construct(t);
}
/** The index of one past the last segment of the path. */ limit() {
return this.offset + this.length;
}
popFirst(e) {
return e = void 0 === e ? 1 : e, this.construct(this.segments, this.offset + e, this.length - e);
}
popLast() {
return this.construct(this.segments, this.offset, this.length - 1);
}
firstSegment() {
return this.segments[this.offset];
}
lastSegment() {
return this.get(this.length - 1);
}
get(e) {
return this.segments[this.offset + e];
}
isEmpty() {
return 0 === this.length;
}
isPrefixOf(e) {
if (e.length < this.length) return !1;
for (let t = 0; t < this.length; t++) if (this.get(t) !== e.get(t)) return !1;
return !0;
}
isImmediateParentOf(e) {
if (this.length + 1 !== e.length) return !1;
for (let t = 0; t < this.length; t++) if (this.get(t) !== e.get(t)) return !1;
return !0;
}
forEach(e) {
for (let t = this.offset, n = this.limit(); t < n; t++) e(this.segments[t]);
}
toArray() {
return this.segments.slice(this.offset, this.limit());
}
/**
* Compare 2 paths segment by segment, prioritizing numeric IDs
* (e.g., "__id123__") in numeric ascending order, followed by string
* segments in lexicographical order.
*/ static comparator(e, t) {
const n = Math.min(e.length, t.length);
for (let r = 0; r < n; r++) {
const n = BasePath.compareSegments(e.get(r), t.get(r));
if (0 !== n) return n;
}
return __PRIVATE_primitiveComparator(e.length, t.length);
}
static compareSegments(e, t) {
const n = BasePath.isNumericId(e), r = BasePath.isNumericId(t);
return n && !r ? -1 : !n && r ? 1 : n && r ? BasePath.extractNumericId(e).compare(BasePath.extractNumericId(t)) : __PRIVATE_compareUtf8Strings(e, t);
}
// Checks if a segment is a numeric ID (starts with "__id" and ends with "__").
static isNumericId(e) {
return e.startsWith("__id") && e.endsWith("__");
}
static extractNumericId(e) {
return bloomBlob.Integer.fromString(e.substring(4, e.length - 2));
}
}
/**
* A slash-separated path for navigating resources (documents and collections)
* within Firestore.
*
* @internal
*/ class ResourcePath extends BasePath {
construct(e, t, n) {
return new ResourcePath(e, t, n);
}
canonicalString() {
// NOTE: The client is ignorant of any path segments containing escape
// sequences (e.g. __id123__) and just passes them through raw (they exist
// for legacy reasons and should not be used frequently).
return this.toArray().join("/");
}
toString() {
return this.canonicalString();
}
/**
* Returns a string representation of this path
* where each path segment has been encoded with
* `encodeURIComponent`.
*/ toUriEncodedString() {
return this.toArray().map(encodeURIComponent).join("/");
}
/**
* Creates a resource path from the given slash-delimited string. If multiple
* arguments are provided, all components are combined. Leading and trailing
* slashes from all components are ignored.
*/ static fromString(...e) {
// NOTE: The client is ignorant of any path segments containing escape
// sequences (e.g. __id123__) and just passes them through raw (they exist
// for legacy reasons and should not be used frequently).
const t = [];
for (const n of e) {
if (n.indexOf("//") >= 0) throw new FirestoreError(N.INVALID_ARGUMENT, `Invalid segment (${n}). Paths must not contain // in them.`);
// Strip leading and trailing slashed.
t.push(...n.split("/").filter((e => e.length > 0)));
}
return new ResourcePath(t);
}
static emptyPath() {
return new ResourcePath([]);
}
}
const q = /^[_a-zA-Z][_a-zA-Z0-9]*$/;
/**
* A dot-separated path for navigating sub-objects within a document.
* @internal
*/ class FieldPath$1 extends BasePath {
construct(e, t, n) {
return new FieldPath$1(e, t, n);
}
/**
* Returns true if the string could be used as a segment in a field path
* without escaping.
*/ static isValidIdentifier(e) {
return q.test(e);
}
canonicalString() {
return this.toArray().map((e => (e = e.replace(/\\/g, "\\\\").replace(/`/g, "\\`"),
FieldPath$1.isValidIdentifier(e) || (e = "`" + e + "`"), e))).join(".");
}
toString() {
return this.canonicalString();
}
/**
* Returns true if this field references the key of a document.
*/ isKeyField() {
return 1 === this.length && this.get(0) === k;
}
/**
* The field designating the key of a document.
*/ static keyField() {
return new FieldPath$1([ k ]);
}
/**
* Parses a field string from the given server-formatted string.
*
* - Splitting the empty string is not allowed (for now at least).
* - Empty segments within the string (e.g. if there are two consecutive
* separators) are not allowed.
*
* TODO(b/37244157): we should make this more strict. Right now, it allows
* non-identifier path components, even if they aren't escaped.
*/ static fromServerFormat(e) {
const t = [];
let n = "", r = 0;
const __PRIVATE_addCurrentSegment = () => {
if (0 === n.length) throw new FirestoreError(N.INVALID_ARGUMENT, `Invalid field path (${e}). Paths must not be empty, begin with '.', end with '.', or contain '..'`);
t.push(n), n = "";
};
let i = !1;
for (;r < e.length; ) {
const t = e[r];
if ("\\" === t) {
if (r + 1 === e.length) throw new FirestoreError(N.INVALID_ARGUMENT, "Path has trailing escape character: " + e);
const t = e[r + 1];
if ("\\" !== t && "." !== t && "`" !== t) throw new FirestoreError(N.INVALID_ARGUMENT, "Path has invalid escape sequence: " + e);
n += t, r += 2;
} else "`" === t ? (i = !i, r++) : "." !== t || i ? (n += t, r++) : (__PRIVATE_addCurrentSegment(),
r++);
}
if (__PRIVATE_addCurrentSegment(), i) throw new FirestoreError(N.INVALID_ARGUMENT, "Unterminated ` in path: " + e);
return new FieldPath$1(t);
}
static emptyPath() {
return new FieldPath$1([]);
}
}
/**
* @license
* Copyright 2017 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @internal
*/ class DocumentKey {
constructor(e) {
this.path = e;
}
static fromPath(e) {
return new DocumentKey(ResourcePath.fromString(e));
}
static fromName(e) {
return new DocumentKey(ResourcePath.fromString(e).popFirst(5));
}
static empty() {
return new DocumentKey(ResourcePath.emptyPath());
}
get collectionGroup() {
return this.path.popLast().lastSegment();
}
/** Returns true if the document is in the specified collectionId. */ hasCollectionId(e) {
return this.path.length >= 2 && this.path.get(this.path.length - 2) === e;
}
/** Returns the collection group (i.e. the name of the parent collection) for this key. */ getCollectionGroup() {
return this.path.get(this.path.length - 2);
}
/** Returns the fully qualified path to the parent collection. */ getCollectionPath() {
return this.path.popLast();
}
isEqual(e) {
return null !== e && 0 === ResourcePath.comparator(this.path, e.path);
}
toString() {
return this.path.toString();
}
static comparator(e, t) {
return ResourcePath.comparator(e.path, t.path);
}
static isDocumentKey(e) {
return e.length % 2 == 0;
}
/**
* Creates and returns a new document key with the given segments.
*
* @param segments - The segments of the path to the document
* @returns A new instance of DocumentKey
*/ static fromSegments(e) {
return new DocumentKey(new ResourcePath(e.slice()));
}
}
/**
* @license
* Copyright 2017 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ function __PRIVATE_validateNonEmptyArgument(e, t, n) {
if (!n) throw new FirestoreError(N.INVALID_ARGUMENT, `Function ${e}() cannot be called with an empty ${t}.`);
}
/**
* Validates that two boolean options are not set at the same time.
* @internal
*/ function __PRIVATE_validateIsNotUsedTogether(e, t, n, r) {
if (!0 === t && !0 === r) throw new FirestoreError(N.INVALID_ARGUMENT, `${e} and ${n} cannot be used together.`);
}
/**
* Validates that `path` refers to a document (indicated by the fact it contains
* an even numbers of segments).
*/ function __PRIVATE_validateDocumentPath(e) {
if (!DocumentKey.isDocumentKey(e)) throw new FirestoreError(N.INVALID_ARGUMENT, `Invalid document reference. Document references must have an even number of segments, but ${e} has ${e.length}.`);
}
/**
* Validates that `path` refers to a collection (indicated by the fact it
* contains an odd numbers of segments).
*/ function __PRIVATE_validateCollectionPath(e) {
if (DocumentKey.isDocumentKey(e)) throw new FirestoreError(N.INVALID_ARGUMENT, `Invalid collection reference. Collection references must have an odd number of segments, but ${e} has ${e.length}.`);
}
/**
* Returns true if it's a non-null object without a custom prototype
* (i.e. excludes Array, Date, etc.).
*/ function __PRIVATE_isPlainObject(e) {
return "object" == typeof e && null !== e && (Object.getPrototypeOf(e) === Object.prototype || null === Object.getPrototypeOf(e));
}
/** Returns a string describing the type / value of the provided input. */ function __PRIVATE_valueDescription(e) {
if (void 0 === e) return "undefined";
if (null === e) return "null";
if ("string" == typeof e) return e.length > 20 && (e = `${e.substring(0, 20)}...`),
JSON.stringify(e);
if ("number" == typeof e || "boolean" == typeof e) return "" + e;
if ("object" == typeof e) {
if (e instanceof Array) return "an array";
{
const t =
/** try to get the constructor name for an object. */
function __PRIVATE_tryGetCustomObjectType(e) {
if (e.constructor) return e.constructor.name;
return null;
}
/**
* Casts `obj` to `T`, optionally unwrapping Compat types to expose the
* underlying instance. Throws if `obj` is not an instance of `T`.
*
* This cast is used in the Lite and Full SDK to verify instance types for
* arguments passed to the public API.
* @internal
*/ (e);
return t ? `a custom ${t} object` : "an object";
}
}
return "function" == typeof e ? "a function" : fail(12329, {
type: typeof e
});
}
function __PRIVATE_cast(e,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
t) {
if ("_delegate" in e && (
// Unwrap Compat types
// eslint-disable-next-line @typescript-eslint/no-explicit-any
e = e._delegate), !(e instanceof t)) {
if (t.name === e.constructor.name) throw new FirestoreError(N.INVALID_ARGUMENT, "Type does not match the expected instance. Did you pass a reference from a different Firestore SDK?");
{
const n = __PRIVATE_valueDescription(e);
throw new FirestoreError(N.INVALID_ARGUMENT, `Expected type '${t.name}', but it was: ${n}`);
}
}
return e;
}
function __PRIVATE_validatePositiveNumber(e, t) {
if (t <= 0) throw new FirestoreError(N.INVALID_ARGUMENT, `Function ${e}() requires a positive number, but it was: ${t}.`);
}
/**
* @license
* Copyright 2025 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Helper function to define a JSON schema {@link Property}.
* @private
* @internal
*/ function property(e, t) {
const n = {
typeString: e
};
return t && (n.value = t), n;
}
/**
* Validates the JSON object based on the provided schema, and narrows the type to the provided
* JSON schema.
* @private
* @internal
*
* @param json A JSON object to validate.
* @param scheme a {@link JsonSchema} that defines the properties to validate.
* @returns true if the JSON schema exists within the object. Throws a FirestoreError otherwise.
*/ function __PRIVATE_validateJSON(e, t) {
if (!__PRIVATE_isPlainObject(e)) throw new FirestoreError(N.INVALID_ARGUMENT, "JSON must be an object");
let n;
for (const r in t) if (t[r]) {
const i = t[r].typeString, s = "value" in t[r] ? {
value: t[r].value
} : void 0;
if (!(r in e)) {
n = `JSON missing required field: '${r}'`;
break;
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const o = e[r];
if (i && typeof o !== i) {
n = `JSON field '${r}' must be a ${i}.`;
break;
}
if (void 0 !== s && o !== s.value) {
n = `Expected '${r}' field to equal '${s.value}'`;
break;
}
}
if (n) throw new FirestoreError(N.INVALID_ARGUMENT, n);
return !0;
}
/**
* @license
* Copyright 2017 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// The earliest date supported by Firestore timestamps (0001-01-01T00:00:00Z).
const Q = -62135596800, $ = 1e6;
// Number of nanoseconds in a millisecond.
/**
* A `Timestamp` represents a point in time independent of any time zone or
* calendar, represented as seconds and fractions of seconds at nanosecond
* resolution in UTC Epoch time.
*
* It is encoded using the Proleptic Gregorian Calendar which extends the
* Gregorian calendar backwards to year one. It is encoded assuming all minutes
* are 60 seconds long, i.e. leap seconds are "smeared" so that no leap second
* table is needed for interpretation. Range is from 0001-01-01T00:00:00Z to
* 9999-12-31T23:59:59.999999999Z.
*
* For examples and further specifications, refer to the
* {@link https://github.com/google/protobuf/blob/master/src/google/protobuf/timestamp.proto | Timestamp definition}.
*/
class Timestamp {
/**
* Creates a new timestamp with the current date, with millisecond precision.
*
* @returns a new timestamp representing the current date.
*/
static now() {
return Timestamp.fromMillis(Date.now());
}
/**
* Creates a new timestamp from the given date.
*
* @param date - The date to initialize the `Timestamp` from.
* @returns A new `Timestamp` representing the same point in time as the given
* date.
*/ static fromDate(e) {
return Timestamp.fromMillis(e.getTime());
}
/**
* Creates a new timestamp from the given number of millisecond