UNPKG

@firebase/firestore

Version:

The Cloud Firestore component of the Firebase JS SDK.

1,340 lines (1,270 loc) • 705 kB
import { base64 as t, getUA as e, isMobileCordova as n, isReactNative as s, isElectron as i, isIE as r, isUWP as o, isBrowserExtension as c, createMockUserToken as u, getModularInstance as a } from "@firebase/util"; import { Logger as h, LogLevel as l } from "@firebase/logger"; import { XhrIo as f, EventType as d, ErrorCode as w, createWebChannelTransport as _, getStatEventTarget as m, FetchXmlHttpFactory as y, WebChannel as g, Event as p, Stat as E } from "@firebase/webchannel-wrapper"; /** * @license * Copyright 2018 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. */ /** * `ListenSequence` is a monotonic sequence. It is initialized with a minimum value to * exceed. All subsequent calls to next will return increasing values. If provided with a * `SequenceNumberSyncer`, it will additionally bump its next value when told of a new value, as * well as write out sequence numbers that it produces via `next()`. */ class T { constructor(t, e) { this.previousValue = t, e && (e.sequenceNumberHandler = t => this.t(t), this.i = t => e.writeSequenceNumber(t)); } t(t) { return this.previousValue = Math.max(t, this.previousValue), this.previousValue; } next() { const t = ++this.previousValue; return this.i && this.i(t), t; } } T.o = -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. */ const I = { // Causes are copied from: // https://github.com/grpc/grpc/blob/bceec94ea4fc5f0085d81235d8e1c06798dc341a/include/grpc%2B%2B/impl/codegen/status_code_enum.h /** Not an error; returned on success. */ OK: "ok", /** The operation was cancelled (typically by the caller). */ CANCELLED: "cancelled", /** Unknown error or an error from a different error domain. */ UNKNOWN: "unknown", /** * Client specified an invalid argument. Note that this differs from * FAILED_PRECONDITION. INVALID_ARGUMENT indicates arguments that are * problematic regardless of the state of the system (e.g., a malformed file * name). */ INVALID_ARGUMENT: "invalid-argument", /** * Deadline expired before operation could complete. For operations that * change the state of the system, this error may be returned even if the * operation has completed successfully. For example, a successful response * from a server could have been delayed long enough for the deadline to * expire. */ DEADLINE_EXCEEDED: "deadline-exceeded", /** Some requested entity (e.g., file or directory) was not found. */ NOT_FOUND: "not-found", /** * Some entity that we attempted to create (e.g., file or directory) already * exists. */ ALREADY_EXISTS: "already-exists", /** * The caller does not have permission to execute the specified operation. * PERMISSION_DENIED must not be used for rejections caused by exhausting * some resource (use RESOURCE_EXHAUSTED instead for those errors). * PERMISSION_DENIED must not be used if the caller can not be identified * (use UNAUTHENTICATED instead for those errors). */ PERMISSION_DENIED: "permission-denied", /** * The request does not have valid authentication credentials for the * operation. */ UNAUTHENTICATED: "unauthenticated", /** * Some resource has been exhausted, perhaps a per-user quota, or perhaps the * entire file system is out of space. */ RESOURCE_EXHAUSTED: "resource-exhausted", /** * Operation was rejected because the system is not in a state required for * the operation's execution. For example, directory to be deleted may be * non-empty, an rmdir operation is applied to a non-directory, etc. * * A litmus test that may help a service implementor in deciding * between FAILED_PRECONDITION, ABORTED, and UNAVAILABLE: * (a) Use UNAVAILABLE if the client can retry just the failing call. * (b) Use ABORTED if the client should retry at a higher-level * (e.g., restarting a read-modify-write sequence). * (c) Use FAILED_PRECONDITION if the client should not retry until * the system state has been explicitly fixed. E.g., if an "rmdir" * fails because the directory is non-empty, FAILED_PRECONDITION * should be returned since the client should not retry unless * they have first fixed up the directory by deleting files from it. * (d) Use FAILED_PRECONDITION if the client performs conditional * REST Get/Update/Delete on a resource and the resource on the * server does not match the condition. E.g., conflicting * read-modify-write on the same resource. */ FAILED_PRECONDITION: "failed-precondition", /** * The operation was aborted, typically due to a concurrency issue like * sequencer check failures, transaction aborts, etc. * * See litmus test above for deciding between FAILED_PRECONDITION, ABORTED, * and UNAVAILABLE. */ ABORTED: "aborted", /** * Operation was attempted past the valid range. E.g., seeking or reading * past end of file. * * Unlike INVALID_ARGUMENT, this error indicates a problem that may be fixed * if the system state changes. For example, a 32-bit file system will * generate INVALID_ARGUMENT if asked to read at an offset that is not in the * range [0,2^32-1], but it will generate OUT_OF_RANGE if asked to read from * an offset past the current file size. * * There is a fair bit of overlap between FAILED_PRECONDITION and * OUT_OF_RANGE. We recommend using OUT_OF_RANGE (the more specific error) * when it applies so that callers who are iterating through a space can * easily look for an OUT_OF_RANGE error to detect when they are done. */ OUT_OF_RANGE: "out-of-range", /** Operation is not implemented or not supported/enabled in this service. */ UNIMPLEMENTED: "unimplemented", /** * Internal errors. Means some invariants expected by underlying System has * been broken. If you see one of these errors, Something is very broken. */ INTERNAL: "internal", /** * The service is currently unavailable. This is a most likely a transient * condition and may be corrected by retrying with a backoff. * * See litmus test above for deciding between FAILED_PRECONDITION, ABORTED, * and UNAVAILABLE. */ UNAVAILABLE: "unavailable", /** Unrecoverable data loss or corruption. */ DATA_LOSS: "data-loss" }; /** An error returned by a Firestore operation. */ class A 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 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. */ /** * @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 h("@firebase/firestore"); // Helper methods are needed because variables can't be exported as read/write function b() { return R.logLevel; } /** * Sets the verbosity of Cloud Firestore logs (debug, error, or silent). * * @param logLevel - The verbosity you set for activity and error logging. Can * be any of the following values: * * <ul> * <li>`debug` for the most verbose logging level, primarily for * debugging.</li> * <li>`error` to log errors only.</li> * <li><code>`silent` to turn off logging.</li> * </ul> */ function v(t, ...e) { if (R.logLevel <= l.DEBUG) { const n = e.map(S); R.debug(`Firestore (8.6.7): ${t}`, ...n); } } function P(t, ...e) { if (R.logLevel <= l.ERROR) { const n = e.map(S); R.error(`Firestore (8.6.7): ${t}`, ...n); } } function V(t, ...e) { if (R.logLevel <= l.WARN) { const n = e.map(S); R.warn(`Firestore (8.6.7): ${t}`, ...n); } } /** * Converts an additional log parameter to a string representation. */ function S(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; } 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 D(t = "Unexpected state") { // Log the failure in addition to throw an exception, just in case the // exception is swallowed. const e = "FIRESTORE (8.6.7) 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 C(t, e) { t || D(); } /** * Casts `obj` to `T`. In non-production builds, verifies that `obj` is an * instance of `T` before casting. */ function N(t, // eslint-disable-next-line @typescript-eslint/no-explicit-any e) { 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. */ /** * Generates `nBytes` of random bytes. * * If `nBytes < 0` , an error will be thrown. */ function x(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 F { static u() { // 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 s = x(40); for (let i = 0; i < s.length; ++i) // Only accept values that are [0, maxMultiple), this ensures they can // be evenly mapped to indices of `chars` via a modulo operation. n.length < 20 && s[i] < e && (n += t.charAt(s[i] % t.length)); } return n; } } function k(t, e) { return t < e ? -1 : t > e ? 1 : 0; } /** Helper to compare arrays using isEqual(). */ function $(t, e, n) { return t.length === e.length && t.every(((t, s) => n(t, e[s]))); } /** * Returns the immediate lexicographically-following string. This is useful to * construct an inclusive range for indexeddb iterators. */ function O(t) { // Return the input string, with an additional NUL byte appended. return t + "\0"; } /** * @license * Copyright 2017 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // The earliest date supported by Firestore timestamps (0001-01-01T00:00:00Z). /** * 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 M { /** * 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 A(I.INVALID_ARGUMENT, "Timestamp nanoseconds out of range: " + e); if (e >= 1e9) throw new A(I.INVALID_ARGUMENT, "Timestamp nanoseconds out of range: " + e); if (t < -62135596800) throw new A(I.INVALID_ARGUMENT, "Timestamp seconds out of range: " + t); // This will break in the year 10,000. if (t >= 253402300800) throw new A(I.INVALID_ARGUMENT, "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 M.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 M.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 M(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 ? k(this.nanoseconds, t.nanoseconds) : k(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 L { constructor(t) { this.timestamp = t; } static fromTimestamp(t) { return new L(t); } static min() { return new L(new M(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 KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ function B(t) { let e = 0; for (const n in t) Object.prototype.hasOwnProperty.call(t, n) && e++; return e; } function q(t, e) { for (const n in t) Object.prototype.hasOwnProperty.call(t, n) && e(n, t[n]); } function U(t) { for (const e in t) if (Object.prototype.hasOwnProperty.call(t, e)) return !1; return !0; } /** * @license * Copyright 2017 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Path represents an ordered sequence of string segments. */ class Q { constructor(t, e, n) { void 0 === e ? e = 0 : e > t.length && D(), void 0 === n ? n = t.length - e : n > t.length - e && D(), this.segments = t, this.offset = e, this.len = n; } get length() { return this.len; } isEqual(t) { return 0 === Q.comparator(this, t); } child(t) { const e = this.segments.slice(this.offset, this.limit()); return t instanceof Q ? 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 s = 0; s < n; s++) { const n = t.get(s), i = e.get(s); if (n < i) return -1; if (n > i) 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 Q { 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 A(I.INVALID_ARGUMENT, `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 W extends Q { construct(t, e, n) { return new W(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, "\\`"), W.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 W([ "__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 = "", s = 0; const i = () => { if (0 === n.length) throw new A(I.INVALID_ARGUMENT, `Invalid field path (${t}). Paths must not be empty, begin with '.', end with '.', or contain '..'`); e.push(n), n = ""; }; let r = !1; for (;s < t.length; ) { const e = t[s]; if ("\\" === e) { if (s + 1 === t.length) throw new A(I.INVALID_ARGUMENT, "Path has trailing escape character: " + t); const e = t[s + 1]; if ("\\" !== e && "." !== e && "`" !== e) throw new A(I.INVALID_ARGUMENT, "Path has invalid escape sequence: " + t); n += e, s += 2; } else "`" === e ? (r = !r, s++) : "." !== e || r ? (n += e, s++) : (i(), s++); } if (i(), r) throw new A(I.INVALID_ARGUMENT, "Unterminated ` in path: " + t); return new W(e); } static emptyPath() { return new W([]); } } /** * @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. */ /** * Provides a set of fields that can be used to partially patch a document. * FieldMask is used in conjunction with ObjectValue. * Examples: * foo - Overwrites foo entirely with the provided value. If foo is not * present in the companion ObjectValue, the field is deleted. * foo.bar - Overwrites only the field bar of the object foo. * If foo is not an object, foo is replaced with an object * containing foo */ class G { constructor(t) { this.fields = t, // TODO(dimond): validation of FieldMask // Sort the field mask to support `FieldMask.isEqual()` and assert below. t.sort(W.comparator); } /** * Verifies that `fieldPath` is included by at least one field in this field * mask. * * This is an O(n) operation, where `n` is the size of the field mask. */ covers(t) { for (const e of this.fields) if (e.isPrefixOf(t)) return !0; return !1; } isEqual(t) { return $(this.fields, t.fields, ((t, e) => t.isEqual(e))); } } /** * @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. */ // WebSafe uses a different URL-encoding safe alphabet that doesn't match // the encoding used on the backend. /** Converts a Base64 encoded string to a binary string. */ function z(e) { return String.fromCharCode.apply(null, // We use `decodeStringToByteArray()` instead of `decodeString()` since // `decodeString()` returns Unicode strings, which doesn't match the values // returned by `atob()`'s Latin1 representation. t.decodeStringToByteArray(e, false)); } /** Converts a binary string to a Base64 encoded string. */ /** * @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. */ /** * Immutable class that represents a "proto" byte string. * * Proto byte strings can either be Base64-encoded strings or Uint8Arrays when * sent on the wire. This class abstracts away this differentiation by holding * the proto byte string in a common class that must be converted into a string * before being sent as a proto. */ class H { constructor(t) { this.binaryString = t; } static fromBase64String(t) { const e = z(t); return new H(e); } static fromUint8Array(t) { const e = /** * Helper function to convert an Uint8array to a binary string. */ function(t) { let e = ""; for (let n = 0; n < t.length; ++n) e += String.fromCharCode(t[n]); return e; } /** * Helper function to convert a binary string to an Uint8Array. */ (t); return new H(e); } toBase64() { return function(e) { const n = []; for (let t = 0; t < e.length; t++) n[t] = e.charCodeAt(t); return t.encodeByteArray(n, !1); }(this.binaryString); } toUint8Array() { return function(t) { const e = new Uint8Array(t.length); for (let n = 0; n < t.length; n++) e[n] = t.charCodeAt(n); return e; } /** * @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 RegExp matching ISO 8601 UTC timestamps with optional fraction. (this.binaryString); } approximateByteSize() { return 2 * this.binaryString.length; } compareTo(t) { return k(this.binaryString, t.binaryString); } isEqual(t) { return this.binaryString === t.binaryString; } } H.EMPTY_BYTE_STRING = new H(""); const J = new RegExp(/^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d(?:\.(\d+))?Z$/); /** * Converts the possible Proto values for a timestamp value into a "seconds and * nanos" representation. */ function Y(t) { // The json interface (for the browser) will return an iso timestamp string, // while the proto js library (for node) will return a // google.protobuf.Timestamp instance. if (C(!!t), "string" == typeof t) { // The date string can have higher precision (nanos) than the Date class // (millis), so we do some custom parsing here. // Parse the nanos right out of the string. let e = 0; const n = J.exec(t); if (C(!!n), n[1]) { // Pad the fraction out to 9 digits (nanos). let t = n[1]; t = (t + "000000000").substr(0, 9), e = Number(t); } // Parse the date to get the seconds. const s = new Date(t); return { seconds: Math.floor(s.getTime() / 1e3), nanos: e }; } return { seconds: X(t.seconds), nanos: X(t.nanos) }; } /** * Converts the possible Proto types for numbers into a JavaScript number. * Returns 0 if the value is not numeric. */ function X(t) { // TODO(bjornick): Handle int64 greater than 53 bits. return "number" == typeof t ? t : "string" == typeof t ? Number(t) : 0; } /** Converts the possible Proto types for Blobs into a ByteString. */ function Z(t) { return "string" == typeof t ? H.fromBase64String(t) : H.fromUint8Array(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. */ /** * Represents a locally-applied ServerTimestamp. * * Server Timestamps are backed by MapValues that contain an internal field * `__type__` with a value of `server_timestamp`. The previous value and local * write time are stored in its `__previous_value__` and `__local_write_time__` * fields respectively. * * Notes: * - ServerTimestampValue instances are created as the result of applying a * transform. They can only exist in the local view of a document. Therefore * they do not need to be parsed or serialized. * - When evaluated locally (e.g. for snapshot.data()), they by default * evaluate to `null`. This behavior can be configured by passing custom * FieldValueOptions to value(). * - With respect to other ServerTimestampValues, they sort by their * localWriteTime. */ function tt(t) { var e, n; return "server_timestamp" === (null === (n = ((null === (e = null == t ? void 0 : t.mapValue) || void 0 === e ? void 0 : e.fields) || {}).__type__) || void 0 === n ? void 0 : n.stringValue); } /** * Creates a new ServerTimestamp proto value (using the internal format). */ /** * Returns the value of the field before this ServerTimestamp was set. * * Preserving the previous values allows the user to display the last resoled * value until the backend responds with the timestamp. */ function et(t) { const e = t.mapValue.fields.__previous_value__; return tt(e) ? et(e) : e; } /** * Returns the local time at which this timestamp was first set. */ function nt(t) { const e = Y(t.mapValue.fields.__local_write_time__.timestampValue); return new M(e.seconds, e.nanos); } /** * @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. */ /** Sentinel value that sorts before any Mutation Batch ID. */ /** * Returns whether a variable is either undefined or null. */ function st(t) { return null == t; } /** Returns whether the value represents -0. */ function it(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 */ function rt(t) { return "number" == typeof t && Number.isInteger(t) && !it(t) && t <= Number.MAX_SAFE_INTEGER && t >= Number.MIN_SAFE_INTEGER; } /** * @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 ot { constructor(t) { this.path = t; } static fromPath(t) { return new ot(K.fromString(t)); } static fromName(t) { return new ot(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 ot(new K(t.slice())); } } /** * @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. */ /** Extracts the backend's type order for the provided value. */ function ct(t) { return "nullValue" in t ? 0 /* NullValue */ : "booleanValue" in t ? 1 /* BooleanValue */ : "integerValue" in t || "doubleValue" in t ? 2 /* NumberValue */ : "timestampValue" in t ? 3 /* TimestampValue */ : "stringValue" in t ? 5 /* StringValue */ : "bytesValue" in t ? 6 /* BlobValue */ : "referenceValue" in t ? 7 /* RefValue */ : "geoPointValue" in t ? 8 /* GeoPointValue */ : "arrayValue" in t ? 9 /* ArrayValue */ : "mapValue" in t ? tt(t) ? 4 /* ServerTimestampValue */ : 10 /* ObjectValue */ : D(); } /** Tests `left` and `right` for equality based on the backend semantics. */ function ut(t, e) { const n = ct(t); if (n !== ct(e)) return !1; switch (n) { case 0 /* NullValue */ : return !0; case 1 /* BooleanValue */ : return t.booleanValue === e.booleanValue; case 4 /* ServerTimestampValue */ : return nt(t).isEqual(nt(e)); case 3 /* TimestampValue */ : return function(t, e) { if ("string" == typeof t.timestampValue && "string" == typeof e.timestampValue && t.timestampValue.length === e.timestampValue.length) // Use string equality for ISO 8601 timestamps return t.timestampValue === e.timestampValue; const n = Y(t.timestampValue), s = Y(e.timestampValue); return n.seconds === s.seconds && n.nanos === s.nanos; }(t, e); case 5 /* StringValue */ : return t.stringValue === e.stringValue; case 6 /* BlobValue */ : return function(t, e) { return Z(t.bytesValue).isEqual(Z(e.bytesValue)); }(t, e); case 7 /* RefValue */ : return t.referenceValue === e.referenceValue; case 8 /* GeoPointValue */ : return function(t, e) { return X(t.geoPointValue.latitude) === X(e.geoPointValue.latitude) && X(t.geoPointValue.longitude) === X(e.geoPointValue.longitude); }(t, e); case 2 /* NumberValue */ : return function(t, e) { if ("integerValue" in t && "integerValue" in e) return X(t.integerValue) === X(e.integerValue); if ("doubleValue" in t && "doubleValue" in e) { const n = X(t.doubleValue), s = X(e.doubleValue); return n === s ? it(n) === it(s) : isNaN(n) && isNaN(s); } return !1; }(t, e); case 9 /* ArrayValue */ : return $(t.arrayValue.values || [], e.arrayValue.values || [], ut); case 10 /* ObjectValue */ : return function(t, e) { const n = t.mapValue.fields || {}, s = e.mapValue.fields || {}; if (B(n) !== B(s)) return !1; for (const t in n) if (n.hasOwnProperty(t) && (void 0 === s[t] || !ut(n[t], s[t]))) return !1; return !0; } /** Returns true if the ArrayValue contains the specified element. */ (t, e); default: return D(); } } function at(t, e) { return void 0 !== (t.values || []).find((t => ut(t, e))); } function ht(t, e) { const n = ct(t), s = ct(e); if (n !== s) return k(n, s); switch (n) { case 0 /* NullValue */ : return 0; case 1 /* BooleanValue */ : return k(t.booleanValue, e.booleanValue); case 2 /* NumberValue */ : return function(t, e) { const n = X(t.integerValue || t.doubleValue), s = X(e.integerValue || e.doubleValue); return n < s ? -1 : n > s ? 1 : n === s ? 0 : // one or both are NaN. isNaN(n) ? isNaN(s) ? 0 : -1 : 1; }(t, e); case 3 /* TimestampValue */ : return lt(t.timestampValue, e.timestampValue); case 4 /* ServerTimestampValue */ : return lt(nt(t), nt(e)); case 5 /* StringValue */ : return k(t.stringValue, e.stringValue); case 6 /* BlobValue */ : return function(t, e) { const n = Z(t), s = Z(e); return n.compareTo(s); }(t.bytesValue, e.bytesValue); case 7 /* RefValue */ : return function(t, e) { const n = t.split("/"), s = e.split("/"); for (let t = 0; t < n.length && t < s.length; t++) { const e = k(n[t], s[t]); if (0 !== e) return e; } return k(n.length, s.length); }(t.referenceValue, e.referenceValue); case 8 /* GeoPointValue */ : return function(t, e) { const n = k(X(t.latitude), X(e.latitude)); if (0 !== n) return n; return k(X(t.longitude), X(e.longitude)); }(t.geoPointValue, e.geoPointValue); case 9 /* ArrayValue */ : return function(t, e) { const n = t.values || [], s = e.values || []; for (let t = 0; t < n.length && t < s.length; ++t) { const e = ht(n[t], s[t]); if (e) return e; } return k(n.length, s.length); }(t.arrayValue, e.arrayValue); case 10 /* ObjectValue */ : return function(t, e) { const n = t.fields || {}, s = Object.keys(n), i = e.fields || {}, r = Object.keys(i); // Even though MapValues are likely sorted correctly based on their insertion // order (e.g. when received from the backend), local modifications can bring // elements out of order. We need to re-sort the elements to ensure that // canonical IDs are independent of insertion order. s.sort(), r.sort(); for (let t = 0; t < s.length && t < r.length; ++t) { const e = k(s[t], r[t]); if (0 !== e) return e; const o = ht(n[s[t]], i[r[t]]); if (0 !== o) return o; } return k(s.length, r.length); } /** * Generates the canonical ID for the provided field value (as used in Target * serialization). */ (t.mapValue, e.mapValue); def