UNPKG

@firebase/firestore

Version:

The Cloud Firestore component of the Firebase JS SDK.

1,386 lines (1,321 loc) • 225 kB
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