text: import { registerVersion, _registerComponent, _getProvider, getApp } from 'https://www.gstatic.com/firebasejs/9.6.6/firebase-app.js';
  
  /**
   * @license
   * Copyright 2017 Google LLC
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *   http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  /**
   * 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() {
      return typeof indexedDB === 'object';
  }
  /**
   * 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 = () => {
                  var _a;
                  reject(((_a = request.error) === null || _a === void 0 ? void 0 : _a.message) || '');
              };
          }
          catch (error) {
              reject(error);
          }
      });
  }
  /**
   *
   * This method checks whether cookie is enabled within current browser
   * @return true if cookie is enabled within current browser
   */
  function areCookiesEnabled() {
      if (typeof navigator === 'undefined' || !navigator.cookieEnabled) {
          return false;
      }
      return true;
  }
  
  /**
   * @license
   * Copyright 2017 Google LLC
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *   http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  /**
   * @fileoverview Standardized Firebase Error.
   *
   * Usage:
   *
   *   // Typescript string literals for type-safe codes
   *   type Err =
   *     'unknown' |
   *     'object-not-found'
   *     ;
   *
   *   // Closure enum for type-safe error codes
   *   // at-enum {string}
   *   var Err = {
   *     UNKNOWN: 'unknown',
   *     OBJECT_NOT_FOUND: 'object-not-found',
   *   }
   *
   *   let errors: Map<Err, string> = {
   *     'generic-error': "Unknown error",
   *     'file-not-found': "Could not find file: {$file}",
   *   };
   *
   *   // Type-safe function - must pass a valid error code as param.
   *   let error = new ErrorFactory<Err>('service', 'Service', errors);
   *
   *   ...
   *   throw error.create(Err.GENERIC);
   *   ...
   *   throw error.create(Err.FILE_NOT_FOUND, {'file': fileName});
   *   ...
   *   // Service: Could not file file: foo.txt (service/file-not-found).
   *
   *   catch (e) {
   *     assert(e.message === "Could not find file: foo.txt.");
   *     if (e.code === 'service/file-not-found') {
   *       console.log("Could not read file: " + e['file']);
   *     }
   *   }
   */
  const ERROR_NAME = 'FirebaseError';
  // Based on code from:
  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error#Custom_Error_Types
  class FirebaseError extends Error {
      constructor(
      /** The error code for this error. */
      code, message, 
      /** Custom data for this error. */
      customData) {
          super(message);
          this.code = code;
          this.customData = customData;
          /** The custom name for all FirebaseErrors. */
          this.name = ERROR_NAME;
          // Fix For ES5
          // https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work
          Object.setPrototypeOf(this, FirebaseError.prototype);
          // Maintains proper stack trace for where our error was thrown.
          // Only available on V8.
          if (Error.captureStackTrace) {
              Error.captureStackTrace(this, ErrorFactory.prototype.create);
          }
      }
  }
  class ErrorFactory {
      constructor(service, serviceName, errors) {
          this.service = service;
          this.serviceName = serviceName;
          this.errors = errors;
      }
      create(code, ...data) {
          const customData = data[0] || {};
          const fullCode = `${this.service}/${code}`;
          const template = this.errors[code];
          const message = template ? replaceTemplate(template, customData) : 'Error';
          // Service Name: Error message (service/code).
          const fullMessage = `${this.serviceName}: ${message} (${fullCode}).`;
          const error = new FirebaseError(fullCode, fullMessage, customData);
          return error;
      }
  }
  function replaceTemplate(template, data) {
      return template.replace(PATTERN, (_, key) => {
          const value = data[key];
          return value != null ? String(value) : `<${key}?>`;
      });
  }
  const PATTERN = /\{\$([^}]+)}/g;
  
  /**
   * @license
   * Copyright 2021 Google LLC
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *   http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  function getModularInstance(service) {
      if (service && service._delegate) {
          return service._delegate;
      }
      else {
          return service;
      }
  }
  
  /**
   * Component for service name T, e.g. `auth`, `auth-internal`
   */
  class Component {
      /**
       *
       * @param name The public service name, e.g. app, auth, firestore, database
       * @param instanceFactory Service factory responsible for creating the public interface
       * @param type whether the service provided by the component is public or private
       */
      constructor(name, instanceFactory, type) {
          this.name = name;
          this.instanceFactory = instanceFactory;
          this.type = type;
          this.multipleInstances = false;
          /**
           * Properties to be added to the service namespace
           */
          this.serviceProps = {};
          this.instantiationMode = "LAZY" /* LAZY */;
          this.onInstanceCreated = null;
      }
      setInstantiationMode(mode) {
          this.instantiationMode = mode;
          return this;
      }
      setMultipleInstances(multipleInstances) {
          this.multipleInstances = multipleInstances;
          return this;
      }
      setServiceProps(props) {
          this.serviceProps = props;
          return this;
      }
      setInstanceCreatedCallback(callback) {
          this.onInstanceCreated = callback;
          return this;
      }
  }
  
  function toArray(arr) {
    return Array.prototype.slice.call(arr);
  }
  
  function promisifyRequest(request) {
    return new Promise(function(resolve, reject) {
      request.onsuccess = function() {
        resolve(request.result);
      };
  
      request.onerror = function() {
        reject(request.error);
      };
    });
  }
  
  function promisifyRequestCall(obj, method, args) {
    var request;
    var p = new Promise(function(resolve, reject) {
      request = obj[method].apply(obj, args);
      promisifyRequest(request).then(resolve, reject);
    });
  
    p.request = request;
    return p;
  }
  
  function promisifyCursorRequestCall(obj, method, args) {
    var p = promisifyRequestCall(obj, method, args);
    return p.then(function(value) {
      if (!value) return;
      return new Cursor(value, p.request);
    });
  }
  
  function proxyProperties(ProxyClass, targetProp, properties) {
    properties.forEach(function(prop) {
      Object.defineProperty(ProxyClass.prototype, prop, {
        get: function() {
          return this[targetProp][prop];
        },
        set: function(val) {
          this[targetProp][prop] = val;
        }
      });
    });
  }
  
  function proxyRequestMethods(ProxyClass, targetProp, Constructor, properties) {
    properties.forEach(function(prop) {
      if (!(prop in Constructor.prototype)) return;
      ProxyClass.prototype[prop] = function() {
        return promisifyRequestCall(this[targetProp], prop, arguments);
      };
    });
  }
  
  function proxyMethods(ProxyClass, targetProp, Constructor, properties) {
    properties.forEach(function(prop) {
      if (!(prop in Constructor.prototype)) return;
      ProxyClass.prototype[prop] = function() {
        return this[targetProp][prop].apply(this[targetProp], arguments);
      };
    });
  }
  
  function proxyCursorRequestMethods(ProxyClass, targetProp, Constructor, properties) {
    properties.forEach(function(prop) {
      if (!(prop in Constructor.prototype)) return;
      ProxyClass.prototype[prop] = function() {
        return promisifyCursorRequestCall(this[targetProp], prop, arguments);
      };
    });
  }
  
  function Index(index) {
    this._index = index;
  }
  
  proxyProperties(Index, '_index', [
    'name',
    'keyPath',
    'multiEntry',
    'unique'
  ]);
  
  proxyRequestMethods(Index, '_index', IDBIndex, [
    'get',
    'getKey',
    'getAll',
    'getAllKeys',
    'count'
  ]);
  
  proxyCursorRequestMethods(Index, '_index', IDBIndex, [
    'openCursor',
    'openKeyCursor'
  ]);
  
  function Cursor(cursor, request) {
    this._cursor = cursor;
    this._request = request;
  }
  
  proxyProperties(Cursor, '_cursor', [
    'direction',
    'key',
    'primaryKey',
    'value'
  ]);
  
  proxyRequestMethods(Cursor, '_cursor', IDBCursor, [
    'update',
    'delete'
  ]);
  
  // proxy 'next' methods
  ['advance', 'continue', 'continuePrimaryKey'].forEach(function(methodName) {
    if (!(methodName in IDBCursor.prototype)) return;
    Cursor.prototype[methodName] = function() {
      var cursor = this;
      var args = arguments;
      return Promise.resolve().then(function() {
        cursor._cursor[methodName].apply(cursor._cursor, args);
        return promisifyRequest(cursor._request).then(function(value) {
          if (!value) return;
          return new Cursor(value, cursor._request);
        });
      });
    };
  });
  
  function ObjectStore(store) {
    this._store = store;
  }
  
  ObjectStore.prototype.createIndex = function() {
    return new Index(this._store.createIndex.apply(this._store, arguments));
  };
  
  ObjectStore.prototype.index = function() {
    return new Index(this._store.index.apply(this._store, arguments));
  };
  
  proxyProperties(ObjectStore, '_store', [
    'name',
    'keyPath',
    'indexNames',
    'autoIncrement'
  ]);
  
  proxyRequestMethods(ObjectStore, '_store', IDBObjectStore, [
    'put',
    'add',
    'delete',
    'clear',
    'get',
    'getAll',
    'getKey',
    'getAllKeys',
    'count'
  ]);
  
  proxyCursorRequestMethods(ObjectStore, '_store', IDBObjectStore, [
    'openCursor',
    'openKeyCursor'
  ]);
  
  proxyMethods(ObjectStore, '_store', IDBObjectStore, [
    'deleteIndex'
  ]);
  
  function Transaction(idbTransaction) {
    this._tx = idbTransaction;
    this.complete = new Promise(function(resolve, reject) {
      idbTransaction.oncomplete = function() {
        resolve();
      };
      idbTransaction.onerror = function() {
        reject(idbTransaction.error);
      };
      idbTransaction.onabort = function() {
        reject(idbTransaction.error);
      };
    });
  }
  
  Transaction.prototype.objectStore = function() {
    return new ObjectStore(this._tx.objectStore.apply(this._tx, arguments));
  };
  
  proxyProperties(Transaction, '_tx', [
    'objectStoreNames',
    'mode'
  ]);
  
  proxyMethods(Transaction, '_tx', IDBTransaction, [
    'abort'
  ]);
  
  function UpgradeDB(db, oldVersion, transaction) {
    this._db = db;
    this.oldVersion = oldVersion;
    this.transaction = new Transaction(transaction);
  }
  
  UpgradeDB.prototype.createObjectStore = function() {
    return new ObjectStore(this._db.createObjectStore.apply(this._db, arguments));
  };
  
  proxyProperties(UpgradeDB, '_db', [
    'name',
    'version',
    'objectStoreNames'
  ]);
  
  proxyMethods(UpgradeDB, '_db', IDBDatabase, [
    'deleteObjectStore',
    'close'
  ]);
  
  function DB(db) {
    this._db = db;
  }
  
  DB.prototype.transaction = function() {
    return new Transaction(this._db.transaction.apply(this._db, arguments));
  };
  
  proxyProperties(DB, '_db', [
    'name',
    'version',
    'objectStoreNames'
  ]);
  
  proxyMethods(DB, '_db', IDBDatabase, [
    'close'
  ]);
  
  // Add cursor iterators
  // TODO: remove this once browsers do the right thing with promises
  ['openCursor', 'openKeyCursor'].forEach(function(funcName) {
    [ObjectStore, Index].forEach(function(Constructor) {
      // Don't create iterateKeyCursor if openKeyCursor doesn't exist.
      if (!(funcName in Constructor.prototype)) return;
  
      Constructor.prototype[funcName.replace('open', 'iterate')] = function() {
        var args = toArray(arguments);
        var callback = args[args.length - 1];
        var nativeObject = this._store || this._index;
        var request = nativeObject[funcName].apply(nativeObject, args.slice(0, -1));
        request.onsuccess = function() {
          callback(request.result);
        };
      };
    });
  });
  
  // polyfill getAll
  [Index, ObjectStore].forEach(function(Constructor) {
    if (Constructor.prototype.getAll) return;
    Constructor.prototype.getAll = function(query, count) {
      var instance = this;
      var items = [];
  
      return new Promise(function(resolve) {
        instance.iterateCursor(query, function(cursor) {
          if (!cursor) {
            resolve(items);
            return;
          }
          items.push(cursor.value);
  
          if (count !== undefined && items.length == count) {
            resolve(items);
            return;
          }
          cursor.continue();
        });
      });
    };
  });
  
  function openDb(name, version, upgradeCallback) {
    var p = promisifyRequestCall(indexedDB, 'open', [name, version]);
    var request = p.request;
  
    if (request) {
      request.onupgradeneeded = function(event) {
        if (upgradeCallback) {
          upgradeCallback(new UpgradeDB(request.result, event.oldVersion, request.transaction));
        }
      };
    }
  
    return p.then(function(db) {
      return new DB(db);
    });
  }
  
  function deleteDb(name) {
    return promisifyRequestCall(indexedDB, 'deleteDatabase', [name]);
  }
  
  const name$1 = "@firebase/installations";
  const version$1 = "0.5.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 PENDING_TIMEOUT_MS = 10000;
  const PACKAGE_VERSION = `w:${version$1}`;
  const INTERNAL_AUTH_VERSION = 'FIS_v2';
  const INSTALLATIONS_API_URL = 'https://firebaseinstallations.googleapis.com/v1';
  const TOKEN_EXPIRATION_BUFFER = 60 * 60 * 1000; // One hour
  const SERVICE = 'installations';
  const SERVICE_NAME = 'Installations';
  
  /**
   * @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 ERROR_DESCRIPTION_MAP = {
      ["missing-app-config-values" /* MISSING_APP_CONFIG_VALUES */]: 'Missing App configuration value: "{$valueName}"',
      ["not-registered" /* NOT_REGISTERED */]: 'Firebase Installation is not registered.',
      ["installation-not-found" /* INSTALLATION_NOT_FOUND */]: 'Firebase Installation not found.',
      ["request-failed" /* REQUEST_FAILED */]: '{$requestName} request failed with error "{$serverCode} {$serverStatus}: {$serverMessage}"',
      ["app-offline" /* APP_OFFLINE */]: 'Could not process request. Application offline.',
      ["delete-pending-registration" /* DELETE_PENDING_REGISTRATION */]: "Can't delete installation while there is a pending registration request."
  };
  const ERROR_FACTORY$1 = new ErrorFactory(SERVICE, SERVICE_NAME, ERROR_DESCRIPTION_MAP);
  /** Returns true if error is a FirebaseError that is based on an error from the server. */
  function isServerError(error) {
      return (error instanceof FirebaseError &&
          error.code.includes("request-failed" /* REQUEST_FAILED */));
  }
  
  /**
   * @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 getInstallationsEndpoint({ projectId }) {
      return `${INSTALLATIONS_API_URL}/projects/${projectId}/installations`;
  }
  function extractAuthTokenInfoFromResponse(response) {
      return {
          token: response.token,
          requestStatus: 2 /* COMPLETED */,
          expiresIn: getExpiresInFromResponseExpiresIn(response.expiresIn),
          creationTime: Date.now()
      };
  }
  async function getErrorFromResponse(requestName, response) {
      const responseJson = await response.json();
      const errorData = responseJson.error;
      return ERROR_FACTORY$1.create("request-failed" /* REQUEST_FAILED */, {
          requestName,
          serverCode: errorData.code,
          serverMessage: errorData.message,
          serverStatus: errorData.status
      });
  }
  function getHeaders$1({ apiKey }) {
      return new Headers({
          'Content-Type': 'application/json',
          Accept: 'application/json',
          'x-goog-api-key': apiKey
      });
  }
  function getHeadersWithAuth(appConfig, { refreshToken }) {
      const headers = getHeaders$1(appConfig);
      headers.append('Authorization', getAuthorizationHeader(refreshToken));
      return headers;
  }
  /**
   * Calls the passed in fetch wrapper and returns the response.
   * If the returned response has a status of 5xx, re-runs the function once and
   * returns the response.
   */
  async function retryIfServerError(fn) {
      const result = await fn();
      if (result.status >= 500 && result.status < 600) {
          // Internal Server Error. Retry request.
          return fn();
      }
      return result;
  }
  function getExpiresInFromResponseExpiresIn(responseExpiresIn) {
      // This works because the server will never respond with fractions of a second.
      return Number(responseExpiresIn.replace('s', '000'));
  }
  function getAuthorizationHeader(refreshToken) {
      return `${INTERNAL_AUTH_VERSION} ${refreshToken}`;
  }
  
  /**
   * @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.
   */
  async function createInstallationRequest(appConfig, { fid }) {
      const endpoint = getInstallationsEndpoint(appConfig);
      const headers = getHeaders$1(appConfig);
      const body = {
          fid,
          authVersion: INTERNAL_AUTH_VERSION,
          appId: appConfig.appId,
          sdkVersion: PACKAGE_VERSION
      };
      const request = {
          method: 'POST',
          headers,
          body: JSON.stringify(body)
      };
      const response = await retryIfServerError(() => fetch(endpoint, request));
      if (response.ok) {
          const responseValue = await response.json();
          const registeredInstallationEntry = {
              fid: responseValue.fid || fid,
              registrationStatus: 2 /* COMPLETED */,
              refreshToken: responseValue.refreshToken,
              authToken: extractAuthTokenInfoFromResponse(responseValue.authToken)
          };
          return registeredInstallationEntry;
      }
      else {
          throw await getErrorFromResponse('Create Installation', response);
      }
  }
  
  /**
   * @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.
   */
  /** Returns a promise that resolves after given time passes. */
  function sleep(ms) {
      return new Promise(resolve => {
          setTimeout(resolve, ms);
      });
  }
  
  /**
   * @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 bufferToBase64UrlSafe(array) {
      const b64 = btoa(String.fromCharCode(...array));
      return b64.replace(/\+/g, '-').replace(/\//g, '_');
  }
  
  /**
   * @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 VALID_FID_PATTERN = /^[cdef][\w-]{21}$/;
  const INVALID_FID = '';
  /**
   * Generates a new FID using random values from Web Crypto API.
   * Returns an empty string if FID generation fails for any reason.
   */
  function generateFid() {
      try {
          // A valid FID has exactly 22 base64 characters, which is 132 bits, or 16.5
          // bytes. our implementation generates a 17 byte array instead.
          const fidByteArray = new Uint8Array(17);
          const crypto = self.crypto || self.msCrypto;
          crypto.getRandomValues(fidByteArray);
          // Replace the first 4 random bits with the constant FID header of 0b0111.
          fidByteArray[0] = 0b01110000 + (fidByteArray[0] % 0b00010000);
          const fid = encode(fidByteArray);
          return VALID_FID_PATTERN.test(fid) ? fid : INVALID_FID;
      }
      catch (_a) {
          // FID generation errored
          return INVALID_FID;
      }
  }
  /** Converts a FID Uint8Array to a base64 string representation. */
  function encode(fidByteArray) {
      const b64String = bufferToBase64UrlSafe(fidByteArray);
      // Remove the 23rd character that was added because of the extra 4 bits at the
      // end of our 17 byte array, and the '=' padding.
      return b64String.substr(0, 22);
  }
  
  /**
   * @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.
   */
  /** Returns a string key that can be used to identify the app. */
  function getKey$1(appConfig) {
      return `${appConfig.appName}!${appConfig.appId}`;
  }
  
  /**
   * @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 fidChangeCallbacks = new Map();
  /**
   * Calls the onIdChange callbacks with the new FID value, and broadcasts the
   * change to other tabs.
   */
  function fidChanged(appConfig, fid) {
      const key = getKey$1(appConfig);
      callFidChangeCallbacks(key, fid);
      broadcastFidChange(key, fid);
  }
  function callFidChangeCallbacks(key, fid) {
      const callbacks = fidChangeCallbacks.get(key);
      if (!callbacks) {
          return;
      }
      for (const callback of callbacks) {
          callback(fid);
      }
  }
  function broadcastFidChange(key, fid) {
      const channel = getBroadcastChannel();
      if (channel) {
          channel.postMessage({ key, fid });
      }
      closeBroadcastChannel();
  }
  let broadcastChannel = null;
  /** Opens and returns a BroadcastChannel if it is supported by the browser. */
  function getBroadcastChannel() {
      if (!broadcastChannel && 'BroadcastChannel' in self) {
          broadcastChannel = new BroadcastChannel('[Firebase] FID Change');
          broadcastChannel.onmessage = e => {
              callFidChangeCallbacks(e.data.key, e.data.fid);
          };
      }
      return broadcastChannel;
  }
  function closeBroadcastChannel() {
      if (fidChangeCallbacks.size === 0 && broadcastChannel) {
          broadcastChannel.close();
          broadcastChannel = null;
      }
  }
  
  /**
   * @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 DATABASE_NAME$1 = 'firebase-installations-database';
  const DATABASE_VERSION$1 = 1;
  const OBJECT_STORE_NAME$1 = 'firebase-installations-store';
  let dbPromise$1 = null;
  function getDbPromise$1() {
      if (!dbPromise$1) {
          dbPromise$1 = openDb(DATABASE_NAME$1, DATABASE_VERSION$1, upgradeDB => {
              // 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 (upgradeDB.oldVersion) {
                  case 0:
                      upgradeDB.createObjectStore(OBJECT_STORE_NAME$1);
              }
          });
      }
      return dbPromise$1;
  }
  /** Assigns or overwrites the record for the given key with the given value. */
  async function set(appConfig, value) {
      const key = getKey$1(appConfig);
      const db = await getDbPromise$1();
      const tx = db.transaction(OBJECT_STORE_NAME$1, 'readwrite');
      const objectStore = tx.objectStore(OBJECT_STORE_NAME$1);
      const oldValue = await objectStore.get(key);
      await objectStore.put(value, key);
      await tx.complete;
      if (!oldValue || oldValue.fid !== value.fid) {
          fidChanged(appConfig, value.fid);
      }
      return value;
  }
  /** Removes record(s) from the objectStore that match the given key. */
  async function remove(appConfig) {
      const key = getKey$1(appConfig);
      const db = await getDbPromise$1();
      const tx = db.transaction(OBJECT_STORE_NAME$1, 'readwrite');
      await tx.objectStore(OBJECT_STORE_NAME$1).delete(key);
      await tx.complete;
  }
  /**
   * Atomically updates a record with the result of updateFn, which gets
   * called with the current value. If newValue is undefined, the record is
   * deleted instead.
   * @return Updated value
   */
  async function update(appConfig, updateFn) {
      const key = getKey$1(appConfig);
      const db = await getDbPromise$1();
      const tx = db.transaction(OBJECT_STORE_NAME$1, 'readwrite');
      const store = tx.objectStore(OBJECT_STORE_NAME$1);
      const oldValue = await store.get(key);
      const newValue = updateFn(oldValue);
      if (newValue === undefined) {
          await store.delete(key);
      }
      else {
          await store.put(newValue, key);
      }
      await tx.complete;
      if (newValue && (!oldValue || oldValue.fid !== newValue.fid)) {
          fidChanged(appConfig, newValue.fid);
      }
      return newValue;
  }
  
  /**
   * @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.
   */
  /**
   * Updates and returns the InstallationEntry from the database.
   * Also triggers a registration request if it is necessary and possible.
   */
  async function getInstallationEntry(appConfig) {
      let registrationPromise;
      const installationEntry = await update(appConfig, oldEntry => {
          const installationEntry = updateOrCreateInstallationEntry(oldEntry);
          const entryWithPromise = triggerRegistrationIfNecessary(appConfig, installationEntry);
          registrationPromise = entryWithPromise.registrationPromise;
          return entryWithPromise.installationEntry;
      });
      if (installationEntry.fid === INVALID_FID) {
          // FID generation failed. Waiting for the FID from the server.
          return { installationEntry: await registrationPromise };
      }
      return {
          installationEntry,
          registrationPromise
      };
  }
  /**
   * Creates a new Installation Entry if one does not exist.
   * Also clears timed out pending requests.
   */
  function updateOrCreateInstallationEntry(oldEntry) {
      const entry = oldEntry || {
          fid: generateFid(),
          registrationStatus: 0 /* NOT_STARTED */
      };
      return clearTimedOutRequest(entry);
  }
  /**
   * If the Firebase Installation is not registered yet, this will trigger the
   * registration and return an InProgressInstallationEntry.
   *
   * If registrationPromise does not exist, the installationEntry is guaranteed
   * to be registered.
   */
  function triggerRegistrationIfNecessary(appConfig, installationEntry) {
      if (installationEntry.registrationStatus === 0 /* NOT_STARTED */) {
          if (!navigator.onLine) {
              // Registration required but app is offline.
              const registrationPromiseWithError = Promise.reject(ERROR_FACTORY$1.create("app-offline" /* APP_OFFLINE */));
              return {
                  installationEntry,
                  registrationPromise: registrationPromiseWithError
              };
          }
          // Try registering. Change status to IN_PROGRESS.
          const inProgressEntry = {
              fid: installationEntry.fid,
              registrationStatus: 1 /* IN_PROGRESS */,
              registrationTime: Date.now()
          };
          const registrationPromise = registerInstallation(appConfig, inProgressEntry);
          return { installationEntry: inProgressEntry, registrationPromise };
      }
      else if (installationEntry.registrationStatus === 1 /* IN_PROGRESS */) {
          return {
              installationEntry,
              registrationPromise: waitUntilFidRegistration(appConfig)
          };
      }
      else {
          return { installationEntry };
      }
  }
  /** This will be executed only once for each new Firebase Installation. */
  async function registerInstallation(appConfig, installationEntry) {
      try {
          const registeredInstallationEntry = await createInstallationRequest(appConfig, installationEntry);
          return set(appConfig, registeredInstallationEntry);
      }
      catch (e) {
          if (isServerError(e) && e.customData.serverCode === 409) {
              // Server returned a "FID can not be used" error.
              // Generate a new ID next time.
              await remove(appConfig);
          }
          else {
              // Registration failed. Set FID as not registered.
              await set(appConfig, {
                  fid: installationEntry.fid,
                  registrationStatus: 0 /* NOT_STARTED */
              });
          }
          throw e;
      }
  }
  /** Call if FID registration is pending in another request. */
  async function waitUntilFidRegistration(appConfig) {
      // Unfortunately, there is no way of reliably observing when a value in
      // IndexedDB changes (yet, see https://github.com/WICG/indexed-db-observers),
      // so we need to poll.
      let entry = await updateInstallationRequest(appConfig);
      while (entry.registrationStatus === 1 /* IN_PROGRESS */) {
          // createInstallation request still in progress.
          await sleep(100);
          entry = await updateInstallationRequest(appConfig);
      }
      if (entry.registrationStatus === 0 /* NOT_STARTED */) {
          // The request timed out or failed in a different call. Try again.
          const { installationEntry, registrationPromise } = await getInstallationEntry(appConfig);
          if (registrationPromise) {
              return registrationPromise;
          }
          else {
              // if there is no registrationPromise, entry is registered.
              return installationEntry;
          }
      }
      return entry;
  }
  /**
   * Called only if there is a CreateInstallation request in progress.
   *
   * Updates the InstallationEntry in the DB based on the status of the
   * CreateInstallation request.
   *
   * Returns the updated InstallationEntry.
   */
  function updateInstallationRequest(appConfig) {
      return update(appConfig, oldEntry => {
          if (!oldEntry) {
              throw ERROR_FACTORY$1.create("installation-not-found" /* INSTALLATION_NOT_FOUND */);
          }
          return clearTimedOutRequest(oldEntry);
      });
  }
  function clearTimedOutRequest(entry) {
      if (hasInstallationRequestTimedOut(entry)) {
          return {
              fid: entry.fid,
              registrationStatus: 0 /* NOT_STARTED */
          };
      }
      return entry;
  }
  function hasInstallationRequestTimedOut(installationEntry) {
      return (installationEntry.registrationStatus === 1 /* IN_PROGRESS */ &&
          installationEntry.registrationTime + PENDING_TIMEOUT_MS < Date.now());
  }
  
  /**
   * @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.
   */
  async function generateAuthTokenRequest({ appConfig, platformLoggerProvider }, installationEntry) {
      const endpoint = getGenerateAuthTokenEndpoint(appConfig, installationEntry);
      const headers = getHeadersWithAuth(appConfig, installationEntry);
      // If platform logger exists, add the platform info string to the header.
      const platformLogger = platformLoggerProvider.getImmediate({
          optional: true
      });
      if (platformLogger) {
          headers.append('x-firebase-client', platformLogger.getPlatformInfoString());
      }
      const body = {
          installation: {
              sdkVersion: PACKAGE_VERSION
          }
      };
      const request = {
          method: 'POST',
          headers,
          body: JSON.stringify(body)
      };
      const response = await retryIfServerError(() => fetch(endpoint, request));
      if (response.ok) {
          const responseValue = await response.json();
          const completedAuthToken = extractAuthTokenInfoFromResponse(responseValue);
          return completedAuthToken;
      }
      else {
          throw await getErrorFromResponse('Generate Auth Token', response);
      }
  }
  function getGenerateAuthTokenEndpoint(appConfig, { fid }) {
      return `${getInstallationsEndpoint(appConfig)}/${fid}/authTokens:generate`;
  }
  
  /**
   * @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.
   */
  /**
   * Returns a valid authentication token for the installation. Generates a new
   * token if one doesn't exist, is expired or about to expire.
   *
   * Should only be called if the Firebase Installation is registered.
   */
  async function refreshAuthToken(installations, forceRefresh = false) {
      let tokenPromise;
      const entry = await update(installations.appConfig, oldEntry => {
          if (!isEntryRegistered(oldEntry)) {
              throw ERROR_FACTORY$1.create("not-registered" /* NOT_REGISTERED */);
          }
          const oldAuthToken = oldEntry.authToken;
          if (!forceRefresh && isAuthTokenValid(oldAuthToken)) {
              // There is a valid token in the DB.
              return oldEntry;
          }
          else if (oldAuthToken.requestStatus === 1 /* IN_PROGRESS */) {
              // There already is a token request in progress.
              tokenPromise = waitUntilAuthTokenRequest(installations, forceRefresh);
              return oldEntry;
          }
          else {
              // No token or token expired.
              if (!navigator.onLine) {
                  throw ERROR_FACTORY$1.create("app-offline" /* APP_OFFLINE */);
              }
              const inProgressEntry = makeAuthTokenRequestInProgressEntry(oldEntry);
              tokenPromise = fetchAuthTokenFromServer(installations, inProgressEntry);
              return inProgressEntry;
          }
      });
      const authToken = tokenPromise
          ? await tokenPromise
          : entry.authToken;
      return authToken;
  }
  /**
   * Call only if FID is registered and Auth Token request is in progress.
   *
   * Waits until the current pending request finishes. If the request times out,
   * tries once in this thread as well.
   */
  async function waitUntilAuthTokenRequest(installations, forceRefresh) {
      // Unfortunately, there is no way of reliably observing when a value in
      // IndexedDB changes (yet, see https://github.com/WICG/indexed-db-observers),
      // so we need to poll.
      let entry = await updateAuthTokenRequest(installations.appConfig);
      while (entry.authToken.requestStatus === 1 /* IN_PROGRESS */) {
          // generateAuthToken still in progress.
          await sleep(100);
          entry = await updateAuthTokenRequest(installations.appConfig);
      }
      const authToken = entry.authToken;
      if (authToken.requestStatus === 0 /* NOT_STARTED */) {
          // The request timed out or failed in a different call. Try again.
          return refreshAuthToken(installations, forceRefresh);
      }
      else {
          return authToken;
      }
  }
  /**
   * Called only if there is a GenerateAuthToken request in progress.
   *
   * Updates the InstallationEntry in the DB based on the status of the
   * GenerateAuthToken request.
   *
   * Returns the updated InstallationEntry.
   */
  function updateAuthTokenRequest(appConfig) {
      return update(appConfig, oldEntry => {
          if (!isEntryRegistered(oldEntry)) {
              throw ERROR_FACTORY$1.create("not-registered" /* NOT_REGISTERED */);
          }
          const oldAuthToken = oldEntry.authToken;
          if (hasAuthTokenRequestTimedOut(oldAuthToken)) {
              return Object.assign(Object.assign({}, oldEntry), { authToken: { requestStatus: 0 /* NOT_STARTED */ } });
          }
          return oldEntry;
      });
  }
  async function fetchAuthTokenFromServer(installations, installationEntry) {
      try {
          const authToken = await generateAuthTokenRequest(installations, installationEntry);
          const updatedInstallationEntry = Object.assign(Object.assign({}, installationEntry), { authToken });
          await set(installations.appConfig, updatedInstallationEntry);
          return authToken;
      }
      catch (e) {
          if (isServerError(e) &&
              (e.customData.serverCode === 401 || e.customData.serverCode === 404)) {
              // Server returned a "FID not found" or a "Invalid authentication" error.
              // Generate a new ID next time.
              await remove(installations.appConfig);
          }
          else {
              const updatedInstallationEntry = Object.assign(Object.assign({}, installationEntry), { authToken: { requestStatus: 0 /* NOT_STARTED */ } });
              await set(installations.appConfig, updatedInstallationEntry);
          }
          throw e;
      }
  }
  function isEntryRegistered(installationEntry) {
      return (installationEntry !== undefined &&
          installationEntry.registrationStatus === 2 /* COMPLETED */);
  }
  function isAuthTokenValid(authToken) {
      return (authToken.requestStatus === 2 /* COMPLETED */ &&
          !isAuthTokenExpired(authToken));
  }
  function isAuthTokenExpired(authToken) {
      const now = Date.now();
      return (now < authToken.creationTime ||
          authToken.creationTime + authToken.expiresIn < now + TOKEN_EXPIRATION_BUFFER);
  }
  /** Returns an updated InstallationEntry with an InProgressAuthToken. */
  function makeAuthTokenRequestInProgressEntry(oldEntry) {
      const inProgressAuthToken = {
          requestStatus: 1 /* IN_PROGRESS */,
          requestTime: Date.now()
      };
      return Object.assign(Object.assign({}, oldEntry), { authToken: inProgressAuthToken });
  }
  function hasAuthTokenRequestTimedOut(authToken) {
      return (authToken.requestStatus === 1 /* IN_PROGRESS */ &&
          authToken.requestTime + PENDING_TIMEOUT_MS < Date.now());
  }
  
  /**
   * @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.
   */
  /**
   * Creates a Firebase Installation if there isn't one for the app and
   * returns the Installation ID.
   * @param installations - The `Installations` instance.
   *
   * @public
   */
  async function getId(installations) {
      const installationsImpl = installations;
      const { installationEntry, registrationPromise } = await getInstallationEntry(installationsImpl.appConfig);
      if (registrationPromise) {
          registrationPromise.catch(console.error);
      }
      else {
          // If the installation is already registered, update the authentication
          // token if needed.
          refreshAuthToken(installationsImpl).catch(console.error);
      }
      return installationEntry.fid;
  }
  
  /**
   * @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.
   */
  /**
   * Returns a Firebase Installations auth token, identifying the current
   * Firebase Installation.
   * @param installations - The `Installations` instance.
   * @param forceRefresh - Force refresh regardless of token expiration.
   *
   * @public
   */
  async function getToken$2(installations, forceRefresh = false) {
      const installationsImpl = installations;
      await completeInstallationRegistration(installationsImpl.appConfig);
      // At this point we either have a Registered Installation in the DB, or we've
      // already thrown an error.
      const authToken = await refreshAuthToken(installationsImpl, forceRefresh);
      return authToken.token;
  }
  async function completeInstallationRegistration(appConfig) {
      const { registrationPromise } = await getInstallationEntry(appConfig);
      if (registrationPromise) {
          // A createInstallation request is in progress. Wait until it finishes.
          await registrationPromise;
      }
  }
  
  /**
   * @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 extractAppConfig$1(app) {
      if (!app || !app.options) {
          throw getMissingValueError$1('App Configuration');
      }
      if (!app.name) {
          throw getMissingValueError$1('App Name');
      }
      // Required app config keys
      const configKeys = [
          'projectId',
          'apiKey',
          'appId'
      ];
      for (const keyName of configKeys) {
          if (!app.options[keyName]) {
              throw getMissingValueError$1(keyName);
          }
      }
      return {
          appName: app.name,
          projectId: app.options.projectId,
          apiKey: app.options.apiKey,
          appId: app.options.appId
      };
  }
  function getMissingValueError$1(valueName) {
      return ERROR_FACTORY$1.create("missing-app-config-values" /* MISSING_APP_CONFIG_VALUES */, {
          valueName
      });
  }
  
  /**
   * @license
   * Copyright 2020 Google LLC
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *   http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  const INSTALLATIONS_NAME = 'installations';
  const INSTALLATIONS_NAME_INTERNAL = 'installations-internal';
  const publicFactory = (container) => {
      const app = container.getProvider('app').getImmediate();
      // Throws if app isn't configured properly.
      const appConfig = extractAppConfig$1(app);
      const platformLoggerProvider = _getProvider(app, 'platform-logger');
      const installationsImpl = {
          app,
          appConfig,
          platformLoggerProvider,
          _delete: () => Promise.resolve()
      };
      return installationsImpl;
  };
  const internalFactory = (container) => {
      const app = container.getProvider('app').getImmediate();
      // Internal FIS instance relies on public FIS instance.
      const installations = _getProvider(app, INSTALLATIONS_NAME).getImmediate();
      const installationsInternal = {
          getId: () => getId(installations),
          getToken: (forceRefresh) => getToken$2(installations, forceRefresh)
      };
      return installationsInternal;
  };
  function registerInstallations() {
      _registerComponent(new Component(INSTALLATIONS_NAME, publicFactory, "PUBLIC" /* PUBLIC */));
      _registerComponent(new Component(INSTALLATIONS_NAME_INTERNAL, internalFactory, "PRIVATE" /* PRIVATE */));
  }
  
  /**
   * Firebase Installations
   *
   * @packageDocumentation
   */
  registerInstallations();
  registerVersion(name$1, version$1);
  // BUILD_TARGET will be replaced by values like esm5, esm2017, cjs5, etc during the compilation
  registerVersion(name$1, version$1, 'esm2017');
  
  /**
   * @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_SW_PATH = '/firebase-messaging-sw.js';
  const DEFAULT_SW_SCOPE = '/firebase-cloud-messaging-push-scope';
  const DEFAULT_VAPID_KEY = 'BDOU99-h67HcA6JeFXHbSNMu7e2yNNu3RzoMj8TM4W88jITfq7ZmPvIM1Iv-4_l2LxQcYwhqby2xGpWwzjfAnG4';
  const ENDPOINT = 'https://fcmregistrations.googleapis.com/v1';
  const CONSOLE_CAMPAIGN_ID = 'google.c.a.c_id';
  const CONSOLE_CAMPAIGN_NAME = 'google.c.a.c_l';
  const CONSOLE_CAMPAIGN_TIME = 'google.c.a.ts';
  /** Set to '1' if Analytics is enabled for the campaign */
  const CONSOLE_CAMPAIGN_ANALYTICS_ENABLED = 'google.c.a.e';
  var MessageType$1;
  (function (MessageType) {
      MessageType[MessageType["DATA_MESSAGE"] = 1] = "DATA_MESSAGE";
      MessageType[MessageType["DISPLAY_NOTIFICATION"] = 3] = "DISPLAY_NOTIFICATION";
  })(MessageType$1 || (MessageType$1 = {}));
  
  /**
   * @license
   * Copyright 2018 Google LLC
   *
   * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
   * in compliance with the License. You may obtain a copy of the License at
   *
   * http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software distributed under the License
   * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
   * or implied. See the License for the specific language governing permissions and limitations under
   * the License.
   */
  var MessageType;
  (function (MessageType) {
      MessageType["PUSH_RECEIVED"] = "push-received";
      MessageType["NOTIFICATION_CLICKED"] = "notification-clicked";
  })(MessageType || (MessageType = {}));
  
  /**
   * @license
   * Copyright 2017 Google LLC
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *   http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  function arrayToBase64(array) {
      const uint8Array = new Uint8Array(array);
      const base64String = btoa(String.fromCharCode(...uint8Array));
      return base64String.replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_');
  }
  function base64ToArray(base64String) {
      const padding = '='.repeat((4 - (base64String.length % 4)) % 4);
      const base64 = (base64String + padding)
          .replace(/\-/g, '+')
          .replace(/_/g, '/');
      const rawData = atob(base64);
      const outputArray = new Uint8Array(rawData.length);
      for (let i = 0; i < rawData.length; ++i) {
          outputArray[i] = rawData.charCodeAt(i);
      }
      return outputArray;
  }
  
  /**
   * @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 OLD_DB_NAME = 'fcm_token_details_db';
  /**
   * The last DB version of 'fcm_token_details_db' was 4. This is one higher, so that the upgrade
   * callback is called for all versions of the old DB.
   */
  const OLD_DB_VERSION = 5;
  const OLD_OBJECT_STORE_NAME = 'fcm_token_object_Store';
  async function migrateOldDatabase(senderId) {
      if ('databases' in indexedDB) {
          // indexedDb.databases() is an IndexedDB v3 API and does not exist in all browsers. TODO: Remove
          // typecast when it lands in TS types.
          const databases = await indexedDB.databases();
          const dbNames = databases.map(db => db.name);
          if (!dbNames.includes(OLD_DB_NAME)) {
              // old DB didn't exist, no need to open.
              return null;
          }
      }
      let tokenDetails = null;
      const db = await openDb(OLD_DB_NAME, OLD_DB_VERSION, async (db) => {
          var _a;
          if (db.oldVersion < 2) {
              // Database too old, skip migration.
              return;
          }
          if (!db.objectStoreNames.contains(OLD_OBJECT_STORE_NAME)) {
              // Database did not exist. Nothing to do.
              return;
          }
          const objectStore = db.transaction.objectStore(OLD_OBJECT_STORE_NAME);
          const value = await objectStore.index('fcmSenderId').get(senderId);
          await objectStore.clear();
          if (!value) {
              // No entry in the database, nothing to migrate.
              return;
          }
          if (db.oldVersion === 2) {
              const oldDetails = value;
              if (!oldDetails.auth || !oldDetails.p256dh || !oldDetails.endpoint) {
                  return;
              }
              tokenDetails = {
                  token: oldDetails.fcmToken,
                  createTime: (_a = oldDetails.createTime) !== null && _a !== void 0 ? _a : Date.now(),
                  subscriptionOptions: {
                      auth: oldDetails.auth,
                      p256dh: oldDetails.p256dh,
                      endpoint: oldDetails.endpoint,
                      swScope: oldDetails.swScope,
                      vapidKey: typeof oldDetails.vapidKey === 'string'
                          ? oldDetails.vapidKey
                          : arrayToBase64(oldDetails.vapidKey)
                  }
              };
          }
          else if (db.oldVersion === 3) {
              const oldDetails = value;
              tokenDetails = {
                  token: oldDetails.fcmToken,
                  createTime: oldDetails.createTime,
                  subscriptionOptions: {
                      auth: arrayToBase64(oldDetails.auth),
                      p256dh: arrayToBase64(oldDetails.p256dh),
                      endpoint: oldDetails.endpoint,
                      swScope: oldDetails.swScope,
                      vapidKey: arrayToBase64(oldDetails.vapidKey)
                  }
              };
          }
          else if (db.oldVersion === 4) {
              const oldDetails = value;
              tokenDetails = {
                  token: oldDetails.fcmToken,
                  createTime: oldDetails.createTime,
                  subscriptionOptions: {
                      auth: arrayToBase64(oldDetails.auth),
                      p256dh: arrayToBase64(oldDetails.p256dh),
                      endpoint: oldDetails.endpoint,
                      swScope: oldDetails.swScope,
                      vapidKey: arrayToBase64(oldDetails.vapidKey)
                  }
              };
          }
      });
      db.close();
      // Delete all old databases.
      await deleteDb(OLD_DB_NAME);
      await deleteDb('fcm_vapid_details_db');
      await deleteDb('undefined');
      return checkTokenDetails(tokenDetails) ? tokenDetails : null;
  }
  function checkTokenDetails(tokenDetails) {
      if (!tokenDetails || !tokenDetails.subscriptionOptions) {
          return false;
      }
      const { subscriptionOptions } = tokenDetails;
      return (typeof tokenDetails.createTime === 'number' &&
          tokenDetails.createTime > 0 &&
          typeof tokenDetails.token === 'string' &&
          tokenDetails.token.length > 0 &&
          typeof subscriptionOptions.auth === 'string' &&
          subscriptionOptions.auth.length > 0 &&
          typeof subscriptionOptions.p256dh === 'string' &&
          subscriptionOptions.p256dh.length > 0 &&
          typeof subscriptionOptions.endpoint === 'string' &&
          subscriptionOptions.endpoint.length > 0 &&
          typeof subscriptionOptions.swScope === 'string' &&
          subscriptionOptions.swScope.length > 0 &&
          typeof subscriptionOptions.vapidKey === 'string' &&
          subscriptionOptions.vapidKey.length > 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.
   */
  // Exported for tests.
  const DATABASE_NAME = 'firebase-messaging-database';
  const DATABASE_VERSION = 1;
  const OBJECT_STORE_NAME = 'firebase-messaging-store';
  let dbPromise = null;
  function getDbPromise() {
      if (!dbPromise) {
          dbPromise = openDb(DATABASE_NAME, DATABASE_VERSION, upgradeDb => {
              // 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 (upgradeDb.oldVersion) {
                  case 0:
                      upgradeDb.createObjectStore(OBJECT_STORE_NAME);
              }
          });
      }
      return dbPromise;
  }
  /** Gets record(s) from the objectStore that match the given key. */
  async function dbGet(firebaseDependencies) {
      const key = getKey(firebaseDependencies);
      const db = await getDbPromise();
      const tokenDetails = await db
          .transaction(OBJECT_STORE_NAME)
          .objectStore(OBJECT_STORE_NAME)
          .get(key);
      if (tokenDetails) {
          return tokenDetails;
      }
      else {
          // Check if there is a tokenDetails object in the old DB.
          const oldTokenDetails = await migrateOldDatabase(firebaseDependencies.appConfig.senderId);
          if (oldTokenDetails) {
              await dbSet(firebaseDependencies, oldTokenDetails);
              return oldTokenDetails;
          }
      }
  }
  /** Assigns or overwrites the record for the given key with the given value. */
  async function dbSet(firebaseDependencies, tokenDetails) {
      const key = getKey(firebaseDependencies);
      const db = await getDbPromise();
      const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');
      await tx.objectStore(OBJECT_STORE_NAME).put(tokenDetails, key);
      await tx.complete;
      return tokenDetails;
  }
  /** Removes record(s) from the objectStore that match the given key. */
  async function dbRemove(firebaseDependencies) {
      const key = getKey(firebaseDependencies);
      const db = await getDbPromise();
      const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');
      await tx.objectStore(OBJECT_STORE_NAME).delete(key);
      await tx.complete;
  }
  function getKey({ appConfig }) {
      return appConfig.appId;
  }
  
  /**
   * @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 ERROR_MAP = {
      ["missing-app-config-values" /* MISSING_APP_CONFIG_VALUES */]: 'Missing App configuration value: "{$valueName}"',
      ["only-available-in-window" /* AVAILABLE_IN_WINDOW */]: 'This method is available in a Window context.',
      ["only-available-in-sw" /* AVAILABLE_IN_SW */]: 'This method is available in a service worker context.',
      ["permission-default" /* PERMISSION_DEFAULT */]: 'The notification permission was not granted and dismissed instead.',
      ["permission-blocked" /* PERMISSION_BLOCKED */]: 'The notification permission was not granted and blocked instead.',
      ["unsupported-browser" /* UNSUPPORTED_BROWSER */]: "This browser doesn't support the API's required to use the Firebase SDK.",
      ["indexed-db-unsupported" /* INDEXED_DB_UNSUPPORTED */]: "This browser doesn't support indexedDb.open() (ex. Safari iFrame, Firefox Private Browsing, etc)",
      ["failed-service-worker-registration" /* FAILED_DEFAULT_REGISTRATION */]: 'We are unable to register the default service worker. {$browserErrorMessage}',
      ["token-subscribe-failed" /* TOKEN_SUBSCRIBE_FAILED */]: 'A problem occurred while subscribing the user to FCM: {$errorInfo}',
      ["token-subscribe-no-token" /* TOKEN_SUBSCRIBE_NO_TOKEN */]: 'FCM returned no token when subscribing the user to push.',
      ["token-unsubscribe-failed" /* TOKEN_UNSUBSCRIBE_FAILED */]: 'A problem occurred while unsubscribing the ' +
          'user from FCM: {$errorInfo}',
      ["token-update-failed" /* TOKEN_UPDATE_FAILED */]: 'A problem occurred while updating the user from FCM: {$errorInfo}',
      ["token-update-no-token" /* TOKEN_UPDATE_NO_TOKEN */]: 'FCM returned no token when updating the user to push.',
      ["use-sw-after-get-token" /* USE_SW_AFTER_GET_TOKEN */]: 'The useServiceWorker() method may only be called once and must be ' +
          'called before calling getToken() to ensure your service worker is used.',
      ["invalid-sw-registration" /* INVALID_SW_REGISTRATION */]: 'The input to useServiceWorker() must be a ServiceWorkerRegistration.',
      ["invalid-bg-handler" /* INVALID_BG_HANDLER */]: 'The input to setBackgroundMessageHandler() must be a function.',
      ["invalid-vapid-key" /* INVALID_VAPID_KEY */]: 'The public VAPID key must be a string.',
      ["use-vapid-key-after-get-token" /* USE_VAPID_KEY_AFTER_GET_TOKEN */]: 'The usePublicVapidKey() method may only be called once and must be ' +
          'called before calling getToken() to ensure your VAPID key is used.'
  };
  const ERROR_FACTORY = new ErrorFactory('messaging', 'Messaging', ERROR_MAP);
  
  /**
   * @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.
   */
  async function requestGetToken(firebaseDependencies, subscriptionOptions) {
      const headers = await getHeaders(firebaseDependencies);
      const body = getBody(subscriptionOptions);
      const subscribeOptions = {
          method: 'POST',
          headers,
          body: JSON.stringify(body)
      };
      let responseData;
      try {
          const response = await fetch(getEndpoint(firebaseDependencies.appConfig), subscribeOptions);
          responseData = await response.json();
      }
      catch (err) {
          throw ERROR_FACTORY.create("token-subscribe-failed" /* TOKEN_SUBSCRIBE_FAILED */, {
              errorInfo: err
          });
      }
      if (responseData.error) {
          const message = responseData.error.message;
          throw ERROR_FACTORY.create("token-subscribe-failed" /* TOKEN_SUBSCRIBE_FAILED */, {
              errorInfo: message
          });
      }
      if (!responseData.token) {
          throw ERROR_FACTORY.create("token-subscribe-no-token" /* TOKEN_SUBSCRIBE_NO_TOKEN */);
      }
      return responseData.token;
  }
  async function requestUpdateToken(firebaseDependencies, tokenDetails) {
      const headers = await getHeaders(firebaseDependencies);
      const body = getBody(tokenDetails.subscriptionOptions);
      const updateOptions = {
          method: 'PATCH',
          headers,
          body: JSON.stringify(body)
      };
      let responseData;
      try {
          const response = await fetch(`${getEndpoint(firebaseDependencies.appConfig)}/${tokenDetails.token}`, updateOptions);
          responseData = await response.json();
      }
      catch (err) {
          throw ERROR_FACTORY.create("token-update-failed" /* TOKEN_UPDATE_FAILED */, {
              errorInfo: err
          });
      }
      if (responseData.error) {
          const message = responseData.error.message;
          throw ERROR_FACTORY.create("token-update-failed" /* TOKEN_UPDATE_FAILED */, {
              errorInfo: message
          });
      }
      if (!responseData.token) {
          throw ERROR_FACTORY.create("token-update-no-token" /* TOKEN_UPDATE_NO_TOKEN */);
      }
      return responseData.token;
  }
  async function requestDeleteToken(firebaseDependencies, token) {
      const headers = await getHeaders(firebaseDependencies);
      const unsubscribeOptions = {
          method: 'DELETE',
          headers
      };
      try {
          const response = await fetch(`${getEndpoint(firebaseDependencies.appConfig)}/${token}`, unsubscribeOptions);
          const responseData = await response.json();
          if (responseData.error) {
              const message = responseData.error.message;
              throw ERROR_FACTORY.create("token-unsubscribe-failed" /* TOKEN_UNSUBSCRIBE_FAILED */, {
                  errorInfo: message
              });
          }
      }
      catch (err) {
          throw ERROR_FACTORY.create("token-unsubscribe-failed" /* TOKEN_UNSUBSCRIBE_FAILED */, {
              errorInfo: err
          });
      }
  }
  function getEndpoint({ projectId }) {
      return `${ENDPOINT}/projects/${projectId}/registrations`;
  }
  async function getHeaders({ appConfig, installations }) {
      const authToken = await installations.getToken();
      return new Headers({
          'Content-Type': 'application/json',
          Accept: 'application/json',
          'x-goog-api-key': appConfig.apiKey,
          'x-goog-firebase-installations-auth': `FIS ${authToken}`
      });
  }
  function getBody({ p256dh, auth, endpoint, vapidKey }) {
      const body = {
          web: {
              endpoint,
              auth,
              p256dh
          }
      };
      if (vapidKey !== DEFAULT_VAPID_KEY) {
          body.web.applicationPubKey = vapidKey;
      }
      return body;
  }
  
  /**
   * @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.
   */
  // UpdateRegistration will be called once every week.
  const TOKEN_EXPIRATION_MS = 7 * 24 * 60 * 60 * 1000; // 7 days
  async function getTokenInternal(messaging) {
      const pushSubscription = await getPushSubscription(messaging.swRegistration, messaging.vapidKey);
      const subscriptionOptions = {
          vapidKey: messaging.vapidKey,
          swScope: messaging.swRegistration.scope,
          endpoint: pushSubscription.endpoint,
          auth: arrayToBase64(pushSubscription.getKey('auth')),
          p256dh: arrayToBase64(pushSubscription.getKey('p256dh'))
      };
      const tokenDetails = await dbGet(messaging.firebaseDependencies);
      if (!tokenDetails) {
          // No token, get a new one.
          return getNewToken(messaging.firebaseDependencies, subscriptionOptions);
      }
      else if (!isTokenValid(tokenDetails.subscriptionOptions, subscriptionOptions)) {
          // Invalid token, get a new one.
          try {
              await requestDeleteToken(messaging.firebaseDependencies, tokenDetails.token);
          }
          catch (e) {
              // Suppress errors because of #2364
              console.warn(e);
          }
          return getNewToken(messaging.firebaseDependencies, subscriptionOptions);
      }
      else if (Date.now() >= tokenDetails.createTime + TOKEN_EXPIRATION_MS) {
          // Weekly token refresh
          return updateToken(messaging, {
              token: tokenDetails.token,
              createTime: Date.now(),
              subscriptionOptions
          });
      }
      else {
          // Valid token, nothing to do.
          return tokenDetails.token;
      }
  }
  /**
   * This method deletes the token from the database, unsubscribes the token from FCM, and unregisters
   * the push subscription if it exists.
   */
  async function deleteTokenInternal(messaging) {
      const tokenDetails = await dbGet(messaging.firebaseDependencies);
      if (tokenDetails) {
          await requestDeleteToken(messaging.firebaseDependencies, tokenDetails.token);
          await dbRemove(messaging.firebaseDependencies);
      }
      // Unsubscribe from the push subscription.
      const pushSubscription = await messaging.swRegistration.pushManager.getSubscription();
      if (pushSubscription) {
          return pushSubscription.unsubscribe();
      }
      // If there's no SW, consider it a success.
      return true;
  }
  async function updateToken(messaging, tokenDetails) {
      try {
          const updatedToken = await requestUpdateToken(messaging.firebaseDependencies, tokenDetails);
          const updatedTokenDetails = Object.assign(Object.assign({}, tokenDetails), { token: updatedToken, createTime: Date.now() });
          await dbSet(messaging.firebaseDependencies, updatedTokenDetails);
          return updatedToken;
      }
      catch (e) {
          await deleteTokenInternal(messaging);
          throw e;
      }
  }
  async function getNewToken(firebaseDependencies, subscriptionOptions) {
      const token = await requestGetToken(firebaseDependencies, subscriptionOptions);
      const tokenDetails = {
          token,
          createTime: Date.now(),
          subscriptionOptions
      };
      await dbSet(firebaseDependencies, tokenDetails);
      return tokenDetails.token;
  }
  /**
   * Gets a PushSubscription for the current user.
   */
  async function getPushSubscription(swRegistration, vapidKey) {
      const subscription = await swRegistration.pushManager.getSubscription();
      if (subscription) {
          return subscription;
      }
      return swRegistration.pushManager.subscribe({
          userVisibleOnly: true,
          // Chrome <= 75 doesn't support base64-encoded VAPID key. For backward compatibility, VAPID key
          // submitted to pushManager#subscribe must be of type Uint8Array.
          applicationServerKey: base64ToArray(vapidKey)
      });
  }
  /**
   * Checks if the saved tokenDetails object matches the configuration provided.
   */
  function isTokenValid(dbOptions, currentOptions) {
      const isVapidKeyEqual = currentOptions.vapidKey === dbOptions.vapidKey;
      const isEndpointEqual = currentOptions.endpoint === dbOptions.endpoint;
      const isAuthEqual = currentOptions.auth === dbOptions.auth;
      const isP256dhEqual = currentOptions.p256dh === dbOptions.p256dh;
      return isVapidKeyEqual && isEndpointEqual && isAuthEqual && isP256dhEqual;
  }
  
  /**
   * @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.
   */
  function externalizePayload(internalPayload) {
      const payload = {
          from: internalPayload.from,
          // eslint-disable-next-line camelcase
          collapseKey: internalPayload.collapse_key,
          // eslint-disable-next-line camelcase
          messageId: internalPayload.fcmMessageId
      };
      propagateNotificationPayload(payload, internalPayload);
      propagateDataPayload(payload, internalPayload);
      propagateFcmOptions(payload, internalPayload);
      return payload;
  }
  function propagateNotificationPayload(payload, messagePayloadInternal) {
      if (!messagePayloadInternal.notification) {
          return;
      }
      payload.notification = {};
      const title = messagePayloadInternal.notification.title;
      if (!!title) {
          payload.notification.title = title;
      }
      const body = messagePayloadInternal.notification.body;
      if (!!body) {
          payload.notification.body = body;
      }
      const image = messagePayloadInternal.notification.image;
      if (!!image) {
          payload.notification.image = image;
      }
  }
  function propagateDataPayload(payload, messagePayloadInternal) {
      if (!messagePayloadInternal.data) {
          return;
      }
      payload.data = messagePayloadInternal.data;
  }
  function propagateFcmOptions(payload, messagePayloadInternal) {
      if (!messagePayloadInternal.fcmOptions) {
          return;
      }
      payload.fcmOptions = {};
      const link = messagePayloadInternal.fcmOptions.link;
      if (!!link) {
          payload.fcmOptions.link = link;
      }
      // eslint-disable-next-line camelcase
      const analyticsLabel = messagePayloadInternal.fcmOptions.analytics_label;
      if (!!analyticsLabel) {
          payload.fcmOptions.analyticsLabel = analyticsLabel;
      }
  }
  
  /**
   * @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 isConsoleMessage(data) {
      // This message has a campaign ID, meaning it was sent using the Firebase Console.
      return typeof data === 'object' && !!data && CONSOLE_CAMPAIGN_ID in data;
  }
  
  /**
   * @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.
   */
  _mergeStrings('hts/frbslgigp.ogepscmv/ieo/eaylg', 'tp:/ieaeogn-agolai.o/1frlglgc/o');
  _mergeStrings('AzSCbw63g1R0nCw85jG8', 'Iaya3yLKwmgvh7cF0q4');
  function _mergeStrings(s1, s2) {
      const resultArray = [];
      for (let i = 0; i < s1.length; i++) {
          resultArray.push(s1.charAt(i));
          if (i < s2.length) {
              resultArray.push(s2.charAt(i));
          }
      }
      return resultArray.join('');
  }
  
  /**
   * @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 extractAppConfig(app) {
      if (!app || !app.options) {
          throw getMissingValueError('App Configuration Object');
      }
      if (!app.name) {
          throw getMissingValueError('App Name');
      }
      // Required app config keys
      const configKeys = [
          'projectId',
          'apiKey',
          'appId',
          'messagingSenderId'
      ];
      const { options } = app;
      for (const keyName of configKeys) {
          if (!options[keyName]) {
              throw getMissingValueError(keyName);
          }
      }
      return {
          appName: app.name,
          projectId: options.projectId,
          apiKey: options.apiKey,
          appId: options.appId,
          senderId: options.messagingSenderId
      };
  }
  function getMissingValueError(valueName) {
      return ERROR_FACTORY.create("missing-app-config-values" /* MISSING_APP_CONFIG_VALUES */, {
          valueName
      });
  }
  
  /**
   * @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.
   */
  class MessagingService {
      constructor(app, installations, analyticsProvider) {
          // logging is only done with end user consent. Default to false.
          this.deliveryMetricsExportedToBigQueryEnabled = false;
          this.onBackgroundMessageHandler = null;
          this.onMessageHandler = null;
          this.logEvents = [];
          this.isLogServiceStarted = false;
          const appConfig = extractAppConfig(app);
          this.firebaseDependencies = {
              app,
              appConfig,
              installations,
              analyticsProvider
          };
      }
      _delete() {
          return Promise.resolve();
      }
  }
  
  /**
   * @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.
   */
  async function registerDefaultSw(messaging) {
      try {
          messaging.swRegistration = await navigator.serviceWorker.register(DEFAULT_SW_PATH, {
              scope: DEFAULT_SW_SCOPE
          });
          // The timing when browser updates sw when sw has an update is unreliable from experiment. It
          // leads to version conflict when the SDK upgrades to a newer version in the main page, but sw
          // is stuck with the old version. For example,
          // https://github.com/firebase/firebase-js-sdk/issues/2590 The following line reliably updates
          // sw if there was an update.
          messaging.swRegistration.update().catch(() => {
              /* it is non blocking and we don't care if it failed */
          });
      }
      catch (e) {
          throw ERROR_FACTORY.create("failed-service-worker-registration" /* FAILED_DEFAULT_REGISTRATION */, {
              browserErrorMessage: e.message
          });
      }
  }
  
  /**
   * @license
   * Copyright 2020 Google LLC
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *   http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  async function updateSwReg(messaging, swRegistration) {
      if (!swRegistration && !messaging.swRegistration) {
          await registerDefaultSw(messaging);
      }
      if (!swRegistration && !!messaging.swRegistration) {
          return;
      }
      if (!(swRegistration instanceof ServiceWorkerRegistration)) {
          throw ERROR_FACTORY.create("invalid-sw-registration" /* INVALID_SW_REGISTRATION */);
      }
      messaging.swRegistration = swRegistration;
  }
  
  /**
   * @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.
   */
  async function updateVapidKey(messaging, vapidKey) {
      if (!!vapidKey) {
          messaging.vapidKey = vapidKey;
      }
      else if (!messaging.vapidKey) {
          messaging.vapidKey = DEFAULT_VAPID_KEY;
      }
  }
  
  /**
   * @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.
   */
  async function getToken$1(messaging, options) {
      if (!navigator) {
          throw ERROR_FACTORY.create("only-available-in-window" /* AVAILABLE_IN_WINDOW */);
      }
      if (Notification.permission === 'default') {
          await Notification.requestPermission();
      }
      if (Notification.permission !== 'granted') {
          throw ERROR_FACTORY.create("permission-blocked" /* PERMISSION_BLOCKED */);
      }
      await updateVapidKey(messaging, options === null || options === void 0 ? void 0 : options.vapidKey);
      await updateSwReg(messaging, options === null || options === void 0 ? void 0 : options.serviceWorkerRegistration);
      return getTokenInternal(messaging);
  }
  
  /**
   * @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.
   */
  async function logToScion(messaging, messageType, data) {
      const eventType = getEventType(messageType);
      const analytics = await messaging.firebaseDependencies.analyticsProvider.get();
      analytics.logEvent(eventType, {
          /* eslint-disable camelcase */
          message_id: data[CONSOLE_CAMPAIGN_ID],
          message_name: data[CONSOLE_CAMPAIGN_NAME],
          message_time: data[CONSOLE_CAMPAIGN_TIME],
          message_device_time: Math.floor(Date.now() / 1000)
          /* eslint-enable camelcase */
      });
  }
  function getEventType(messageType) {
      switch (messageType) {
          case MessageType.NOTIFICATION_CLICKED:
              return 'notification_open';
          case MessageType.PUSH_RECEIVED:
              return 'notification_foreground';
          default:
              throw new 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.
   */
  async function messageEventListener(messaging, event) {
      const internalPayload = event.data;
      if (!internalPayload.isFirebaseMessaging) {
          return;
      }
      if (messaging.onMessageHandler &&
          internalPayload.messageType === MessageType.PUSH_RECEIVED) {
          if (typeof messaging.onMessageHandler === 'function') {
              messaging.onMessageHandler(externalizePayload(internalPayload));
          }
          else {
              messaging.onMessageHandler.next(externalizePayload(internalPayload));
          }
      }
      // Log to Scion if applicable
      const dataPayload = internalPayload.data;
      if (isConsoleMessage(dataPayload) &&
          dataPayload[CONSOLE_CAMPAIGN_ANALYTICS_ENABLED] === '1') {
          await logToScion(messaging, internalPayload.messageType, dataPayload);
      }
  }
  
  const name = "@firebase/messaging";
  const version = "0.9.8";
  
  /**
   * @license
   * Copyright 2020 Google LLC
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *   http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  const WindowMessagingFactory = (container) => {
      const messaging = new MessagingService(container.getProvider('app').getImmediate(), container.getProvider('installations-internal').getImmediate(), container.getProvider('analytics-internal'));
      navigator.serviceWorker.addEventListener('message', e => messageEventListener(messaging, e));
      return messaging;
  };
  const WindowMessagingInternalFactory = (container) => {
      const messaging = container
          .getProvider('messaging')
          .getImmediate();
      const messagingInternal = {
          getToken: (options) => getToken$1(messaging, options)
      };
      return messagingInternal;
  };
  function registerMessagingInWindow() {
      _registerComponent(new Component('messaging', WindowMessagingFactory, "PUBLIC" /* PUBLIC */));
      _registerComponent(new Component('messaging-internal', WindowMessagingInternalFactory, "PRIVATE" /* PRIVATE */));
      registerVersion(name, version);
      // BUILD_TARGET will be replaced by values like esm5, esm2017, cjs5, etc during the compilation
      registerVersion(name, version, 'esm2017');
  }
  
  /**
   * @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.
   */
  /**
   * Checks if all required APIs exist in the browser.
   * @returns a Promise that resolves to a boolean.
   *
   * @public
   */
  async function isWindowSupported() {
      try {
          // This throws if open() is unsupported, so adding it to the conditional
          // statement below can cause an uncaught error.
          await validateIndexedDBOpenable();
      }
      catch (e) {
          return false;
      }
      // firebase-js-sdk/issues/2393 reveals that idb#open in Safari iframe and Firefox private browsing
      // might be prohibited to run. In these contexts, an error would be thrown during the messaging
      // instantiating phase, informing the developers to import/call isSupported for special handling.
      return (typeof window !== 'undefined' &&
          isIndexedDBAvailable() &&
          areCookiesEnabled() &&
          'serviceWorker' in navigator &&
          'PushManager' in window &&
          'Notification' in window &&
          'fetch' in window &&
          ServiceWorkerRegistration.prototype.hasOwnProperty('showNotification') &&
          PushSubscription.prototype.hasOwnProperty('getKey'));
  }
  
  /**
   * @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.
   */
  async function deleteToken$1(messaging) {
      if (!navigator) {
          throw ERROR_FACTORY.create("only-available-in-window" /* AVAILABLE_IN_WINDOW */);
      }
      if (!messaging.swRegistration) {
          await registerDefaultSw(messaging);
      }
      return deleteTokenInternal(messaging);
  }
  
  /**
   * @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.
   */
  function onMessage$1(messaging, nextOrObserver) {
      if (!navigator) {
          throw ERROR_FACTORY.create("only-available-in-window" /* AVAILABLE_IN_WINDOW */);
      }
      messaging.onMessageHandler = nextOrObserver;
      return () => {
          messaging.onMessageHandler = null;
      };
  }
  
  /**
   * @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.
   */
  /**
   * Retrieves a Firebase Cloud Messaging instance.
   *
   * @returns The Firebase Cloud Messaging instance associated with the provided firebase app.
   *
   * @public
   */
  function getMessagingInWindow(app = getApp()) {
      // Conscious decision to make this async check non-blocking during the messaging instance
      // initialization phase for performance consideration. An error would be thrown latter for
      // developer's information. Developers can then choose to import and call `isSupported` for
      // special handling.
      isWindowSupported().then(isSupported => {
          // If `isWindowSupported()` resolved, but returned false.
          if (!isSupported) {
              throw ERROR_FACTORY.create("unsupported-browser" /* UNSUPPORTED_BROWSER */);
          }
      }, _ => {
          // If `isWindowSupported()` rejected.
          throw ERROR_FACTORY.create("indexed-db-unsupported" /* INDEXED_DB_UNSUPPORTED */);
      });
      return _getProvider(getModularInstance(app), 'messaging').getImmediate();
  }
  /**
   * Subscribes the {@link Messaging} instance to push notifications. Returns an Firebase Cloud
   * Messaging registration token that can be used to send push messages to that {@link Messaging}
   * instance.
   *
   * If a notification permission isn't already granted, this method asks the user for permission. The
   * returned promise rejects if the user does not allow the app to show notifications.
   *
   * @param messaging - The {@link Messaging} instance.
   * @param options - Provides an optional vapid key and an optinoal service worker registration
   *
   * @returns The promise resolves with an FCM registration token.
   *
   * @public
   */
  async function getToken(messaging, options) {
      messaging = getModularInstance(messaging);
      return getToken$1(messaging, options);
  }
  /**
   * Deletes the registration token associated with this {@link Messaging} instance and unsubscribes
   * the {@link Messaging} instance from the push subscription.
   *
   * @param messaging - The {@link Messaging} instance.
   *
   * @returns The promise resolves when the token has been successfully deleted.
   *
   * @public
   */
  function deleteToken(messaging) {
      messaging = getModularInstance(messaging);
      return deleteToken$1(messaging);
  }
  /**
   * When a push message is received and the user is currently on a page for your origin, the
   * message is passed to the page and an `onMessage()` event is dispatched with the payload of
   * the push message.
   *
   *
   * @param messaging - The {@link Messaging} instance.
   * @param nextOrObserver - This function, or observer object with `next` defined,
   *     is called when a message is received and the user is currently viewing your page.
   * @returns To stop listening for messages execute this returned function.
   *
   * @public
   */
  function onMessage(messaging, nextOrObserver) {
      messaging = getModularInstance(messaging);
      return onMessage$1(messaging, nextOrObserver);
  }
  
  /**
   * Firebase Cloud Messaging
   *
   * @packageDocumentation
   */
  registerMessagingInWindow();
  
  export { deleteToken, getMessagingInWindow as getMessaging, getToken, isWindowSupported as isSupported, onMessage };
  
  //# sourceMappingURL=firebase-messaging.js.map
  