@firebase/firestore
Version:
The Cloud Firestore component of the Firebase JS SDK.
1,386 lines (1,321 loc) • 225 kB
JavaScript
import { _getProvider as t, getApp as e, _removeServiceInstance as n, _registerComponent as r, registerVersion as s, SDK_VERSION as i } from "@firebase/app";
import { Component as o } from "@firebase/component";
import { createMockUserToken as u, getModularInstance as c } from "@firebase/util";
import { Logger as a, LogLevel as h } from "@firebase/logger";
/**
* @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 l = "8.6.7";
/**
* @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 f {
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. */ f.UNAUTHENTICATED = new f(null),
// TODO(mikelehen): Look into getting a proper uid-equivalent for
// non-FirebaseAuth providers.
f.GOOGLE_CREDENTIALS = new f("google-credentials-uid"), f.FIRST_PARTY = new f("first-party-uid");
/**
* @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 d = new a("@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 w(t) {
d.setLogLevel(t);
}
function m(t, ...e) {
if (d.logLevel <= h.DEBUG) {
const n = e.map(_);
d.debug(`Firestore (${l}): ${t}`, ...n);
}
}
function p(t, ...e) {
if (d.logLevel <= h.ERROR) {
const n = e.map(_);
d.error(`Firestore (${l}): ${t}`, ...n);
}
}
function y(t, ...e) {
if (d.logLevel <= h.WARN) {
const n = e.map(_);
d.warn(`Firestore (${l}): ${t}`, ...n);
}
}
/**
* Converts an additional log parameter to a string representation.
*/ function _(t) {
if ("string" == typeof t) return t;
try {
return e = t, JSON.stringify(e);
} catch (e) {
// Converting to JSON failed, just log the object directly
return t;
}
/**
* @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. */
var 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.
*/
/**
* Unconditionally fails, throwing an Error with the given message.
* Messages are stripped in production builds.
*
* Returns `never` and can be used in expressions:
* @example
* let futureVar = fail('not implemented yet');
*/ function g(t = "Unexpected state") {
// Log the failure in addition to throw an exception, just in case the
// exception is swallowed.
const e = `FIRESTORE (${l}) INTERNAL ASSERTION FAILED: ` + t;
// 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 p(e), new Error(e);
}
/**
* Fails if the given assertion condition is false, throwing an Error with the
* given message if it did.
*
* Messages are stripped in production builds.
*/ function v(t, e) {
t || g();
}
/**
* Casts `obj` to `T`. In non-production builds, verifies that `obj` is an
* instance of `T` before casting.
*/ function b(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 E = "ok", T = "cancelled", I = "unknown", A = "invalid-argument", P = "deadline-exceeded", R = "not-found", V = "already-exists", N = "permission-denied", D = "unauthenticated", $ = "resource-exhausted", F = "failed-precondition", S = "aborted", q = "out-of-range", x = "unimplemented", O = "internal", C = "unavailable", L = "data-loss";
/** An error returned by a Firestore operation. */ class U extends Error {
/** @hideconstructor */
constructor(
/**
* The backend error code associated with this error.
*/
t,
/**
* A custom error description.
*/
e) {
super(e), this.code = t, this.message = e,
/** The custom name for all FirestoreErrors. */
this.name = "FirebaseError",
// 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 k {
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 j {
constructor(t, e) {
this.user = e, this.type = "OAuth", this.authHeaders = {},
// Set the headers using Object Literal notation to avoid minification
this.authHeaders.Authorization = `Bearer ${t}`;
}
}
/** A CredentialsProvider that always yields an empty token. */ class M {
constructor() {
/**
* 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(null);
}
invalidateToken() {}
setChangeListener(t, e) {
this.changeListener = e,
// Fire with initial user.
t.enqueueRetryable((() => e(f.UNAUTHENTICATED)));
}
removeChangeListener() {
this.changeListener = null;
}
}
/**
* A CredentialsProvider that always returns a constant token. Used for
* emulator token mocking.
*/ class B {
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() {}
setChangeListener(t, e) {
this.changeListener = e,
// Fire with initial user.
t.enqueueRetryable((() => e(this.token.user)));
}
removeChangeListener() {
this.changeListener = null;
}
}
class Q {
constructor(t) {
/** Tracks the current User. */
this.currentUser = f.UNAUTHENTICATED,
/** Promise that allows blocking on the initialization of Firebase Auth. */
this.t = new k,
/**
* Counter used to detect if the token changed while a getToken request was
* outstanding.
*/
this.i = 0, this.forceRefresh = !1, this.auth = null, this.asyncQueue = null, this.o = () => {
this.i++, this.currentUser = this.u(), this.t.resolve(), this.changeListener && this.asyncQueue.enqueueRetryable((() => this.changeListener(this.currentUser)));
};
const e = t => {
m("FirebaseCredentialsProvider", "Auth detected"), this.auth = t, this.auth.addAuthTokenListener(this.o);
};
t.onInit((t => e(t))),
// 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 n = t.getImmediate({
optional: !0
});
n ? e(n) : (
// If auth is still not available, proceed with `null` user
m("FirebaseCredentialsProvider", "Auth not yet detected"), this.t.resolve());
}
}), 0);
}
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 t = this.i, e = this.forceRefresh;
return this.forceRefresh = !1, this.auth ? this.auth.getToken(e).then((e =>
// 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 !== t ? (m("FirebaseCredentialsProvider", "getToken aborted due to token change."),
this.getToken()) : e ? (v("string" == typeof e.accessToken), new j(e.accessToken, this.currentUser)) : null)) : Promise.resolve(null);
}
invalidateToken() {
this.forceRefresh = !0;
}
setChangeListener(t, e) {
this.asyncQueue = t,
// Blocks the AsyncQueue until the next user is available.
this.asyncQueue.enqueueRetryable((async () => {
await this.t.promise, await e(this.currentUser), this.changeListener = e;
}));
}
removeChangeListener() {
this.auth && this.auth.removeAuthTokenListener(this.o), this.changeListener = () => Promise.resolve();
}
// 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 t = this.auth && this.auth.getUid();
return v(null === t || "string" == typeof t), new f(t);
}
}
/*
* 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 z {
constructor(t, e, n) {
this.h = t, this.l = e, this.m = n, this.type = "FirstParty", this.user = f.FIRST_PARTY;
}
get authHeaders() {
const t = {
"X-Goog-AuthUser": this.l
}, e = this.h.auth.getAuthHeaderValueForFirstParty([]);
// Use array notation to prevent minification
return e && (t.Authorization = e), this.m && (t["X-Goog-Iam-Authorization-Token"] = this.m),
t;
}
}
/*
* 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 W {
constructor(t, e, n) {
this.h = t, this.l = e, this.m = n;
}
getToken() {
return Promise.resolve(new z(this.h, this.l, this.m));
}
setChangeListener(t, e) {
// Fire with initial uid.
t.enqueueRetryable((() => e(f.FIRST_PARTY)));
}
removeChangeListener() {}
invalidateToken() {}
}
/**
* 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 G {
/**
* 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 useFetchStreams Whether to use the Fetch API instead of
* XMLHTTPRequest
*/
constructor(t, e, n, r, s, i, o, u) {
this.databaseId = t, this.appId = e, this.persistenceKey = n, this.host = r, this.ssl = s,
this.forceLongPolling = i, this.autoDetectLongPolling = o, this.useFetchStreams = u;
}
}
/** The default database name for a project. */
/** Represents the database ID a Firestore client is associated with. */
class H {
constructor(t, e) {
this.projectId = t, this.database = e || "(default)";
}
get isDefaultDatabase() {
return "(default)" === this.database;
}
isEqual(t) {
return t instanceof H && t.projectId === this.projectId && t.database === this.database;
}
}
/**
* @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.
*/
/**
* Path represents an ordered sequence of string segments.
*/
class Y {
constructor(t, e, n) {
void 0 === e ? e = 0 : e > t.length && g(), void 0 === n ? n = t.length - e : n > t.length - e && g(),
this.segments = t, this.offset = e, this.len = n;
}
get length() {
return this.len;
}
isEqual(t) {
return 0 === Y.comparator(this, t);
}
child(t) {
const e = this.segments.slice(this.offset, this.limit());
return t instanceof Y ? 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, n = this.limit(); e < n; e++) t(this.segments[e]);
}
toArray() {
return this.segments.slice(this.offset, this.limit());
}
static comparator(t, e) {
const n = Math.min(t.length, e.length);
for (let r = 0; r < n; r++) {
const n = t.get(r), s = e.get(r);
if (n < s) return -1;
if (n > s) return 1;
}
return t.length < e.length ? -1 : t.length > e.length ? 1 : 0;
}
}
/**
* A slash-separated path for navigating resources (documents and collections)
* within Firestore.
*/ class K extends Y {
construct(t, e, n) {
return new K(t, e, 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();
}
/**
* 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 n of t) {
if (n.indexOf("//") >= 0) throw new U(A, `Invalid segment (${n}). Paths must not contain // in them.`);
// Strip leading and traling slashed.
e.push(...n.split("/").filter((t => t.length > 0)));
}
return new K(e);
}
static emptyPath() {
return new K([]);
}
}
const J = /^[_a-zA-Z][_a-zA-Z0-9]*$/;
/** A dot-separated path for navigating sub-objects within a document. */ class Z extends Y {
construct(t, e, n) {
return new Z(t, e, n);
}
/**
* Returns true if the string could be used as a segment in a field path
* without escaping.
*/ static isValidIdentifier(t) {
return J.test(t);
}
canonicalString() {
return this.toArray().map((t => (t = t.replace(/\\/g, "\\\\").replace(/`/g, "\\`"),
Z.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 && "__name__" === this.get(0);
}
/**
* The field designating the key of a document.
*/ static keyField() {
return new Z([ "__name__" ]);
}
/**
* 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 n = "", r = 0;
const s = () => {
if (0 === n.length) throw new U(A, `Invalid field path (${t}). Paths must not be empty, begin with '.', end with '.', or contain '..'`);
e.push(n), n = "";
};
let i = !1;
for (;r < t.length; ) {
const e = t[r];
if ("\\" === e) {
if (r + 1 === t.length) throw new U(A, "Path has trailing escape character: " + t);
const e = t[r + 1];
if ("\\" !== e && "." !== e && "`" !== e) throw new U(A, "Path has invalid escape sequence: " + t);
n += e, r += 2;
} else "`" === e ? (i = !i, r++) : "." !== e || i ? (n += e, r++) : (s(), r++);
}
if (s(), i) throw new U(A, "Unterminated ` in path: " + t);
return new Z(e);
}
static emptyPath() {
return new Z([]);
}
}
/**
* @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 X {
constructor(t) {
this.path = t;
}
static fromPath(t) {
return new X(K.fromString(t));
}
static fromName(t) {
return new X(K.fromString(t).popFirst(5));
}
/** 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;
}
isEqual(t) {
return null !== t && 0 === K.comparator(this.path, t.path);
}
toString() {
return this.path.toString();
}
static comparator(t, e) {
return K.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 X(new K(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 tt(t, e, n) {
if (!n) throw new U(A, `Function ${t}() cannot be called with an empty ${e}.`);
}
/**
* Validates that two boolean options are not set at the same time.
*/
/**
* Validates that `path` refers to a document (indicated by the fact it contains
* an even numbers of segments).
*/
function et(t) {
if (!X.isDocumentKey(t)) throw new U(A, `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 nt(t) {
if (X.isDocumentKey(t)) throw new U(A, `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 rt(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 =
/** Hacky method to try to get the constructor name for an object. */
function(t) {
if (t.constructor) {
const e = /function\s+([^\s(]+)\s*\(/.exec(t.constructor.toString());
if (e && e.length > 1) return e[1];
}
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.
*/ (t);
return e ? `a custom ${e} object` : "an object";
}
}
return "function" == typeof t ? "a function" : g();
}
function st(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 U(A, "Type does not match the expected instance. Did you pass a reference from a different Firestore SDK?");
{
const n = rt(t);
throw new U(A, `Expected type '${e.name}', but it was: ${n}`);
}
}
return t;
}
function it(t, e) {
if (e <= 0) throw new U(A, `Function ${t}() requires a positive number, but it was: ${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.
*/
/**
* Returns whether a variable is either undefined or null.
*/ function ot(t) {
return null == t;
}
/** Returns whether the value represents -0. */ function ut(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 ct = {
BatchGetDocuments: "batchGet",
Commit: "commit",
RunQuery: "runQuery"
};
/**
* Maps RPC names to the corresponding REST endpoint name.
*
* We use array notation to avoid mangling.
*/
/**
* @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 at, ht;
/**
* 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 lt(t) {
if (void 0 === t) return p("RPC_ERROR", "HTTP error has no status"), I;
// 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 E;
case 400:
// Bad Request
return F;
// 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 N;
case 404:
// Not Found
return R;
case 409:
// Conflict
return S;
// Other possibilities:
// return Code.ALREADY_EXISTS;
case 416:
// Range Not Satisfiable
return q;
case 429:
// Too Many Requests
return $;
case 499:
// Client Closed Request
return T;
case 500:
// Internal Server Error
return I;
// Other possibilities:
// return Code.INTERNAL;
// return Code.DATA_LOSS;
case 501:
// Unimplemented
return x;
case 503:
// Service Unavailable
return C;
case 504:
// Gateway Timeout
return P;
default:
return t >= 200 && t < 300 ? E : t >= 400 && t < 500 ? F : t >= 500 && t < 600 ? O : I;
}
}
/**
* @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).
*/ (ht = at || (at = {}))[ht.OK = 0] = "OK", ht[ht.CANCELLED = 1] = "CANCELLED",
ht[ht.UNKNOWN = 2] = "UNKNOWN", ht[ht.INVALID_ARGUMENT = 3] = "INVALID_ARGUMENT",
ht[ht.DEADLINE_EXCEEDED = 4] = "DEADLINE_EXCEEDED", ht[ht.NOT_FOUND = 5] = "NOT_FOUND",
ht[ht.ALREADY_EXISTS = 6] = "ALREADY_EXISTS", ht[ht.PERMISSION_DENIED = 7] = "PERMISSION_DENIED",
ht[ht.UNAUTHENTICATED = 16] = "UNAUTHENTICATED", ht[ht.RESOURCE_EXHAUSTED = 8] = "RESOURCE_EXHAUSTED",
ht[ht.FAILED_PRECONDITION = 9] = "FAILED_PRECONDITION", ht[ht.ABORTED = 10] = "ABORTED",
ht[ht.OUT_OF_RANGE = 11] = "OUT_OF_RANGE", ht[ht.UNIMPLEMENTED = 12] = "UNIMPLEMENTED",
ht[ht.INTERNAL = 13] = "INTERNAL", ht[ht.UNAVAILABLE = 14] = "UNAVAILABLE", ht[ht.DATA_LOSS = 15] = "DATA_LOSS";
class ft extends
/**
* Base class for all Rest-based connections to the backend (WebChannel and
* HTTP).
*/
class {
constructor(t) {
this.databaseInfo = t, this.databaseId = t.databaseId;
const e = t.ssl ? "https" : "http";
this.p = e + "://" + t.host, this.g = "projects/" + this.databaseId.projectId + "/databases/" + this.databaseId.database + "/documents";
}
v(t, e, n, r) {
const s = this.T(t, e);
m("RestConnection", "Sending: ", s, n);
const i = {};
return this.I(i, r), this.A(t, s, i, n).then((t => (m("RestConnection", "Received: ", t),
t)), (e => {
throw y("RestConnection", `${t} failed with error: `, e, "url: ", s, "request:", n),
e;
}));
}
P(t, e, n, r) {
// The REST API automatically aggregates all of the streamed results, so we
// can just use the normal invoke() method.
return this.v(t, e, n, r);
}
/**
* Modifies the headers for a request, adding any authorization token if
* present and any additional headers for the request.
*/ I(t, e) {
if (t["X-Goog-Api-Client"] = "gl-js/ fire/" + l,
// 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) for (const n in e.authHeaders) e.authHeaders.hasOwnProperty(n) && (t[n] = e.authHeaders[n]);
}
T(t, e) {
const n = ct[t];
return `${this.p}/v1/${e}:${n}`;
}
} {
/**
* @param databaseInfo - The connection info.
* @param fetchImpl - `fetch` or a Polyfill that implements the fetch API.
*/
constructor(t, e) {
super(t), this.R = e;
}
V(t, e) {
throw new Error("Not supported by FetchConnection");
}
async A(t, e, n, r) {
const s = JSON.stringify(r);
let i;
try {
i = await this.R(e, {
method: "POST",
headers: n,
body: s
});
} catch (t) {
throw new U(lt(t.status), "Request failed with error: " + t.statusText);
}
if (!i.ok) throw new U(lt(i.status), "Request failed with error: " + i.statusText);
return i.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 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 dt(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), n = new Uint8Array(t);
if (e && "function" == typeof e.getRandomValues) e.getRandomValues(n); else
// Falls back to Math.random
for (let e = 0; e < t; e++) n[e] = 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.
*/ class wt {
static N() {
// Alphanumeric characters
const t = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", e = Math.floor(256 / t.length) * t.length;
// The largest byte value that is a multiple of `char.length`.
let n = "";
for (;n.length < 20; ) {
const r = dt(40);
for (let s = 0; s < r.length; ++s)
// 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[s] < e && (n += t.charAt(r[s] % t.length));
}
return n;
}
}
function mt(t, e) {
return t < e ? -1 : t > e ? 1 : 0;
}
/** Helper to compare arrays using isEqual(). */ function pt(t, e, n) {
return t.length === e.length && t.every(((t, r) => n(t, e[r])));
}
/**
* @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).
/**
* 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 yt {
/**
* Creates a new timestamp.
*
* @param seconds - The number of seconds of UTC time since Unix epoch
* 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to
* 9999-12-31T23:59:59Z inclusive.
* @param nanoseconds - The non-negative fractions of a second at nanosecond
* resolution. Negative second values with fractions must still have
* non-negative nanoseconds values that count forward in time. Must be
* from 0 to 999,999,999 inclusive.
*/
constructor(
/**
* The number of seconds of UTC time since Unix epoch 1970-01-01T00:00:00Z.
*/
t,
/**
* The fractions of a second at nanosecond resolution.*
*/
e) {
if (this.seconds = t, this.nanoseconds = e, e < 0) throw new U(A, "Timestamp nanoseconds out of range: " + e);
if (e >= 1e9) throw new U(A, "Timestamp nanoseconds out of range: " + e);
if (t < -62135596800) throw new U(A, "Timestamp seconds out of range: " + t);
// This will break in the year 10,000.
if (t >= 253402300800) throw new U(A, "Timestamp seconds out of range: " + t);
}
/**
* Creates a new timestamp with the current date, with millisecond precision.
*
* @returns a new timestamp representing the current date.
*/ static now() {
return yt.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(t) {
return yt.fromMillis(t.getTime());
}
/**
* Creates a new timestamp from the given number of milliseconds.
*
* @param milliseconds - Number of milliseconds since Unix epoch
* 1970-01-01T00:00:00Z.
* @returns A new `Timestamp` representing the same point in time as the given
* number of milliseconds.
*/ static fromMillis(t) {
const e = Math.floor(t / 1e3), n = Math.floor(1e6 * (t - 1e3 * e));
return new yt(e, n);
}
/**
* Converts a `Timestamp` to a JavaScript `Date` object. This conversion
* causes a loss of precision since `Date` objects only support millisecond
* precision.
*
* @returns JavaScript `Date` object representing the same point in time as
* this `Timestamp`, with millisecond precision.
*/ toDate() {
return new Date(this.toMillis());
}
/**
* Converts a `Timestamp` to a numeric timestamp (in milliseconds since
* epoch). This operation causes a loss of precision.
*
* @returns The point in time corresponding to this timestamp, represented as
* the number of milliseconds since Unix epoch 1970-01-01T00:00:00Z.
*/ toMillis() {
return 1e3 * this.seconds + this.nanoseconds / 1e6;
}
_compareTo(t) {
return this.seconds === t.seconds ? mt(this.nanoseconds, t.nanoseconds) : mt(this.seconds, t.seconds);
}
/**
* Returns true if this `Timestamp` is equal to the provided one.
*
* @param other - The `Timestamp` to compare against.
* @returns true if this `Timestamp` is equal to the provided one.
*/ isEqual(t) {
return t.seconds === this.seconds && t.nanoseconds === this.nanoseconds;
}
/** Returns a textual representation of this Timestamp. */ toString() {
return "Timestamp(seconds=" + this.seconds + ", nanoseconds=" + this.nanoseconds + ")";
}
/** Returns a JSON-serializable representation of this Timestamp. */ toJSON() {
return {
seconds: this.seconds,
nanoseconds: this.nanoseconds
};
}
/**
* Converts this object to a primitive string, which allows Timestamp objects
* to be compared using the `>`, `<=`, `>=` and `>` operators.
*/ valueOf() {
// This method returns a string of the form <seconds>.<nanoseconds> where
// <seconds> is translated to have a non-negative value and both <seconds>
// and <nanoseconds> are left-padded with zeroes to be a consistent length.
// Strings with this format then have a lexiographical ordering that matches
// the expected ordering. The <seconds> translation is done to avoid having
// a leading negative sign (i.e. a leading '-' character) in its string
// representation, which would affect its lexiographical ordering.
const t = this.seconds - -62135596800;
// Note: Up to 12 decimal digits are required to represent all valid
// 'seconds' values.
return String(t).padStart(12, "0") + "." + String(this.nanoseconds).padStart(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.
*/
/**
* A version of a document in Firestore. This corresponds to the version
* timestamp, such as update_time or read_time.
*/ class _t {
constructor(t) {
this.timestamp = t;
}
static fromTimestamp(t) {
return new _t(t);
}
static min() {
return new _t(new yt(0, 0));
}
compareTo(t) {
return this.timestamp._compareTo(t.timestamp);
}
isEqual(t) {
return this.timestamp.isEqual(t.timestamp);
}
/** Returns a number representation of the version for use in spec tests. */ toMicroseconds() {
// Convert to microseconds.
return 1e6 * this.timestamp.seconds + this.timestamp.nanoseconds / 1e3;
}
toString() {
return "SnapshotVersion(" + this.timestamp.toString() + ")";
}
toTimestamp() {
return this.timestamp;
}
}
/**
* @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 KI