summaryrefslogtreecommitdiff
path: root/frontend-old/node_modules/firebase/firebase-app.js
diff options
context:
space:
mode:
authoraltaf-creator <dev@altafcreator.com>2025-11-09 11:15:19 +0800
committeraltaf-creator <dev@altafcreator.com>2025-11-09 11:15:19 +0800
commit8eff962cab608341a6f2fedc640a0e32d96f26e2 (patch)
tree05534d1a720ddc3691d346c69b4972555820a061 /frontend-old/node_modules/firebase/firebase-app.js
pain
Diffstat (limited to 'frontend-old/node_modules/firebase/firebase-app.js')
-rw-r--r--frontend-old/node_modules/firebase/firebase-app.js2799
1 files changed, 2799 insertions, 0 deletions
diff --git a/frontend-old/node_modules/firebase/firebase-app.js b/frontend-old/node_modules/firebase/firebase-app.js
new file mode 100644
index 0000000..5693cc3
--- /dev/null
+++ b/frontend-old/node_modules/firebase/firebase-app.js
@@ -0,0 +1,2799 @@
+/**
+ * @license
+ * Copyright 2025 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.
+ */
+// This value is retrieved and hardcoded by the NPM postinstall script
+const getDefaultsFromPostinstall = () => undefined;
+
+/**
+ * @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_()
+// TODO(dlarocque): Define this as a class, since we no longer target ES5.
+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 new DecodeBase64StringError();
+ }
+ 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;
+ }
+ }
+ }
+ }
+};
+/**
+ * An error encountered while decoding base64 string.
+ */
+class DecodeBase64StringError extends Error {
+ constructor() {
+ super(...arguments);
+ this.name = 'DecodeBase64StringError';
+ }
+}
+/**
+ * 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, '');
+};
+/**
+ * URL-safe base64 decoding
+ *
+ * NOTE: DO NOT use the global atob() function - it does NOT support the
+ * base64Url variant encoding.
+ *
+ * @param str To be decoded
+ * @return Decoded result, if possible
+ */
+const base64Decode = function (str) {
+ try {
+ return base64.decodeString(str, true);
+ }
+ catch (e) {
+ console.error('base64Decode failed: ', e);
+ }
+ return null;
+};
+/**
+ * @license
+ * Copyright 2022 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.
+ */
+/**
+ * Polyfill for `globalThis` object.
+ * @returns the `globalThis` object for the given environment.
+ * @public
+ */
+function getGlobal() {
+ if (typeof self !== 'undefined') {
+ return self;
+ }
+ if (typeof window !== 'undefined') {
+ return window;
+ }
+ if (typeof global !== 'undefined') {
+ return global;
+ }
+ throw new Error('Unable to locate global object.');
+}
+/**
+ * @license
+ * Copyright 2022 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 getDefaultsFromGlobal = () => getGlobal().__FIREBASE_DEFAULTS__;
+/**
+ * Attempt to read defaults from a JSON string provided to
+ * process(.)env(.)__FIREBASE_DEFAULTS__ or a JSON file whose path is in
+ * process(.)env(.)__FIREBASE_DEFAULTS_PATH__
+ * The dots are in parens because certain compilers (Vite?) cannot
+ * handle seeing that variable in comments.
+ * See https://github.com/firebase/firebase-js-sdk/issues/6838
+ */
+const getDefaultsFromEnvVariable = () => {
+ if (typeof process === 'undefined' || typeof process.env === 'undefined') {
+ return;
+ }
+ const defaultsJsonString = process.env.__FIREBASE_DEFAULTS__;
+ if (defaultsJsonString) {
+ return JSON.parse(defaultsJsonString);
+ }
+};
+const getDefaultsFromCookie = () => {
+ if (typeof document === 'undefined') {
+ return;
+ }
+ let match;
+ try {
+ match = document.cookie.match(/__FIREBASE_DEFAULTS__=([^;]+)/);
+ }
+ catch (e) {
+ // Some environments such as Angular Universal SSR have a
+ // `document` object but error on accessing `document.cookie`.
+ return;
+ }
+ const decoded = match && base64Decode(match[1]);
+ return decoded && JSON.parse(decoded);
+};
+/**
+ * Get the __FIREBASE_DEFAULTS__ object. It checks in order:
+ * (1) if such an object exists as a property of `globalThis`
+ * (2) if such an object was provided on a shell environment variable
+ * (3) if such an object exists in a cookie
+ * @public
+ */
+const getDefaults = () => {
+ try {
+ return (getDefaultsFromPostinstall() ||
+ getDefaultsFromGlobal() ||
+ getDefaultsFromEnvVariable() ||
+ getDefaultsFromCookie());
+ }
+ catch (e) {
+ /**
+ * Catch-all for being unable to get __FIREBASE_DEFAULTS__ due
+ * to any environment case we have not accounted for. Log to
+ * info instead of swallowing so we can find these unknown cases
+ * and add paths for them if needed.
+ */
+ console.info(`Unable to get __FIREBASE_DEFAULTS__ due to: ${e}`);
+ return;
+ }
+};
+/**
+ * Returns Firebase app config stored in the __FIREBASE_DEFAULTS__ object.
+ * @public
+ */
+const getDefaultAppConfig = () => getDefaults()?.config;
+/**
+ * @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 Deferred {
+ constructor() {
+ this.reject = () => { };
+ this.resolve = () => { };
+ this.promise = new Promise((resolve, reject) => {
+ this.resolve = resolve;
+ this.reject = reject;
+ });
+ }
+ /**
+ * Our API internals are not promisified and cannot because our callback APIs have subtle expectations around
+ * invoking promises inline, which Promises are forbidden to do. This method accepts an optional node-style callback
+ * and returns a node-style callback which will resolve or reject the Deferred's promise.
+ */
+ wrapCallback(callback) {
+ return (error, value) => {
+ if (error) {
+ this.reject(error);
+ }
+ else {
+ this.resolve(value);
+ }
+ if (typeof callback === 'function') {
+ // Attaching noop handler just in case developer wasn't expecting
+ // promises
+ this.promise.catch(() => { });
+ // Some of our callbacks don't expect a value and our own tests
+ // assert that the parameter length is 1
+ if (callback.length === 1) {
+ callback(error);
+ }
+ else {
+ callback(error, value);
+ }
+ }
+ };
+ }
+}
+/**
+ * Detect Browser Environment.
+ * Note: This will return true for certain test frameworks that are incompletely
+ * mimicking a browser, and should not lead to assuming all browser APIs are
+ * available.
+ */
+function isBrowser() {
+ return typeof window !== 'undefined' || isWebWorker();
+}
+/**
+ * Detect Web Worker context.
+ */
+function isWebWorker() {
+ return (typeof WorkerGlobalScope !== 'undefined' &&
+ typeof self !== 'undefined' &&
+ self instanceof WorkerGlobalScope);
+}
+/**
+ * This method checks if indexedDB is supported by current browser/service worker context
+ * @return true if indexedDB is supported by current browser/service worker context
+ */
+function isIndexedDBAvailable() {
+ try {
+ return typeof indexedDB === 'object';
+ }
+ catch (e) {
+ return false;
+ }
+}
+/**
+ * This method validates browser/sw context for indexedDB by opening a dummy indexedDB database and reject
+ * if errors occur during the database open operation.
+ *
+ * @throws exception if current browser/sw context can't run idb.open (ex: Safari iframe, Firefox
+ * private browsing)
+ */
+function validateIndexedDBOpenable() {
+ return new Promise((resolve, reject) => {
+ try {
+ let preExist = true;
+ const DB_CHECK_NAME = 'validate-browser-context-for-indexeddb-analytics-module';
+ const request = self.indexedDB.open(DB_CHECK_NAME);
+ request.onsuccess = () => {
+ request.result.close();
+ // delete database only when it doesn't pre-exist
+ if (!preExist) {
+ self.indexedDB.deleteDatabase(DB_CHECK_NAME);
+ }
+ resolve(true);
+ };
+ request.onupgradeneeded = () => {
+ preExist = false;
+ };
+ request.onerror = () => {
+ reject(request.error?.message || '');
+ };
+ }
+ catch (error) {
+ reject(error);
+ }
+ });
+}
+/**
+ * @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 as FirebaseError)?.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
+ // TODO(dlarocque): Replace this with `new.target`: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html#support-for-newtarget
+ // which we can now use since we no longer target ES5.
+ 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;
+/**
+ * Deep equal two objects. Support Arrays and Objects.
+ */
+function deepEqual(a, b) {
+ if (a === b) {
+ return true;
+ }
+ const aKeys = Object.keys(a);
+ const bKeys = Object.keys(b);
+ for (const k of aKeys) {
+ if (!bKeys.includes(k)) {
+ return false;
+ }
+ const aProp = a[k];
+ const bProp = b[k];
+ if (isObject(aProp) && isObject(bProp)) {
+ if (!deepEqual(aProp, bProp)) {
+ return false;
+ }
+ }
+ else if (aProp !== bProp) {
+ return false;
+ }
+ }
+ for (const k of bKeys) {
+ if (!aKeys.includes(k)) {
+ return false;
+ }
+ }
+ return true;
+}
+function isObject(thing) {
+ return thing !== null && typeof thing === 'object';
+}
+
+/**
+ * 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" /* InstantiationMode.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 2019 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 DEFAULT_ENTRY_NAME$1 = '[DEFAULT]';
+/**
+ * @license
+ * Copyright 2019 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.
+ */
+/**
+ * Provider for instance for service name T, e.g. 'auth', 'auth-internal'
+ * NameServiceMapping[T] is an alias for the type of the instance
+ */
+class Provider {
+ constructor(name, container) {
+ this.name = name;
+ this.container = container;
+ this.component = null;
+ this.instances = new Map();
+ this.instancesDeferred = new Map();
+ this.instancesOptions = new Map();
+ this.onInitCallbacks = new Map();
+ }
+ /**
+ * @param identifier A provider can provide multiple instances of a service
+ * if this.component.multipleInstances is true.
+ */
+ get(identifier) {
+ // if multipleInstances is not supported, use the default name
+ const normalizedIdentifier = this.normalizeInstanceIdentifier(identifier);
+ if (!this.instancesDeferred.has(normalizedIdentifier)) {
+ const deferred = new Deferred();
+ this.instancesDeferred.set(normalizedIdentifier, deferred);
+ if (this.isInitialized(normalizedIdentifier) ||
+ this.shouldAutoInitialize()) {
+ // initialize the service if it can be auto-initialized
+ try {
+ const instance = this.getOrInitializeService({
+ instanceIdentifier: normalizedIdentifier
+ });
+ if (instance) {
+ deferred.resolve(instance);
+ }
+ }
+ catch (e) {
+ // when the instance factory throws an exception during get(), it should not cause
+ // a fatal error. We just return the unresolved promise in this case.
+ }
+ }
+ }
+ return this.instancesDeferred.get(normalizedIdentifier).promise;
+ }
+ getImmediate(options) {
+ // if multipleInstances is not supported, use the default name
+ const normalizedIdentifier = this.normalizeInstanceIdentifier(options?.identifier);
+ const optional = options?.optional ?? false;
+ if (this.isInitialized(normalizedIdentifier) ||
+ this.shouldAutoInitialize()) {
+ try {
+ return this.getOrInitializeService({
+ instanceIdentifier: normalizedIdentifier
+ });
+ }
+ catch (e) {
+ if (optional) {
+ return null;
+ }
+ else {
+ throw e;
+ }
+ }
+ }
+ else {
+ // In case a component is not initialized and should/cannot be auto-initialized at the moment, return null if the optional flag is set, or throw
+ if (optional) {
+ return null;
+ }
+ else {
+ throw Error(`Service ${this.name} is not available`);
+ }
+ }
+ }
+ getComponent() {
+ return this.component;
+ }
+ setComponent(component) {
+ if (component.name !== this.name) {
+ throw Error(`Mismatching Component ${component.name} for Provider ${this.name}.`);
+ }
+ if (this.component) {
+ throw Error(`Component for ${this.name} has already been provided`);
+ }
+ this.component = component;
+ // return early without attempting to initialize the component if the component requires explicit initialization (calling `Provider.initialize()`)
+ if (!this.shouldAutoInitialize()) {
+ return;
+ }
+ // if the service is eager, initialize the default instance
+ if (isComponentEager(component)) {
+ try {
+ this.getOrInitializeService({ instanceIdentifier: DEFAULT_ENTRY_NAME$1 });
+ }
+ catch (e) {
+ // when the instance factory for an eager Component throws an exception during the eager
+ // initialization, it should not cause a fatal error.
+ // TODO: Investigate if we need to make it configurable, because some component may want to cause
+ // a fatal error in this case?
+ }
+ }
+ // Create service instances for the pending promises and resolve them
+ // NOTE: if this.multipleInstances is false, only the default instance will be created
+ // and all promises with resolve with it regardless of the identifier.
+ for (const [instanceIdentifier, instanceDeferred] of this.instancesDeferred.entries()) {
+ const normalizedIdentifier = this.normalizeInstanceIdentifier(instanceIdentifier);
+ try {
+ // `getOrInitializeService()` should always return a valid instance since a component is guaranteed. use ! to make typescript happy.
+ const instance = this.getOrInitializeService({
+ instanceIdentifier: normalizedIdentifier
+ });
+ instanceDeferred.resolve(instance);
+ }
+ catch (e) {
+ // when the instance factory throws an exception, it should not cause
+ // a fatal error. We just leave the promise unresolved.
+ }
+ }
+ }
+ clearInstance(identifier = DEFAULT_ENTRY_NAME$1) {
+ this.instancesDeferred.delete(identifier);
+ this.instancesOptions.delete(identifier);
+ this.instances.delete(identifier);
+ }
+ // app.delete() will call this method on every provider to delete the services
+ // TODO: should we mark the provider as deleted?
+ async delete() {
+ const services = Array.from(this.instances.values());
+ await Promise.all([
+ ...services
+ .filter(service => 'INTERNAL' in service) // legacy services
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ .map(service => service.INTERNAL.delete()),
+ ...services
+ .filter(service => '_delete' in service) // modularized services
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ .map(service => service._delete())
+ ]);
+ }
+ isComponentSet() {
+ return this.component != null;
+ }
+ isInitialized(identifier = DEFAULT_ENTRY_NAME$1) {
+ return this.instances.has(identifier);
+ }
+ getOptions(identifier = DEFAULT_ENTRY_NAME$1) {
+ return this.instancesOptions.get(identifier) || {};
+ }
+ initialize(opts = {}) {
+ const { options = {} } = opts;
+ const normalizedIdentifier = this.normalizeInstanceIdentifier(opts.instanceIdentifier);
+ if (this.isInitialized(normalizedIdentifier)) {
+ throw Error(`${this.name}(${normalizedIdentifier}) has already been initialized`);
+ }
+ if (!this.isComponentSet()) {
+ throw Error(`Component ${this.name} has not been registered yet`);
+ }
+ const instance = this.getOrInitializeService({
+ instanceIdentifier: normalizedIdentifier,
+ options
+ });
+ // resolve any pending promise waiting for the service instance
+ for (const [instanceIdentifier, instanceDeferred] of this.instancesDeferred.entries()) {
+ const normalizedDeferredIdentifier = this.normalizeInstanceIdentifier(instanceIdentifier);
+ if (normalizedIdentifier === normalizedDeferredIdentifier) {
+ instanceDeferred.resolve(instance);
+ }
+ }
+ return instance;
+ }
+ /**
+ *
+ * @param callback - a function that will be invoked after the provider has been initialized by calling provider.initialize().
+ * The function is invoked SYNCHRONOUSLY, so it should not execute any longrunning tasks in order to not block the program.
+ *
+ * @param identifier An optional instance identifier
+ * @returns a function to unregister the callback
+ */
+ onInit(callback, identifier) {
+ const normalizedIdentifier = this.normalizeInstanceIdentifier(identifier);
+ const existingCallbacks = this.onInitCallbacks.get(normalizedIdentifier) ??
+ new Set();
+ existingCallbacks.add(callback);
+ this.onInitCallbacks.set(normalizedIdentifier, existingCallbacks);
+ const existingInstance = this.instances.get(normalizedIdentifier);
+ if (existingInstance) {
+ callback(existingInstance, normalizedIdentifier);
+ }
+ return () => {
+ existingCallbacks.delete(callback);
+ };
+ }
+ /**
+ * Invoke onInit callbacks synchronously
+ * @param instance the service instance`
+ */
+ invokeOnInitCallbacks(instance, identifier) {
+ const callbacks = this.onInitCallbacks.get(identifier);
+ if (!callbacks) {
+ return;
+ }
+ for (const callback of callbacks) {
+ try {
+ callback(instance, identifier);
+ }
+ catch {
+ // ignore errors in the onInit callback
+ }
+ }
+ }
+ getOrInitializeService({ instanceIdentifier, options = {} }) {
+ let instance = this.instances.get(instanceIdentifier);
+ if (!instance && this.component) {
+ instance = this.component.instanceFactory(this.container, {
+ instanceIdentifier: normalizeIdentifierForFactory(instanceIdentifier),
+ options
+ });
+ this.instances.set(instanceIdentifier, instance);
+ this.instancesOptions.set(instanceIdentifier, options);
+ /**
+ * Invoke onInit listeners.
+ * Note this.component.onInstanceCreated is different, which is used by the component creator,
+ * while onInit listeners are registered by consumers of the provider.
+ */
+ this.invokeOnInitCallbacks(instance, instanceIdentifier);
+ /**
+ * Order is important
+ * onInstanceCreated() should be called after this.instances.set(instanceIdentifier, instance); which
+ * makes `isInitialized()` return true.
+ */
+ if (this.component.onInstanceCreated) {
+ try {
+ this.component.onInstanceCreated(this.container, instanceIdentifier, instance);
+ }
+ catch {
+ // ignore errors in the onInstanceCreatedCallback
+ }
+ }
+ }
+ return instance || null;
+ }
+ normalizeInstanceIdentifier(identifier = DEFAULT_ENTRY_NAME$1) {
+ if (this.component) {
+ return this.component.multipleInstances ? identifier : DEFAULT_ENTRY_NAME$1;
+ }
+ else {
+ return identifier; // assume multiple instances are supported before the component is provided.
+ }
+ }
+ shouldAutoInitialize() {
+ return (!!this.component &&
+ this.component.instantiationMode !== "EXPLICIT" /* InstantiationMode.EXPLICIT */);
+ }
+}
+// undefined should be passed to the service factory for the default instance
+function normalizeIdentifierForFactory(identifier) {
+ return identifier === DEFAULT_ENTRY_NAME$1 ? undefined : identifier;
+}
+function isComponentEager(component) {
+ return component.instantiationMode === "EAGER" /* InstantiationMode.EAGER */;
+}
+/**
+ * @license
+ * Copyright 2019 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.
+ */
+/**
+ * ComponentContainer that provides Providers for service name T, e.g. `auth`, `auth-internal`
+ */
+class ComponentContainer {
+ constructor(name) {
+ this.name = name;
+ this.providers = new Map();
+ }
+ /**
+ *
+ * @param component Component being added
+ * @param overwrite When a component with the same name has already been registered,
+ * if overwrite is true: overwrite the existing component with the new component and create a new
+ * provider with the new component. It can be useful in tests where you want to use different mocks
+ * for different tests.
+ * if overwrite is false: throw an exception
+ */
+ addComponent(component) {
+ const provider = this.getProvider(component.name);
+ if (provider.isComponentSet()) {
+ throw new Error(`Component ${component.name} has already been registered with ${this.name}`);
+ }
+ provider.setComponent(component);
+ }
+ addOrOverwriteComponent(component) {
+ const provider = this.getProvider(component.name);
+ if (provider.isComponentSet()) {
+ // delete the existing provider from the container, so we can register the new component
+ this.providers.delete(component.name);
+ }
+ this.addComponent(component);
+ }
+ /**
+ * getProvider provides a type safe interface where it can only be called with a field name
+ * present in NameServiceMapping interface.
+ *
+ * Firebase SDKs providing services should extend NameServiceMapping interface to register
+ * themselves.
+ */
+ getProvider(name) {
+ if (this.providers.has(name)) {
+ return this.providers.get(name);
+ }
+ // create a Provider for a service that hasn't registered with Firebase
+ const provider = new Provider(name, this);
+ this.providers.set(name, provider);
+ return provider;
+ }
+ getProviders() {
+ return Array.from(this.providers.values());
+ }
+}
+
+/**
+ * @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 container for all of the Logger instances
+ */
+const instances = [];
+/**
+ * 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;
+ /**
+ * Capture the current instance for later use
+ */
+ instances.push(this);
+ }
+ 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);
+ }
+}
+function setLogLevel$1(level) {
+ instances.forEach(inst => {
+ inst.setLogLevel(level);
+ });
+}
+function setUserLogHandler(logCallback, options) {
+ for (const instance of instances) {
+ let customLogLevel = null;
+ if (options && options.level) {
+ customLogLevel = levelStringToEnum[options.level];
+ }
+ if (logCallback === null) {
+ instance.userLogHandler = null;
+ }
+ else {
+ instance.userLogHandler = (instance, level, ...args) => {
+ const message = args
+ .map(arg => {
+ if (arg == null) {
+ return null;
+ }
+ else if (typeof arg === 'string') {
+ return arg;
+ }
+ else if (typeof arg === 'number' || typeof arg === 'boolean') {
+ return arg.toString();
+ }
+ else if (arg instanceof Error) {
+ return arg.message;
+ }
+ else {
+ try {
+ return JSON.stringify(arg);
+ }
+ catch (ignored) {
+ return null;
+ }
+ }
+ })
+ .filter(arg => arg)
+ .join(' ');
+ if (level >= (customLogLevel ?? instance.logLevel)) {
+ logCallback({
+ level: LogLevel[level].toLowerCase(),
+ message,
+ args,
+ type: instance.name
+ });
+ }
+ };
+ }
+ }
+}
+
+const instanceOfAny = (object, constructors) => constructors.some((c) => object instanceof c);
+let idbProxyableTypes;
+let cursorAdvanceMethods;
+// This is a function to prevent it throwing up in node environments.
+function getIdbProxyableTypes() {
+ return (idbProxyableTypes ||
+ (idbProxyableTypes = [
+ IDBDatabase,
+ IDBObjectStore,
+ IDBIndex,
+ IDBCursor,
+ IDBTransaction,
+ ]));
+}
+// This is a function to prevent it throwing up in node environments.
+function getCursorAdvanceMethods() {
+ return (cursorAdvanceMethods ||
+ (cursorAdvanceMethods = [
+ IDBCursor.prototype.advance,
+ IDBCursor.prototype.continue,
+ IDBCursor.prototype.continuePrimaryKey,
+ ]));
+}
+const cursorRequestMap = new WeakMap();
+const transactionDoneMap = new WeakMap();
+const transactionStoreNamesMap = new WeakMap();
+const transformCache = new WeakMap();
+const reverseTransformCache = new WeakMap();
+function promisifyRequest(request) {
+ const promise = new Promise((resolve, reject) => {
+ const unlisten = () => {
+ request.removeEventListener('success', success);
+ request.removeEventListener('error', error);
+ };
+ const success = () => {
+ resolve(wrap(request.result));
+ unlisten();
+ };
+ const error = () => {
+ reject(request.error);
+ unlisten();
+ };
+ request.addEventListener('success', success);
+ request.addEventListener('error', error);
+ });
+ promise
+ .then((value) => {
+ // Since cursoring reuses the IDBRequest (*sigh*), we cache it for later retrieval
+ // (see wrapFunction).
+ if (value instanceof IDBCursor) {
+ cursorRequestMap.set(value, request);
+ }
+ // Catching to avoid "Uncaught Promise exceptions"
+ })
+ .catch(() => { });
+ // This mapping exists in reverseTransformCache but doesn't doesn't exist in transformCache. This
+ // is because we create many promises from a single IDBRequest.
+ reverseTransformCache.set(promise, request);
+ return promise;
+}
+function cacheDonePromiseForTransaction(tx) {
+ // Early bail if we've already created a done promise for this transaction.
+ if (transactionDoneMap.has(tx))
+ return;
+ const done = new Promise((resolve, reject) => {
+ const unlisten = () => {
+ tx.removeEventListener('complete', complete);
+ tx.removeEventListener('error', error);
+ tx.removeEventListener('abort', error);
+ };
+ const complete = () => {
+ resolve();
+ unlisten();
+ };
+ const error = () => {
+ reject(tx.error || new DOMException('AbortError', 'AbortError'));
+ unlisten();
+ };
+ tx.addEventListener('complete', complete);
+ tx.addEventListener('error', error);
+ tx.addEventListener('abort', error);
+ });
+ // Cache it for later retrieval.
+ transactionDoneMap.set(tx, done);
+}
+let idbProxyTraps = {
+ get(target, prop, receiver) {
+ if (target instanceof IDBTransaction) {
+ // Special handling for transaction.done.
+ if (prop === 'done')
+ return transactionDoneMap.get(target);
+ // Polyfill for objectStoreNames because of Edge.
+ if (prop === 'objectStoreNames') {
+ return target.objectStoreNames || transactionStoreNamesMap.get(target);
+ }
+ // Make tx.store return the only store in the transaction, or undefined if there are many.
+ if (prop === 'store') {
+ return receiver.objectStoreNames[1]
+ ? undefined
+ : receiver.objectStore(receiver.objectStoreNames[0]);
+ }
+ }
+ // Else transform whatever we get back.
+ return wrap(target[prop]);
+ },
+ set(target, prop, value) {
+ target[prop] = value;
+ return true;
+ },
+ has(target, prop) {
+ if (target instanceof IDBTransaction &&
+ (prop === 'done' || prop === 'store')) {
+ return true;
+ }
+ return prop in target;
+ },
+};
+function replaceTraps(callback) {
+ idbProxyTraps = callback(idbProxyTraps);
+}
+function wrapFunction(func) {
+ // Due to expected object equality (which is enforced by the caching in `wrap`), we
+ // only create one new func per func.
+ // Edge doesn't support objectStoreNames (booo), so we polyfill it here.
+ if (func === IDBDatabase.prototype.transaction &&
+ !('objectStoreNames' in IDBTransaction.prototype)) {
+ return function (storeNames, ...args) {
+ const tx = func.call(unwrap(this), storeNames, ...args);
+ transactionStoreNamesMap.set(tx, storeNames.sort ? storeNames.sort() : [storeNames]);
+ return wrap(tx);
+ };
+ }
+ // Cursor methods are special, as the behaviour is a little more different to standard IDB. In
+ // IDB, you advance the cursor and wait for a new 'success' on the IDBRequest that gave you the
+ // cursor. It's kinda like a promise that can resolve with many values. That doesn't make sense
+ // with real promises, so each advance methods returns a new promise for the cursor object, or
+ // undefined if the end of the cursor has been reached.
+ if (getCursorAdvanceMethods().includes(func)) {
+ return function (...args) {
+ // Calling the original function with the proxy as 'this' causes ILLEGAL INVOCATION, so we use
+ // the original object.
+ func.apply(unwrap(this), args);
+ return wrap(cursorRequestMap.get(this));
+ };
+ }
+ return function (...args) {
+ // Calling the original function with the proxy as 'this' causes ILLEGAL INVOCATION, so we use
+ // the original object.
+ return wrap(func.apply(unwrap(this), args));
+ };
+}
+function transformCachableValue(value) {
+ if (typeof value === 'function')
+ return wrapFunction(value);
+ // This doesn't return, it just creates a 'done' promise for the transaction,
+ // which is later returned for transaction.done (see idbObjectHandler).
+ if (value instanceof IDBTransaction)
+ cacheDonePromiseForTransaction(value);
+ if (instanceOfAny(value, getIdbProxyableTypes()))
+ return new Proxy(value, idbProxyTraps);
+ // Return the same value back if we're not going to transform it.
+ return value;
+}
+function wrap(value) {
+ // We sometimes generate multiple promises from a single IDBRequest (eg when cursoring), because
+ // IDB is weird and a single IDBRequest can yield many responses, so these can't be cached.
+ if (value instanceof IDBRequest)
+ return promisifyRequest(value);
+ // If we've already transformed this value before, reuse the transformed value.
+ // This is faster, but it also provides object equality.
+ if (transformCache.has(value))
+ return transformCache.get(value);
+ const newValue = transformCachableValue(value);
+ // Not all types are transformed.
+ // These may be primitive types, so they can't be WeakMap keys.
+ if (newValue !== value) {
+ transformCache.set(value, newValue);
+ reverseTransformCache.set(newValue, value);
+ }
+ return newValue;
+}
+const unwrap = (value) => reverseTransformCache.get(value);
+
+/**
+ * Open a database.
+ *
+ * @param name Name of the database.
+ * @param version Schema version.
+ * @param callbacks Additional callbacks.
+ */
+function openDB(name, version, { blocked, upgrade, blocking, terminated } = {}) {
+ const request = indexedDB.open(name, version);
+ const openPromise = wrap(request);
+ if (upgrade) {
+ request.addEventListener('upgradeneeded', (event) => {
+ upgrade(wrap(request.result), event.oldVersion, event.newVersion, wrap(request.transaction), event);
+ });
+ }
+ if (blocked) {
+ request.addEventListener('blocked', (event) => blocked(
+ // Casting due to https://github.com/microsoft/TypeScript-DOM-lib-generator/pull/1405
+ event.oldVersion, event.newVersion, event));
+ }
+ openPromise
+ .then((db) => {
+ if (terminated)
+ db.addEventListener('close', () => terminated());
+ if (blocking) {
+ db.addEventListener('versionchange', (event) => blocking(event.oldVersion, event.newVersion, event));
+ }
+ })
+ .catch(() => { });
+ return openPromise;
+}
+const readMethods = ['get', 'getKey', 'getAll', 'getAllKeys', 'count'];
+const writeMethods = ['put', 'add', 'delete', 'clear'];
+const cachedMethods = new Map();
+function getMethod(target, prop) {
+ if (!(target instanceof IDBDatabase &&
+ !(prop in target) &&
+ typeof prop === 'string')) {
+ return;
+ }
+ if (cachedMethods.get(prop))
+ return cachedMethods.get(prop);
+ const targetFuncName = prop.replace(/FromIndex$/, '');
+ const useIndex = prop !== targetFuncName;
+ const isWrite = writeMethods.includes(targetFuncName);
+ if (
+ // Bail if the target doesn't exist on the target. Eg, getAll isn't in Edge.
+ !(targetFuncName in (useIndex ? IDBIndex : IDBObjectStore).prototype) ||
+ !(isWrite || readMethods.includes(targetFuncName))) {
+ return;
+ }
+ const method = async function (storeName, ...args) {
+ // isWrite ? 'readwrite' : undefined gzipps better, but fails in Edge :(
+ const tx = this.transaction(storeName, isWrite ? 'readwrite' : 'readonly');
+ let target = tx.store;
+ if (useIndex)
+ target = target.index(args.shift());
+ // Must reject if op rejects.
+ // If it's a write operation, must reject if tx.done rejects.
+ // Must reject with op rejection first.
+ // Must resolve with op value.
+ // Must handle both promises (no unhandled rejections)
+ return (await Promise.all([
+ target[targetFuncName](...args),
+ isWrite && tx.done,
+ ]))[0];
+ };
+ cachedMethods.set(prop, method);
+ return method;
+}
+replaceTraps((oldTraps) => ({
+ ...oldTraps,
+ get: (target, prop, receiver) => getMethod(target, prop) || oldTraps.get(target, prop, receiver),
+ has: (target, prop) => !!getMethod(target, prop) || oldTraps.has(target, prop),
+}));
+
+/**
+ * @license
+ * Copyright 2019 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 PlatformLoggerServiceImpl {
+ constructor(container) {
+ this.container = container;
+ }
+ // In initial implementation, this will be called by installations on
+ // auth token refresh, and installations will send this string.
+ getPlatformInfoString() {
+ const providers = this.container.getProviders();
+ // Loop through providers and get library/version pairs from any that are
+ // version components.
+ return providers
+ .map(provider => {
+ if (isVersionServiceProvider(provider)) {
+ const service = provider.getImmediate();
+ return `${service.library}/${service.version}`;
+ }
+ else {
+ return null;
+ }
+ })
+ .filter(logString => logString)
+ .join(' ');
+ }
+}
+/**
+ *
+ * @param provider check if this provider provides a VersionService
+ *
+ * NOTE: Using Provider<'app-version'> is a hack to indicate that the provider
+ * provides VersionService. The provider is not necessarily a 'app-version'
+ * provider.
+ */
+function isVersionServiceProvider(provider) {
+ const component = provider.getComponent();
+ return component?.type === "VERSION" /* ComponentType.VERSION */;
+}
+const name$q = "https://www.gstatic.com/firebasejs/12.5.0/firebase-app.js";
+const version$1 = "0.14.5";
+/**
+ * @license
+ * Copyright 2019 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 logger = new Logger('https://www.gstatic.com/firebasejs/12.5.0/firebase-app.js');
+const name$p = "@firebase/app-compat";
+const name$o = "@firebase/analytics-compat";
+const name$n = "@firebase/analytics";
+const name$m = "@firebase/app-check-compat";
+const name$l = "@firebase/app-check";
+const name$k = "@firebase/auth";
+const name$j = "@firebase/auth-compat";
+const name$i = "@firebase/database";
+const name$h = "@firebase/data-connect";
+const name$g = "@firebase/database-compat";
+const name$f = "@firebase/functions";
+const name$e = "@firebase/functions-compat";
+const name$d = "@firebase/installations";
+const name$c = "@firebase/installations-compat";
+const name$b = "@firebase/messaging";
+const name$a = "@firebase/messaging-compat";
+const name$9 = "@firebase/performance";
+const name$8 = "@firebase/performance-compat";
+const name$7 = "@firebase/remote-config";
+const name$6 = "@firebase/remote-config-compat";
+const name$5 = "@firebase/storage";
+const name$4 = "@firebase/storage-compat";
+const name$3 = "@firebase/firestore";
+const name$2 = "@firebase/ai";
+const name$1 = "@firebase/firestore-compat";
+const name$r = "firebase";
+const version$2 = "12.5.0";
+/**
+ * @license
+ * Copyright 2019 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 default app name
+ *
+ * @internal
+ */
+const DEFAULT_ENTRY_NAME = '[DEFAULT]';
+const PLATFORM_LOG_STRING = {
+ [name$q]: 'fire-core',
+ [name$p]: 'fire-core-compat',
+ [name$n]: 'fire-analytics',
+ [name$o]: 'fire-analytics-compat',
+ [name$l]: 'fire-app-check',
+ [name$m]: 'fire-app-check-compat',
+ [name$k]: 'fire-auth',
+ [name$j]: 'fire-auth-compat',
+ [name$i]: 'fire-rtdb',
+ [name$h]: 'fire-data-connect',
+ [name$g]: 'fire-rtdb-compat',
+ [name$f]: 'fire-fn',
+ [name$e]: 'fire-fn-compat',
+ [name$d]: 'fire-iid',
+ [name$c]: 'fire-iid-compat',
+ [name$b]: 'fire-fcm',
+ [name$a]: 'fire-fcm-compat',
+ [name$9]: 'fire-perf',
+ [name$8]: 'fire-perf-compat',
+ [name$7]: 'fire-rc',
+ [name$6]: 'fire-rc-compat',
+ [name$5]: 'fire-gcs',
+ [name$4]: 'fire-gcs-compat',
+ [name$3]: 'fire-fst',
+ [name$1]: 'fire-fst-compat',
+ [name$2]: 'fire-vertex',
+ 'fire-js': 'fire-js', // Platform identifier for JS SDK.
+ [name$r]: 'fire-js-all'
+};
+/**
+ * @license
+ * Copyright 2019 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
+ */
+const _apps = new Map();
+/**
+ * @internal
+ */
+const _serverApps = new Map();
+/**
+ * Registered components.
+ *
+ * @internal
+ */
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+const _components = new Map();
+/**
+ * @param component - the component being added to this app's container
+ *
+ * @internal
+ */
+function _addComponent(app, component) {
+ try {
+ app.container.addComponent(component);
+ }
+ catch (e) {
+ logger.debug(`Component ${component.name} failed to register with FirebaseApp ${app.name}`, e);
+ }
+}
+/**
+ *
+ * @internal
+ */
+function _addOrOverwriteComponent(app, component) {
+ app.container.addOrOverwriteComponent(component);
+}
+/**
+ *
+ * @param component - the component to register
+ * @returns whether or not the component is registered successfully
+ *
+ * @internal
+ */
+function _registerComponent(component) {
+ const componentName = component.name;
+ if (_components.has(componentName)) {
+ logger.debug(`There were multiple attempts to register component ${componentName}.`);
+ return false;
+ }
+ _components.set(componentName, component);
+ // add the component to existing app instances
+ for (const app of _apps.values()) {
+ _addComponent(app, component);
+ }
+ for (const serverApp of _serverApps.values()) {
+ _addComponent(serverApp, component);
+ }
+ return true;
+}
+/**
+ *
+ * @param app - FirebaseApp instance
+ * @param name - service name
+ *
+ * @returns the provider for the service with the matching name
+ *
+ * @internal
+ */
+function _getProvider(app, name) {
+ const heartbeatController = app.container
+ .getProvider('heartbeat')
+ .getImmediate({ optional: true });
+ if (heartbeatController) {
+ void heartbeatController.triggerHeartbeat();
+ }
+ return app.container.getProvider(name);
+}
+/**
+ *
+ * @param app - FirebaseApp instance
+ * @param name - service name
+ * @param instanceIdentifier - service instance identifier in case the service supports multiple instances
+ *
+ * @internal
+ */
+function _removeServiceInstance(app, name, instanceIdentifier = DEFAULT_ENTRY_NAME) {
+ _getProvider(app, name).clearInstance(instanceIdentifier);
+}
+/**
+ *
+ * @param obj - an object of type FirebaseApp, FirebaseOptions or FirebaseAppSettings.
+ *
+ * @returns true if the provide object is of type FirebaseApp.
+ *
+ * @internal
+ */
+function _isFirebaseApp(obj) {
+ return obj.options !== undefined;
+}
+/**
+ *
+ * @param obj - an object of type FirebaseApp, FirebaseOptions or FirebaseAppSettings.
+ *
+ * @returns true if the provided object is of type FirebaseServerAppImpl.
+ *
+ * @internal
+ */
+function _isFirebaseServerAppSettings(obj) {
+ if (_isFirebaseApp(obj)) {
+ return false;
+ }
+ return ('authIdToken' in obj ||
+ 'appCheckToken' in obj ||
+ 'releaseOnDeref' in obj ||
+ 'automaticDataCollectionEnabled' in obj);
+}
+/**
+ *
+ * @param obj - an object of type FirebaseApp.
+ *
+ * @returns true if the provided object is of type FirebaseServerAppImpl.
+ *
+ * @internal
+ */
+function _isFirebaseServerApp(obj) {
+ if (obj === null || obj === undefined) {
+ return false;
+ }
+ return obj.settings !== undefined;
+}
+/**
+ * Test only
+ *
+ * @internal
+ */
+function _clearComponents() {
+ _components.clear();
+}
+/**
+ * @license
+ * Copyright 2019 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 ERRORS = {
+ ["no-app" /* AppError.NO_APP */]: "No Firebase App '{$appName}' has been created - " +
+ 'call initializeApp() first',
+ ["bad-app-name" /* AppError.BAD_APP_NAME */]: "Illegal App name: '{$appName}'",
+ ["duplicate-app" /* AppError.DUPLICATE_APP */]: "Firebase App named '{$appName}' already exists with different options or config",
+ ["app-deleted" /* AppError.APP_DELETED */]: "Firebase App named '{$appName}' already deleted",
+ ["server-app-deleted" /* AppError.SERVER_APP_DELETED */]: 'Firebase Server App has been deleted',
+ ["no-options" /* AppError.NO_OPTIONS */]: 'Need to provide options, when not being deployed to hosting via source.',
+ ["invalid-app-argument" /* AppError.INVALID_APP_ARGUMENT */]: 'firebase.{$appName}() takes either no argument or a ' +
+ 'Firebase App instance.',
+ ["invalid-log-argument" /* AppError.INVALID_LOG_ARGUMENT */]: 'First argument to `onLog` must be null or a function.',
+ ["idb-open" /* AppError.IDB_OPEN */]: 'Error thrown when opening IndexedDB. Original error: {$originalErrorMessage}.',
+ ["idb-get" /* AppError.IDB_GET */]: 'Error thrown when reading from IndexedDB. Original error: {$originalErrorMessage}.',
+ ["idb-set" /* AppError.IDB_WRITE */]: 'Error thrown when writing to IndexedDB. Original error: {$originalErrorMessage}.',
+ ["idb-delete" /* AppError.IDB_DELETE */]: 'Error thrown when deleting from IndexedDB. Original error: {$originalErrorMessage}.',
+ ["finalization-registry-not-supported" /* AppError.FINALIZATION_REGISTRY_NOT_SUPPORTED */]: 'FirebaseServerApp deleteOnDeref field defined but the JS runtime does not support FinalizationRegistry.',
+ ["invalid-server-app-environment" /* AppError.INVALID_SERVER_APP_ENVIRONMENT */]: 'FirebaseServerApp is not for use in browser environments.'
+};
+const ERROR_FACTORY = new ErrorFactory('app', 'Firebase', ERRORS);
+/**
+ * @license
+ * Copyright 2019 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 FirebaseAppImpl {
+ constructor(options, config, container) {
+ this._isDeleted = false;
+ this._options = { ...options };
+ this._config = { ...config };
+ this._name = config.name;
+ this._automaticDataCollectionEnabled =
+ config.automaticDataCollectionEnabled;
+ this._container = container;
+ this.container.addComponent(new Component('app', () => this, "PUBLIC" /* ComponentType.PUBLIC */));
+ }
+ get automaticDataCollectionEnabled() {
+ this.checkDestroyed();
+ return this._automaticDataCollectionEnabled;
+ }
+ set automaticDataCollectionEnabled(val) {
+ this.checkDestroyed();
+ this._automaticDataCollectionEnabled = val;
+ }
+ get name() {
+ this.checkDestroyed();
+ return this._name;
+ }
+ get options() {
+ this.checkDestroyed();
+ return this._options;
+ }
+ get config() {
+ this.checkDestroyed();
+ return this._config;
+ }
+ get container() {
+ return this._container;
+ }
+ get isDeleted() {
+ return this._isDeleted;
+ }
+ set isDeleted(val) {
+ this._isDeleted = val;
+ }
+ /**
+ * This function will throw an Error if the App has already been deleted -
+ * use before performing API actions on the App.
+ */
+ checkDestroyed() {
+ if (this.isDeleted) {
+ throw ERROR_FACTORY.create("app-deleted" /* AppError.APP_DELETED */, { appName: this._name });
+ }
+ }
+}
+/**
+ * @license
+ * Copyright 2023 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+// Parse the token and check to see if the `exp` claim is in the future.
+// Reports an error to the console if the token or claim could not be parsed, or if `exp` is in
+// the past.
+function validateTokenTTL(base64Token, tokenName) {
+ const secondPart = base64Decode(base64Token.split('.')[1]);
+ if (secondPart === null) {
+ console.error(`FirebaseServerApp ${tokenName} is invalid: second part could not be parsed.`);
+ return;
+ }
+ const expClaim = JSON.parse(secondPart).exp;
+ if (expClaim === undefined) {
+ console.error(`FirebaseServerApp ${tokenName} is invalid: expiration claim could not be parsed`);
+ return;
+ }
+ const exp = JSON.parse(secondPart).exp * 1000;
+ const now = new Date().getTime();
+ const diff = exp - now;
+ if (diff <= 0) {
+ console.error(`FirebaseServerApp ${tokenName} is invalid: the token has expired.`);
+ }
+}
+class FirebaseServerAppImpl extends FirebaseAppImpl {
+ constructor(options, serverConfig, name, container) {
+ // Build configuration parameters for the FirebaseAppImpl base class.
+ const automaticDataCollectionEnabled = serverConfig.automaticDataCollectionEnabled !== undefined
+ ? serverConfig.automaticDataCollectionEnabled
+ : true;
+ // Create the FirebaseAppSettings object for the FirebaseAppImp constructor.
+ const config = {
+ name,
+ automaticDataCollectionEnabled
+ };
+ if (options.apiKey !== undefined) {
+ // Construct the parent FirebaseAppImp object.
+ super(options, config, container);
+ }
+ else {
+ const appImpl = options;
+ super(appImpl.options, config, container);
+ }
+ // Now construct the data for the FirebaseServerAppImpl.
+ this._serverConfig = {
+ automaticDataCollectionEnabled,
+ ...serverConfig
+ };
+ // Ensure that the current time is within the `authIdtoken` window of validity.
+ if (this._serverConfig.authIdToken) {
+ validateTokenTTL(this._serverConfig.authIdToken, 'authIdToken');
+ }
+ // Ensure that the current time is within the `appCheckToken` window of validity.
+ if (this._serverConfig.appCheckToken) {
+ validateTokenTTL(this._serverConfig.appCheckToken, 'appCheckToken');
+ }
+ this._finalizationRegistry = null;
+ if (typeof FinalizationRegistry !== 'undefined') {
+ this._finalizationRegistry = new FinalizationRegistry(() => {
+ this.automaticCleanup();
+ });
+ }
+ this._refCount = 0;
+ this.incRefCount(this._serverConfig.releaseOnDeref);
+ // Do not retain a hard reference to the dref object, otherwise the FinalizationRegistry
+ // will never trigger.
+ this._serverConfig.releaseOnDeref = undefined;
+ serverConfig.releaseOnDeref = undefined;
+ registerVersion(name$q, version$1, 'serverapp');
+ }
+ toJSON() {
+ return undefined;
+ }
+ get refCount() {
+ return this._refCount;
+ }
+ // Increment the reference count of this server app. If an object is provided, register it
+ // with the finalization registry.
+ incRefCount(obj) {
+ if (this.isDeleted) {
+ return;
+ }
+ this._refCount++;
+ if (obj !== undefined && this._finalizationRegistry !== null) {
+ this._finalizationRegistry.register(obj, this);
+ }
+ }
+ // Decrement the reference count.
+ decRefCount() {
+ if (this.isDeleted) {
+ return 0;
+ }
+ return --this._refCount;
+ }
+ // Invoked by the FinalizationRegistry callback to note that this app should go through its
+ // reference counts and delete itself if no reference count remain. The coordinating logic that
+ // handles this is in deleteApp(...).
+ automaticCleanup() {
+ void deleteApp(this);
+ }
+ get settings() {
+ this.checkDestroyed();
+ return this._serverConfig;
+ }
+ /**
+ * This function will throw an Error if the App has already been deleted -
+ * use before performing API actions on the App.
+ */
+ checkDestroyed() {
+ if (this.isDeleted) {
+ throw ERROR_FACTORY.create("server-app-deleted" /* AppError.SERVER_APP_DELETED */);
+ }
+ }
+}
+/**
+ * @license
+ * Copyright 2019 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 current SDK version.
+ *
+ * @public
+ */
+const SDK_VERSION = version$2;
+function initializeApp(_options, rawConfig = {}) {
+ let options = _options;
+ if (typeof rawConfig !== 'object') {
+ const name = rawConfig;
+ rawConfig = { name };
+ }
+ const config = {
+ name: DEFAULT_ENTRY_NAME,
+ automaticDataCollectionEnabled: true,
+ ...rawConfig
+ };
+ const name = config.name;
+ if (typeof name !== 'string' || !name) {
+ throw ERROR_FACTORY.create("bad-app-name" /* AppError.BAD_APP_NAME */, {
+ appName: String(name)
+ });
+ }
+ options || (options = getDefaultAppConfig());
+ if (!options) {
+ throw ERROR_FACTORY.create("no-options" /* AppError.NO_OPTIONS */);
+ }
+ const existingApp = _apps.get(name);
+ if (existingApp) {
+ // return the existing app if options and config deep equal the ones in the existing app.
+ if (deepEqual(options, existingApp.options) &&
+ deepEqual(config, existingApp.config)) {
+ return existingApp;
+ }
+ else {
+ throw ERROR_FACTORY.create("duplicate-app" /* AppError.DUPLICATE_APP */, { appName: name });
+ }
+ }
+ const container = new ComponentContainer(name);
+ for (const component of _components.values()) {
+ container.addComponent(component);
+ }
+ const newApp = new FirebaseAppImpl(options, config, container);
+ _apps.set(name, newApp);
+ return newApp;
+}
+function initializeServerApp(_options, _serverAppConfig = {}) {
+ if (isBrowser() && !isWebWorker()) {
+ // FirebaseServerApp isn't designed to be run in browsers.
+ throw ERROR_FACTORY.create("invalid-server-app-environment" /* AppError.INVALID_SERVER_APP_ENVIRONMENT */);
+ }
+ let firebaseOptions;
+ let serverAppSettings = _serverAppConfig || {};
+ if (_options) {
+ if (_isFirebaseApp(_options)) {
+ firebaseOptions = _options.options;
+ }
+ else if (_isFirebaseServerAppSettings(_options)) {
+ serverAppSettings = _options;
+ }
+ else {
+ firebaseOptions = _options;
+ }
+ }
+ if (serverAppSettings.automaticDataCollectionEnabled === undefined) {
+ serverAppSettings.automaticDataCollectionEnabled = true;
+ }
+ firebaseOptions || (firebaseOptions = getDefaultAppConfig());
+ if (!firebaseOptions) {
+ throw ERROR_FACTORY.create("no-options" /* AppError.NO_OPTIONS */);
+ }
+ // Build an app name based on a hash of the configuration options.
+ const nameObj = {
+ ...serverAppSettings,
+ ...firebaseOptions
+ };
+ // However, Do not mangle the name based on releaseOnDeref, since it will vary between the
+ // construction of FirebaseServerApp instances. For example, if the object is the request headers.
+ if (nameObj.releaseOnDeref !== undefined) {
+ delete nameObj.releaseOnDeref;
+ }
+ const hashCode = (s) => {
+ return [...s].reduce((hash, c) => (Math.imul(31, hash) + c.charCodeAt(0)) | 0, 0);
+ };
+ if (serverAppSettings.releaseOnDeref !== undefined) {
+ if (typeof FinalizationRegistry === 'undefined') {
+ throw ERROR_FACTORY.create("finalization-registry-not-supported" /* AppError.FINALIZATION_REGISTRY_NOT_SUPPORTED */, {});
+ }
+ }
+ const nameString = '' + hashCode(JSON.stringify(nameObj));
+ const existingApp = _serverApps.get(nameString);
+ if (existingApp) {
+ existingApp.incRefCount(serverAppSettings.releaseOnDeref);
+ return existingApp;
+ }
+ const container = new ComponentContainer(nameString);
+ for (const component of _components.values()) {
+ container.addComponent(component);
+ }
+ const newApp = new FirebaseServerAppImpl(firebaseOptions, serverAppSettings, nameString, container);
+ _serverApps.set(nameString, newApp);
+ return newApp;
+}
+/**
+ * Retrieves a {@link @firebase/app#FirebaseApp} instance.
+ *
+ * When called with no arguments, the default app is returned. When an app name
+ * is provided, the app corresponding to that name is returned.
+ *
+ * An exception is thrown if the app being retrieved has not yet been
+ * initialized.
+ *
+ * @example
+ * ```javascript
+ * // Return the default app
+ * const app = getApp();
+ * ```
+ *
+ * @example
+ * ```javascript
+ * // Return a named app
+ * const otherApp = getApp("otherApp");
+ * ```
+ *
+ * @param name - Optional name of the app to return. If no name is
+ * provided, the default is `"[DEFAULT]"`.
+ *
+ * @returns The app corresponding to the provided app name.
+ * If no app name is provided, the default app is returned.
+ *
+ * @public
+ */
+function getApp(name = DEFAULT_ENTRY_NAME) {
+ const app = _apps.get(name);
+ if (!app && name === DEFAULT_ENTRY_NAME && getDefaultAppConfig()) {
+ return initializeApp();
+ }
+ if (!app) {
+ throw ERROR_FACTORY.create("no-app" /* AppError.NO_APP */, { appName: name });
+ }
+ return app;
+}
+/**
+ * A (read-only) array of all initialized apps.
+ * @public
+ */
+function getApps() {
+ return Array.from(_apps.values());
+}
+/**
+ * Renders this app unusable and frees the resources of all associated
+ * services.
+ *
+ * @example
+ * ```javascript
+ * deleteApp(app)
+ * .then(function() {
+ * console.log("App deleted successfully");
+ * })
+ * .catch(function(error) {
+ * console.log("Error deleting app:", error);
+ * });
+ * ```
+ *
+ * @public
+ */
+async function deleteApp(app) {
+ let cleanupProviders = false;
+ const name = app.name;
+ if (_apps.has(name)) {
+ cleanupProviders = true;
+ _apps.delete(name);
+ }
+ else if (_serverApps.has(name)) {
+ const firebaseServerApp = app;
+ if (firebaseServerApp.decRefCount() <= 0) {
+ _serverApps.delete(name);
+ cleanupProviders = true;
+ }
+ }
+ if (cleanupProviders) {
+ await Promise.all(app.container
+ .getProviders()
+ .map(provider => provider.delete()));
+ app.isDeleted = true;
+ }
+}
+/**
+ * Registers a library's name and version for platform logging purposes.
+ * @param library - Name of 1p or 3p library (e.g. firestore, angularfire)
+ * @param version - Current version of that library.
+ * @param variant - Bundle variant, e.g., node, rn, etc.
+ *
+ * @public
+ */
+function registerVersion(libraryKeyOrName, version, variant) {
+ // TODO: We can use this check to whitelist strings when/if we set up
+ // a good whitelist system.
+ let library = PLATFORM_LOG_STRING[libraryKeyOrName] ?? libraryKeyOrName;
+ if (variant) {
+ library += `-${variant}`;
+ }
+ const libraryMismatch = library.match(/\s|\//);
+ const versionMismatch = version.match(/\s|\//);
+ if (libraryMismatch || versionMismatch) {
+ const warning = [
+ `Unable to register library "${library}" with version "${version}":`
+ ];
+ if (libraryMismatch) {
+ warning.push(`library name "${library}" contains illegal characters (whitespace or "/")`);
+ }
+ if (libraryMismatch && versionMismatch) {
+ warning.push('and');
+ }
+ if (versionMismatch) {
+ warning.push(`version name "${version}" contains illegal characters (whitespace or "/")`);
+ }
+ logger.warn(warning.join(' '));
+ return;
+ }
+ _registerComponent(new Component(`${library}-version`, () => ({ library, version }), "VERSION" /* ComponentType.VERSION */));
+}
+/**
+ * Sets log handler for all Firebase SDKs.
+ * @param logCallback - An optional custom log handler that executes user code whenever
+ * the Firebase SDK makes a logging call.
+ *
+ * @public
+ */
+function onLog(logCallback, options) {
+ if (logCallback !== null && typeof logCallback !== 'function') {
+ throw ERROR_FACTORY.create("invalid-log-argument" /* AppError.INVALID_LOG_ARGUMENT */);
+ }
+ setUserLogHandler(logCallback, options);
+}
+/**
+ * Sets log level for all Firebase SDKs.
+ *
+ * All of the log types above the current log level are captured (i.e. if
+ * you set the log level to `info`, errors are logged, but `debug` and
+ * `verbose` logs are not).
+ *
+ * @public
+ */
+function setLogLevel(logLevel) {
+ setLogLevel$1(logLevel);
+}
+/**
+ * @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.
+ */
+const DB_NAME = 'firebase-heartbeat-database';
+const DB_VERSION = 1;
+const STORE_NAME = 'firebase-heartbeat-store';
+let dbPromise = null;
+function getDbPromise() {
+ if (!dbPromise) {
+ dbPromise = openDB(DB_NAME, DB_VERSION, {
+ upgrade: (db, oldVersion) => {
+ // We don't use 'break' in this switch statement, the fall-through
+ // behavior is what we want, because if there are multiple versions between
+ // the old version and the current version, we want ALL the migrations
+ // that correspond to those versions to run, not only the last one.
+ // eslint-disable-next-line default-case
+ switch (oldVersion) {
+ case 0:
+ try {
+ db.createObjectStore(STORE_NAME);
+ }
+ catch (e) {
+ // Safari/iOS browsers throw occasional exceptions on
+ // db.createObjectStore() that may be a bug. Avoid blocking
+ // the rest of the app functionality.
+ console.warn(e);
+ }
+ }
+ }
+ }).catch(e => {
+ throw ERROR_FACTORY.create("idb-open" /* AppError.IDB_OPEN */, {
+ originalErrorMessage: e.message
+ });
+ });
+ }
+ return dbPromise;
+}
+async function readHeartbeatsFromIndexedDB(app) {
+ try {
+ const db = await getDbPromise();
+ const tx = db.transaction(STORE_NAME);
+ const result = await tx.objectStore(STORE_NAME).get(computeKey(app));
+ // We already have the value but tx.done can throw,
+ // so we need to await it here to catch errors
+ await tx.done;
+ return result;
+ }
+ catch (e) {
+ if (e instanceof FirebaseError) {
+ logger.warn(e.message);
+ }
+ else {
+ const idbGetError = ERROR_FACTORY.create("idb-get" /* AppError.IDB_GET */, {
+ originalErrorMessage: e?.message
+ });
+ logger.warn(idbGetError.message);
+ }
+ }
+}
+async function writeHeartbeatsToIndexedDB(app, heartbeatObject) {
+ try {
+ const db = await getDbPromise();
+ const tx = db.transaction(STORE_NAME, 'readwrite');
+ const objectStore = tx.objectStore(STORE_NAME);
+ await objectStore.put(heartbeatObject, computeKey(app));
+ await tx.done;
+ }
+ catch (e) {
+ if (e instanceof FirebaseError) {
+ logger.warn(e.message);
+ }
+ else {
+ const idbGetError = ERROR_FACTORY.create("idb-set" /* AppError.IDB_WRITE */, {
+ originalErrorMessage: e?.message
+ });
+ logger.warn(idbGetError.message);
+ }
+ }
+}
+function computeKey(app) {
+ return `${app.name}!${app.options.appId}`;
+}
+/**
+ * @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.
+ */
+const MAX_HEADER_BYTES = 1024;
+const MAX_NUM_STORED_HEARTBEATS = 30;
+class HeartbeatServiceImpl {
+ constructor(container) {
+ this.container = container;
+ /**
+ * In-memory cache for heartbeats, used by getHeartbeatsHeader() to generate
+ * the header string.
+ * Stores one record per date. This will be consolidated into the standard
+ * format of one record per user agent string before being sent as a header.
+ * Populated from indexedDB when the controller is instantiated and should
+ * be kept in sync with indexedDB.
+ * Leave public for easier testing.
+ */
+ this._heartbeatsCache = null;
+ const app = this.container.getProvider('app').getImmediate();
+ this._storage = new HeartbeatStorageImpl(app);
+ this._heartbeatsCachePromise = this._storage.read().then(result => {
+ this._heartbeatsCache = result;
+ return result;
+ });
+ }
+ /**
+ * Called to report a heartbeat. The function will generate
+ * a HeartbeatsByUserAgent object, update heartbeatsCache, and persist it
+ * to IndexedDB.
+ * Note that we only store one heartbeat per day. So if a heartbeat for today is
+ * already logged, subsequent calls to this function in the same day will be ignored.
+ */
+ async triggerHeartbeat() {
+ try {
+ const platformLogger = this.container
+ .getProvider('platform-logger')
+ .getImmediate();
+ // This is the "Firebase user agent" string from the platform logger
+ // service, not the browser user agent.
+ const agent = platformLogger.getPlatformInfoString();
+ const date = getUTCDateString();
+ if (this._heartbeatsCache?.heartbeats == null) {
+ this._heartbeatsCache = await this._heartbeatsCachePromise;
+ // If we failed to construct a heartbeats cache, then return immediately.
+ if (this._heartbeatsCache?.heartbeats == null) {
+ return;
+ }
+ }
+ // Do not store a heartbeat if one is already stored for this day
+ // or if a header has already been sent today.
+ if (this._heartbeatsCache.lastSentHeartbeatDate === date ||
+ this._heartbeatsCache.heartbeats.some(singleDateHeartbeat => singleDateHeartbeat.date === date)) {
+ return;
+ }
+ else {
+ // There is no entry for this date. Create one.
+ this._heartbeatsCache.heartbeats.push({ date, agent });
+ // If the number of stored heartbeats exceeds the maximum number of stored heartbeats, remove the heartbeat with the earliest date.
+ // Since this is executed each time a heartbeat is pushed, the limit can only be exceeded by one, so only one needs to be removed.
+ if (this._heartbeatsCache.heartbeats.length > MAX_NUM_STORED_HEARTBEATS) {
+ const earliestHeartbeatIdx = getEarliestHeartbeatIdx(this._heartbeatsCache.heartbeats);
+ this._heartbeatsCache.heartbeats.splice(earliestHeartbeatIdx, 1);
+ }
+ }
+ return this._storage.overwrite(this._heartbeatsCache);
+ }
+ catch (e) {
+ logger.warn(e);
+ }
+ }
+ /**
+ * Returns a base64 encoded string which can be attached to the heartbeat-specific header directly.
+ * It also clears all heartbeats from memory as well as in IndexedDB.
+ *
+ * NOTE: Consuming product SDKs should not send the header if this method
+ * returns an empty string.
+ */
+ async getHeartbeatsHeader() {
+ try {
+ if (this._heartbeatsCache === null) {
+ await this._heartbeatsCachePromise;
+ }
+ // If it's still null or the array is empty, there is no data to send.
+ if (this._heartbeatsCache?.heartbeats == null ||
+ this._heartbeatsCache.heartbeats.length === 0) {
+ return '';
+ }
+ const date = getUTCDateString();
+ // Extract as many heartbeats from the cache as will fit under the size limit.
+ const { heartbeatsToSend, unsentEntries } = extractHeartbeatsForHeader(this._heartbeatsCache.heartbeats);
+ const headerString = base64urlEncodeWithoutPadding(JSON.stringify({ version: 2, heartbeats: heartbeatsToSend }));
+ // Store last sent date to prevent another being logged/sent for the same day.
+ this._heartbeatsCache.lastSentHeartbeatDate = date;
+ if (unsentEntries.length > 0) {
+ // Store any unsent entries if they exist.
+ this._heartbeatsCache.heartbeats = unsentEntries;
+ // This seems more likely than emptying the array (below) to lead to some odd state
+ // since the cache isn't empty and this will be called again on the next request,
+ // and is probably safest if we await it.
+ await this._storage.overwrite(this._heartbeatsCache);
+ }
+ else {
+ this._heartbeatsCache.heartbeats = [];
+ // Do not wait for this, to reduce latency.
+ void this._storage.overwrite(this._heartbeatsCache);
+ }
+ return headerString;
+ }
+ catch (e) {
+ logger.warn(e);
+ return '';
+ }
+ }
+}
+function getUTCDateString() {
+ const today = new Date();
+ // Returns date format 'YYYY-MM-DD'
+ return today.toISOString().substring(0, 10);
+}
+function extractHeartbeatsForHeader(heartbeatsCache, maxSize = MAX_HEADER_BYTES) {
+ // Heartbeats grouped by user agent in the standard format to be sent in
+ // the header.
+ const heartbeatsToSend = [];
+ // Single date format heartbeats that are not sent.
+ let unsentEntries = heartbeatsCache.slice();
+ for (const singleDateHeartbeat of heartbeatsCache) {
+ // Look for an existing entry with the same user agent.
+ const heartbeatEntry = heartbeatsToSend.find(hb => hb.agent === singleDateHeartbeat.agent);
+ if (!heartbeatEntry) {
+ // If no entry for this user agent exists, create one.
+ heartbeatsToSend.push({
+ agent: singleDateHeartbeat.agent,
+ dates: [singleDateHeartbeat.date]
+ });
+ if (countBytes(heartbeatsToSend) > maxSize) {
+ // If the header would exceed max size, remove the added heartbeat
+ // entry and stop adding to the header.
+ heartbeatsToSend.pop();
+ break;
+ }
+ }
+ else {
+ heartbeatEntry.dates.push(singleDateHeartbeat.date);
+ // If the header would exceed max size, remove the added date
+ // and stop adding to the header.
+ if (countBytes(heartbeatsToSend) > maxSize) {
+ heartbeatEntry.dates.pop();
+ break;
+ }
+ }
+ // Pop unsent entry from queue. (Skipped if adding the entry exceeded
+ // quota and the loop breaks early.)
+ unsentEntries = unsentEntries.slice(1);
+ }
+ return {
+ heartbeatsToSend,
+ unsentEntries
+ };
+}
+class HeartbeatStorageImpl {
+ constructor(app) {
+ this.app = app;
+ this._canUseIndexedDBPromise = this.runIndexedDBEnvironmentCheck();
+ }
+ async runIndexedDBEnvironmentCheck() {
+ if (!isIndexedDBAvailable()) {
+ return false;
+ }
+ else {
+ return validateIndexedDBOpenable()
+ .then(() => true)
+ .catch(() => false);
+ }
+ }
+ /**
+ * Read all heartbeats.
+ */
+ async read() {
+ const canUseIndexedDB = await this._canUseIndexedDBPromise;
+ if (!canUseIndexedDB) {
+ return { heartbeats: [] };
+ }
+ else {
+ const idbHeartbeatObject = await readHeartbeatsFromIndexedDB(this.app);
+ if (idbHeartbeatObject?.heartbeats) {
+ return idbHeartbeatObject;
+ }
+ else {
+ return { heartbeats: [] };
+ }
+ }
+ }
+ // overwrite the storage with the provided heartbeats
+ async overwrite(heartbeatsObject) {
+ const canUseIndexedDB = await this._canUseIndexedDBPromise;
+ if (!canUseIndexedDB) {
+ return;
+ }
+ else {
+ const existingHeartbeatsObject = await this.read();
+ return writeHeartbeatsToIndexedDB(this.app, {
+ lastSentHeartbeatDate: heartbeatsObject.lastSentHeartbeatDate ??
+ existingHeartbeatsObject.lastSentHeartbeatDate,
+ heartbeats: heartbeatsObject.heartbeats
+ });
+ }
+ }
+ // add heartbeats
+ async add(heartbeatsObject) {
+ const canUseIndexedDB = await this._canUseIndexedDBPromise;
+ if (!canUseIndexedDB) {
+ return;
+ }
+ else {
+ const existingHeartbeatsObject = await this.read();
+ return writeHeartbeatsToIndexedDB(this.app, {
+ lastSentHeartbeatDate: heartbeatsObject.lastSentHeartbeatDate ??
+ existingHeartbeatsObject.lastSentHeartbeatDate,
+ heartbeats: [
+ ...existingHeartbeatsObject.heartbeats,
+ ...heartbeatsObject.heartbeats
+ ]
+ });
+ }
+ }
+}
+/**
+ * Calculate bytes of a HeartbeatsByUserAgent array after being wrapped
+ * in a platform logging header JSON object, stringified, and converted
+ * to base 64.
+ */
+function countBytes(heartbeatsCache) {
+ // base64 has a restricted set of characters, all of which should be 1 byte.
+ return base64urlEncodeWithoutPadding(
+ // heartbeatsCache wrapper properties
+ JSON.stringify({ version: 2, heartbeats: heartbeatsCache })).length;
+}
+/**
+ * Returns the index of the heartbeat with the earliest date.
+ * If the heartbeats array is empty, -1 is returned.
+ */
+function getEarliestHeartbeatIdx(heartbeats) {
+ if (heartbeats.length === 0) {
+ return -1;
+ }
+ let earliestHeartbeatIdx = 0;
+ let earliestHeartbeatDate = heartbeats[0].date;
+ for (let i = 1; i < heartbeats.length; i++) {
+ if (heartbeats[i].date < earliestHeartbeatDate) {
+ earliestHeartbeatDate = heartbeats[i].date;
+ earliestHeartbeatIdx = i;
+ }
+ }
+ return earliestHeartbeatIdx;
+}
+/**
+ * @license
+ * Copyright 2019 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 registerCoreComponents(variant) {
+ _registerComponent(new Component('platform-logger', container => new PlatformLoggerServiceImpl(container), "PRIVATE" /* ComponentType.PRIVATE */));
+ _registerComponent(new Component('heartbeat', container => new HeartbeatServiceImpl(container), "PRIVATE" /* ComponentType.PRIVATE */));
+ // Register `app` package.
+ registerVersion(name$q, version$1, variant);
+ // BUILD_TARGET will be replaced by values like esm, cjs, etc during the compilation
+ registerVersion(name$q, version$1, 'esm2020');
+ // Register platform SDK identifier (no version).
+ registerVersion('fire-js', '');
+}
+/**
+ * Firebase App
+ *
+ * @remarks This package coordinates the communication between the different Firebase components
+ * @packageDocumentation
+ */
+registerCoreComponents('');
+
+var name = "firebase";
+var version = "12.5.0";
+
+/**
+ * @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.
+ */
+registerVersion(name, version, 'cdn');
+
+export { FirebaseError, SDK_VERSION, DEFAULT_ENTRY_NAME as _DEFAULT_ENTRY_NAME, _addComponent, _addOrOverwriteComponent, _apps, _clearComponents, _components, _getProvider, _isFirebaseApp, _isFirebaseServerApp, _isFirebaseServerAppSettings, _registerComponent, _removeServiceInstance, _serverApps, deleteApp, getApp, getApps, initializeApp, initializeServerApp, onLog, registerVersion, setLogLevel };
+
+//# sourceMappingURL=firebase-app.js.map