{"version":3,"file":"firebase-remote-config.js","sources":["../../node_modules/tslib/tslib.es6.js","../util/src/errors.ts","../component/src/component.ts","../../node_modules/idb/lib/idb.mjs","../installations/src/util/constants.ts","../installations/src/util/errors.ts","../installations/src/api/common.ts","../installations/src/util/sleep.ts","../installations/src/helpers/buffer-to-base64-url-safe.ts","../installations/src/helpers/generate-fid.ts","../installations/src/util/get-key.ts","../installations/src/helpers/fid-changed.ts","../installations/src/helpers/idb-manager.ts","../installations/src/index.ts","../logger/src/logger.ts","../installations/src/helpers/get-installation-entry.ts","../installations/src/api/create-installation-request.ts","../installations/src/api/generate-auth-token-request.ts","../installations/src/helpers/refresh-auth-token.ts","../installations/src/functions/get-token.ts","../installations/src/api/delete-installation-request.ts","../installations/src/functions/on-id-change.ts","../installations/src/helpers/extract-app-config.ts","../installations/src/functions/get-id.ts","../installations/src/functions/delete-installation.ts","../remote-config/src/client/caching_client.ts","../remote-config/src/errors.ts","../remote-config/src/client/rest_client.ts","../remote-config/src/language.ts","../remote-config/src/client/remote_config_fetch_client.ts","../remote-config/src/value.ts","../remote-config/src/remote_config.ts","../remote-config/src/storage/storage.ts","../remote-config/src/storage/storage_cache.ts","../remote-config/src/client/retrying_client.ts","../remote-config/src/client/exponential_backoff.ts","../remote-config/index.ts"],"sourcesContent":["/*! *****************************************************************************\r\nCopyright (c) Microsoft Corporation.\r\n\r\nPermission to use, copy, modify, and/or distribute this software for any\r\npurpose with or without fee is hereby granted.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\r\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\r\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\r\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\r\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\r\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\r\nPERFORMANCE OF THIS SOFTWARE.\r\n***************************************************************************** */\r\n/* global Reflect, Promise */\r\n\r\nvar extendStatics = function(d, b) {\r\n extendStatics = Object.setPrototypeOf ||\r\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\r\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\r\n return extendStatics(d, b);\r\n};\r\n\r\nexport function __extends(d, b) {\r\n extendStatics(d, b);\r\n function __() { this.constructor = d; }\r\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r\n}\r\n\r\nexport var __assign = function() {\r\n __assign = Object.assign || function __assign(t) {\r\n for (var s, i = 1, n = arguments.length; i < n; i++) {\r\n s = arguments[i];\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\r\n }\r\n return t;\r\n }\r\n return __assign.apply(this, arguments);\r\n}\r\n\r\nexport function __rest(s, e) {\r\n var t = {};\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\r\n t[p] = s[p];\r\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\r\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\r\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))\r\n t[p[i]] = s[p[i]];\r\n }\r\n return t;\r\n}\r\n\r\nexport function __decorate(decorators, target, key, desc) {\r\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\r\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\r\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\r\n return c > 3 && r && Object.defineProperty(target, key, r), r;\r\n}\r\n\r\nexport function __param(paramIndex, decorator) {\r\n return function (target, key) { decorator(target, key, paramIndex); }\r\n}\r\n\r\nexport function __metadata(metadataKey, metadataValue) {\r\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(metadataKey, metadataValue);\r\n}\r\n\r\nexport function __awaiter(thisArg, _arguments, P, generator) {\r\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n}\r\n\r\nexport function __generator(thisArg, body) {\r\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\r\n return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n function verb(n) { return function (v) { return step([n, v]); }; }\r\n function step(op) {\r\n if (f) throw new TypeError(\"Generator is already executing.\");\r\n while (_) try {\r\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\r\n if (y = 0, t) op = [op[0] & 2, t.value];\r\n switch (op[0]) {\r\n case 0: case 1: t = op; break;\r\n case 4: _.label++; return { value: op[1], done: false };\r\n case 5: _.label++; y = op[1]; op = [0]; continue;\r\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n default:\r\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n if (t[2]) _.ops.pop();\r\n _.trys.pop(); continue;\r\n }\r\n op = body.call(thisArg, _);\r\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n }\r\n}\r\n\r\nexport function __createBinding(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n o[k2] = m[k];\r\n}\r\n\r\nexport function __exportStar(m, exports) {\r\n for (var p in m) if (p !== \"default\" && !exports.hasOwnProperty(p)) exports[p] = m[p];\r\n}\r\n\r\nexport function __values(o) {\r\n var s = typeof Symbol === \"function\" && Symbol.iterator, m = s && o[s], i = 0;\r\n if (m) return m.call(o);\r\n if (o && typeof o.length === \"number\") return {\r\n next: function () {\r\n if (o && i >= o.length) o = void 0;\r\n return { value: o && o[i++], done: !o };\r\n }\r\n };\r\n throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\r\n}\r\n\r\nexport function __read(o, n) {\r\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\r\n if (!m) return o;\r\n var i = m.call(o), r, ar = [], e;\r\n try {\r\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\r\n }\r\n catch (error) { e = { error: error }; }\r\n finally {\r\n try {\r\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\r\n }\r\n finally { if (e) throw e.error; }\r\n }\r\n return ar;\r\n}\r\n\r\nexport function __spread() {\r\n for (var ar = [], i = 0; i < arguments.length; i++)\r\n ar = ar.concat(__read(arguments[i]));\r\n return ar;\r\n}\r\n\r\nexport function __spreadArrays() {\r\n for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;\r\n for (var r = Array(s), k = 0, i = 0; i < il; i++)\r\n for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)\r\n r[k] = a[j];\r\n return r;\r\n};\r\n\r\nexport function __await(v) {\r\n return this instanceof __await ? (this.v = v, this) : new __await(v);\r\n}\r\n\r\nexport function __asyncGenerator(thisArg, _arguments, generator) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var g = generator.apply(thisArg, _arguments || []), i, q = [];\r\n return i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i;\r\n function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }\r\n function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }\r\n function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }\r\n function fulfill(value) { resume(\"next\", value); }\r\n function reject(value) { resume(\"throw\", value); }\r\n function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }\r\n}\r\n\r\nexport function __asyncDelegator(o) {\r\n var i, p;\r\n return i = {}, verb(\"next\"), verb(\"throw\", function (e) { throw e; }), verb(\"return\"), i[Symbol.iterator] = function () { return this; }, i;\r\n function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === \"return\" } : f ? f(v) : v; } : f; }\r\n}\r\n\r\nexport function __asyncValues(o) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var m = o[Symbol.asyncIterator], i;\r\n return m ? m.call(o) : (o = typeof __values === \"function\" ? __values(o) : o[Symbol.iterator](), i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i);\r\n function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }\r\n function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }\r\n}\r\n\r\nexport function __makeTemplateObject(cooked, raw) {\r\n if (Object.defineProperty) { Object.defineProperty(cooked, \"raw\", { value: raw }); } else { cooked.raw = raw; }\r\n return cooked;\r\n};\r\n\r\nexport function __importStar(mod) {\r\n if (mod && mod.__esModule) return mod;\r\n var result = {};\r\n if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];\r\n result.default = mod;\r\n return result;\r\n}\r\n\r\nexport function __importDefault(mod) {\r\n return (mod && mod.__esModule) ? mod : { default: mod };\r\n}\r\n\r\nexport function __classPrivateFieldGet(receiver, privateMap) {\r\n if (!privateMap.has(receiver)) {\r\n throw new TypeError(\"attempted to get private field on non-instance\");\r\n }\r\n return privateMap.get(receiver);\r\n}\r\n\r\nexport function __classPrivateFieldSet(receiver, privateMap, value) {\r\n if (!privateMap.has(receiver)) {\r\n throw new TypeError(\"attempted to set private field on non-instance\");\r\n }\r\n privateMap.set(receiver, value);\r\n return value;\r\n}\r\n","/**\n * @license\n * Copyright 2017 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * @fileoverview Standardized Firebase Error.\n *\n * Usage:\n *\n * // Typescript string literals for type-safe codes\n * type Err =\n * 'unknown' |\n * 'object-not-found'\n * ;\n *\n * // Closure enum for type-safe error codes\n * // at-enum {string}\n * var Err = {\n * UNKNOWN: 'unknown',\n * OBJECT_NOT_FOUND: 'object-not-found',\n * }\n *\n * let errors: Map = {\n * 'generic-error': \"Unknown error\",\n * 'file-not-found': \"Could not find file: {$file}\",\n * };\n *\n * // Type-safe function - must pass a valid error code as param.\n * let error = new ErrorFactory('service', 'Service', errors);\n *\n * ...\n * throw error.create(Err.GENERIC);\n * ...\n * throw error.create(Err.FILE_NOT_FOUND, {'file': fileName});\n * ...\n * // Service: Could not file file: foo.txt (service/file-not-found).\n *\n * catch (e) {\n * assert(e.message === \"Could not find file: foo.txt.\");\n * if (e.code === 'service/file-not-found') {\n * console.log(\"Could not read file: \" + e['file']);\n * }\n * }\n */\n\nexport type ErrorMap = {\n readonly [K in ErrorCode]: string;\n};\n\nconst ERROR_NAME = 'FirebaseError';\n\nexport interface StringLike {\n toString(): string;\n}\n\nexport interface ErrorData {\n [key: string]: unknown;\n}\n\nexport interface FirebaseError extends Error, ErrorData {\n // Unique code for error - format is service/error-code-string.\n readonly code: string;\n\n // Developer-friendly error message.\n readonly message: string;\n\n // Always 'FirebaseError'.\n readonly name: typeof ERROR_NAME;\n\n // Where available - stack backtrace in a string.\n readonly stack?: string;\n}\n\n// Based on code from:\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error#Custom_Error_Types\nexport class FirebaseError extends Error {\n readonly name = ERROR_NAME;\n\n constructor(readonly code: string, message: string) {\n super(message);\n\n // Fix For ES5\n // https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work\n Object.setPrototypeOf(this, FirebaseError.prototype);\n\n // Maintains proper stack trace for where our error was thrown.\n // Only available on V8.\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, ErrorFactory.prototype.create);\n }\n }\n}\n\nexport class ErrorFactory<\n ErrorCode extends string,\n ErrorParams extends { readonly [K in ErrorCode]?: ErrorData } = {}\n> {\n constructor(\n private readonly service: string,\n private readonly serviceName: string,\n private readonly errors: ErrorMap\n ) {}\n\n create(\n code: K,\n ...data: K extends keyof ErrorParams ? [ErrorParams[K]] : []\n ): FirebaseError {\n const customData = (data[0] as ErrorData) || {};\n const fullCode = `${this.service}/${code}`;\n const template = this.errors[code];\n\n const message = template ? replaceTemplate(template, customData) : 'Error';\n // Service Name: Error message (service/code).\n const fullMessage = `${this.serviceName}: ${message} (${fullCode}).`;\n\n const error = new FirebaseError(fullCode, fullMessage);\n\n // Keys with an underscore at the end of their name are not included in\n // error.data for some reason.\n // TODO: Replace with Object.entries when lib is updated to es2017.\n for (const key of Object.keys(customData)) {\n if (key.slice(-1) !== '_') {\n if (key in error) {\n console.warn(\n `Overwriting FirebaseError base field \"${key}\" can cause unexpected behavior.`\n );\n }\n error[key] = customData[key];\n }\n }\n\n return error;\n }\n}\n\nfunction replaceTemplate(template: string, data: ErrorData): string {\n return template.replace(PATTERN, (_, key) => {\n const value = data[key];\n return value != null ? String(value) : `<${key}?>`;\n });\n}\n\nconst PATTERN = /\\{\\$([^}]+)}/g;\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n InstantiationMode,\n InstanceFactory,\n ComponentType,\n Dictionary,\n Name\n} from './types';\n\n/**\n * Component for service name T, e.g. `auth`, `auth-internal`\n */\nexport class Component {\n multipleInstances = false;\n /**\n * Properties to be added to the service namespace\n */\n serviceProps: Dictionary = {};\n\n instantiationMode = InstantiationMode.LAZY;\n\n /**\n *\n * @param name The public service name, e.g. app, auth, firestore, database\n * @param instanceFactory Service factory responsible for creating the public interface\n * @param type whether the service provided by the component is public or private\n */\n constructor(\n readonly name: T,\n readonly instanceFactory: InstanceFactory,\n readonly type: ComponentType\n ) {}\n\n setInstantiationMode(mode: InstantiationMode): this {\n this.instantiationMode = mode;\n return this;\n }\n\n setMultipleInstances(multipleInstances: boolean): this {\n this.multipleInstances = multipleInstances;\n return this;\n }\n\n setServiceProps(props: Dictionary): this {\n this.serviceProps = props;\n return this;\n }\n}\n","function toArray(arr) {\n return Array.prototype.slice.call(arr);\n}\n\nfunction promisifyRequest(request) {\n return new Promise(function(resolve, reject) {\n request.onsuccess = function() {\n resolve(request.result);\n };\n\n request.onerror = function() {\n reject(request.error);\n };\n });\n}\n\nfunction promisifyRequestCall(obj, method, args) {\n var request;\n var p = new Promise(function(resolve, reject) {\n request = obj[method].apply(obj, args);\n promisifyRequest(request).then(resolve, reject);\n });\n\n p.request = request;\n return p;\n}\n\nfunction promisifyCursorRequestCall(obj, method, args) {\n var p = promisifyRequestCall(obj, method, args);\n return p.then(function(value) {\n if (!value) return;\n return new Cursor(value, p.request);\n });\n}\n\nfunction proxyProperties(ProxyClass, targetProp, properties) {\n properties.forEach(function(prop) {\n Object.defineProperty(ProxyClass.prototype, prop, {\n get: function() {\n return this[targetProp][prop];\n },\n set: function(val) {\n this[targetProp][prop] = val;\n }\n });\n });\n}\n\nfunction proxyRequestMethods(ProxyClass, targetProp, Constructor, properties) {\n properties.forEach(function(prop) {\n if (!(prop in Constructor.prototype)) return;\n ProxyClass.prototype[prop] = function() {\n return promisifyRequestCall(this[targetProp], prop, arguments);\n };\n });\n}\n\nfunction proxyMethods(ProxyClass, targetProp, Constructor, properties) {\n properties.forEach(function(prop) {\n if (!(prop in Constructor.prototype)) return;\n ProxyClass.prototype[prop] = function() {\n return this[targetProp][prop].apply(this[targetProp], arguments);\n };\n });\n}\n\nfunction proxyCursorRequestMethods(ProxyClass, targetProp, Constructor, properties) {\n properties.forEach(function(prop) {\n if (!(prop in Constructor.prototype)) return;\n ProxyClass.prototype[prop] = function() {\n return promisifyCursorRequestCall(this[targetProp], prop, arguments);\n };\n });\n}\n\nfunction Index(index) {\n this._index = index;\n}\n\nproxyProperties(Index, '_index', [\n 'name',\n 'keyPath',\n 'multiEntry',\n 'unique'\n]);\n\nproxyRequestMethods(Index, '_index', IDBIndex, [\n 'get',\n 'getKey',\n 'getAll',\n 'getAllKeys',\n 'count'\n]);\n\nproxyCursorRequestMethods(Index, '_index', IDBIndex, [\n 'openCursor',\n 'openKeyCursor'\n]);\n\nfunction Cursor(cursor, request) {\n this._cursor = cursor;\n this._request = request;\n}\n\nproxyProperties(Cursor, '_cursor', [\n 'direction',\n 'key',\n 'primaryKey',\n 'value'\n]);\n\nproxyRequestMethods(Cursor, '_cursor', IDBCursor, [\n 'update',\n 'delete'\n]);\n\n// proxy 'next' methods\n['advance', 'continue', 'continuePrimaryKey'].forEach(function(methodName) {\n if (!(methodName in IDBCursor.prototype)) return;\n Cursor.prototype[methodName] = function() {\n var cursor = this;\n var args = arguments;\n return Promise.resolve().then(function() {\n cursor._cursor[methodName].apply(cursor._cursor, args);\n return promisifyRequest(cursor._request).then(function(value) {\n if (!value) return;\n return new Cursor(value, cursor._request);\n });\n });\n };\n});\n\nfunction ObjectStore(store) {\n this._store = store;\n}\n\nObjectStore.prototype.createIndex = function() {\n return new Index(this._store.createIndex.apply(this._store, arguments));\n};\n\nObjectStore.prototype.index = function() {\n return new Index(this._store.index.apply(this._store, arguments));\n};\n\nproxyProperties(ObjectStore, '_store', [\n 'name',\n 'keyPath',\n 'indexNames',\n 'autoIncrement'\n]);\n\nproxyRequestMethods(ObjectStore, '_store', IDBObjectStore, [\n 'put',\n 'add',\n 'delete',\n 'clear',\n 'get',\n 'getAll',\n 'getKey',\n 'getAllKeys',\n 'count'\n]);\n\nproxyCursorRequestMethods(ObjectStore, '_store', IDBObjectStore, [\n 'openCursor',\n 'openKeyCursor'\n]);\n\nproxyMethods(ObjectStore, '_store', IDBObjectStore, [\n 'deleteIndex'\n]);\n\nfunction Transaction(idbTransaction) {\n this._tx = idbTransaction;\n this.complete = new Promise(function(resolve, reject) {\n idbTransaction.oncomplete = function() {\n resolve();\n };\n idbTransaction.onerror = function() {\n reject(idbTransaction.error);\n };\n idbTransaction.onabort = function() {\n reject(idbTransaction.error);\n };\n });\n}\n\nTransaction.prototype.objectStore = function() {\n return new ObjectStore(this._tx.objectStore.apply(this._tx, arguments));\n};\n\nproxyProperties(Transaction, '_tx', [\n 'objectStoreNames',\n 'mode'\n]);\n\nproxyMethods(Transaction, '_tx', IDBTransaction, [\n 'abort'\n]);\n\nfunction UpgradeDB(db, oldVersion, transaction) {\n this._db = db;\n this.oldVersion = oldVersion;\n this.transaction = new Transaction(transaction);\n}\n\nUpgradeDB.prototype.createObjectStore = function() {\n return new ObjectStore(this._db.createObjectStore.apply(this._db, arguments));\n};\n\nproxyProperties(UpgradeDB, '_db', [\n 'name',\n 'version',\n 'objectStoreNames'\n]);\n\nproxyMethods(UpgradeDB, '_db', IDBDatabase, [\n 'deleteObjectStore',\n 'close'\n]);\n\nfunction DB(db) {\n this._db = db;\n}\n\nDB.prototype.transaction = function() {\n return new Transaction(this._db.transaction.apply(this._db, arguments));\n};\n\nproxyProperties(DB, '_db', [\n 'name',\n 'version',\n 'objectStoreNames'\n]);\n\nproxyMethods(DB, '_db', IDBDatabase, [\n 'close'\n]);\n\n// Add cursor iterators\n// TODO: remove this once browsers do the right thing with promises\n['openCursor', 'openKeyCursor'].forEach(function(funcName) {\n [ObjectStore, Index].forEach(function(Constructor) {\n // Don't create iterateKeyCursor if openKeyCursor doesn't exist.\n if (!(funcName in Constructor.prototype)) return;\n\n Constructor.prototype[funcName.replace('open', 'iterate')] = function() {\n var args = toArray(arguments);\n var callback = args[args.length - 1];\n var nativeObject = this._store || this._index;\n var request = nativeObject[funcName].apply(nativeObject, args.slice(0, -1));\n request.onsuccess = function() {\n callback(request.result);\n };\n };\n });\n});\n\n// polyfill getAll\n[Index, ObjectStore].forEach(function(Constructor) {\n if (Constructor.prototype.getAll) return;\n Constructor.prototype.getAll = function(query, count) {\n var instance = this;\n var items = [];\n\n return new Promise(function(resolve) {\n instance.iterateCursor(query, function(cursor) {\n if (!cursor) {\n resolve(items);\n return;\n }\n items.push(cursor.value);\n\n if (count !== undefined && items.length == count) {\n resolve(items);\n return;\n }\n cursor.continue();\n });\n });\n };\n});\n\nexport function openDb(name, version, upgradeCallback) {\n var p = promisifyRequestCall(indexedDB, 'open', [name, version]);\n var request = p.request;\n\n if (request) {\n request.onupgradeneeded = function(event) {\n if (upgradeCallback) {\n upgradeCallback(new UpgradeDB(request.result, event.oldVersion, request.transaction));\n }\n };\n }\n\n return p.then(function(db) {\n return new DB(db);\n });\n}\n\nexport function deleteDb(name) {\n return promisifyRequestCall(indexedDB, 'deleteDatabase', [name]);\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { version } from '../../package.json';\n\nexport const PENDING_TIMEOUT_MS = 10000;\n\nexport const PACKAGE_VERSION = `w:${version}`;\nexport const INTERNAL_AUTH_VERSION = 'FIS_v2';\n\nexport const INSTALLATIONS_API_URL =\n 'https://firebaseinstallations.googleapis.com/v1';\n\nexport const TOKEN_EXPIRATION_BUFFER = 60 * 60 * 1000; // One hour\n\nexport const SERVICE = 'installations';\nexport const SERVICE_NAME = 'Installations';\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ErrorFactory, FirebaseError } from '@firebase/util';\nimport { SERVICE, SERVICE_NAME } from './constants';\n\nexport const enum ErrorCode {\n MISSING_APP_CONFIG_VALUES = 'missing-app-config-values',\n NOT_REGISTERED = 'not-registered',\n INSTALLATION_NOT_FOUND = 'installation-not-found',\n REQUEST_FAILED = 'request-failed',\n APP_OFFLINE = 'app-offline',\n DELETE_PENDING_REGISTRATION = 'delete-pending-registration'\n}\n\nconst ERROR_DESCRIPTION_MAP: { readonly [key in ErrorCode]: string } = {\n [ErrorCode.MISSING_APP_CONFIG_VALUES]:\n 'Missing App configuration value: \"{$valueName}\"',\n [ErrorCode.NOT_REGISTERED]: 'Firebase Installation is not registered.',\n [ErrorCode.INSTALLATION_NOT_FOUND]: 'Firebase Installation not found.',\n [ErrorCode.REQUEST_FAILED]:\n '{$requestName} request failed with error \"{$serverCode} {$serverStatus}: {$serverMessage}\"',\n [ErrorCode.APP_OFFLINE]: 'Could not process request. Application offline.',\n [ErrorCode.DELETE_PENDING_REGISTRATION]:\n \"Can't delete installation while there is a pending registration request.\"\n};\n\ninterface ErrorParams {\n [ErrorCode.MISSING_APP_CONFIG_VALUES]: {\n valueName: string;\n };\n [ErrorCode.REQUEST_FAILED]: {\n requestName: string;\n [index: string]: string | number; // to make Typescript 3.8 happy\n } & ServerErrorData;\n}\n\nexport const ERROR_FACTORY = new ErrorFactory(\n SERVICE,\n SERVICE_NAME,\n ERROR_DESCRIPTION_MAP\n);\n\nexport interface ServerErrorData {\n serverCode: number;\n serverMessage: string;\n serverStatus: string;\n}\n\nexport type ServerError = FirebaseError & ServerErrorData;\n\n/** Returns true if error is a FirebaseError that is based on an error from the server. */\nexport function isServerError(error: unknown): error is ServerError {\n return (\n error instanceof FirebaseError &&\n error.code.includes(ErrorCode.REQUEST_FAILED)\n );\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { FirebaseError } from '@firebase/util';\nimport { GenerateAuthTokenResponse } from '../interfaces/api-response';\nimport { AppConfig } from '../interfaces/app-config';\nimport {\n CompletedAuthToken,\n RegisteredInstallationEntry,\n RequestStatus\n} from '../interfaces/installation-entry';\nimport {\n INSTALLATIONS_API_URL,\n INTERNAL_AUTH_VERSION\n} from '../util/constants';\nimport { ERROR_FACTORY, ErrorCode } from '../util/errors';\n\nexport function getInstallationsEndpoint({ projectId }: AppConfig): string {\n return `${INSTALLATIONS_API_URL}/projects/${projectId}/installations`;\n}\n\nexport function extractAuthTokenInfoFromResponse(\n response: GenerateAuthTokenResponse\n): CompletedAuthToken {\n return {\n token: response.token,\n requestStatus: RequestStatus.COMPLETED,\n expiresIn: getExpiresInFromResponseExpiresIn(response.expiresIn),\n creationTime: Date.now()\n };\n}\n\nexport async function getErrorFromResponse(\n requestName: string,\n response: Response\n): Promise {\n const responseJson: ErrorResponse = await response.json();\n const errorData = responseJson.error;\n return ERROR_FACTORY.create(ErrorCode.REQUEST_FAILED, {\n requestName,\n serverCode: errorData.code,\n serverMessage: errorData.message,\n serverStatus: errorData.status\n });\n}\n\nexport function getHeaders({ apiKey }: AppConfig): Headers {\n return new Headers({\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n 'x-goog-api-key': apiKey\n });\n}\n\nexport function getHeadersWithAuth(\n appConfig: AppConfig,\n { refreshToken }: RegisteredInstallationEntry\n): Headers {\n const headers = getHeaders(appConfig);\n headers.append('Authorization', getAuthorizationHeader(refreshToken));\n return headers;\n}\n\nexport interface ErrorResponse {\n error: {\n code: number;\n message: string;\n status: string;\n };\n}\n\n/**\n * Calls the passed in fetch wrapper and returns the response.\n * If the returned response has a status of 5xx, re-runs the function once and\n * returns the response.\n */\nexport async function retryIfServerError(\n fn: () => Promise\n): Promise {\n const result = await fn();\n\n if (result.status >= 500 && result.status < 600) {\n // Internal Server Error. Retry request.\n return fn();\n }\n\n return result;\n}\n\nfunction getExpiresInFromResponseExpiresIn(responseExpiresIn: string): number {\n // This works because the server will never respond with fractions of a second.\n return Number(responseExpiresIn.replace('s', '000'));\n}\n\nfunction getAuthorizationHeader(refreshToken: string): string {\n return `${INTERNAL_AUTH_VERSION} ${refreshToken}`;\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/** Returns a promise that resolves after given time passes. */\nexport function sleep(ms: number): Promise {\n return new Promise(resolve => {\n setTimeout(resolve, ms);\n });\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport function bufferToBase64UrlSafe(array: Uint8Array): string {\n const b64 = btoa(String.fromCharCode(...array));\n return b64.replace(/\\+/g, '-').replace(/\\//g, '_');\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { bufferToBase64UrlSafe } from './buffer-to-base64-url-safe';\n\nexport const VALID_FID_PATTERN = /^[cdef][\\w-]{21}$/;\nexport const INVALID_FID = '';\n\n/**\n * Generates a new FID using random values from Web Crypto API.\n * Returns an empty string if FID generation fails for any reason.\n */\nexport function generateFid(): string {\n try {\n // A valid FID has exactly 22 base64 characters, which is 132 bits, or 16.5\n // bytes. our implementation generates a 17 byte array instead.\n const fidByteArray = new Uint8Array(17);\n const crypto =\n self.crypto || ((self as unknown) as { msCrypto: Crypto }).msCrypto;\n crypto.getRandomValues(fidByteArray);\n\n // Replace the first 4 random bits with the constant FID header of 0b0111.\n fidByteArray[0] = 0b01110000 + (fidByteArray[0] % 0b00010000);\n\n const fid = encode(fidByteArray);\n\n return VALID_FID_PATTERN.test(fid) ? fid : INVALID_FID;\n } catch {\n // FID generation errored\n return INVALID_FID;\n }\n}\n\n/** Converts a FID Uint8Array to a base64 string representation. */\nfunction encode(fidByteArray: Uint8Array): string {\n const b64String = bufferToBase64UrlSafe(fidByteArray);\n\n // Remove the 23rd character that was added because of the extra 4 bits at the\n // end of our 17 byte array, and the '=' padding.\n return b64String.substr(0, 22);\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { AppConfig } from '../interfaces/app-config';\n\n/** Returns a string key that can be used to identify the app. */\nexport function getKey(appConfig: AppConfig): string {\n return `${appConfig.appName}!${appConfig.appId}`;\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { getKey } from '../util/get-key';\nimport { AppConfig } from '../interfaces/app-config';\nimport { IdChangeCallbackFn } from '../functions';\n\nconst fidChangeCallbacks: Map> = new Map();\n\n/**\n * Calls the onIdChange callbacks with the new FID value, and broadcasts the\n * change to other tabs.\n */\nexport function fidChanged(appConfig: AppConfig, fid: string): void {\n const key = getKey(appConfig);\n\n callFidChangeCallbacks(key, fid);\n broadcastFidChange(key, fid);\n}\n\nexport function addCallback(\n appConfig: AppConfig,\n callback: IdChangeCallbackFn\n): void {\n // Open the broadcast channel if it's not already open,\n // to be able to listen to change events from other tabs.\n getBroadcastChannel();\n\n const key = getKey(appConfig);\n\n let callbackSet = fidChangeCallbacks.get(key);\n if (!callbackSet) {\n callbackSet = new Set();\n fidChangeCallbacks.set(key, callbackSet);\n }\n callbackSet.add(callback);\n}\n\nexport function removeCallback(\n appConfig: AppConfig,\n callback: IdChangeCallbackFn\n): void {\n const key = getKey(appConfig);\n\n const callbackSet = fidChangeCallbacks.get(key);\n\n if (!callbackSet) {\n return;\n }\n\n callbackSet.delete(callback);\n if (callbackSet.size === 0) {\n fidChangeCallbacks.delete(key);\n }\n\n // Close broadcast channel if there are no more callbacks.\n closeBroadcastChannel();\n}\n\nfunction callFidChangeCallbacks(key: string, fid: string): void {\n const callbacks = fidChangeCallbacks.get(key);\n if (!callbacks) {\n return;\n }\n\n for (const callback of callbacks) {\n callback(fid);\n }\n}\n\nfunction broadcastFidChange(key: string, fid: string): void {\n const channel = getBroadcastChannel();\n if (channel) {\n channel.postMessage({ key, fid });\n }\n closeBroadcastChannel();\n}\n\nlet broadcastChannel: BroadcastChannel | null = null;\n/** Opens and returns a BroadcastChannel if it is supported by the browser. */\nfunction getBroadcastChannel(): BroadcastChannel | null {\n if (!broadcastChannel && 'BroadcastChannel' in self) {\n broadcastChannel = new BroadcastChannel('[Firebase] FID Change');\n broadcastChannel.onmessage = e => {\n callFidChangeCallbacks(e.data.key, e.data.fid);\n };\n }\n return broadcastChannel;\n}\n\nfunction closeBroadcastChannel(): void {\n if (fidChangeCallbacks.size === 0 && broadcastChannel) {\n broadcastChannel.close();\n broadcastChannel = null;\n }\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { DB, openDb } from 'idb';\nimport { AppConfig } from '../interfaces/app-config';\nimport { InstallationEntry } from '../interfaces/installation-entry';\nimport { getKey } from '../util/get-key';\nimport { fidChanged } from './fid-changed';\n\nconst DATABASE_NAME = 'firebase-installations-database';\nconst DATABASE_VERSION = 1;\nconst OBJECT_STORE_NAME = 'firebase-installations-store';\n\nlet dbPromise: Promise | null = null;\nfunction getDbPromise(): Promise {\n if (!dbPromise) {\n dbPromise = openDb(DATABASE_NAME, DATABASE_VERSION, upgradeDB => {\n // We don't use 'break' in this switch statement, the fall-through\n // behavior is what we want, because if there are multiple versions between\n // the old version and the current version, we want ALL the migrations\n // that correspond to those versions to run, not only the last one.\n // eslint-disable-next-line default-case\n switch (upgradeDB.oldVersion) {\n case 0:\n upgradeDB.createObjectStore(OBJECT_STORE_NAME);\n }\n });\n }\n return dbPromise;\n}\n\n/** Gets record(s) from the objectStore that match the given key. */\nexport async function get(\n appConfig: AppConfig\n): Promise {\n const key = getKey(appConfig);\n const db = await getDbPromise();\n return db\n .transaction(OBJECT_STORE_NAME)\n .objectStore(OBJECT_STORE_NAME)\n .get(key);\n}\n\n/** Assigns or overwrites the record for the given key with the given value. */\nexport async function set(\n appConfig: AppConfig,\n value: ValueType\n): Promise {\n const key = getKey(appConfig);\n const db = await getDbPromise();\n const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');\n const objectStore = tx.objectStore(OBJECT_STORE_NAME);\n const oldValue = await objectStore.get(key);\n await objectStore.put(value, key);\n await tx.complete;\n\n if (!oldValue || oldValue.fid !== value.fid) {\n fidChanged(appConfig, value.fid);\n }\n\n return value;\n}\n\n/** Removes record(s) from the objectStore that match the given key. */\nexport async function remove(appConfig: AppConfig): Promise {\n const key = getKey(appConfig);\n const db = await getDbPromise();\n const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');\n await tx.objectStore(OBJECT_STORE_NAME).delete(key);\n await tx.complete;\n}\n\n/**\n * Atomically updates a record with the result of updateFn, which gets\n * called with the current value. If newValue is undefined, the record is\n * deleted instead.\n * @return Updated value\n */\nexport async function update(\n appConfig: AppConfig,\n updateFn: (previousValue: InstallationEntry | undefined) => ValueType\n): Promise {\n const key = getKey(appConfig);\n const db = await getDbPromise();\n const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');\n const store = tx.objectStore(OBJECT_STORE_NAME);\n const oldValue: InstallationEntry | undefined = await store.get(key);\n const newValue = updateFn(oldValue);\n\n if (newValue === undefined) {\n await store.delete(key);\n } else {\n await store.put(newValue, key);\n }\n await tx.complete;\n\n if (newValue && (!oldValue || oldValue.fid !== newValue.fid)) {\n fidChanged(appConfig, newValue.fid);\n }\n\n return newValue;\n}\n\nexport async function clear(): Promise {\n const db = await getDbPromise();\n const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');\n await tx.objectStore(OBJECT_STORE_NAME).clear();\n await tx.complete;\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport firebase from '@firebase/app';\nimport {\n _FirebaseNamespace,\n FirebaseService\n} from '@firebase/app-types/private';\nimport { Component, ComponentType } from '@firebase/component';\nimport { FirebaseInstallations } from '@firebase/installations-types';\nimport {\n deleteInstallation,\n getId,\n getToken,\n IdChangeCallbackFn,\n IdChangeUnsubscribeFn,\n onIdChange\n} from './functions';\nimport { extractAppConfig } from './helpers/extract-app-config';\nimport { FirebaseDependencies } from './interfaces/firebase-dependencies';\n\nimport { name, version } from '../package.json';\n\nexport function registerInstallations(instance: _FirebaseNamespace): void {\n const installationsName = 'installations';\n\n instance.INTERNAL.registerComponent(\n new Component(\n installationsName,\n container => {\n const app = container.getProvider('app').getImmediate();\n\n // Throws if app isn't configured properly.\n const appConfig = extractAppConfig(app);\n const platformLoggerProvider = container.getProvider('platform-logger');\n const dependencies: FirebaseDependencies = {\n appConfig,\n platformLoggerProvider\n };\n\n const installations: FirebaseInstallations & FirebaseService = {\n app,\n getId: () => getId(dependencies),\n getToken: (forceRefresh?: boolean) =>\n getToken(dependencies, forceRefresh),\n delete: () => deleteInstallation(dependencies),\n onIdChange: (callback: IdChangeCallbackFn): IdChangeUnsubscribeFn =>\n onIdChange(dependencies, callback)\n };\n return installations;\n },\n ComponentType.PUBLIC\n )\n );\n\n instance.registerVersion(name, version);\n}\n\nregisterInstallations(firebase as _FirebaseNamespace);\n\n/**\n * Define extension behavior of `registerInstallations`\n */\ndeclare module '@firebase/app-types' {\n interface FirebaseNamespace {\n installations(app?: FirebaseApp): FirebaseInstallations;\n }\n interface FirebaseApp {\n installations(): FirebaseInstallations;\n }\n}\n","/**\n * @license\n * Copyright 2017 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport type LogLevelString =\n | 'debug'\n | 'verbose'\n | 'info'\n | 'warn'\n | 'error'\n | 'silent';\n\nexport interface LogOptions {\n level: LogLevelString;\n}\n\nexport type LogCallback = (callbackParams: LogCallbackParams) => void;\n\nexport interface LogCallbackParams {\n level: LogLevelString;\n message: string;\n args: unknown[];\n type: string;\n}\n\n/**\n * A container for all of the Logger instances\n */\nexport const instances: Logger[] = [];\n\n/**\n * The JS SDK supports 5 log levels and also allows a user the ability to\n * silence the logs altogether.\n *\n * The order is a follows:\n * DEBUG < VERBOSE < INFO < WARN < ERROR\n *\n * All of the log types above the current log level will be captured (i.e. if\n * you set the log level to `INFO`, errors will still be logged, but `DEBUG` and\n * `VERBOSE` logs will not)\n */\nexport enum LogLevel {\n DEBUG,\n VERBOSE,\n INFO,\n WARN,\n ERROR,\n SILENT\n}\n\nconst levelStringToEnum: { [key in LogLevelString]: LogLevel } = {\n 'debug': LogLevel.DEBUG,\n 'verbose': LogLevel.VERBOSE,\n 'info': LogLevel.INFO,\n 'warn': LogLevel.WARN,\n 'error': LogLevel.ERROR,\n 'silent': LogLevel.SILENT\n};\n\n/**\n * The default log level\n */\nconst defaultLogLevel: LogLevel = LogLevel.INFO;\n\n/**\n * We allow users the ability to pass their own log handler. We will pass the\n * type of log, the current log level, and any other arguments passed (i.e. the\n * messages that the user wants to log) to this function.\n */\nexport type LogHandler = (\n loggerInstance: Logger,\n logType: LogLevel,\n ...args: unknown[]\n) => void;\n\n/**\n * By default, `console.debug` is not displayed in the developer console (in\n * chrome). To avoid forcing users to have to opt-in to these logs twice\n * (i.e. once for firebase, and once in the console), we are sending `DEBUG`\n * logs to the `console.log` function.\n */\nconst ConsoleMethod = {\n [LogLevel.DEBUG]: 'log',\n [LogLevel.VERBOSE]: 'log',\n [LogLevel.INFO]: 'info',\n [LogLevel.WARN]: 'warn',\n [LogLevel.ERROR]: 'error'\n};\n\n/**\n * The default log handler will forward DEBUG, VERBOSE, INFO, WARN, and ERROR\n * messages on to their corresponding console counterparts (if the log method\n * is supported by the current log level)\n */\nconst defaultLogHandler: LogHandler = (instance, logType, ...args): void => {\n if (logType < instance.logLevel) {\n return;\n }\n const now = new Date().toISOString();\n const method = ConsoleMethod[logType as keyof typeof ConsoleMethod];\n if (method) {\n console[method as 'log' | 'info' | 'warn' | 'error'](\n `[${now}] ${instance.name}:`,\n ...args\n );\n } else {\n throw new Error(\n `Attempted to log a message with an invalid logType (value: ${logType})`\n );\n }\n};\n\nexport class Logger {\n /**\n * Gives you an instance of a Logger to capture messages according to\n * Firebase's logging scheme.\n *\n * @param name The name that the logs will be associated with\n */\n constructor(public name: string) {\n /**\n * Capture the current instance for later use\n */\n instances.push(this);\n }\n\n /**\n * The log level of the given Logger instance.\n */\n private _logLevel = defaultLogLevel;\n\n get logLevel(): LogLevel {\n return this._logLevel;\n }\n\n set logLevel(val: LogLevel) {\n if (!(val in LogLevel)) {\n throw new TypeError(`Invalid value \"${val}\" assigned to \\`logLevel\\``);\n }\n this._logLevel = val;\n }\n\n // Workaround for setter/getter having to be the same type.\n setLogLevel(val: LogLevel | LogLevelString): void {\n this._logLevel = typeof val === 'string' ? levelStringToEnum[val] : val;\n }\n\n /**\n * The main (internal) log handler for the Logger instance.\n * Can be set to a new function in internal package code but not by user.\n */\n private _logHandler: LogHandler = defaultLogHandler;\n get logHandler(): LogHandler {\n return this._logHandler;\n }\n set logHandler(val: LogHandler) {\n if (typeof val !== 'function') {\n throw new TypeError('Value assigned to `logHandler` must be a function');\n }\n this._logHandler = val;\n }\n\n /**\n * The optional, additional, user-defined log handler for the Logger instance.\n */\n private _userLogHandler: LogHandler | null = null;\n get userLogHandler(): LogHandler | null {\n return this._userLogHandler;\n }\n set userLogHandler(val: LogHandler | null) {\n this._userLogHandler = val;\n }\n\n /**\n * The functions below are all based on the `console` interface\n */\n\n debug(...args: unknown[]): void {\n this._userLogHandler && this._userLogHandler(this, LogLevel.DEBUG, ...args);\n this._logHandler(this, LogLevel.DEBUG, ...args);\n }\n log(...args: unknown[]): void {\n this._userLogHandler &&\n this._userLogHandler(this, LogLevel.VERBOSE, ...args);\n this._logHandler(this, LogLevel.VERBOSE, ...args);\n }\n info(...args: unknown[]): void {\n this._userLogHandler && this._userLogHandler(this, LogLevel.INFO, ...args);\n this._logHandler(this, LogLevel.INFO, ...args);\n }\n warn(...args: unknown[]): void {\n this._userLogHandler && this._userLogHandler(this, LogLevel.WARN, ...args);\n this._logHandler(this, LogLevel.WARN, ...args);\n }\n error(...args: unknown[]): void {\n this._userLogHandler && this._userLogHandler(this, LogLevel.ERROR, ...args);\n this._logHandler(this, LogLevel.ERROR, ...args);\n }\n}\n\nexport function setLogLevel(level: LogLevelString | LogLevel): void {\n instances.forEach(inst => {\n inst.setLogLevel(level);\n });\n}\n\nexport function setUserLogHandler(\n logCallback: LogCallback | null,\n options?: LogOptions\n): void {\n for (const instance of instances) {\n let customLogLevel: LogLevel | null = null;\n if (options && options.level) {\n customLogLevel = levelStringToEnum[options.level];\n }\n if (logCallback === null) {\n instance.userLogHandler = null;\n } else {\n instance.userLogHandler = (\n instance: Logger,\n level: LogLevel,\n ...args: unknown[]\n ) => {\n const message = args\n .map(arg => {\n if (arg == null) {\n return null;\n } else if (typeof arg === 'string') {\n return arg;\n } else if (typeof arg === 'number' || typeof arg === 'boolean') {\n return arg.toString();\n } else if (arg instanceof Error) {\n return arg.message;\n } else {\n try {\n return JSON.stringify(arg);\n } catch (ignored) {\n return null;\n }\n }\n })\n .filter(arg => arg)\n .join(' ');\n if (level >= (customLogLevel ?? instance.logLevel)) {\n logCallback({\n level: LogLevel[level].toLowerCase() as LogLevelString,\n message,\n args,\n type: instance.name\n });\n }\n };\n }\n }\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { createInstallationRequest } from '../api/create-installation-request';\nimport { AppConfig } from '../interfaces/app-config';\nimport {\n InProgressInstallationEntry,\n InstallationEntry,\n RegisteredInstallationEntry,\n RequestStatus\n} from '../interfaces/installation-entry';\nimport { PENDING_TIMEOUT_MS } from '../util/constants';\nimport { ERROR_FACTORY, ErrorCode, isServerError } from '../util/errors';\nimport { sleep } from '../util/sleep';\nimport { generateFid, INVALID_FID } from './generate-fid';\nimport { remove, set, update } from './idb-manager';\n\nexport interface InstallationEntryWithRegistrationPromise {\n installationEntry: InstallationEntry;\n /** Exist iff the installationEntry is not registered. */\n registrationPromise?: Promise;\n}\n\n/**\n * Updates and returns the InstallationEntry from the database.\n * Also triggers a registration request if it is necessary and possible.\n */\nexport async function getInstallationEntry(\n appConfig: AppConfig\n): Promise {\n let registrationPromise: Promise | undefined;\n\n const installationEntry = await update(appConfig, oldEntry => {\n const installationEntry = updateOrCreateInstallationEntry(oldEntry);\n const entryWithPromise = triggerRegistrationIfNecessary(\n appConfig,\n installationEntry\n );\n registrationPromise = entryWithPromise.registrationPromise;\n return entryWithPromise.installationEntry;\n });\n\n if (installationEntry.fid === INVALID_FID) {\n // FID generation failed. Waiting for the FID from the server.\n return { installationEntry: await registrationPromise! };\n }\n\n return {\n installationEntry,\n registrationPromise\n };\n}\n\n/**\n * Creates a new Installation Entry if one does not exist.\n * Also clears timed out pending requests.\n */\nfunction updateOrCreateInstallationEntry(\n oldEntry: InstallationEntry | undefined\n): InstallationEntry {\n const entry: InstallationEntry = oldEntry || {\n fid: generateFid(),\n registrationStatus: RequestStatus.NOT_STARTED\n };\n\n return clearTimedOutRequest(entry);\n}\n\n/**\n * If the Firebase Installation is not registered yet, this will trigger the\n * registration and return an InProgressInstallationEntry.\n *\n * If registrationPromise does not exist, the installationEntry is guaranteed\n * to be registered.\n */\nfunction triggerRegistrationIfNecessary(\n appConfig: AppConfig,\n installationEntry: InstallationEntry\n): InstallationEntryWithRegistrationPromise {\n if (installationEntry.registrationStatus === RequestStatus.NOT_STARTED) {\n if (!navigator.onLine) {\n // Registration required but app is offline.\n const registrationPromiseWithError = Promise.reject(\n ERROR_FACTORY.create(ErrorCode.APP_OFFLINE)\n );\n return {\n installationEntry,\n registrationPromise: registrationPromiseWithError\n };\n }\n\n // Try registering. Change status to IN_PROGRESS.\n const inProgressEntry: InProgressInstallationEntry = {\n fid: installationEntry.fid,\n registrationStatus: RequestStatus.IN_PROGRESS,\n registrationTime: Date.now()\n };\n const registrationPromise = registerInstallation(\n appConfig,\n inProgressEntry\n );\n return { installationEntry: inProgressEntry, registrationPromise };\n } else if (\n installationEntry.registrationStatus === RequestStatus.IN_PROGRESS\n ) {\n return {\n installationEntry,\n registrationPromise: waitUntilFidRegistration(appConfig)\n };\n } else {\n return { installationEntry };\n }\n}\n\n/** This will be executed only once for each new Firebase Installation. */\nasync function registerInstallation(\n appConfig: AppConfig,\n installationEntry: InProgressInstallationEntry\n): Promise {\n try {\n const registeredInstallationEntry = await createInstallationRequest(\n appConfig,\n installationEntry\n );\n return set(appConfig, registeredInstallationEntry);\n } catch (e) {\n if (isServerError(e) && e.serverCode === 409) {\n // Server returned a \"FID can not be used\" error.\n // Generate a new ID next time.\n await remove(appConfig);\n } else {\n // Registration failed. Set FID as not registered.\n await set(appConfig, {\n fid: installationEntry.fid,\n registrationStatus: RequestStatus.NOT_STARTED\n });\n }\n throw e;\n }\n}\n\n/** Call if FID registration is pending in another request. */\nasync function waitUntilFidRegistration(\n appConfig: AppConfig\n): Promise {\n // Unfortunately, there is no way of reliably observing when a value in\n // IndexedDB changes (yet, see https://github.com/WICG/indexed-db-observers),\n // so we need to poll.\n\n let entry: InstallationEntry = await updateInstallationRequest(appConfig);\n while (entry.registrationStatus === RequestStatus.IN_PROGRESS) {\n // createInstallation request still in progress.\n await sleep(100);\n\n entry = await updateInstallationRequest(appConfig);\n }\n\n if (entry.registrationStatus === RequestStatus.NOT_STARTED) {\n // The request timed out or failed in a different call. Try again.\n const {\n installationEntry,\n registrationPromise\n } = await getInstallationEntry(appConfig);\n\n if (registrationPromise) {\n return registrationPromise;\n } else {\n // if there is no registrationPromise, entry is registered.\n return installationEntry as RegisteredInstallationEntry;\n }\n }\n\n return entry;\n}\n\n/**\n * Called only if there is a CreateInstallation request in progress.\n *\n * Updates the InstallationEntry in the DB based on the status of the\n * CreateInstallation request.\n *\n * Returns the updated InstallationEntry.\n */\nfunction updateInstallationRequest(\n appConfig: AppConfig\n): Promise {\n return update(appConfig, oldEntry => {\n if (!oldEntry) {\n throw ERROR_FACTORY.create(ErrorCode.INSTALLATION_NOT_FOUND);\n }\n return clearTimedOutRequest(oldEntry);\n });\n}\n\nfunction clearTimedOutRequest(entry: InstallationEntry): InstallationEntry {\n if (hasInstallationRequestTimedOut(entry)) {\n return {\n fid: entry.fid,\n registrationStatus: RequestStatus.NOT_STARTED\n };\n }\n\n return entry;\n}\n\nfunction hasInstallationRequestTimedOut(\n installationEntry: InstallationEntry\n): boolean {\n return (\n installationEntry.registrationStatus === RequestStatus.IN_PROGRESS &&\n installationEntry.registrationTime + PENDING_TIMEOUT_MS < Date.now()\n );\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { CreateInstallationResponse } from '../interfaces/api-response';\nimport { AppConfig } from '../interfaces/app-config';\nimport {\n InProgressInstallationEntry,\n RegisteredInstallationEntry,\n RequestStatus\n} from '../interfaces/installation-entry';\nimport { INTERNAL_AUTH_VERSION, PACKAGE_VERSION } from '../util/constants';\nimport {\n extractAuthTokenInfoFromResponse,\n getErrorFromResponse,\n getHeaders,\n getInstallationsEndpoint,\n retryIfServerError\n} from './common';\n\nexport async function createInstallationRequest(\n appConfig: AppConfig,\n { fid }: InProgressInstallationEntry\n): Promise {\n const endpoint = getInstallationsEndpoint(appConfig);\n\n const headers = getHeaders(appConfig);\n const body = {\n fid,\n authVersion: INTERNAL_AUTH_VERSION,\n appId: appConfig.appId,\n sdkVersion: PACKAGE_VERSION\n };\n\n const request: RequestInit = {\n method: 'POST',\n headers,\n body: JSON.stringify(body)\n };\n\n const response = await retryIfServerError(() => fetch(endpoint, request));\n if (response.ok) {\n const responseValue: CreateInstallationResponse = await response.json();\n const registeredInstallationEntry: RegisteredInstallationEntry = {\n fid: responseValue.fid || fid,\n registrationStatus: RequestStatus.COMPLETED,\n refreshToken: responseValue.refreshToken,\n authToken: extractAuthTokenInfoFromResponse(responseValue.authToken)\n };\n return registeredInstallationEntry;\n } else {\n throw await getErrorFromResponse('Create Installation', response);\n }\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { GenerateAuthTokenResponse } from '../interfaces/api-response';\nimport { AppConfig } from '../interfaces/app-config';\nimport { FirebaseDependencies } from '../interfaces/firebase-dependencies';\nimport {\n CompletedAuthToken,\n RegisteredInstallationEntry\n} from '../interfaces/installation-entry';\nimport { PACKAGE_VERSION } from '../util/constants';\nimport {\n extractAuthTokenInfoFromResponse,\n getErrorFromResponse,\n getHeadersWithAuth,\n getInstallationsEndpoint,\n retryIfServerError\n} from './common';\n\nexport async function generateAuthTokenRequest(\n { appConfig, platformLoggerProvider }: FirebaseDependencies,\n installationEntry: RegisteredInstallationEntry\n): Promise {\n const endpoint = getGenerateAuthTokenEndpoint(appConfig, installationEntry);\n\n const headers = getHeadersWithAuth(appConfig, installationEntry);\n\n // If platform logger exists, add the platform info string to the header.\n const platformLogger = platformLoggerProvider.getImmediate({\n optional: true\n });\n if (platformLogger) {\n headers.append('x-firebase-client', platformLogger.getPlatformInfoString());\n }\n\n const body = {\n installation: {\n sdkVersion: PACKAGE_VERSION\n }\n };\n\n const request: RequestInit = {\n method: 'POST',\n headers,\n body: JSON.stringify(body)\n };\n\n const response = await retryIfServerError(() => fetch(endpoint, request));\n if (response.ok) {\n const responseValue: GenerateAuthTokenResponse = await response.json();\n const completedAuthToken: CompletedAuthToken = extractAuthTokenInfoFromResponse(\n responseValue\n );\n return completedAuthToken;\n } else {\n throw await getErrorFromResponse('Generate Auth Token', response);\n }\n}\n\nfunction getGenerateAuthTokenEndpoint(\n appConfig: AppConfig,\n { fid }: RegisteredInstallationEntry\n): string {\n return `${getInstallationsEndpoint(appConfig)}/${fid}/authTokens:generate`;\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { generateAuthTokenRequest } from '../api/generate-auth-token-request';\nimport { AppConfig } from '../interfaces/app-config';\nimport { FirebaseDependencies } from '../interfaces/firebase-dependencies';\nimport {\n AuthToken,\n CompletedAuthToken,\n InProgressAuthToken,\n InstallationEntry,\n RegisteredInstallationEntry,\n RequestStatus\n} from '../interfaces/installation-entry';\nimport { PENDING_TIMEOUT_MS, TOKEN_EXPIRATION_BUFFER } from '../util/constants';\nimport { ERROR_FACTORY, ErrorCode, isServerError } from '../util/errors';\nimport { sleep } from '../util/sleep';\nimport { remove, set, update } from './idb-manager';\n\n/**\n * Returns a valid authentication token for the installation. Generates a new\n * token if one doesn't exist, is expired or about to expire.\n *\n * Should only be called if the Firebase Installation is registered.\n */\nexport async function refreshAuthToken(\n dependencies: FirebaseDependencies,\n forceRefresh = false\n): Promise {\n let tokenPromise: Promise | undefined;\n const entry = await update(dependencies.appConfig, oldEntry => {\n if (!isEntryRegistered(oldEntry)) {\n throw ERROR_FACTORY.create(ErrorCode.NOT_REGISTERED);\n }\n\n const oldAuthToken = oldEntry.authToken;\n if (!forceRefresh && isAuthTokenValid(oldAuthToken)) {\n // There is a valid token in the DB.\n return oldEntry;\n } else if (oldAuthToken.requestStatus === RequestStatus.IN_PROGRESS) {\n // There already is a token request in progress.\n tokenPromise = waitUntilAuthTokenRequest(dependencies, forceRefresh);\n return oldEntry;\n } else {\n // No token or token expired.\n if (!navigator.onLine) {\n throw ERROR_FACTORY.create(ErrorCode.APP_OFFLINE);\n }\n\n const inProgressEntry = makeAuthTokenRequestInProgressEntry(oldEntry);\n tokenPromise = fetchAuthTokenFromServer(dependencies, inProgressEntry);\n return inProgressEntry;\n }\n });\n\n const authToken = tokenPromise\n ? await tokenPromise\n : (entry.authToken as CompletedAuthToken);\n return authToken;\n}\n\n/**\n * Call only if FID is registered and Auth Token request is in progress.\n *\n * Waits until the current pending request finishes. If the request times out,\n * tries once in this thread as well.\n */\nasync function waitUntilAuthTokenRequest(\n dependencies: FirebaseDependencies,\n forceRefresh: boolean\n): Promise {\n // Unfortunately, there is no way of reliably observing when a value in\n // IndexedDB changes (yet, see https://github.com/WICG/indexed-db-observers),\n // so we need to poll.\n\n let entry = await updateAuthTokenRequest(dependencies.appConfig);\n while (entry.authToken.requestStatus === RequestStatus.IN_PROGRESS) {\n // generateAuthToken still in progress.\n await sleep(100);\n\n entry = await updateAuthTokenRequest(dependencies.appConfig);\n }\n\n const authToken = entry.authToken;\n if (authToken.requestStatus === RequestStatus.NOT_STARTED) {\n // The request timed out or failed in a different call. Try again.\n return refreshAuthToken(dependencies, forceRefresh);\n } else {\n return authToken;\n }\n}\n\n/**\n * Called only if there is a GenerateAuthToken request in progress.\n *\n * Updates the InstallationEntry in the DB based on the status of the\n * GenerateAuthToken request.\n *\n * Returns the updated InstallationEntry.\n */\nfunction updateAuthTokenRequest(\n appConfig: AppConfig\n): Promise {\n return update(appConfig, oldEntry => {\n if (!isEntryRegistered(oldEntry)) {\n throw ERROR_FACTORY.create(ErrorCode.NOT_REGISTERED);\n }\n\n const oldAuthToken = oldEntry.authToken;\n if (hasAuthTokenRequestTimedOut(oldAuthToken)) {\n return {\n ...oldEntry,\n authToken: { requestStatus: RequestStatus.NOT_STARTED }\n };\n }\n\n return oldEntry;\n });\n}\n\nasync function fetchAuthTokenFromServer(\n dependencies: FirebaseDependencies,\n installationEntry: RegisteredInstallationEntry\n): Promise {\n try {\n const authToken = await generateAuthTokenRequest(\n dependencies,\n installationEntry\n );\n const updatedInstallationEntry: RegisteredInstallationEntry = {\n ...installationEntry,\n authToken\n };\n await set(dependencies.appConfig, updatedInstallationEntry);\n return authToken;\n } catch (e) {\n if (isServerError(e) && (e.serverCode === 401 || e.serverCode === 404)) {\n // Server returned a \"FID not found\" or a \"Invalid authentication\" error.\n // Generate a new ID next time.\n await remove(dependencies.appConfig);\n } else {\n const updatedInstallationEntry: RegisteredInstallationEntry = {\n ...installationEntry,\n authToken: { requestStatus: RequestStatus.NOT_STARTED }\n };\n await set(dependencies.appConfig, updatedInstallationEntry);\n }\n throw e;\n }\n}\n\nfunction isEntryRegistered(\n installationEntry: InstallationEntry | undefined\n): installationEntry is RegisteredInstallationEntry {\n return (\n installationEntry !== undefined &&\n installationEntry.registrationStatus === RequestStatus.COMPLETED\n );\n}\n\nfunction isAuthTokenValid(authToken: AuthToken): boolean {\n return (\n authToken.requestStatus === RequestStatus.COMPLETED &&\n !isAuthTokenExpired(authToken)\n );\n}\n\nfunction isAuthTokenExpired(authToken: CompletedAuthToken): boolean {\n const now = Date.now();\n return (\n now < authToken.creationTime ||\n authToken.creationTime + authToken.expiresIn < now + TOKEN_EXPIRATION_BUFFER\n );\n}\n\n/** Returns an updated InstallationEntry with an InProgressAuthToken. */\nfunction makeAuthTokenRequestInProgressEntry(\n oldEntry: RegisteredInstallationEntry\n): RegisteredInstallationEntry {\n const inProgressAuthToken: InProgressAuthToken = {\n requestStatus: RequestStatus.IN_PROGRESS,\n requestTime: Date.now()\n };\n return {\n ...oldEntry,\n authToken: inProgressAuthToken\n };\n}\n\nfunction hasAuthTokenRequestTimedOut(authToken: AuthToken): boolean {\n return (\n authToken.requestStatus === RequestStatus.IN_PROGRESS &&\n authToken.requestTime + PENDING_TIMEOUT_MS < Date.now()\n );\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { getInstallationEntry } from '../helpers/get-installation-entry';\nimport { refreshAuthToken } from '../helpers/refresh-auth-token';\nimport { AppConfig } from '../interfaces/app-config';\nimport { FirebaseDependencies } from '../interfaces/firebase-dependencies';\n\nexport async function getToken(\n dependencies: FirebaseDependencies,\n forceRefresh = false\n): Promise {\n await completeInstallationRegistration(dependencies.appConfig);\n\n // At this point we either have a Registered Installation in the DB, or we've\n // already thrown an error.\n const authToken = await refreshAuthToken(dependencies, forceRefresh);\n return authToken.token;\n}\n\nasync function completeInstallationRegistration(\n appConfig: AppConfig\n): Promise {\n const { registrationPromise } = await getInstallationEntry(appConfig);\n\n if (registrationPromise) {\n // A createInstallation request is in progress. Wait until it finishes.\n await registrationPromise;\n }\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { AppConfig } from '../interfaces/app-config';\nimport { RegisteredInstallationEntry } from '../interfaces/installation-entry';\nimport {\n getErrorFromResponse,\n getHeadersWithAuth,\n getInstallationsEndpoint,\n retryIfServerError\n} from './common';\n\nexport async function deleteInstallationRequest(\n appConfig: AppConfig,\n installationEntry: RegisteredInstallationEntry\n): Promise {\n const endpoint = getDeleteEndpoint(appConfig, installationEntry);\n\n const headers = getHeadersWithAuth(appConfig, installationEntry);\n const request: RequestInit = {\n method: 'DELETE',\n headers\n };\n\n const response = await retryIfServerError(() => fetch(endpoint, request));\n if (!response.ok) {\n throw await getErrorFromResponse('Delete Installation', response);\n }\n}\n\nfunction getDeleteEndpoint(\n appConfig: AppConfig,\n { fid }: RegisteredInstallationEntry\n): string {\n return `${getInstallationsEndpoint(appConfig)}/${fid}`;\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { addCallback, removeCallback } from '../helpers/fid-changed';\nimport { FirebaseDependencies } from '../interfaces/firebase-dependencies';\n\nexport type IdChangeCallbackFn = (installationId: string) => void;\nexport type IdChangeUnsubscribeFn = () => void;\n\n/**\n * Sets a new callback that will get called when Installation ID changes.\n * Returns an unsubscribe function that will remove the callback when called.\n */\nexport function onIdChange(\n { appConfig }: FirebaseDependencies,\n callback: IdChangeCallbackFn\n): IdChangeUnsubscribeFn {\n addCallback(appConfig, callback);\n\n return () => {\n removeCallback(appConfig, callback);\n };\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { FirebaseApp, FirebaseOptions } from '@firebase/app-types';\nimport { FirebaseError } from '@firebase/util';\nimport { AppConfig } from '../interfaces/app-config';\nimport { ERROR_FACTORY, ErrorCode } from '../util/errors';\n\nexport function extractAppConfig(app: FirebaseApp): AppConfig {\n if (!app || !app.options) {\n throw getMissingValueError('App Configuration');\n }\n\n if (!app.name) {\n throw getMissingValueError('App Name');\n }\n\n // Required app config keys\n const configKeys: Array = [\n 'projectId',\n 'apiKey',\n 'appId'\n ];\n\n for (const keyName of configKeys) {\n if (!app.options[keyName]) {\n throw getMissingValueError(keyName);\n }\n }\n\n return {\n appName: app.name,\n projectId: app.options.projectId!,\n apiKey: app.options.apiKey!,\n appId: app.options.appId!\n };\n}\n\nfunction getMissingValueError(valueName: string): FirebaseError {\n return ERROR_FACTORY.create(ErrorCode.MISSING_APP_CONFIG_VALUES, {\n valueName\n });\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { getInstallationEntry } from '../helpers/get-installation-entry';\nimport { refreshAuthToken } from '../helpers/refresh-auth-token';\nimport { FirebaseDependencies } from '../interfaces/firebase-dependencies';\n\nexport async function getId(\n dependencies: FirebaseDependencies\n): Promise {\n const { installationEntry, registrationPromise } = await getInstallationEntry(\n dependencies.appConfig\n );\n\n if (registrationPromise) {\n registrationPromise.catch(console.error);\n } else {\n // If the installation is already registered, update the authentication\n // token if needed.\n refreshAuthToken(dependencies).catch(console.error);\n }\n\n return installationEntry.fid;\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { deleteInstallationRequest } from '../api/delete-installation-request';\nimport { remove, update } from '../helpers/idb-manager';\nimport { FirebaseDependencies } from '../interfaces/firebase-dependencies';\nimport { RequestStatus } from '../interfaces/installation-entry';\nimport { ERROR_FACTORY, ErrorCode } from '../util/errors';\n\nexport async function deleteInstallation(\n dependencies: FirebaseDependencies\n): Promise {\n const { appConfig } = dependencies;\n\n const entry = await update(appConfig, oldEntry => {\n if (oldEntry && oldEntry.registrationStatus === RequestStatus.NOT_STARTED) {\n // Delete the unregistered entry without sending a deleteInstallation request.\n return undefined;\n }\n return oldEntry;\n });\n\n if (entry) {\n if (entry.registrationStatus === RequestStatus.IN_PROGRESS) {\n // Can't delete while trying to register.\n throw ERROR_FACTORY.create(ErrorCode.DELETE_PENDING_REGISTRATION);\n } else if (entry.registrationStatus === RequestStatus.COMPLETED) {\n if (!navigator.onLine) {\n throw ERROR_FACTORY.create(ErrorCode.APP_OFFLINE);\n } else {\n await deleteInstallationRequest(appConfig, entry);\n await remove(appConfig);\n }\n }\n }\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { StorageCache } from '../storage/storage_cache';\nimport {\n FetchResponse,\n RemoteConfigFetchClient,\n FetchRequest\n} from './remote_config_fetch_client';\nimport { Storage } from '../storage/storage';\nimport { Logger } from '@firebase/logger';\n\n/**\n * Implements the {@link RemoteConfigClient} abstraction with success response caching.\n *\n *

Comparable to the browser's Cache API for responses, but the Cache API requires a Service\n * Worker, which requires HTTPS, which would significantly complicate SDK installation. Also, the\n * Cache API doesn't support matching entries by time.\n */\nexport class CachingClient implements RemoteConfigFetchClient {\n constructor(\n private readonly client: RemoteConfigFetchClient,\n private readonly storage: Storage,\n private readonly storageCache: StorageCache,\n private readonly logger: Logger\n ) {}\n\n /**\n * Returns true if the age of the cached fetched configs is less than or equal to\n * {@link Settings#minimumFetchIntervalInSeconds}.\n *\n *

This is comparable to passing `headers = { 'Cache-Control': max-age }` to the\n * native Fetch API.\n *\n *

Visible for testing.\n */\n isCachedDataFresh(\n cacheMaxAgeMillis: number,\n lastSuccessfulFetchTimestampMillis: number | undefined\n ): boolean {\n // Cache can only be fresh if it's populated.\n if (!lastSuccessfulFetchTimestampMillis) {\n this.logger.debug('Config fetch cache check. Cache unpopulated.');\n return false;\n }\n\n // Calculates age of cache entry.\n const cacheAgeMillis = Date.now() - lastSuccessfulFetchTimestampMillis;\n\n const isCachedDataFresh = cacheAgeMillis <= cacheMaxAgeMillis;\n\n this.logger.debug(\n 'Config fetch cache check.' +\n ` Cache age millis: ${cacheAgeMillis}.` +\n ` Cache max age millis (minimumFetchIntervalMillis setting): ${cacheMaxAgeMillis}.` +\n ` Is cache hit: ${isCachedDataFresh}.`\n );\n\n return isCachedDataFresh;\n }\n\n async fetch(request: FetchRequest): Promise {\n // Reads from persisted storage to avoid cache miss if callers don't wait on initialization.\n const [\n lastSuccessfulFetchTimestampMillis,\n lastSuccessfulFetchResponse\n ] = await Promise.all([\n this.storage.getLastSuccessfulFetchTimestampMillis(),\n this.storage.getLastSuccessfulFetchResponse()\n ]);\n\n // Exits early on cache hit.\n if (\n lastSuccessfulFetchResponse &&\n this.isCachedDataFresh(\n request.cacheMaxAgeMillis,\n lastSuccessfulFetchTimestampMillis\n )\n ) {\n return lastSuccessfulFetchResponse;\n }\n\n // Deviates from pure decorator by not honoring a passed ETag since we don't have a public API\n // that allows the caller to pass an ETag.\n request.eTag =\n lastSuccessfulFetchResponse && lastSuccessfulFetchResponse.eTag;\n\n // Falls back to service on cache miss.\n const response = await this.client.fetch(request);\n\n // Fetch throws for non-success responses, so success is guaranteed here.\n\n const storageOperations = [\n // Uses write-through cache for consistency with synchronous public API.\n this.storageCache.setLastSuccessfulFetchTimestampMillis(Date.now())\n ];\n\n if (response.status === 200) {\n // Caches response only if it has changed, ie non-304 responses.\n storageOperations.push(\n this.storage.setLastSuccessfulFetchResponse(response)\n );\n }\n\n await Promise.all(storageOperations);\n\n return response;\n }\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ErrorFactory, FirebaseError } from '@firebase/util';\n\nexport const enum ErrorCode {\n REGISTRATION_WINDOW = 'registration-window',\n REGISTRATION_PROJECT_ID = 'registration-project-id',\n REGISTRATION_API_KEY = 'registration-api-key',\n REGISTRATION_APP_ID = 'registration-app-id',\n STORAGE_OPEN = 'storage-open',\n STORAGE_GET = 'storage-get',\n STORAGE_SET = 'storage-set',\n STORAGE_DELETE = 'storage-delete',\n FETCH_NETWORK = 'fetch-client-network',\n FETCH_TIMEOUT = 'fetch-timeout',\n FETCH_THROTTLE = 'fetch-throttle',\n FETCH_PARSE = 'fetch-client-parse',\n FETCH_STATUS = 'fetch-status'\n}\n\nconst ERROR_DESCRIPTION_MAP: { readonly [key in ErrorCode]: string } = {\n [ErrorCode.REGISTRATION_WINDOW]:\n 'Undefined window object. This SDK only supports usage in a browser environment.',\n [ErrorCode.REGISTRATION_PROJECT_ID]:\n 'Undefined project identifier. Check Firebase app initialization.',\n [ErrorCode.REGISTRATION_API_KEY]:\n 'Undefined API key. Check Firebase app initialization.',\n [ErrorCode.REGISTRATION_APP_ID]:\n 'Undefined app identifier. Check Firebase app initialization.',\n [ErrorCode.STORAGE_OPEN]:\n 'Error thrown when opening storage. Original error: {$originalErrorMessage}.',\n [ErrorCode.STORAGE_GET]:\n 'Error thrown when reading from storage. Original error: {$originalErrorMessage}.',\n [ErrorCode.STORAGE_SET]:\n 'Error thrown when writing to storage. Original error: {$originalErrorMessage}.',\n [ErrorCode.STORAGE_DELETE]:\n 'Error thrown when deleting from storage. Original error: {$originalErrorMessage}.',\n [ErrorCode.FETCH_NETWORK]:\n 'Fetch client failed to connect to a network. Check Internet connection.' +\n ' Original error: {$originalErrorMessage}.',\n [ErrorCode.FETCH_TIMEOUT]:\n 'The config fetch request timed out. ' +\n ' Configure timeout using \"fetchTimeoutMillis\" SDK setting.',\n [ErrorCode.FETCH_THROTTLE]:\n 'The config fetch request timed out while in an exponential backoff state.' +\n ' Configure timeout using \"fetchTimeoutMillis\" SDK setting.' +\n ' Unix timestamp in milliseconds when fetch request throttling ends: {$throttleEndTimeMillis}.',\n [ErrorCode.FETCH_PARSE]:\n 'Fetch client could not parse response.' +\n ' Original error: {$originalErrorMessage}.',\n [ErrorCode.FETCH_STATUS]:\n 'Fetch server returned an HTTP error status. HTTP status: {$httpStatus}.'\n};\n\n// Note this is effectively a type system binding a code to params. This approach overlaps with the\n// role of TS interfaces, but works well for a few reasons:\n// 1) JS is unaware of TS interfaces, eg we can't test for interface implementation in JS\n// 2) callers should have access to a human-readable summary of the error and this interpolates\n// params into an error message;\n// 3) callers should be able to programmatically access data associated with an error, which\n// ErrorData provides.\ninterface ErrorParams {\n [ErrorCode.STORAGE_OPEN]: { originalErrorMessage: string | undefined };\n [ErrorCode.STORAGE_GET]: { originalErrorMessage: string | undefined };\n [ErrorCode.STORAGE_SET]: { originalErrorMessage: string | undefined };\n [ErrorCode.STORAGE_DELETE]: { originalErrorMessage: string | undefined };\n [ErrorCode.FETCH_NETWORK]: { originalErrorMessage: string };\n [ErrorCode.FETCH_THROTTLE]: { throttleEndTimeMillis: number };\n [ErrorCode.FETCH_PARSE]: { originalErrorMessage: string };\n [ErrorCode.FETCH_STATUS]: { httpStatus: number };\n}\n\nexport const ERROR_FACTORY = new ErrorFactory(\n 'remoteconfig' /* service */,\n 'Remote Config' /* service name */,\n ERROR_DESCRIPTION_MAP\n);\n\n// Note how this is like typeof/instanceof, but for ErrorCode.\nexport function hasErrorCode(e: Error, errorCode: ErrorCode): boolean {\n return e instanceof FirebaseError && e.code.indexOf(errorCode) !== -1;\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { FirebaseInstallations } from '@firebase/installations-types';\nimport {\n FetchResponse,\n RemoteConfigFetchClient,\n FirebaseRemoteConfigObject,\n FetchRequest\n} from './remote_config_fetch_client';\nimport { ERROR_FACTORY, ErrorCode } from '../errors';\nimport { getUserLanguage } from '../language';\n\n/**\n * Defines request body parameters required to call the fetch API:\n * https://firebase.google.com/docs/reference/remote-config/rest\n *\n *

Not exported because this file encapsulates REST API specifics.\n *\n *

Not passing User Properties because Analytics' source of truth on Web is server-side.\n */\ninterface FetchRequestBody {\n // Disables camelcase linting for request body params.\n /* eslint-disable camelcase*/\n sdk_version: string;\n app_instance_id: string;\n app_instance_id_token: string;\n app_id: string;\n language_code: string;\n /* eslint-enable camelcase */\n}\n\n/**\n * Implements the Client abstraction for the Remote Config REST API.\n */\nexport class RestClient implements RemoteConfigFetchClient {\n constructor(\n private readonly firebaseInstallations: FirebaseInstallations,\n private readonly sdkVersion: string,\n private readonly namespace: string,\n private readonly projectId: string,\n private readonly apiKey: string,\n private readonly appId: string\n ) {}\n\n /**\n * Fetches from the Remote Config REST API.\n *\n * @throws a {@link ErrorCode.FETCH_NETWORK} error if {@link GlobalFetch#fetch} can't\n * connect to the network.\n * @throws a {@link ErrorCode.FETCH_PARSE} error if {@link Response#json} can't parse the\n * fetch response.\n * @throws a {@link ErrorCode.FETCH_STATUS} error if the service returns an HTTP error status.\n */\n async fetch(request: FetchRequest): Promise {\n const [installationId, installationToken] = await Promise.all([\n this.firebaseInstallations.getId(),\n this.firebaseInstallations.getToken()\n ]);\n\n const urlBase =\n window.FIREBASE_REMOTE_CONFIG_URL_BASE ||\n 'https://firebaseremoteconfig.googleapis.com';\n\n const url = `${urlBase}/v1/projects/${this.projectId}/namespaces/${this.namespace}:fetch?key=${this.apiKey}`;\n\n const headers = {\n 'Content-Type': 'application/json',\n 'Content-Encoding': 'gzip',\n // Deviates from pure decorator by not passing max-age header since we don't currently have\n // service behavior using that header.\n 'If-None-Match': request.eTag || '*'\n };\n\n const requestBody: FetchRequestBody = {\n /* eslint-disable camelcase */\n sdk_version: this.sdkVersion,\n app_instance_id: installationId,\n app_instance_id_token: installationToken,\n app_id: this.appId,\n language_code: getUserLanguage()\n /* eslint-enable camelcase */\n };\n\n const options = {\n method: 'POST',\n headers,\n body: JSON.stringify(requestBody)\n };\n\n // This logic isn't REST-specific, but shimming abort logic isn't worth another decorator.\n const fetchPromise = fetch(url, options);\n const timeoutPromise = new Promise((_resolve, reject) => {\n // Maps async event listener to Promise API.\n request.signal.addEventListener(() => {\n // Emulates https://heycam.github.io/webidl/#aborterror\n const error = new Error('The operation was aborted.');\n error.name = 'AbortError';\n reject(error);\n });\n });\n\n let response;\n try {\n await Promise.race([fetchPromise, timeoutPromise]);\n response = await fetchPromise;\n } catch (originalError) {\n let errorCode = ErrorCode.FETCH_NETWORK;\n if (originalError.name === 'AbortError') {\n errorCode = ErrorCode.FETCH_TIMEOUT;\n }\n throw ERROR_FACTORY.create(errorCode, {\n originalErrorMessage: originalError.message\n });\n }\n\n let status = response.status;\n\n // Normalizes nullable header to optional.\n const responseEtag = response.headers.get('ETag') || undefined;\n\n let config: FirebaseRemoteConfigObject | undefined;\n let state: string | undefined;\n\n // JSON parsing throws SyntaxError if the response body isn't a JSON string.\n // Requesting application/json and checking for a 200 ensures there's JSON data.\n if (response.status === 200) {\n let responseBody;\n try {\n responseBody = await response.json();\n } catch (originalError) {\n throw ERROR_FACTORY.create(ErrorCode.FETCH_PARSE, {\n originalErrorMessage: originalError.message\n });\n }\n config = responseBody['entries'];\n state = responseBody['state'];\n }\n\n // Normalizes based on legacy state.\n if (state === 'INSTANCE_STATE_UNSPECIFIED') {\n status = 500;\n } else if (state === 'NO_CHANGE') {\n status = 304;\n } else if (state === 'NO_TEMPLATE' || state === 'EMPTY_CONFIG') {\n // These cases can be fixed remotely, so normalize to safe value.\n config = {};\n }\n\n // Normalize to exception-based control flow for non-success cases.\n // Encapsulates HTTP specifics in this class as much as possible. Status is still the best for\n // differentiating success states (200 from 304; the state body param is undefined in a\n // standard 304).\n if (status !== 304 && status !== 200) {\n throw ERROR_FACTORY.create(ErrorCode.FETCH_STATUS, {\n httpStatus: status\n });\n }\n\n return { status, eTag: responseEtag, config };\n }\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Attempts to get the most accurate browser language setting.\n *\n *

Adapted from getUserLanguage in packages/auth/src/utils.js for TypeScript.\n *\n *

Defers default language specification to server logic for consistency.\n *\n * @param navigatorLanguage Enables tests to override read-only {@link NavigatorLanguage}.\n */\nexport function getUserLanguage(\n navigatorLanguage: NavigatorLanguage = navigator\n): string {\n return (\n // Most reliable, but only supported in Chrome/Firefox.\n (navigatorLanguage.languages && navigatorLanguage.languages[0]) ||\n // Supported in most browsers, but returns the language of the browser\n // UI, not the language set in browser settings.\n navigatorLanguage.language\n // Polyfill otherwise.\n );\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Defines a client, as in https://en.wikipedia.org/wiki/Client%E2%80%93server_model, for the\n * Remote Config server (https://firebase.google.com/docs/reference/remote-config/rest).\n *\n *

Abstracts throttle, response cache and network implementation details.\n *\n *

Modeled after the native {@link GlobalFetch} interface, which is relatively modern and\n * convenient, but simplified for Remote Config's use case.\n *\n * Disambiguation: {@link GlobalFetch} interface and the Remote Config service define \"fetch\"\n * methods. The RestClient uses the former to make HTTP calls. This interface abstracts the latter.\n */\nexport interface RemoteConfigFetchClient {\n /**\n * @throws if response status is not 200 or 304.\n */\n fetch(request: FetchRequest): Promise;\n}\n\n/**\n * Defines a self-descriptive reference for config key-value pairs.\n */\nexport interface FirebaseRemoteConfigObject {\n [key: string]: string;\n}\n\n/**\n * Shims a minimal AbortSignal.\n *\n *

AbortController's AbortSignal conveniently decouples fetch timeout logic from other aspects\n * of networking, such as retries. Firebase doesn't use AbortController enough to justify a\n * polyfill recommendation, like we do with the Fetch API, but this minimal shim can easily be\n * swapped out if/when we do.\n */\nexport class RemoteConfigAbortSignal {\n listeners: Array<() => void> = [];\n addEventListener(listener: () => void): void {\n this.listeners.push(listener);\n }\n abort(): void {\n this.listeners.forEach(listener => listener());\n }\n}\n\n/**\n * Defines per-request inputs for the Remote Config fetch request.\n *\n *

Modeled after the native {@link Request} interface, but simplified for Remote Config's\n * use case.\n */\nexport interface FetchRequest {\n /**\n * Uses cached config if it is younger than this age.\n *\n *

Required because it's defined by settings, which always have a value.\n *\n *

Comparable to passing `headers = { 'Cache-Control': max-age }` to the native\n * Fetch API.\n */\n cacheMaxAgeMillis: number;\n\n /**\n * An event bus for the signal to abort a request.\n *\n *

Required because all requests should be abortable.\n *\n *

Comparable to the native\n * Fetch API's \"signal\" field on its request configuration object\n * https://fetch.spec.whatwg.org/#dom-requestinit-signal.\n *\n *

Disambiguation: Remote Config commonly refers to API inputs as\n * \"signals\". See the private ConfigFetchRequestBody interface for those:\n * http://google3/firebase/remote_config/web/src/core/rest_client.ts?l=14&rcl=255515243.\n */\n signal: RemoteConfigAbortSignal;\n\n /**\n * The ETag header value from the last response.\n *\n *

Optional in case this is the first request.\n *\n *

Comparable to passing `headers = { 'If-None-Match': }` to the native Fetch API.\n */\n eTag?: string;\n}\n\n/**\n * Defines a successful response (200 or 304).\n *\n *

Modeled after the native {@link Response} interface, but simplified for Remote Config's\n * use case.\n */\nexport interface FetchResponse {\n /**\n * The HTTP status, which is useful for differentiating success responses with data from\n * those without.\n *\n *

{@link RemoteConfigClient} is modeled after the native {@link GlobalFetch} interface, so\n * HTTP status is first-class.\n *\n *

Disambiguation: the fetch response returns a legacy \"state\" value that is redundant with the\n * HTTP status code. The former is normalized into the latter.\n */\n status: number;\n\n /**\n * Defines the ETag response header value.\n *\n *

Only defined for 200 and 304 responses.\n */\n eTag?: string;\n\n /**\n * Defines the map of parameters returned as \"entries\" in the fetch response body.\n *\n *

Only defined for 200 responses.\n */\n config?: FirebaseRemoteConfigObject;\n\n // Note: we're not extracting experiment metadata until\n // ABT and Analytics have Web SDKs.\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Value as ValueType, ValueSource } from '@firebase/remote-config-types';\n\nconst DEFAULT_VALUE_FOR_BOOLEAN = false;\nconst DEFAULT_VALUE_FOR_STRING = '';\nconst DEFAULT_VALUE_FOR_NUMBER = 0;\n\nconst BOOLEAN_TRUTHY_VALUES = ['1', 'true', 't', 'yes', 'y', 'on'];\n\nexport class Value implements ValueType {\n constructor(\n private readonly _source: ValueSource,\n private readonly _value: string = DEFAULT_VALUE_FOR_STRING\n ) {}\n\n asString(): string {\n return this._value;\n }\n\n asBoolean(): boolean {\n if (this._source === 'static') {\n return DEFAULT_VALUE_FOR_BOOLEAN;\n }\n return BOOLEAN_TRUTHY_VALUES.indexOf(this._value.toLowerCase()) >= 0;\n }\n\n asNumber(): number {\n if (this._source === 'static') {\n return DEFAULT_VALUE_FOR_NUMBER;\n }\n let num = Number(this._value);\n if (isNaN(num)) {\n num = DEFAULT_VALUE_FOR_NUMBER;\n }\n return num;\n }\n\n getSource(): ValueSource {\n return this._source;\n }\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { FirebaseApp } from '@firebase/app-types';\nimport {\n RemoteConfig as RemoteConfigType,\n FetchStatus,\n Settings,\n Value as ValueType,\n LogLevel as RemoteConfigLogLevel\n} from '@firebase/remote-config-types';\nimport { StorageCache } from './storage/storage_cache';\nimport {\n RemoteConfigFetchClient,\n RemoteConfigAbortSignal\n} from './client/remote_config_fetch_client';\nimport { Value } from './value';\nimport { ErrorCode, hasErrorCode } from './errors';\nimport { Storage } from './storage/storage';\nimport { Logger, LogLevel as FirebaseLogLevel } from '@firebase/logger';\n\nconst DEFAULT_FETCH_TIMEOUT_MILLIS = 60 * 1000; // One minute\nconst DEFAULT_CACHE_MAX_AGE_MILLIS = 12 * 60 * 60 * 1000; // Twelve hours.\n\n/**\n * Encapsulates business logic mapping network and storage dependencies to the public SDK API.\n *\n * See {@link https://github.com/FirebasePrivate/firebase-js-sdk/blob/master/packages/firebase/index.d.ts|interface documentation} for method descriptions.\n */\nexport class RemoteConfig implements RemoteConfigType {\n // Tracks completion of initialization promise.\n private _isInitializationComplete = false;\n\n // De-duplicates initialization calls.\n private _initializePromise?: Promise;\n\n settings: Settings = {\n fetchTimeoutMillis: DEFAULT_FETCH_TIMEOUT_MILLIS,\n minimumFetchIntervalMillis: DEFAULT_CACHE_MAX_AGE_MILLIS\n };\n\n defaultConfig: { [key: string]: string | number | boolean } = {};\n\n // Based on packages/firestore/src/util/log.ts but not static because we need per-instance levels\n // to differentiate 2p and 3p use-cases.\n setLogLevel(logLevel: RemoteConfigLogLevel): void {\n switch (logLevel) {\n case 'debug':\n this._logger.logLevel = FirebaseLogLevel.DEBUG;\n break;\n case 'silent':\n this._logger.logLevel = FirebaseLogLevel.SILENT;\n break;\n default:\n this._logger.logLevel = FirebaseLogLevel.ERROR;\n }\n }\n\n get fetchTimeMillis(): number {\n return this._storageCache.getLastSuccessfulFetchTimestampMillis() || -1;\n }\n\n get lastFetchStatus(): FetchStatus {\n return this._storageCache.getLastFetchStatus() || 'no-fetch-yet';\n }\n\n constructor(\n // Required by FirebaseServiceFactory interface.\n readonly app: FirebaseApp,\n // JS doesn't support private yet\n // (https://github.com/tc39/proposal-class-fields#private-fields), so we hint using an\n // underscore prefix.\n private readonly _client: RemoteConfigFetchClient,\n private readonly _storageCache: StorageCache,\n private readonly _storage: Storage,\n private readonly _logger: Logger\n ) {}\n\n async activate(): Promise {\n const [lastSuccessfulFetchResponse, activeConfigEtag] = await Promise.all([\n this._storage.getLastSuccessfulFetchResponse(),\n this._storage.getActiveConfigEtag()\n ]);\n if (\n !lastSuccessfulFetchResponse ||\n !lastSuccessfulFetchResponse.config ||\n !lastSuccessfulFetchResponse.eTag ||\n lastSuccessfulFetchResponse.eTag === activeConfigEtag\n ) {\n // Either there is no successful fetched config, or is the same as current active\n // config.\n return false;\n }\n await Promise.all([\n this._storageCache.setActiveConfig(lastSuccessfulFetchResponse.config),\n this._storage.setActiveConfigEtag(lastSuccessfulFetchResponse.eTag)\n ]);\n return true;\n }\n\n ensureInitialized(): Promise {\n if (!this._initializePromise) {\n this._initializePromise = this._storageCache\n .loadFromStorage()\n .then(() => {\n this._isInitializationComplete = true;\n });\n }\n return this._initializePromise;\n }\n\n /**\n * @throws a {@link ErrorCode.FETCH_CLIENT_TIMEOUT} if the request takes longer than\n * {@link Settings.fetchTimeoutInSeconds} or\n * {@link DEFAULT_FETCH_TIMEOUT_SECONDS}.\n */\n async fetch(): Promise {\n // Aborts the request after the given timeout, causing the fetch call to\n // reject with an AbortError.\n //\n //

Aborting after the request completes is a no-op, so we don't need a\n // corresponding clearTimeout.\n //\n // Locating abort logic here because:\n // * it uses a developer setting (timeout)\n // * it applies to all retries (like curl's max-time arg)\n // * it is consistent with the Fetch API's signal input\n const abortSignal = new RemoteConfigAbortSignal();\n\n setTimeout(async () => {\n // Note a very low delay, eg < 10ms, can elapse before listeners are initialized.\n abortSignal.abort();\n }, this.settings.fetchTimeoutMillis);\n\n // Catches *all* errors thrown by client so status can be set consistently.\n try {\n await this._client.fetch({\n cacheMaxAgeMillis: this.settings.minimumFetchIntervalMillis,\n signal: abortSignal\n });\n\n await this._storageCache.setLastFetchStatus('success');\n } catch (e) {\n const lastFetchStatus = hasErrorCode(e, ErrorCode.FETCH_THROTTLE)\n ? 'throttle'\n : 'failure';\n await this._storageCache.setLastFetchStatus(lastFetchStatus);\n throw e;\n }\n }\n\n async fetchAndActivate(): Promise {\n await this.fetch();\n return this.activate();\n }\n\n getAll(): { [key: string]: ValueType } {\n return getAllKeys(\n this._storageCache.getActiveConfig(),\n this.defaultConfig\n ).reduce((allConfigs, key) => {\n allConfigs[key] = this.getValue(key);\n return allConfigs;\n }, {} as { [key: string]: ValueType });\n }\n\n getBoolean(key: string): boolean {\n return this.getValue(key).asBoolean();\n }\n\n getNumber(key: string): number {\n return this.getValue(key).asNumber();\n }\n\n getString(key: string): string {\n return this.getValue(key).asString();\n }\n\n getValue(key: string): ValueType {\n if (!this._isInitializationComplete) {\n this._logger.debug(\n `A value was requested for key \"${key}\" before SDK initialization completed.` +\n ' Await on ensureInitialized if the intent was to get a previously activated value.'\n );\n }\n const activeConfig = this._storageCache.getActiveConfig();\n if (activeConfig && activeConfig[key] !== undefined) {\n return new Value('remote', activeConfig[key]);\n } else if (this.defaultConfig && this.defaultConfig[key] !== undefined) {\n return new Value('default', String(this.defaultConfig[key]));\n }\n this._logger.debug(\n `Returning static value for key \"${key}\".` +\n ' Define a default or remote value if this is unintentional.'\n );\n return new Value('static');\n }\n}\n\n/**\n * Dedupes and returns an array of all the keys of the received objects.\n */\nfunction getAllKeys(obj1: {} = {}, obj2: {} = {}): string[] {\n return Object.keys({ ...obj1, ...obj2 });\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { FetchStatus } from '@firebase/remote-config-types';\nimport {\n FetchResponse,\n FirebaseRemoteConfigObject\n} from '../client/remote_config_fetch_client';\nimport { ERROR_FACTORY, ErrorCode } from '../errors';\nimport { FirebaseError } from '@firebase/util';\n\n/**\n * Converts an error event associated with a {@link IDBRequest} to a {@link FirebaseError}.\n */\nfunction toFirebaseError(event: Event, errorCode: ErrorCode): FirebaseError {\n const originalError = (event.target as IDBRequest).error || undefined;\n return ERROR_FACTORY.create(errorCode, {\n originalErrorMessage: originalError && originalError.message\n });\n}\n\n/**\n * A general-purpose store keyed by app + namespace + {@link\n * ProjectNamespaceKeyFieldValue}.\n *\n *

The Remote Config SDK can be used with multiple app installations, and each app can interact\n * with multiple namespaces, so this store uses app (ID + name) and namespace as common parent keys\n * for a set of key-value pairs. See {@link Storage#createCompositeKey}.\n *\n *

Visible for testing.\n */\nexport const APP_NAMESPACE_STORE = 'app_namespace_store';\n\nconst DB_NAME = 'firebase_remote_config';\nconst DB_VERSION = 1;\n\n/**\n * Encapsulates metadata concerning throttled fetch requests.\n */\nexport interface ThrottleMetadata {\n // The number of times fetch has backed off. Used for resuming backoff after a timeout.\n backoffCount: number;\n // The Unix timestamp in milliseconds when callers can retry a request.\n throttleEndTimeMillis: number;\n}\n\n/**\n * Provides type-safety for the \"key\" field used by {@link APP_NAMESPACE_STORE}.\n *\n *

This seems like a small price to avoid potentially subtle bugs caused by a typo.\n */\ntype ProjectNamespaceKeyFieldValue =\n | 'active_config'\n | 'active_config_etag'\n | 'last_fetch_status'\n | 'last_successful_fetch_timestamp_millis'\n | 'last_successful_fetch_response'\n | 'settings'\n | 'throttle_metadata';\n\n// Visible for testing.\nexport function openDatabase(): Promise {\n return new Promise((resolve, reject) => {\n const request = indexedDB.open(DB_NAME, DB_VERSION);\n request.onerror = event => {\n reject(toFirebaseError(event, ErrorCode.STORAGE_OPEN));\n };\n request.onsuccess = event => {\n resolve((event.target as IDBOpenDBRequest).result);\n };\n request.onupgradeneeded = event => {\n const db = (event.target as IDBOpenDBRequest).result;\n\n // We don't use 'break' in this switch statement, the fall-through\n // behavior is what we want, because if there are multiple versions between\n // the old version and the current version, we want ALL the migrations\n // that correspond to those versions to run, not only the last one.\n // eslint-disable-next-line default-case\n switch (event.oldVersion) {\n case 0:\n db.createObjectStore(APP_NAMESPACE_STORE, {\n keyPath: 'compositeKey'\n });\n }\n };\n });\n}\n\n/**\n * Abstracts data persistence.\n */\nexport class Storage {\n /**\n * @param appId enables storage segmentation by app (ID + name).\n * @param appName enables storage segmentation by app (ID + name).\n * @param namespace enables storage segmentation by namespace.\n */\n constructor(\n private readonly appId: string,\n private readonly appName: string,\n private readonly namespace: string,\n private readonly openDbPromise = openDatabase()\n ) {}\n\n getLastFetchStatus(): Promise {\n return this.get('last_fetch_status');\n }\n\n setLastFetchStatus(status: FetchStatus): Promise {\n return this.set('last_fetch_status', status);\n }\n\n // This is comparable to a cache entry timestamp. If we need to expire other data, we could\n // consider adding timestamp to all storage records and an optional max age arg to getters.\n getLastSuccessfulFetchTimestampMillis(): Promise {\n return this.get('last_successful_fetch_timestamp_millis');\n }\n\n setLastSuccessfulFetchTimestampMillis(timestamp: number): Promise {\n return this.set(\n 'last_successful_fetch_timestamp_millis',\n timestamp\n );\n }\n\n getLastSuccessfulFetchResponse(): Promise {\n return this.get('last_successful_fetch_response');\n }\n\n setLastSuccessfulFetchResponse(response: FetchResponse): Promise {\n return this.set('last_successful_fetch_response', response);\n }\n\n getActiveConfig(): Promise {\n return this.get('active_config');\n }\n\n setActiveConfig(config: FirebaseRemoteConfigObject): Promise {\n return this.set('active_config', config);\n }\n\n getActiveConfigEtag(): Promise {\n return this.get('active_config_etag');\n }\n\n setActiveConfigEtag(etag: string): Promise {\n return this.set('active_config_etag', etag);\n }\n\n getThrottleMetadata(): Promise {\n return this.get('throttle_metadata');\n }\n\n setThrottleMetadata(metadata: ThrottleMetadata): Promise {\n return this.set('throttle_metadata', metadata);\n }\n\n deleteThrottleMetadata(): Promise {\n return this.delete('throttle_metadata');\n }\n\n async get(key: ProjectNamespaceKeyFieldValue): Promise {\n const db = await this.openDbPromise;\n return new Promise((resolve, reject) => {\n const transaction = db.transaction([APP_NAMESPACE_STORE], 'readonly');\n const objectStore = transaction.objectStore(APP_NAMESPACE_STORE);\n const compositeKey = this.createCompositeKey(key);\n try {\n const request = objectStore.get(compositeKey);\n request.onerror = event => {\n reject(toFirebaseError(event, ErrorCode.STORAGE_GET));\n };\n request.onsuccess = event => {\n const result = (event.target as IDBRequest).result;\n if (result) {\n resolve(result.value);\n } else {\n resolve(undefined);\n }\n };\n } catch (e) {\n reject(\n ERROR_FACTORY.create(ErrorCode.STORAGE_GET, {\n originalErrorMessage: e && e.message\n })\n );\n }\n });\n }\n\n async set(key: ProjectNamespaceKeyFieldValue, value: T): Promise {\n const db = await this.openDbPromise;\n return new Promise((resolve, reject) => {\n const transaction = db.transaction([APP_NAMESPACE_STORE], 'readwrite');\n const objectStore = transaction.objectStore(APP_NAMESPACE_STORE);\n const compositeKey = this.createCompositeKey(key);\n try {\n const request = objectStore.put({\n compositeKey,\n value\n });\n request.onerror = (event: Event) => {\n reject(toFirebaseError(event, ErrorCode.STORAGE_SET));\n };\n request.onsuccess = () => {\n resolve();\n };\n } catch (e) {\n reject(\n ERROR_FACTORY.create(ErrorCode.STORAGE_SET, {\n originalErrorMessage: e && e.message\n })\n );\n }\n });\n }\n\n async delete(key: ProjectNamespaceKeyFieldValue): Promise {\n const db = await this.openDbPromise;\n return new Promise((resolve, reject) => {\n const transaction = db.transaction([APP_NAMESPACE_STORE], 'readwrite');\n const objectStore = transaction.objectStore(APP_NAMESPACE_STORE);\n const compositeKey = this.createCompositeKey(key);\n try {\n const request = objectStore.delete(compositeKey);\n request.onerror = (event: Event) => {\n reject(toFirebaseError(event, ErrorCode.STORAGE_DELETE));\n };\n request.onsuccess = () => {\n resolve();\n };\n } catch (e) {\n reject(\n ERROR_FACTORY.create(ErrorCode.STORAGE_DELETE, {\n originalErrorMessage: e && e.message\n })\n );\n }\n });\n }\n\n // Facilitates composite key functionality (which is unsupported in IE).\n createCompositeKey(key: ProjectNamespaceKeyFieldValue): string {\n return [this.appId, this.appName, this.namespace, key].join();\n }\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { FetchStatus } from '@firebase/remote-config-types';\nimport { FirebaseRemoteConfigObject } from '../client/remote_config_fetch_client';\nimport { Storage } from './storage';\n\n/**\n * A memory cache layer over storage to support the SDK's synchronous read requirements.\n */\nexport class StorageCache {\n constructor(private readonly storage: Storage) {}\n\n /**\n * Memory caches.\n */\n private lastFetchStatus?: FetchStatus;\n private lastSuccessfulFetchTimestampMillis?: number;\n private activeConfig?: FirebaseRemoteConfigObject;\n\n /**\n * Memory-only getters\n */\n getLastFetchStatus(): FetchStatus | undefined {\n return this.lastFetchStatus;\n }\n\n getLastSuccessfulFetchTimestampMillis(): number | undefined {\n return this.lastSuccessfulFetchTimestampMillis;\n }\n\n getActiveConfig(): FirebaseRemoteConfigObject | undefined {\n return this.activeConfig;\n }\n\n /**\n * Read-ahead getter\n */\n async loadFromStorage(): Promise {\n const lastFetchStatusPromise = this.storage.getLastFetchStatus();\n const lastSuccessfulFetchTimestampMillisPromise = this.storage.getLastSuccessfulFetchTimestampMillis();\n const activeConfigPromise = this.storage.getActiveConfig();\n\n // Note:\n // 1. we consistently check for undefined to avoid clobbering defined values\n // in memory\n // 2. we defer awaiting to improve readability, as opposed to destructuring\n // a Promise.all result, for example\n\n const lastFetchStatus = await lastFetchStatusPromise;\n if (lastFetchStatus) {\n this.lastFetchStatus = lastFetchStatus;\n }\n\n const lastSuccessfulFetchTimestampMillis = await lastSuccessfulFetchTimestampMillisPromise;\n if (lastSuccessfulFetchTimestampMillis) {\n this.lastSuccessfulFetchTimestampMillis = lastSuccessfulFetchTimestampMillis;\n }\n\n const activeConfig = await activeConfigPromise;\n if (activeConfig) {\n this.activeConfig = activeConfig;\n }\n }\n\n /**\n * Write-through setters\n */\n setLastFetchStatus(status: FetchStatus): Promise {\n this.lastFetchStatus = status;\n return this.storage.setLastFetchStatus(status);\n }\n\n setLastSuccessfulFetchTimestampMillis(\n timestampMillis: number\n ): Promise {\n this.lastSuccessfulFetchTimestampMillis = timestampMillis;\n return this.storage.setLastSuccessfulFetchTimestampMillis(timestampMillis);\n }\n\n setActiveConfig(activeConfig: FirebaseRemoteConfigObject): Promise {\n this.activeConfig = activeConfig;\n return this.storage.setActiveConfig(activeConfig);\n }\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n RemoteConfigAbortSignal,\n RemoteConfigFetchClient,\n FetchResponse,\n FetchRequest\n} from './remote_config_fetch_client';\nimport { ThrottleMetadata, Storage } from '../storage/storage';\nimport { calculateBackoffMillis } from './exponential_backoff';\nimport { ErrorCode, ERROR_FACTORY } from '../errors';\nimport { FirebaseError } from '@firebase/util';\n\n/**\n * Supports waiting on a backoff by:\n *\n *

    \n *
  • Promisifying setTimeout, so we can set a timeout in our Promise chain
  • \n *
  • Listening on a signal bus for abort events, just like the Fetch API
  • \n *
  • Failing in the same way the Fetch API fails, so timing out a live request and a throttled\n * request appear the same.
  • \n *
\n *\n *

Visible for testing.\n */\nexport function setAbortableTimeout(\n signal: RemoteConfigAbortSignal,\n throttleEndTimeMillis: number\n): Promise {\n return new Promise((resolve, reject) => {\n // Derives backoff from given end time, normalizing negative numbers to zero.\n const backoffMillis = Math.max(throttleEndTimeMillis - Date.now(), 0);\n\n const timeout = setTimeout(resolve, backoffMillis);\n\n // Adds listener, rather than sets onabort, because signal is a shared object.\n signal.addEventListener(() => {\n clearTimeout(timeout);\n\n // If the request completes before this timeout, the rejection has no effect.\n reject(\n ERROR_FACTORY.create(ErrorCode.FETCH_THROTTLE, {\n throttleEndTimeMillis\n })\n );\n });\n });\n}\n\n/**\n * Returns true if the {@link Error} indicates a fetch request may succeed later.\n */\nfunction isRetriableError(e: Error): boolean {\n if (!(e instanceof FirebaseError)) {\n return false;\n }\n\n // Uses string index defined by ErrorData, which FirebaseError implements.\n const httpStatus = Number(e['httpStatus']);\n\n return (\n httpStatus === 429 ||\n httpStatus === 500 ||\n httpStatus === 503 ||\n httpStatus === 504\n );\n}\n\n/**\n * Decorates a Client with retry logic.\n *\n *

Comparable to CachingClient, but uses backoff logic instead of cache max age and doesn't cache\n * responses (because the SDK has no use for error responses).\n */\nexport class RetryingClient implements RemoteConfigFetchClient {\n constructor(\n private readonly client: RemoteConfigFetchClient,\n private readonly storage: Storage\n ) {}\n\n async fetch(request: FetchRequest): Promise {\n const throttleMetadata = (await this.storage.getThrottleMetadata()) || {\n backoffCount: 0,\n throttleEndTimeMillis: Date.now()\n };\n\n return this.attemptFetch(request, throttleMetadata);\n }\n\n /**\n * A recursive helper for attempting a fetch request repeatedly.\n *\n * @throws any non-retriable errors.\n */\n async attemptFetch(\n request: FetchRequest,\n { throttleEndTimeMillis, backoffCount }: ThrottleMetadata\n ): Promise {\n // Starts with a (potentially zero) timeout to support resumption from stored state.\n // Ensures the throttle end time is honored if the last attempt timed out.\n // Note the SDK will never make a request if the fetch timeout expires at this point.\n await setAbortableTimeout(request.signal, throttleEndTimeMillis);\n\n try {\n const response = await this.client.fetch(request);\n\n // Note the SDK only clears throttle state if response is success or non-retriable.\n await this.storage.deleteThrottleMetadata();\n\n return response;\n } catch (e) {\n if (!isRetriableError(e)) {\n throw e;\n }\n\n // Increments backoff state.\n const throttleMetadata = {\n throttleEndTimeMillis:\n Date.now() + calculateBackoffMillis(backoffCount),\n backoffCount: backoffCount + 1\n };\n\n // Persists state.\n await this.storage.setThrottleMetadata(throttleMetadata);\n\n return this.attemptFetch(request, throttleMetadata);\n }\n }\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * The amount of milliseconds to exponentially increase.\n */\nconst INTERVAL_MILLIS = 1000;\n\n/**\n * The factor to backoff by.\n * Should be a number greater than 1.\n */\nconst BACKOFF_FACTOR = 2;\n\n/**\n * The maximum milliseconds to increase to.\n *\n *

Visible for testing\n */\nexport const MAX_VALUE_MILLIS = 4 * 60 * 60 * 1000; // Four hours, like iOS and Android.\n\n/**\n * The percentage of backoff time to randomize by.\n * See\n * http://go/safe-client-behavior#step-1-determine-the-appropriate-retry-interval-to-handle-spike-traffic\n * for context.\n *\n *

Visible for testing\n */\nexport const RANDOM_FACTOR = 0.5;\n\n/**\n * Based on the backoff method from\n * https://github.com/google/closure-library/blob/master/closure/goog/math/exponentialbackoff.js.\n * Extracted here so we don't need to pass metadata and a stateful ExponentialBackoff object around.\n */\nexport function calculateBackoffMillis(backoffCount: number): number {\n // Calculates an exponentially increasing value.\n // Deviation: calculates value from count and a constant interval, so we only need to save value\n // and count to restore state.\n const currBaseValue =\n INTERVAL_MILLIS * Math.pow(BACKOFF_FACTOR, backoffCount);\n\n // A random \"fuzz\" to avoid waves of retries.\n // Deviation: randomFactor is required.\n const randomWait = Math.round(\n // A fraction of the backoff value to add/subtract.\n // Deviation: changes multiplication order to improve readability.\n RANDOM_FACTOR *\n currBaseValue *\n // A random float (rounded to int by Math.round above) in the range [-1, 1]. Determines\n // if we add or subtract.\n (Math.random() - 0.5) *\n 2\n );\n\n // Limits backoff to max to avoid effectively permanent backoff.\n return Math.min(MAX_VALUE_MILLIS, currBaseValue + randomWait);\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport firebase from '@firebase/app';\nimport '@firebase/installations';\nimport { _FirebaseNamespace } from '@firebase/app-types/private';\nimport { RemoteConfig as RemoteConfigType } from '@firebase/remote-config-types';\nimport { CachingClient } from './src/client/caching_client';\nimport { RestClient } from './src/client/rest_client';\nimport { RemoteConfig } from './src/remote_config';\nimport { Storage } from './src/storage/storage';\nimport { StorageCache } from './src/storage/storage_cache';\nimport { ERROR_FACTORY, ErrorCode } from './src/errors';\nimport { RetryingClient } from './src/client/retrying_client';\nimport { Logger, LogLevel as FirebaseLogLevel } from '@firebase/logger';\nimport { name as packageName, version } from './package.json';\nimport {\n Component,\n ComponentType,\n ComponentContainer\n} from '@firebase/component';\n\n// Facilitates debugging by enabling settings changes without rebuilding asset.\n// Note these debug options are not part of a documented, supported API and can change at any time.\n// Consolidates debug options for easier discovery.\n// Uses transient variables on window to avoid lingering state causing panic.\ndeclare global {\n interface Window {\n FIREBASE_REMOTE_CONFIG_URL_BASE: string;\n }\n}\n\nexport function registerRemoteConfig(\n firebaseInstance: _FirebaseNamespace\n): void {\n firebaseInstance.INTERNAL.registerComponent(\n new Component(\n 'remoteConfig',\n remoteConfigFactory,\n ComponentType.PUBLIC\n ).setMultipleInstances(true)\n );\n\n firebaseInstance.registerVersion(packageName, version);\n\n function remoteConfigFactory(\n container: ComponentContainer,\n namespace?: string\n ): RemoteConfig {\n /* Dependencies */\n // getImmediate for FirebaseApp will always succeed\n const app = container.getProvider('app').getImmediate();\n // The following call will always succeed because rc has `import '@firebase/installations'`\n const installations = container.getProvider('installations').getImmediate();\n\n // Guards against the SDK being used in non-browser environments.\n if (typeof window === 'undefined') {\n throw ERROR_FACTORY.create(ErrorCode.REGISTRATION_WINDOW);\n }\n\n // Normalizes optional inputs.\n const { projectId, apiKey, appId } = app.options;\n if (!projectId) {\n throw ERROR_FACTORY.create(ErrorCode.REGISTRATION_PROJECT_ID);\n }\n if (!apiKey) {\n throw ERROR_FACTORY.create(ErrorCode.REGISTRATION_API_KEY);\n }\n if (!appId) {\n throw ERROR_FACTORY.create(ErrorCode.REGISTRATION_APP_ID);\n }\n namespace = namespace || 'firebase';\n\n const storage = new Storage(appId, app.name, namespace);\n const storageCache = new StorageCache(storage);\n\n const logger = new Logger(packageName);\n\n // Sets ERROR as the default log level.\n // See RemoteConfig#setLogLevel for corresponding normalization to ERROR log level.\n logger.logLevel = FirebaseLogLevel.ERROR;\n\n const restClient = new RestClient(\n installations,\n // Uses the JS SDK version, by which the RC package version can be deduced, if necessary.\n firebaseInstance.SDK_VERSION,\n namespace,\n projectId,\n apiKey,\n appId\n );\n const retryingClient = new RetryingClient(restClient, storage);\n const cachingClient = new CachingClient(\n retryingClient,\n storage,\n storageCache,\n logger\n );\n\n const remoteConfigInstance = new RemoteConfig(\n app,\n cachingClient,\n storageCache,\n storage,\n logger\n );\n\n // Starts warming cache.\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n remoteConfigInstance.ensureInitialized();\n\n return remoteConfigInstance;\n }\n}\n\nregisterRemoteConfig(firebase as _FirebaseNamespace);\n\ndeclare module '@firebase/app-types' {\n interface FirebaseNamespace {\n remoteConfig?: {\n (app?: FirebaseApp): RemoteConfigType;\n };\n }\n interface FirebaseApp {\n remoteConfig(): RemoteConfigType;\n }\n}\n"],"names":["extendStatics","d","b","Object","setPrototypeOf","__proto__","Array","p","hasOwnProperty","__assign","assign","t","s","i","n","arguments","length","prototype","call","apply","this","__awaiter","thisArg","_arguments","P","generator","Promise","resolve","reject","fulfilled","value","step","next","e","rejected","result","done","then","__generator","body","f","y","g","_","label","sent","trys","ops","verb","throw","return","Symbol","iterator","v","op","TypeError","pop","push","__values","o","m","__read","r","ar","error","Error","create","__","constructor","code","message","_super","_this","FirebaseError","captureStackTrace","ErrorFactory","_i","data","customData","fullCode","service","template","errors","replace","PATTERN","key","String","fullMessage","serviceName","_b","keys","_a","slice","console","warn","Component","mode","instantiationMode","multipleInstances","props","serviceProps","name","instanceFactory","type","promisifyRequest","request","onsuccess","onerror","promisifyRequestCall","obj","method","args","proxyProperties","ProxyClass","targetProp","properties","forEach","prop","defineProperty","get","set","val","proxyRequestMethods","Constructor","proxyMethods","proxyCursorRequestMethods","Cursor","Index","index","_index","cursor","_cursor","_request","ObjectStore","store","_store","Transaction","idbTransaction","_tx","complete","oncomplete","onabort","UpgradeDB","db","oldVersion","transaction","_db","DB","IDBIndex","IDBCursor","methodName","createIndex","IDBObjectStore","objectStore","IDBTransaction","createObjectStore","IDBDatabase","funcName","arr","callback","nativeObject","getAll","query","count","instance","items","iterateCursor","undefined","continue","PENDING_TIMEOUT_MS","PACKAGE_VERSION","version","INTERNAL_AUTH_VERSION","INSTALLATIONS_API_URL","TOKEN_EXPIRATION_BUFFER","ERROR_DESCRIPTION_MAP","ERROR_FACTORY","isServerError","includes","getInstallationsEndpoint","projectId","extractAuthTokenInfoFromResponse","response","token","requestStatus","expiresIn","responseExpiresIn","Number","creationTime","Date","now","getErrorFromResponse","requestName","json","responseJson","errorData","serverCode","serverMessage","serverStatus","status","getHeaders","apiKey","Headers","Content-Type","Accept","x-goog-api-key","getHeadersWithAuth","appConfig","refreshToken","headers","append","retryIfServerError","fn","sleep","ms","setTimeout","bufferToBase64UrlSafe","array","btoa","fromCharCode","concat","VALID_FID_PATTERN","INVALID_FID","generateFid","fidByteArray","Uint8Array","self","crypto","msCrypto","getRandomValues","fid","substr","test","getKey","appName","appId","fidChangeCallbacks","Map","fidChanged","callFidChangeCallbacks","channel","getBroadcastChannel","postMessage","closeBroadcastChannel","broadcastFidChange","callbacks","callbacks_1","broadcastChannel","BroadcastChannel","onmessage","size","close","LogLevel","DATABASE_NAME","DATABASE_VERSION","OBJECT_STORE_NAME","dbPromise","getDbPromise","upgradeCallback","upgradeDB","indexedDB","onupgradeneeded","event","tx","oldValue","put","remove","delete","update","updateFn","newValue","getInstallationEntry","oldEntry","installationEntry","clearTimedOutRequest","registrationStatus","entryWithPromise","registrationPromise","updateInstallationRequest","entry","waitUntilFidRegistration","navigator","onLine","registrationPromiseWithError","inProgressEntry","registrationTime","endpoint","authVersion","sdkVersion","JSON","stringify","fetch","ok","responseValue","authToken","createInstallationRequest","registeredInstallationEntry","e_1","registerInstallation","triggerRegistrationIfNecessary","generateAuthTokenRequest","platformLoggerProvider","platformLogger","getImmediate","optional","getPlatformInfoString","installation","refreshAuthToken","dependencies","forceRefresh","isEntryRegistered","inProgressAuthToken","oldAuthToken","isAuthTokenExpired","tokenPromise","updateAuthTokenRequest","waitUntilAuthTokenRequest","requestTime","updatedInstallationEntry","fetchAuthTokenFromServer","getToken","completeInstallationRegistration","deleteInstallationRequest","onIdChange","callbackSet","Set","add","addCallback","getMissingValueError","valueName","firebase","INTERNAL","registerComponent","container","app","getProvider","options","configKeys_1","keyName","extractAppConfig","getId","catch","deleteInstallation","registerVersion","defaultLogHandler","logType","logLevel","toISOString","ConsoleMethod","levelStringToEnum","debug","DEBUG","verbose","VERBOSE","info","INFO","WARN","ERROR","silent","SILENT","defaultLogLevel","Logger","_logLevel","_logHandler","_userLogHandler","CachingClient","cacheMaxAgeMillis","lastSuccessfulFetchTimestampMillis","logger","cacheAgeMillis","isCachedDataFresh","all","storage","getLastSuccessfulFetchTimestampMillis","getLastSuccessfulFetchResponse","lastSuccessfulFetchResponse","eTag","client","storageOperations","storageCache","setLastSuccessfulFetchTimestampMillis","setLastSuccessfulFetchResponse","RestClient","firebaseInstallations","installationId","installationToken","urlBase","window","FIREBASE_REMOTE_CONFIG_URL_BASE","url","namespace","Content-Encoding","If-None-Match","requestBody","sdk_version","app_instance_id","app_instance_id_token","app_id","language_code","navigatorLanguage","languages","language","fetchPromise","timeoutPromise","_resolve","signal","addEventListener","race","errorCode","originalError_1","originalErrorMessage","responseEtag","responseBody","originalError_2","config","state","httpStatus","RemoteConfigAbortSignal","listener","listeners","BOOLEAN_TRUTHY_VALUES","Value","_value","_source","indexOf","toLowerCase","num","isNaN","RemoteConfig","_logger","FirebaseLogLevel","_storageCache","getLastFetchStatus","_storage","getActiveConfigEtag","activeConfigEtag","setActiveConfig","setActiveConfigEtag","_initializePromise","loadFromStorage","_isInitializationComplete","abortSignal","abort","settings","fetchTimeoutMillis","_client","minimumFetchIntervalMillis","setLastFetchStatus","lastFetchStatus","activate","obj1","obj2","getAllKeys","getActiveConfig","defaultConfig","reduce","allConfigs","getValue","asBoolean","asNumber","asString","activeConfig","toFirebaseError","originalError","target","APP_NAMESPACE_STORE","DB_NAME","DB_VERSION","Storage","timestamp","etag","metadata","openDbPromise","compositeKey","createCompositeKey","join","open","keyPath","StorageCache","lastFetchStatusPromise","lastSuccessfulFetchTimestampMillisPromise","activeConfigPromise","timestampMillis","RetryingClient","getThrottleMetadata","throttleMetadata","backoffCount","throttleEndTimeMillis","attemptFetch","backoffMillis","Math","max","timeout","clearTimeout","deleteThrottleMetadata","isRetriableError","currBaseValue","pow","randomWait","round","random","min","setThrottleMetadata","firebaseInstance","installations","packageName","restClient","SDK_VERSION","retryingClient","cachingClient","remoteConfigInstance","ensureInitialized","setMultipleInstances"],"mappings":"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"}