firebase
Version:
Firebase JavaScript library for web and Node.js
1,440 lines (1,399 loc) • 250 kB
JavaScript
import { _registerComponent, registerVersion, _getProvider, getApp, _removeServiceInstance, SDK_VERSION } from 'https://www.gstatic.com/firebasejs/9.7.0/firebase-app.js';
/**
* @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.
*/
/**
* @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 stringToByteArray$1 = function (str) {
// TODO(user): Use native implementations if/when available
const out = [];
let p = 0;
for (let i = 0; i < str.length; i++) {
let c = str.charCodeAt(i);
if (c < 128) {
out[p++] = c;
}
else if (c < 2048) {
out[p++] = (c >> 6) | 192;
out[p++] = (c & 63) | 128;
}
else if ((c & 0xfc00) === 0xd800 &&
i + 1 < str.length &&
(str.charCodeAt(i + 1) & 0xfc00) === 0xdc00) {
// Surrogate Pair
c = 0x10000 + ((c & 0x03ff) << 10) + (str.charCodeAt(++i) & 0x03ff);
out[p++] = (c >> 18) | 240;
out[p++] = ((c >> 12) & 63) | 128;
out[p++] = ((c >> 6) & 63) | 128;
out[p++] = (c & 63) | 128;
}
else {
out[p++] = (c >> 12) | 224;
out[p++] = ((c >> 6) & 63) | 128;
out[p++] = (c & 63) | 128;
}
}
return out;
};
/**
* Turns an array of numbers into the string given by the concatenation of the
* characters to which the numbers correspond.
* @param bytes Array of numbers representing characters.
* @return Stringification of the array.
*/
const byteArrayToString = function (bytes) {
// TODO(user): Use native implementations if/when available
const out = [];
let pos = 0, c = 0;
while (pos < bytes.length) {
const c1 = bytes[pos++];
if (c1 < 128) {
out[c++] = String.fromCharCode(c1);
}
else if (c1 > 191 && c1 < 224) {
const c2 = bytes[pos++];
out[c++] = String.fromCharCode(((c1 & 31) << 6) | (c2 & 63));
}
else if (c1 > 239 && c1 < 365) {
// Surrogate Pair
const c2 = bytes[pos++];
const c3 = bytes[pos++];
const c4 = bytes[pos++];
const u = (((c1 & 7) << 18) | ((c2 & 63) << 12) | ((c3 & 63) << 6) | (c4 & 63)) -
0x10000;
out[c++] = String.fromCharCode(0xd800 + (u >> 10));
out[c++] = String.fromCharCode(0xdc00 + (u & 1023));
}
else {
const c2 = bytes[pos++];
const c3 = bytes[pos++];
out[c++] = String.fromCharCode(((c1 & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
}
}
return out.join('');
};
// We define it as an object literal instead of a class because a class compiled down to es5 can't
// be treeshaked. https://github.com/rollup/rollup/issues/1691
// Static lookup maps, lazily populated by init_()
const base64 = {
/**
* Maps bytes to characters.
*/
byteToCharMap_: null,
/**
* Maps characters to bytes.
*/
charToByteMap_: null,
/**
* Maps bytes to websafe characters.
* @private
*/
byteToCharMapWebSafe_: null,
/**
* Maps websafe characters to bytes.
* @private
*/
charToByteMapWebSafe_: null,
/**
* Our default alphabet, shared between
* ENCODED_VALS and ENCODED_VALS_WEBSAFE
*/
ENCODED_VALS_BASE: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + 'abcdefghijklmnopqrstuvwxyz' + '0123456789',
/**
* Our default alphabet. Value 64 (=) is special; it means "nothing."
*/
get ENCODED_VALS() {
return this.ENCODED_VALS_BASE + '+/=';
},
/**
* Our websafe alphabet.
*/
get ENCODED_VALS_WEBSAFE() {
return this.ENCODED_VALS_BASE + '-_.';
},
/**
* Whether this browser supports the atob and btoa functions. This extension
* started at Mozilla but is now implemented by many browsers. We use the
* ASSUME_* variables to avoid pulling in the full useragent detection library
* but still allowing the standard per-browser compilations.
*
*/
HAS_NATIVE_SUPPORT: typeof atob === 'function',
/**
* Base64-encode an array of bytes.
*
* @param input An array of bytes (numbers with
* value in [0, 255]) to encode.
* @param webSafe Boolean indicating we should use the
* alternative alphabet.
* @return The base64 encoded string.
*/
encodeByteArray(input, webSafe) {
if (!Array.isArray(input)) {
throw Error('encodeByteArray takes an array as a parameter');
}
this.init_();
const byteToCharMap = webSafe
? this.byteToCharMapWebSafe_
: this.byteToCharMap_;
const output = [];
for (let i = 0; i < input.length; i += 3) {
const byte1 = input[i];
const haveByte2 = i + 1 < input.length;
const byte2 = haveByte2 ? input[i + 1] : 0;
const haveByte3 = i + 2 < input.length;
const byte3 = haveByte3 ? input[i + 2] : 0;
const outByte1 = byte1 >> 2;
const outByte2 = ((byte1 & 0x03) << 4) | (byte2 >> 4);
let outByte3 = ((byte2 & 0x0f) << 2) | (byte3 >> 6);
let outByte4 = byte3 & 0x3f;
if (!haveByte3) {
outByte4 = 64;
if (!haveByte2) {
outByte3 = 64;
}
}
output.push(byteToCharMap[outByte1], byteToCharMap[outByte2], byteToCharMap[outByte3], byteToCharMap[outByte4]);
}
return output.join('');
},
/**
* Base64-encode a string.
*
* @param input A string to encode.
* @param webSafe If true, we should use the
* alternative alphabet.
* @return The base64 encoded string.
*/
encodeString(input, webSafe) {
// Shortcut for Mozilla browsers that implement
// a native base64 encoder in the form of "btoa/atob"
if (this.HAS_NATIVE_SUPPORT && !webSafe) {
return btoa(input);
}
return this.encodeByteArray(stringToByteArray$1(input), webSafe);
},
/**
* Base64-decode a string.
*
* @param input to decode.
* @param webSafe True if we should use the
* alternative alphabet.
* @return string representing the decoded value.
*/
decodeString(input, webSafe) {
// Shortcut for Mozilla browsers that implement
// a native base64 encoder in the form of "btoa/atob"
if (this.HAS_NATIVE_SUPPORT && !webSafe) {
return atob(input);
}
return byteArrayToString(this.decodeStringToByteArray(input, webSafe));
},
/**
* Base64-decode a string.
*
* In base-64 decoding, groups of four characters are converted into three
* bytes. If the encoder did not apply padding, the input length may not
* be a multiple of 4.
*
* In this case, the last group will have fewer than 4 characters, and
* padding will be inferred. If the group has one or two characters, it decodes
* to one byte. If the group has three characters, it decodes to two bytes.
*
* @param input Input to decode.
* @param webSafe True if we should use the web-safe alphabet.
* @return bytes representing the decoded value.
*/
decodeStringToByteArray(input, webSafe) {
this.init_();
const charToByteMap = webSafe
? this.charToByteMapWebSafe_
: this.charToByteMap_;
const output = [];
for (let i = 0; i < input.length;) {
const byte1 = charToByteMap[input.charAt(i++)];
const haveByte2 = i < input.length;
const byte2 = haveByte2 ? charToByteMap[input.charAt(i)] : 0;
++i;
const haveByte3 = i < input.length;
const byte3 = haveByte3 ? charToByteMap[input.charAt(i)] : 64;
++i;
const haveByte4 = i < input.length;
const byte4 = haveByte4 ? charToByteMap[input.charAt(i)] : 64;
++i;
if (byte1 == null || byte2 == null || byte3 == null || byte4 == null) {
throw Error();
}
const outByte1 = (byte1 << 2) | (byte2 >> 4);
output.push(outByte1);
if (byte3 !== 64) {
const outByte2 = ((byte2 << 4) & 0xf0) | (byte3 >> 2);
output.push(outByte2);
if (byte4 !== 64) {
const outByte3 = ((byte3 << 6) & 0xc0) | byte4;
output.push(outByte3);
}
}
}
return output;
},
/**
* Lazy static initialization function. Called before
* accessing any of the static map variables.
* @private
*/
init_() {
if (!this.byteToCharMap_) {
this.byteToCharMap_ = {};
this.charToByteMap_ = {};
this.byteToCharMapWebSafe_ = {};
this.charToByteMapWebSafe_ = {};
// We want quick mappings back and forth, so we precompute two maps.
for (let i = 0; i < this.ENCODED_VALS.length; i++) {
this.byteToCharMap_[i] = this.ENCODED_VALS.charAt(i);
this.charToByteMap_[this.byteToCharMap_[i]] = i;
this.byteToCharMapWebSafe_[i] = this.ENCODED_VALS_WEBSAFE.charAt(i);
this.charToByteMapWebSafe_[this.byteToCharMapWebSafe_[i]] = i;
// Be forgiving when decoding and correctly decode both encodings.
if (i >= this.ENCODED_VALS_BASE.length) {
this.charToByteMap_[this.ENCODED_VALS_WEBSAFE.charAt(i)] = i;
this.charToByteMapWebSafe_[this.ENCODED_VALS.charAt(i)] = i;
}
}
}
}
};
/**
* URL-safe base64 encoding
*/
const base64Encode = function (str) {
const utf8Bytes = stringToByteArray$1(str);
return base64.encodeByteArray(utf8Bytes, true);
};
/**
* URL-safe base64 encoding (without "." padding in the end).
* e.g. Used in JSON Web Token (JWT) parts.
*/
const base64urlEncodeWithoutPadding = function (str) {
// Use base64url encoding and remove padding in the end (dot characters).
return base64Encode(str).replace(/\./g, '');
};
/**
* @license
* Copyright 2021 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 createMockUserToken(token, projectId) {
if (token.uid) {
throw new Error('The "uid" field is no longer supported by mockUserToken. Please use "sub" instead for Firebase Auth User ID.');
}
// Unsecured JWTs use "none" as the algorithm.
const header = {
alg: 'none',
type: 'JWT'
};
const project = projectId || 'demo-project';
const iat = token.iat || 0;
const sub = token.sub || token.user_id;
if (!sub) {
throw new Error("mockUserToken must contain 'sub' or 'user_id' field!");
}
const payload = Object.assign({
// Set all required fields to decent defaults
iss: `https://securetoken.google.com/${project}`, aud: project, iat, exp: iat + 3600, auth_time: iat, sub, user_id: sub, firebase: {
sign_in_provider: 'custom',
identities: {}
} }, token);
// Unsecured JWTs use the empty string as a signature.
const signature = '';
return [
base64urlEncodeWithoutPadding(JSON.stringify(header)),
base64urlEncodeWithoutPadding(JSON.stringify(payload)),
signature
].join('.');
}
/**
* @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.
*/
/**
* @fileoverview Standardized Firebase Error.
*
* Usage:
*
* // Typescript string literals for type-safe codes
* type Err =
* 'unknown' |
* 'object-not-found'
* ;
*
* // Closure enum for type-safe error codes
* // at-enum {string}
* var Err = {
* UNKNOWN: 'unknown',
* OBJECT_NOT_FOUND: 'object-not-found',
* }
*
* let errors: Map<Err, string> = {
* 'generic-error': "Unknown error",
* 'file-not-found': "Could not find file: {$file}",
* };
*
* // Type-safe function - must pass a valid error code as param.
* let error = new ErrorFactory<Err>('service', 'Service', errors);
*
* ...
* throw error.create(Err.GENERIC);
* ...
* throw error.create(Err.FILE_NOT_FOUND, {'file': fileName});
* ...
* // Service: Could not file file: foo.txt (service/file-not-found).
*
* catch (e) {
* assert(e.message === "Could not find file: foo.txt.");
* if (e.code === 'service/file-not-found') {
* console.log("Could not read file: " + e['file']);
* }
* }
*/
const ERROR_NAME = 'FirebaseError';
// Based on code from:
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error#Custom_Error_Types
class FirebaseError extends Error {
constructor(
/** The error code for this error. */
code, message,
/** Custom data for this error. */
customData) {
super(message);
this.code = code;
this.customData = customData;
/** The custom name for all FirebaseErrors. */
this.name = ERROR_NAME;
// Fix For ES5
// https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work
Object.setPrototypeOf(this, FirebaseError.prototype);
// Maintains proper stack trace for where our error was thrown.
// Only available on V8.
if (Error.captureStackTrace) {
Error.captureStackTrace(this, ErrorFactory.prototype.create);
}
}
}
class ErrorFactory {
constructor(service, serviceName, errors) {
this.service = service;
this.serviceName = serviceName;
this.errors = errors;
}
create(code, ...data) {
const customData = data[0] || {};
const fullCode = `${this.service}/${code}`;
const template = this.errors[code];
const message = template ? replaceTemplate(template, customData) : 'Error';
// Service Name: Error message (service/code).
const fullMessage = `${this.serviceName}: ${message} (${fullCode}).`;
const error = new FirebaseError(fullCode, fullMessage, customData);
return error;
}
}
function replaceTemplate(template, data) {
return template.replace(PATTERN, (_, key) => {
const value = data[key];
return value != null ? String(value) : `<${key}?>`;
});
}
const PATTERN = /\{\$([^}]+)}/g;
/**
* @license
* Copyright 2021 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 getModularInstance(service) {
if (service && service._delegate) {
return service._delegate;
}
else {
return service;
}
}
/**
* Component for service name T, e.g. `auth`, `auth-internal`
*/
class Component {
/**
*
* @param name The public service name, e.g. app, auth, firestore, database
* @param instanceFactory Service factory responsible for creating the public interface
* @param type whether the service provided by the component is public or private
*/
constructor(name, instanceFactory, type) {
this.name = name;
this.instanceFactory = instanceFactory;
this.type = type;
this.multipleInstances = false;
/**
* Properties to be added to the service namespace
*/
this.serviceProps = {};
this.instantiationMode = "LAZY" /* LAZY */;
this.onInstanceCreated = null;
}
setInstantiationMode(mode) {
this.instantiationMode = mode;
return this;
}
setMultipleInstances(multipleInstances) {
this.multipleInstances = multipleInstances;
return this;
}
setServiceProps(props) {
this.serviceProps = props;
return this;
}
setInstanceCreatedCallback(callback) {
this.onInstanceCreated = callback;
return this;
}
}
/**
* @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 JS SDK supports 5 log levels and also allows a user the ability to
* silence the logs altogether.
*
* The order is a follows:
* DEBUG < VERBOSE < INFO < WARN < ERROR
*
* All of the log types above the current log level will be captured (i.e. if
* you set the log level to `INFO`, errors will still be logged, but `DEBUG` and
* `VERBOSE` logs will not)
*/
var LogLevel;
(function (LogLevel) {
LogLevel[LogLevel["DEBUG"] = 0] = "DEBUG";
LogLevel[LogLevel["VERBOSE"] = 1] = "VERBOSE";
LogLevel[LogLevel["INFO"] = 2] = "INFO";
LogLevel[LogLevel["WARN"] = 3] = "WARN";
LogLevel[LogLevel["ERROR"] = 4] = "ERROR";
LogLevel[LogLevel["SILENT"] = 5] = "SILENT";
})(LogLevel || (LogLevel = {}));
const levelStringToEnum = {
'debug': LogLevel.DEBUG,
'verbose': LogLevel.VERBOSE,
'info': LogLevel.INFO,
'warn': LogLevel.WARN,
'error': LogLevel.ERROR,
'silent': LogLevel.SILENT
};
/**
* The default log level
*/
const defaultLogLevel = LogLevel.INFO;
/**
* By default, `console.debug` is not displayed in the developer console (in
* chrome). To avoid forcing users to have to opt-in to these logs twice
* (i.e. once for firebase, and once in the console), we are sending `DEBUG`
* logs to the `console.log` function.
*/
const ConsoleMethod = {
[LogLevel.DEBUG]: 'log',
[LogLevel.VERBOSE]: 'log',
[LogLevel.INFO]: 'info',
[LogLevel.WARN]: 'warn',
[LogLevel.ERROR]: 'error'
};
/**
* The default log handler will forward DEBUG, VERBOSE, INFO, WARN, and ERROR
* messages on to their corresponding console counterparts (if the log method
* is supported by the current log level)
*/
const defaultLogHandler = (instance, logType, ...args) => {
if (logType < instance.logLevel) {
return;
}
const now = new Date().toISOString();
const method = ConsoleMethod[logType];
if (method) {
console[method](`[${now}] ${instance.name}:`, ...args);
}
else {
throw new Error(`Attempted to log a message with an invalid logType (value: ${logType})`);
}
};
class Logger {
/**
* Gives you an instance of a Logger to capture messages according to
* Firebase's logging scheme.
*
* @param name The name that the logs will be associated with
*/
constructor(name) {
this.name = name;
/**
* The log level of the given Logger instance.
*/
this._logLevel = defaultLogLevel;
/**
* The main (internal) log handler for the Logger instance.
* Can be set to a new function in internal package code but not by user.
*/
this._logHandler = defaultLogHandler;
/**
* The optional, additional, user-defined log handler for the Logger instance.
*/
this._userLogHandler = null;
}
get logLevel() {
return this._logLevel;
}
set logLevel(val) {
if (!(val in LogLevel)) {
throw new TypeError(`Invalid value "${val}" assigned to \`logLevel\``);
}
this._logLevel = val;
}
// Workaround for setter/getter having to be the same type.
setLogLevel(val) {
this._logLevel = typeof val === 'string' ? levelStringToEnum[val] : val;
}
get logHandler() {
return this._logHandler;
}
set logHandler(val) {
if (typeof val !== 'function') {
throw new TypeError('Value assigned to `logHandler` must be a function');
}
this._logHandler = val;
}
get userLogHandler() {
return this._userLogHandler;
}
set userLogHandler(val) {
this._userLogHandler = val;
}
/**
* The functions below are all based on the `console` interface
*/
debug(...args) {
this._userLogHandler && this._userLogHandler(this, LogLevel.DEBUG, ...args);
this._logHandler(this, LogLevel.DEBUG, ...args);
}
log(...args) {
this._userLogHandler &&
this._userLogHandler(this, LogLevel.VERBOSE, ...args);
this._logHandler(this, LogLevel.VERBOSE, ...args);
}
info(...args) {
this._userLogHandler && this._userLogHandler(this, LogLevel.INFO, ...args);
this._logHandler(this, LogLevel.INFO, ...args);
}
warn(...args) {
this._userLogHandler && this._userLogHandler(this, LogLevel.WARN, ...args);
this._logHandler(this, LogLevel.WARN, ...args);
}
error(...args) {
this._userLogHandler && this._userLogHandler(this, LogLevel.ERROR, ...args);
this._logHandler(this, LogLevel.ERROR, ...args);
}
}
/**
* @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 l {
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. */ l.UNAUTHENTICATED = new l(null),
// TODO(mikelehen): Look into getting a proper uid-equivalent for
// non-FirebaseAuth providers.
l.GOOGLE_CREDENTIALS = new l("google-credentials-uid"), l.FIRST_PARTY = new l("first-party-uid"),
l.MOCK_USER = new l("mock-user");
/**
* @license
* Copyright 2017 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
let f = "9.7.0";
/**
* @license
* Copyright 2017 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const d = new Logger("@firebase/firestore");
/**
* Sets the verbosity of Cloud Firestore logs (debug, error, or silent).
*
* @param logLevel - The verbosity you set for activity and error logging. Can
* be any of the following values:
*
* <ul>
* <li>`debug` for the most verbose logging level, primarily for
* debugging.</li>
* <li>`error` to log errors only.</li>
* <li><code>`silent` to turn off logging.</li>
* </ul>
*/ function w(t) {
d.setLogLevel(t);
}
function m(t, ...e) {
if (d.logLevel <= LogLevel.DEBUG) {
const n = e.map(_);
d.debug(`Firestore (${f}): ${t}`, ...n);
}
}
function p(t, ...e) {
if (d.logLevel <= LogLevel.ERROR) {
const n = e.map(_);
d.error(`Firestore (${f}): ${t}`, ...n);
}
}
/**
* @internal
*/ function y(t, ...e) {
if (d.logLevel <= LogLevel.WARN) {
const n = e.map(_);
d.warn(`Firestore (${f}): ${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 (${f}) 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", R = "deadline-exceeded", P = "not-found", V = "already-exists", D = "permission-denied", N = "unauthenticated", $ = "resource-exhausted", S = "failed-precondition", F = "aborted", x = "out-of-range", q = "unimplemented", O = "internal", C = "unavailable", L = "data-loss";
/** An error returned by a Firestore operation. */ class U extends FirebaseError {
/** @hideconstructor */
constructor(
/**
* The backend error code associated with this error.
*/
t,
/**
* A custom error description.
*/
e) {
super(t, e), this.code = t, this.message = e,
// HACK: We write a toString property directly because Error is not a real
// class and so inheritance does not work correctly. We could alternatively
// do the same "back-door inheritance" trick that FirebaseError does.
this.toString = () => `${this.name}: [code=${this.code}]: ${this.message}`;
}
}
/**
* @license
* Copyright 2017 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ class 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.headers = new Map, this.headers.set("Authorization", `Bearer ${t}`);
}
}
/**
* A CredentialsProvider that always yields an empty token.
* @internal
*/ class M {
getToken() {
return Promise.resolve(null);
}
invalidateToken() {}
start(t, e) {
// Fire with initial user.
t.enqueueRetryable((() => e(l.UNAUTHENTICATED)));
}
shutdown() {}
}
/**
* 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() {}
start(t, e) {
this.changeListener = e,
// Fire with initial user.
t.enqueueRetryable((() => e(this.token.user)));
}
shutdown() {
this.changeListener = null;
}
}
/** Credential provider for the Lite SDK. */ class z {
constructor(t) {
this.auth = null, t.onInit((t => {
this.auth = t;
}));
}
getToken() {
return this.auth ? this.auth.getToken().then((t => t ? (v("string" == typeof t.accessToken),
new j(t.accessToken, new l(this.auth.getUid()))) : null)) : Promise.resolve(null);
}
invalidateToken() {}
start(t, e) {}
shutdown() {}
}
/*
* FirstPartyToken provides a fresh token each time its value
* is requested, because if the token is too old, requests will be rejected.
* Technically this may no longer be necessary since the SDK should gracefully
* recover from unauthenticated errors (see b/33147818 for context), but it's
* safer to keep the implementation as-is.
*/ class G {
constructor(t, e, n) {
this.type = "FirstParty", this.user = l.FIRST_PARTY, this.headers = new Map, this.headers.set("X-Goog-AuthUser", e);
const r = t.auth.getAuthHeaderValueForFirstParty([]);
r && this.headers.set("Authorization", r), n && this.headers.set("X-Goog-Iam-Authorization-Token", n);
}
}
/*
* 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 Q {
constructor(t, e, n) {
this.t = t, this.i = e, this.o = n;
}
getToken() {
return Promise.resolve(new G(this.t, this.i, this.o));
}
start(t, e) {
// Fire with initial uid.
t.enqueueRetryable((() => e(l.FIRST_PARTY)));
}
shutdown() {}
invalidateToken() {}
}
class W {
constructor(t) {
this.value = t, this.type = "AppCheck", this.headers = new Map, t && t.length > 0 && this.headers.set("x-firebase-appcheck", this.value);
}
}
/** AppCheck token provider for the Lite SDK. */ class Y {
constructor(t) {
this.u = t, this.appCheck = null, t.onInit((t => {
this.appCheck = t;
}));
}
getToken() {
return this.appCheck ? this.appCheck.getToken().then((t => t ? (v("string" == typeof t.token),
new W(t.token)) : null)) : Promise.resolve(null);
}
invalidateToken() {}
start(t, e) {}
shutdown() {}
}
/**
* Builds a CredentialsProvider depending on the type of
* the credentials passed in.
*/
/**
* @license
* Copyright 2017 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
class H {
/**
* 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.
* @internal
*/
class K {
constructor(t, e) {
this.projectId = t, this.database = e || "(default)";
}
static empty() {
return new K("", "");
}
get isDefaultDatabase() {
return "(default)" === this.database;
}
isEqual(t) {
return t instanceof K && 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 J {
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 === J.comparator(this, t);
}
child(t) {
const e = this.segments.slice(this.offset, this.limit());
return t instanceof J ? 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.
*
* @internal
*/ class X extends J {
construct(t, e, n) {
return new X(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 X(e);
}
static emptyPath() {
return new X([]);
}
}
const Z = /^[_a-zA-Z][_a-zA-Z0-9]*$/;
/**
* A dot-separated path for navigating sub-objects within a document.
* @internal
*/ class tt extends J {
construct(t, e, n) {
return new tt(t, e, n);
}
/**
* Returns true if the string could be used as a segment in a field path
* without escaping.
*/ static isValidIdentifier(t) {
return Z.test(t);
}
canonicalString() {
return this.toArray().map((t => (t = t.replace(/\\/g, "\\\\").replace(/`/g, "\\`"),
tt.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 tt([ "__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 tt(e);
}
static emptyPath() {
return new tt([]);
}
}
/**
* @license
* Copyright 2017 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @internal
*/ class et {
constructor(t) {
this.path = t;
}
static fromPath(t) {
return new et(X.fromString(t));
}
static fromName(t) {
return new et(X.fromString(t).popFirst(5));
}
static empty() {
return new et(X.emptyPath());
}
get collectionGroup() {
return this.path.popLast().lastSegment();
}
/** Returns true if the document is in the specified collectionId. */ hasCollectionId(t) {
return this.path.length >= 2 && this.path.get(this.path.length - 2) === t;
}
/** Returns the collection group (i.e. the name of the parent collection) for this key. */ getCollectionGroup() {
return this.path.get(this.path.length - 2);
}
/** Returns the fully qualified path to the parent collection. */ getCollectionPath() {
return this.path.popLast();
}
isEqual(t) {
return null !== t && 0 === X.comparator(this.path, t.path);
}
toString() {
return this.path.toString();
}
static comparator(t, e) {
return X.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 et(new X(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 nt(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.
* @internal
*/
/**
* Validates that `path` refers to a document (indicated by the fact it contains
* an even numbers of segments).
*/
function rt(t) {
if (!et.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 st(t) {
if (et.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 it(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 |