UNPKG

@firebase/firestore

Version:

The Cloud Firestore component of the Firebase JS SDK.

1,372 lines (1,299 loc) • 305 kB
import { _registerComponent, registerVersion, _isFirebaseServerApp, _getProvider, getApp, _removeServiceInstance, SDK_VERSION } from '@firebase/app'; import { Component } from '@firebase/component'; import { Logger, LogLevel } from '@firebase/logger'; import { FirebaseError, getDefaultEmulatorHostnameAndPort, isCloudWorkstation, pingServer, updateEmulatorBanner, deepEqual, createMockUserToken, getModularInstance } from '@firebase/util'; import { Integer } from '@firebase/webchannel-wrapper/bloom-blob'; const A = "4.7.17"; /** * @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(t) { this.uid = t; } 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(t) { return t.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 P = "11.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. */ const R = new Logger("@firebase/firestore"); /** * 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(t) { R.setLogLevel(t); } function __PRIVATE_logDebug(t, ...e) { if (R.logLevel <= LogLevel.DEBUG) { const r = e.map(__PRIVATE_argToString); R.debug(`Firestore (${P}): ${t}`, ...r); } } function __PRIVATE_logError(t, ...e) { if (R.logLevel <= LogLevel.ERROR) { const r = e.map(__PRIVATE_argToString); R.error(`Firestore (${P}): ${t}`, ...r); } } /** * @internal */ function __PRIVATE_logWarn(t, ...e) { if (R.logLevel <= LogLevel.WARN) { const r = e.map(__PRIVATE_argToString); R.warn(`Firestore (${P}): ${t}`, ...r); } } /** * Converts an additional log parameter to a string representation. */ function __PRIVATE_argToString(t) { if ("string" == typeof t) return t; 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(t) { return JSON.stringify(t); }(t); } catch (e) { // Converting to JSON failed, just log the object directly return 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. */ function fail(t, e, r) { let n = "Unexpected state"; "string" == typeof e ? n = e : r = e, __PRIVATE__fail(t, n, r); } function __PRIVATE__fail(t, e, r) { // Log the failure in addition to throw an exception, just in case the // exception is swallowed. let n = `FIRESTORE (${P}) INTERNAL ASSERTION FAILED: ${e} (ID: ${t.toString(16)})`; if (void 0 !== r) try { n += " CONTEXT: " + JSON.stringify(r); } catch (t) { n += " CONTEXT: " + r; } // 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(n), new Error(n); } function __PRIVATE_hardAssert(t, e, r, n) { let i = "Unexpected state"; "string" == typeof r ? i = r : n = r, t || __PRIVATE__fail(e, i, n); } /** * Casts `obj` to `T`. In non-production builds, verifies that `obj` is an * instance of `T` before casting. */ function __PRIVATE_debugCast(t, // eslint-disable-next-line @typescript-eslint/no-explicit-any e) { return 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. */ const I = "ok", V = "cancelled", p = "unknown", y = "invalid-argument", g = "deadline-exceeded", w = "not-found", F = "already-exists", v = "permission-denied", D = "unauthenticated", b = "resource-exhausted", C = "failed-precondition", S = "aborted", N = "out-of-range", O = "unimplemented", q = "internal", B = "unavailable", $ = "data-loss"; /** An error returned by a Firestore operation. */ class FirestoreError extends FirebaseError { /** @hideconstructor */ constructor( /** * The backend error code associated with this error. */ t, /** * A custom error description. */ e) { super(t, e), this.code = t, this.message = e, // 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(((t, e) => { this.resolve = t, this.reject = 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. */ class __PRIVATE_OAuthToken { constructor(t, e) { this.user = e, this.type = "OAuth", this.headers = new Map, this.headers.set("Authorization", `Bearer ${t}`); } } /** * A CredentialsProvider that always yields an empty token. * @internal */ class __PRIVATE_EmptyAuthCredentialsProvider { getToken() { return Promise.resolve(null); } invalidateToken() {} start(t, e) { // Fire with initial user. t.enqueueRetryable((() => e(User.UNAUTHENTICATED))); } shutdown() {} } /** * A CredentialsProvider that always returns a constant token. Used for * emulator token mocking. */ class __PRIVATE_EmulatorAuthCredentialsProvider { constructor(t) { this.token = t, /** * 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(t, e) { this.changeListener = e, // Fire with initial user. t.enqueueRetryable((() => e(this.token.user))); } shutdown() { this.changeListener = null; } } /** Credential provider for the Lite SDK. */ class __PRIVATE_LiteAuthCredentialsProvider { constructor(t) { this.auth = null, t.onInit((t => { this.auth = t; })); } getToken() { return this.auth ? this.auth.getToken().then((t => t ? (__PRIVATE_hardAssert("string" == typeof t.accessToken, 42297, { t: t }), new __PRIVATE_OAuthToken(t.accessToken, new User(this.auth.getUid()))) : null)) : Promise.resolve(null); } invalidateToken() {} start(t, e) {} shutdown() {} } /* * 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(t, e, r) { this.i = t, this.o = e, this.u = r, this.type = "FirstParty", this.user = User.FIRST_PARTY, this.l = new Map; } /** * Gets an authorization token, using a provided factory function, or return * null. */ h() { return this.u ? this.u() : null; } get headers() { this.l.set("X-Goog-AuthUser", this.i); // Use array notation to prevent minification const t = this.h(); return t && this.l.set("Authorization", t), this.o && this.l.set("X-Goog-Iam-Authorization-Token", this.o), this.l; } } /* * 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(t, e, r) { this.i = t, this.o = e, this.u = r; } getToken() { return Promise.resolve(new __PRIVATE_FirstPartyToken(this.i, this.o, this.u)); } start(t, e) { // Fire with initial uid. t.enqueueRetryable((() => e(User.FIRST_PARTY))); } shutdown() {} invalidateToken() {} } class AppCheckToken { constructor(t) { this.value = t, this.type = "AppCheck", this.headers = new Map, t && t.length > 0 && this.headers.set("x-firebase-appcheck", this.value); } } /** AppCheck token provider for the Lite SDK. */ class __PRIVATE_LiteAppCheckTokenProvider { constructor(e, r) { this.m = r, this.appCheck = null, this.T = null, _isFirebaseServerApp(e) && e.settings.appCheckToken && (this.T = e.settings.appCheckToken), r.onInit((t => { this.appCheck = t; })); } getToken() { return this.T ? Promise.resolve(new AppCheckToken(this.T)) : this.appCheck ? this.appCheck.getToken().then((t => t ? (__PRIVATE_hardAssert("string" == typeof t.token, 3470, { tokenResult: t }), new AppCheckToken(t.token)) : null)) : Promise.resolve(null); } invalidateToken() {} start(t, e) {} shutdown() {} } /** * Builds a CredentialsProvider depending on the type of * the credentials passed in. */ /** * @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 DatabaseInfo { /** * Constructs a DatabaseInfo using the provided host, databaseId and * persistenceKey. * * @param databaseId - The database to use. * @param appId - The Firebase App Id. * @param persistenceKey - A unique identifier for this Firestore's local * storage (used in conjunction with the databaseId). * @param host - The Firestore backend host to connect to. * @param ssl - Whether to use SSL when connecting. * @param forceLongPolling - Whether to use the forceLongPolling option * when using WebChannel as the network transport. * @param autoDetectLongPolling - Whether to use the detectBufferingProxy * option when using WebChannel as the network transport. * @param longPollingOptions Options that configure long-polling. * @param useFetchStreams Whether to use the Fetch API instead of * XMLHTTPRequest */ constructor(t, e, r, n, i, s, o, a, u, _) { this.databaseId = t, this.appId = e, this.persistenceKey = r, this.host = n, this.ssl = i, this.forceLongPolling = s, this.autoDetectLongPolling = o, this.longPollingOptions = a, this.useFetchStreams = u, this.isUsingEmulator = _; } } /** The default database name for a project. */ const Q = "(default)"; /** * Represents the database ID a Firestore client is associated with. * @internal */ class DatabaseId { constructor(t, e) { this.projectId = t, this.database = e || Q; } static empty() { return new DatabaseId("", ""); } get isDefaultDatabase() { return this.database === Q; } isEqual(t) { return t instanceof DatabaseId && t.projectId === this.projectId && t.database === this.database; } } /** * @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(t) { // Polyfills for IE and WebWorker by using `self` and `msCrypto` when `crypto` is not available. const e = // eslint-disable-next-line @typescript-eslint/no-explicit-any "undefined" != typeof self && (self.crypto || self.msCrypto), r = new Uint8Array(t); if (e && "function" == typeof e.getRandomValues) e.getRandomValues(r); else // Falls back to Math.random for (let e = 0; e < t; e++) r[e] = Math.floor(256 * Math.random()); return r; } /** * @license * Copyright 2023 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. */ /** * An instance of the Platform's 'TextEncoder' implementation. */ /** * @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 t = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", e = 62 * Math.floor(256 / 62); // The largest byte value that is a multiple of `char.length`. let r = ""; for (;r.length < 20; ) { const n = __PRIVATE_randomBytes(40); for (let i = 0; i < n.length; ++i) // Only accept values that are [0, maxMultiple), this ensures they can // be evenly mapped to indices of `chars` via a modulo operation. r.length < 20 && n[i] < e && (r += t.charAt(n[i] % 62)); } return r; } } function __PRIVATE_primitiveComparator(t, e) { return t < e ? -1 : t > e ? 1 : 0; } /** Compare strings in UTF-8 encoded byte order */ function __PRIVATE_compareUtf8Strings(t, e) { let r = 0; for (;r < t.length && r < e.length; ) { const n = t.codePointAt(r), i = e.codePointAt(r); if (n !== i) { if (n < 128 && i < 128) // ASCII comparison return __PRIVATE_primitiveComparator(n, i); { // Lazy instantiate TextEncoder const s = new TextEncoder, o = __PRIVATE_compareByteArrays(s.encode(__PRIVATE_getUtf8SafeSubstring(t, r)), s.encode(__PRIVATE_getUtf8SafeSubstring(e, r))); // UTF-8 encode the character at index i for byte comparison. return 0 !== o ? o : __PRIVATE_primitiveComparator(n, i); } } // Increment by 2 for surrogate pairs, 1 otherwise r += n > 65535 ? 2 : 1; } // Compare lengths if all characters are equal return __PRIVATE_primitiveComparator(t.length, e.length); } function __PRIVATE_getUtf8SafeSubstring(t, e) { return t.codePointAt(e) > 65535 ? t.substring(e, e + 2) : t.substring(e, e + 1); } function __PRIVATE_compareByteArrays(t, e) { for (let r = 0; r < t.length && r < e.length; ++r) if (t[r] !== e[r]) return __PRIVATE_primitiveComparator(t[r], e[r]); return __PRIVATE_primitiveComparator(t.length, e.length); } /** Helper to compare arrays using isEqual(). */ function __PRIVATE_arrayEquals(t, e, r) { return t.length === e.length && t.every(((t, n) => r(t, e[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. */ const L = "__name__"; /** * Path represents an ordered sequence of string segments. */ class BasePath { constructor(t, e, r) { void 0 === e ? e = 0 : e > t.length && fail(637, { offset: e, range: t.length }), void 0 === r ? r = t.length - e : r > t.length - e && fail(1746, { length: r, range: t.length - e }), this.segments = t, this.offset = e, this.len = r; } get length() { return this.len; } isEqual(t) { return 0 === BasePath.comparator(this, t); } child(t) { const e = this.segments.slice(this.offset, this.limit()); return t instanceof BasePath ? t.forEach((t => { e.push(t); })) : e.push(t), this.construct(e); } /** The index of one past the last segment of the path. */ limit() { return this.offset + this.length; } popFirst(t) { return t = void 0 === t ? 1 : t, this.construct(this.segments, this.offset + t, this.length - t); } 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(t) { return this.segments[this.offset + t]; } isEmpty() { return 0 === this.length; } isPrefixOf(t) { if (t.length < this.length) return !1; for (let e = 0; e < this.length; e++) if (this.get(e) !== t.get(e)) return !1; return !0; } isImmediateParentOf(t) { if (this.length + 1 !== t.length) return !1; for (let e = 0; e < this.length; e++) if (this.get(e) !== t.get(e)) return !1; return !0; } forEach(t) { for (let e = this.offset, r = this.limit(); e < r; e++) t(this.segments[e]); } 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(t, e) { const r = Math.min(t.length, e.length); for (let n = 0; n < r; n++) { const r = BasePath.compareSegments(t.get(n), e.get(n)); if (0 !== r) return r; } return __PRIVATE_primitiveComparator(t.length, e.length); } static compareSegments(t, e) { const r = BasePath.isNumericId(t), n = BasePath.isNumericId(e); return r && !n ? -1 : !r && n ? 1 : r && n ? BasePath.extractNumericId(t).compare(BasePath.extractNumericId(e)) : __PRIVATE_compareUtf8Strings(t, e); } // Checks if a segment is a numeric ID (starts with "__id" and ends with "__"). static isNumericId(t) { return t.startsWith("__id") && t.endsWith("__"); } static extractNumericId(t) { return Integer.fromString(t.substring(4, t.length - 2)); } } /** * A slash-separated path for navigating resources (documents and collections) * within Firestore. * * @internal */ class ResourcePath extends BasePath { construct(t, e, r) { return new ResourcePath(t, e, r); } 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(...t) { // 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 e = []; for (const r of t) { if (r.indexOf("//") >= 0) throw new FirestoreError(y, `Invalid segment (${r}). Paths must not contain // in them.`); // Strip leading and trailing slashed. e.push(...r.split("/").filter((t => t.length > 0))); } return new ResourcePath(e); } static emptyPath() { return new ResourcePath([]); } } const k = /^[_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(t, e, r) { return new FieldPath$1(t, e, r); } /** * Returns true if the string could be used as a segment in a field path * without escaping. */ static isValidIdentifier(t) { return k.test(t); } canonicalString() { return this.toArray().map((t => (t = t.replace(/\\/g, "\\\\").replace(/`/g, "\\`"), FieldPath$1.isValidIdentifier(t) || (t = "`" + t + "`"), t))).join("."); } toString() { return this.canonicalString(); } /** * Returns true if this field references the key of a document. */ isKeyField() { return 1 === this.length && this.get(0) === L; } /** * The field designating the key of a document. */ static keyField() { return new FieldPath$1([ L ]); } /** * 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(t) { const e = []; let r = "", n = 0; const __PRIVATE_addCurrentSegment = () => { if (0 === r.length) throw new FirestoreError(y, `Invalid field path (${t}). Paths must not be empty, begin with '.', end with '.', or contain '..'`); e.push(r), r = ""; }; let i = !1; for (;n < t.length; ) { const e = t[n]; if ("\\" === e) { if (n + 1 === t.length) throw new FirestoreError(y, "Path has trailing escape character: " + t); const e = t[n + 1]; if ("\\" !== e && "." !== e && "`" !== e) throw new FirestoreError(y, "Path has invalid escape sequence: " + t); r += e, n += 2; } else "`" === e ? (i = !i, n++) : "." !== e || i ? (r += e, n++) : (__PRIVATE_addCurrentSegment(), n++); } if (__PRIVATE_addCurrentSegment(), i) throw new FirestoreError(y, "Unterminated ` in path: " + t); return new FieldPath$1(e); } 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(t) { this.path = t; } static fromPath(t) { return new DocumentKey(ResourcePath.fromString(t)); } static fromName(t) { return new DocumentKey(ResourcePath.fromString(t).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(t) { return this.path.length >= 2 && this.path.get(this.path.length - 2) === t; } /** 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(t) { return null !== t && 0 === ResourcePath.comparator(this.path, t.path); } toString() { return this.path.toString(); } static comparator(t, e) { return ResourcePath.comparator(t.path, e.path); } static isDocumentKey(t) { return t.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(t) { return new DocumentKey(new ResourcePath(t.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(t, e, r) { if (!r) throw new FirestoreError(y, `Function ${t}() cannot be called with an empty ${e}.`); } /** * Validates that two boolean options are not set at the same time. * @internal */ /** * Validates that `path` refers to a document (indicated by the fact it contains * an even numbers of segments). */ function __PRIVATE_validateDocumentPath(t) { if (!DocumentKey.isDocumentKey(t)) throw new FirestoreError(y, `Invalid document reference. Document references must have an even number of segments, but ${t} has ${t.length}.`); } /** * Validates that `path` refers to a collection (indicated by the fact it * contains an odd numbers of segments). */ function __PRIVATE_validateCollectionPath(t) { if (DocumentKey.isDocumentKey(t)) throw new FirestoreError(y, `Invalid collection reference. Collection references must have an odd number of segments, but ${t} has ${t.length}.`); } /** * Returns true if it's a non-null object without a custom prototype * (i.e. excludes Array, Date, etc.). */ /** Returns a string describing the type / value of the provided input. */ function __PRIVATE_valueDescription(t) { if (void 0 === t) return "undefined"; if (null === t) return "null"; if ("string" == typeof t) return t.length > 20 && (t = `${t.substring(0, 20)}...`), JSON.stringify(t); if ("number" == typeof t || "boolean" == typeof t) return "" + t; if ("object" == typeof t) { if (t instanceof Array) return "an array"; { const e = /** try to get the constructor name for an object. */ function __PRIVATE_tryGetCustomObjectType(t) { if (t.constructor) return t.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 */ (t); return e ? `a custom ${e} object` : "an object"; } } return "function" == typeof t ? "a function" : fail(12329, { type: typeof t }); } function __PRIVATE_cast(t, // eslint-disable-next-line @typescript-eslint/no-explicit-any e) { if ("_delegate" in t && ( // Unwrap Compat types // eslint-disable-next-line @typescript-eslint/no-explicit-any t = t._delegate), !(t instanceof e)) { if (e.name === t.constructor.name) throw new FirestoreError(y, "Type does not match the expected instance. Did you pass a reference from a different Firestore SDK?"); { const r = __PRIVATE_valueDescription(t); throw new FirestoreError(y, `Expected type '${e.name}', but it was: ${r}`); } } return t; } function __PRIVATE_validatePositiveNumber(t, e) { if (e <= 0) throw new FirestoreError(y, `Function ${t}() requires a positive number, but it was: ${e}.`); } /** * @license * Copyright 2023 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. */ /** * Compares two `ExperimentalLongPollingOptions` objects for equality. */ /** * Creates and returns a new `ExperimentalLongPollingOptions` with the same * option values as the given instance. */ function __PRIVATE_cloneLongPollingOptions(t) { const e = {}; return void 0 !== t.timeoutSeconds && (e.timeoutSeconds = t.timeoutSeconds), e; } /** * @license * Copyright 2023 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 value returned from the most recent invocation of * `generateUniqueDebugId()`, or null if it has never been invoked. */ let M = null; /** * Generates and returns an initial value for `lastUniqueDebugId`. * * The returned value is randomly selected from a range of integers that are * represented as 8 hexadecimal digits. This means that (within reason) any * numbers generated by incrementing the returned number by 1 will also be * represented by 8 hexadecimal digits. This leads to all "IDs" having the same * length when converted to a hexadecimal string, making reading logs containing * these IDs easier to follow. And since the return value is randomly selected * it will help to differentiate between logs from different executions. */ /** * Generates and returns a unique ID as a hexadecimal string. * * The returned ID is intended to be used in debug logging messages to help * correlate log messages that may be spatially separated in the logs, but * logically related. For example, a network connection could include the same * "debug ID" string in all of its log messages to help trace a specific * connection over time. * * @return the 10-character generated ID (e.g. "0xa1b2c3d4"). */ function __PRIVATE_generateUniqueDebugId() { return null === M ? M = function __PRIVATE_generateInitialUniqueDebugId() { return 268435456 + Math.round(2147483648 * Math.random()); }() : M++, "0x" + M.toString(16); } /** * @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. */ /** * Returns whether a variable is either undefined or null. */ function __PRIVATE_isNullOrUndefined(t) { return null == t; } /** Returns whether the value represents -0. */ function __PRIVATE_isNegativeZero(t) { // Detect if the value is -0.0. Based on polyfill from // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is return 0 === t && 1 / t == -1 / 0; } /** * Returns whether a value is an integer and in the safe integer range * @param value - The value to test for being an integer and in the safe range */ /** * @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. */ const U = "RestConnection", x = { BatchGetDocuments: "batchGet", Commit: "commit", RunQuery: "runQuery", RunAggregationQuery: "runAggregationQuery" }; /** * Maps RPC names to the corresponding REST endpoint name. * * We use array notation to avoid mangling. */ /** * Base class for all Rest-based connections to the backend (WebChannel and * HTTP). */ class __PRIVATE_RestConnection { get A() { // Both `invokeRPC()` and `invokeStreamingRPC()` use their `path` arguments to determine // where to run the query, and expect the `request` to NOT specify the "path". return !1; } constructor(t) { this.databaseInfo = t, this.databaseId = t.databaseId; const e = t.ssl ? "https" : "http", r = encodeURIComponent(this.databaseId.projectId), n = encodeURIComponent(this.databaseId.database); this.P = e + "://" + t.host, this.R = `projects/${r}/databases/${n}`, this.I = this.databaseId.database === Q ? `project_id=${r}` : `project_id=${r}&database_id=${n}`; } V(t, e, r, n, i) { const s = __PRIVATE_generateUniqueDebugId(), o = this.p(t, e.toUriEncodedString()); __PRIVATE_logDebug(U, `Sending RPC '${t}' ${s}:`, o, r); const a = { "google-cloud-resource-prefix": this.R, "x-goog-request-params": this.I }; this.F(a, n, i); const {host: u} = new URL(o), _ = isCloudWorkstation(u); return this.v(t, o, a, r, _).then((e => (__PRIVATE_logDebug(U, `Received RPC '${t}' ${s}: `, e), e)), (e => { throw __PRIVATE_logWarn(U, `RPC '${t}' ${s} failed with error: `, e, "url: ", o, "request:", r), e; })); } D(t, e, r, n, i, s) { // The REST API automatically aggregates all of the streamed results, so we // can just use the normal invoke() method. return this.V(t, e, r, n, i); } /** * Modifies the headers for a request, adding any authorization token if * present and any additional headers for the request. */ F(t, e, r) { t["X-Goog-Api-Client"] = // SDK_VERSION is updated to different value at runtime depending on the entry point, // so we need to get its value when we need it in a function. function __PRIVATE_getGoogApiClientValue() { return "gl-js/ fire/" + P; }(), // Content-Type: text/plain will avoid preflight requests which might // mess with CORS and redirects by proxies. If we add custom headers // we will need to change this code to potentially use the $httpOverwrite // parameter supported by ESF to avoid triggering preflight requests. t["Content-Type"] = "text/plain", this.databaseInfo.appId && (t["X-Firebase-GMPID"] = this.databaseInfo.appId), e && e.headers.forEach(((e, r) => t[r] = e)), r && r.headers.forEach(((e, r) => t[r] = e)); } p(t, e) { const r = x[t]; return `${this.P}/v1/${e}:${r}`; } /** * Closes and cleans up any resources associated with the connection. This * implementation is a no-op because there are no resources associated * with the RestConnection that need to be cleaned up. */ terminate() { // No-op } } /** * @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. */ /** * Error Codes describing the different ways GRPC can fail. These are copied * directly from GRPC's sources here: * * https://github.com/grpc/grpc/blob/bceec94ea4fc5f0085d81235d8e1c06798dc341a/include/grpc%2B%2B/impl/codegen/status_code_enum.h * * Important! The names of these identifiers matter because the string forms * are used for reverse lookups from the webchannel stream. Do NOT change the * names of these identifiers or change this into a const enum. */ var j, z; /** * Converts an HTTP Status Code to the equivalent error code. * * @param status - An HTTP Status Code, like 200, 404, 503, etc. * @returns The equivalent Code. Unknown status codes are mapped to * Code.UNKNOWN. */ function __PRIVATE_mapCodeFromHttpStatus(t) { if (void 0 === t) return __PRIVATE_logError("RPC_ERROR", "HTTP error has no status"), p; // The canonical error codes for Google APIs [1] specify mapping onto HTTP // status codes but the mapping is not bijective. In each case of ambiguity // this function chooses a primary error. // [1] // https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto switch (t) { case 200: // OK return I; case 400: // Bad Request return C; // Other possibilities based on the forward mapping // return Code.INVALID_ARGUMENT; // return Code.OUT_OF_RANGE; case 401: // Unauthorized return D; case 403: // Forbidden return v; case 404: // Not Found return w; case 409: // Conflict return S; // Other possibilities: // return Code.ALREADY_EXISTS; case 416: // Range Not Satisfiable return N; case 429: // Too Many Requests return b; case 499: // Client Closed Request return V; case 500: // Internal Server Error return p; // Other possibilities: // return Code.INTERNAL; // return Code.DATA_LOSS; case 501: // Unimplemented return O; case 503: // Service Unavailable return B; case 504: // Gateway Timeout return g; default: return t >= 200 && t < 300 ? I : t >= 400 && t < 500 ? C : t >= 500 && t < 600 ? q : p; } } /** * @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. */ /** * A Rest-based connection that relies on the native HTTP stack * (e.g. `fetch` or a polyfill). */ (z = j || (j = {}))[z.OK = 0] = "OK", z[z.CANCELLED = 1] = "CANCELLED", z[z.UNKNOWN = 2] = "UNKNOWN", z[z.INVALID_ARGUMENT = 3] = "INVALID_ARGUMENT", z[z.DEADLINE_EXCEEDED = 4] = "DEADLINE_EXCEEDED", z[z.NOT_FOUND = 5] = "NOT_FOUND", z[z.ALREADY_EXISTS = 6] = "ALREADY_EXISTS", z[z.PERMISSION_DENIED = 7] = "PERMISSION_DENIED", z[z.UNAUTHENTICATED = 16] = "UNAUTHENTICATED", z[z.RESOURCE_EXHAUSTED = 8] = "RESOURCE_EXHAUSTED", z[z.FAILED_PRECONDITION = 9] = "FAILED_PRECONDITION", z[z.ABORTED = 10] = "ABORTED", z[z.OUT_OF_RANGE = 11] = "OUT_OF_RANGE", z[z.UNIMPLEMENTED = 12] = "UNIMPLEMENTED", z[z.INTERNAL = 13] = "INTERNAL", z[z.UNAVAILABLE = 14] = "UNAVAILABLE", z[z.DATA_LOSS = 15] = "DATA_LOSS"; class __PRIVATE_FetchConnection extends __PRIVATE_RestConnection { C(t, e) { throw new Error("Not supported by FetchConnection"); } async v(t, e, r, n, i) { var s; const o = JSON.stringify(n); let a; try { const t = { method: "POST", headers: r, body: o }; i && (t.credentials = "include"), a = await fetch(e, t); } catch (t) { const e = t; throw new FirestoreError(__PRIVATE_mapCodeFromHttpStatus(e.status), "Request failed with error: " + e.statusText); } if (!a.ok) { let t = await a.json(); Array.isArray(t) && (t = t[0]); const e = null === (s = null == t ? void 0 : t.error) || void 0 === s ? void 0 : s.message; throw new FirestoreError(__PRIVATE_mapCodeFromHttpStatus(a.status), `Request failed with error: ${null != e ? e : a.statusText}`); } return a.json(); } } /** * @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. */ /** Initializes the HTTP connection for the REST API. */ /** * @license * Copyright 2023 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * yo