firebase-app.js 91 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522
  1. /**
  2. * @license
  3. * Copyright 2017 Google LLC
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. /**
  18. * @license
  19. * Copyright 2017 Google LLC
  20. *
  21. * Licensed under the Apache License, Version 2.0 (the "License");
  22. * you may not use this file except in compliance with the License.
  23. * You may obtain a copy of the License at
  24. *
  25. * http://www.apache.org/licenses/LICENSE-2.0
  26. *
  27. * Unless required by applicable law or agreed to in writing, software
  28. * distributed under the License is distributed on an "AS IS" BASIS,
  29. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  30. * See the License for the specific language governing permissions and
  31. * limitations under the License.
  32. */
  33. const stringToByteArray$1 = function (str) {
  34. // TODO(user): Use native implementations if/when available
  35. const out = [];
  36. let p = 0;
  37. for (let i = 0; i < str.length; i++) {
  38. let c = str.charCodeAt(i);
  39. if (c < 128) {
  40. out[p++] = c;
  41. }
  42. else if (c < 2048) {
  43. out[p++] = (c >> 6) | 192;
  44. out[p++] = (c & 63) | 128;
  45. }
  46. else if ((c & 0xfc00) === 0xd800 &&
  47. i + 1 < str.length &&
  48. (str.charCodeAt(i + 1) & 0xfc00) === 0xdc00) {
  49. // Surrogate Pair
  50. c = 0x10000 + ((c & 0x03ff) << 10) + (str.charCodeAt(++i) & 0x03ff);
  51. out[p++] = (c >> 18) | 240;
  52. out[p++] = ((c >> 12) & 63) | 128;
  53. out[p++] = ((c >> 6) & 63) | 128;
  54. out[p++] = (c & 63) | 128;
  55. }
  56. else {
  57. out[p++] = (c >> 12) | 224;
  58. out[p++] = ((c >> 6) & 63) | 128;
  59. out[p++] = (c & 63) | 128;
  60. }
  61. }
  62. return out;
  63. };
  64. /**
  65. * Turns an array of numbers into the string given by the concatenation of the
  66. * characters to which the numbers correspond.
  67. * @param bytes Array of numbers representing characters.
  68. * @return Stringification of the array.
  69. */
  70. const byteArrayToString = function (bytes) {
  71. // TODO(user): Use native implementations if/when available
  72. const out = [];
  73. let pos = 0, c = 0;
  74. while (pos < bytes.length) {
  75. const c1 = bytes[pos++];
  76. if (c1 < 128) {
  77. out[c++] = String.fromCharCode(c1);
  78. }
  79. else if (c1 > 191 && c1 < 224) {
  80. const c2 = bytes[pos++];
  81. out[c++] = String.fromCharCode(((c1 & 31) << 6) | (c2 & 63));
  82. }
  83. else if (c1 > 239 && c1 < 365) {
  84. // Surrogate Pair
  85. const c2 = bytes[pos++];
  86. const c3 = bytes[pos++];
  87. const c4 = bytes[pos++];
  88. const u = (((c1 & 7) << 18) | ((c2 & 63) << 12) | ((c3 & 63) << 6) | (c4 & 63)) -
  89. 0x10000;
  90. out[c++] = String.fromCharCode(0xd800 + (u >> 10));
  91. out[c++] = String.fromCharCode(0xdc00 + (u & 1023));
  92. }
  93. else {
  94. const c2 = bytes[pos++];
  95. const c3 = bytes[pos++];
  96. out[c++] = String.fromCharCode(((c1 & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
  97. }
  98. }
  99. return out.join('');
  100. };
  101. // We define it as an object literal instead of a class because a class compiled down to es5 can't
  102. // be treeshaked. https://github.com/rollup/rollup/issues/1691
  103. // Static lookup maps, lazily populated by init_()
  104. const base64 = {
  105. /**
  106. * Maps bytes to characters.
  107. */
  108. byteToCharMap_: null,
  109. /**
  110. * Maps characters to bytes.
  111. */
  112. charToByteMap_: null,
  113. /**
  114. * Maps bytes to websafe characters.
  115. * @private
  116. */
  117. byteToCharMapWebSafe_: null,
  118. /**
  119. * Maps websafe characters to bytes.
  120. * @private
  121. */
  122. charToByteMapWebSafe_: null,
  123. /**
  124. * Our default alphabet, shared between
  125. * ENCODED_VALS and ENCODED_VALS_WEBSAFE
  126. */
  127. ENCODED_VALS_BASE: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + 'abcdefghijklmnopqrstuvwxyz' + '0123456789',
  128. /**
  129. * Our default alphabet. Value 64 (=) is special; it means "nothing."
  130. */
  131. get ENCODED_VALS() {
  132. return this.ENCODED_VALS_BASE + '+/=';
  133. },
  134. /**
  135. * Our websafe alphabet.
  136. */
  137. get ENCODED_VALS_WEBSAFE() {
  138. return this.ENCODED_VALS_BASE + '-_.';
  139. },
  140. /**
  141. * Whether this browser supports the atob and btoa functions. This extension
  142. * started at Mozilla but is now implemented by many browsers. We use the
  143. * ASSUME_* variables to avoid pulling in the full useragent detection library
  144. * but still allowing the standard per-browser compilations.
  145. *
  146. */
  147. HAS_NATIVE_SUPPORT: typeof atob === 'function',
  148. /**
  149. * Base64-encode an array of bytes.
  150. *
  151. * @param input An array of bytes (numbers with
  152. * value in [0, 255]) to encode.
  153. * @param webSafe Boolean indicating we should use the
  154. * alternative alphabet.
  155. * @return The base64 encoded string.
  156. */
  157. encodeByteArray(input, webSafe) {
  158. if (!Array.isArray(input)) {
  159. throw Error('encodeByteArray takes an array as a parameter');
  160. }
  161. this.init_();
  162. const byteToCharMap = webSafe
  163. ? this.byteToCharMapWebSafe_
  164. : this.byteToCharMap_;
  165. const output = [];
  166. for (let i = 0; i < input.length; i += 3) {
  167. const byte1 = input[i];
  168. const haveByte2 = i + 1 < input.length;
  169. const byte2 = haveByte2 ? input[i + 1] : 0;
  170. const haveByte3 = i + 2 < input.length;
  171. const byte3 = haveByte3 ? input[i + 2] : 0;
  172. const outByte1 = byte1 >> 2;
  173. const outByte2 = ((byte1 & 0x03) << 4) | (byte2 >> 4);
  174. let outByte3 = ((byte2 & 0x0f) << 2) | (byte3 >> 6);
  175. let outByte4 = byte3 & 0x3f;
  176. if (!haveByte3) {
  177. outByte4 = 64;
  178. if (!haveByte2) {
  179. outByte3 = 64;
  180. }
  181. }
  182. output.push(byteToCharMap[outByte1], byteToCharMap[outByte2], byteToCharMap[outByte3], byteToCharMap[outByte4]);
  183. }
  184. return output.join('');
  185. },
  186. /**
  187. * Base64-encode a string.
  188. *
  189. * @param input A string to encode.
  190. * @param webSafe If true, we should use the
  191. * alternative alphabet.
  192. * @return The base64 encoded string.
  193. */
  194. encodeString(input, webSafe) {
  195. // Shortcut for Mozilla browsers that implement
  196. // a native base64 encoder in the form of "btoa/atob"
  197. if (this.HAS_NATIVE_SUPPORT && !webSafe) {
  198. return btoa(input);
  199. }
  200. return this.encodeByteArray(stringToByteArray$1(input), webSafe);
  201. },
  202. /**
  203. * Base64-decode a string.
  204. *
  205. * @param input to decode.
  206. * @param webSafe True if we should use the
  207. * alternative alphabet.
  208. * @return string representing the decoded value.
  209. */
  210. decodeString(input, webSafe) {
  211. // Shortcut for Mozilla browsers that implement
  212. // a native base64 encoder in the form of "btoa/atob"
  213. if (this.HAS_NATIVE_SUPPORT && !webSafe) {
  214. return atob(input);
  215. }
  216. return byteArrayToString(this.decodeStringToByteArray(input, webSafe));
  217. },
  218. /**
  219. * Base64-decode a string.
  220. *
  221. * In base-64 decoding, groups of four characters are converted into three
  222. * bytes. If the encoder did not apply padding, the input length may not
  223. * be a multiple of 4.
  224. *
  225. * In this case, the last group will have fewer than 4 characters, and
  226. * padding will be inferred. If the group has one or two characters, it decodes
  227. * to one byte. If the group has three characters, it decodes to two bytes.
  228. *
  229. * @param input Input to decode.
  230. * @param webSafe True if we should use the web-safe alphabet.
  231. * @return bytes representing the decoded value.
  232. */
  233. decodeStringToByteArray(input, webSafe) {
  234. this.init_();
  235. const charToByteMap = webSafe
  236. ? this.charToByteMapWebSafe_
  237. : this.charToByteMap_;
  238. const output = [];
  239. for (let i = 0; i < input.length;) {
  240. const byte1 = charToByteMap[input.charAt(i++)];
  241. const haveByte2 = i < input.length;
  242. const byte2 = haveByte2 ? charToByteMap[input.charAt(i)] : 0;
  243. ++i;
  244. const haveByte3 = i < input.length;
  245. const byte3 = haveByte3 ? charToByteMap[input.charAt(i)] : 64;
  246. ++i;
  247. const haveByte4 = i < input.length;
  248. const byte4 = haveByte4 ? charToByteMap[input.charAt(i)] : 64;
  249. ++i;
  250. if (byte1 == null || byte2 == null || byte3 == null || byte4 == null) {
  251. throw new DecodeBase64StringError();
  252. }
  253. const outByte1 = (byte1 << 2) | (byte2 >> 4);
  254. output.push(outByte1);
  255. if (byte3 !== 64) {
  256. const outByte2 = ((byte2 << 4) & 0xf0) | (byte3 >> 2);
  257. output.push(outByte2);
  258. if (byte4 !== 64) {
  259. const outByte3 = ((byte3 << 6) & 0xc0) | byte4;
  260. output.push(outByte3);
  261. }
  262. }
  263. }
  264. return output;
  265. },
  266. /**
  267. * Lazy static initialization function. Called before
  268. * accessing any of the static map variables.
  269. * @private
  270. */
  271. init_() {
  272. if (!this.byteToCharMap_) {
  273. this.byteToCharMap_ = {};
  274. this.charToByteMap_ = {};
  275. this.byteToCharMapWebSafe_ = {};
  276. this.charToByteMapWebSafe_ = {};
  277. // We want quick mappings back and forth, so we precompute two maps.
  278. for (let i = 0; i < this.ENCODED_VALS.length; i++) {
  279. this.byteToCharMap_[i] = this.ENCODED_VALS.charAt(i);
  280. this.charToByteMap_[this.byteToCharMap_[i]] = i;
  281. this.byteToCharMapWebSafe_[i] = this.ENCODED_VALS_WEBSAFE.charAt(i);
  282. this.charToByteMapWebSafe_[this.byteToCharMapWebSafe_[i]] = i;
  283. // Be forgiving when decoding and correctly decode both encodings.
  284. if (i >= this.ENCODED_VALS_BASE.length) {
  285. this.charToByteMap_[this.ENCODED_VALS_WEBSAFE.charAt(i)] = i;
  286. this.charToByteMapWebSafe_[this.ENCODED_VALS.charAt(i)] = i;
  287. }
  288. }
  289. }
  290. }
  291. };
  292. /**
  293. * An error encountered while decoding base64 string.
  294. */
  295. class DecodeBase64StringError extends Error {
  296. constructor() {
  297. super(...arguments);
  298. this.name = 'DecodeBase64StringError';
  299. }
  300. }
  301. /**
  302. * URL-safe base64 encoding
  303. */
  304. const base64Encode = function (str) {
  305. const utf8Bytes = stringToByteArray$1(str);
  306. return base64.encodeByteArray(utf8Bytes, true);
  307. };
  308. /**
  309. * URL-safe base64 encoding (without "." padding in the end).
  310. * e.g. Used in JSON Web Token (JWT) parts.
  311. */
  312. const base64urlEncodeWithoutPadding = function (str) {
  313. // Use base64url encoding and remove padding in the end (dot characters).
  314. return base64Encode(str).replace(/\./g, '');
  315. };
  316. /**
  317. * URL-safe base64 decoding
  318. *
  319. * NOTE: DO NOT use the global atob() function - it does NOT support the
  320. * base64Url variant encoding.
  321. *
  322. * @param str To be decoded
  323. * @return Decoded result, if possible
  324. */
  325. const base64Decode = function (str) {
  326. try {
  327. return base64.decodeString(str, true);
  328. }
  329. catch (e) {
  330. console.error('base64Decode failed: ', e);
  331. }
  332. return null;
  333. };
  334. /**
  335. * @license
  336. * Copyright 2022 Google LLC
  337. *
  338. * Licensed under the Apache License, Version 2.0 (the "License");
  339. * you may not use this file except in compliance with the License.
  340. * You may obtain a copy of the License at
  341. *
  342. * http://www.apache.org/licenses/LICENSE-2.0
  343. *
  344. * Unless required by applicable law or agreed to in writing, software
  345. * distributed under the License is distributed on an "AS IS" BASIS,
  346. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  347. * See the License for the specific language governing permissions and
  348. * limitations under the License.
  349. */
  350. /**
  351. * Polyfill for `globalThis` object.
  352. * @returns the `globalThis` object for the given environment.
  353. * @public
  354. */
  355. function getGlobal() {
  356. if (typeof self !== 'undefined') {
  357. return self;
  358. }
  359. if (typeof window !== 'undefined') {
  360. return window;
  361. }
  362. if (typeof global !== 'undefined') {
  363. return global;
  364. }
  365. throw new Error('Unable to locate global object.');
  366. }
  367. /**
  368. * @license
  369. * Copyright 2022 Google LLC
  370. *
  371. * Licensed under the Apache License, Version 2.0 (the "License");
  372. * you may not use this file except in compliance with the License.
  373. * You may obtain a copy of the License at
  374. *
  375. * http://www.apache.org/licenses/LICENSE-2.0
  376. *
  377. * Unless required by applicable law or agreed to in writing, software
  378. * distributed under the License is distributed on an "AS IS" BASIS,
  379. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  380. * See the License for the specific language governing permissions and
  381. * limitations under the License.
  382. */
  383. const getDefaultsFromGlobal = () => getGlobal().__FIREBASE_DEFAULTS__;
  384. /**
  385. * Attempt to read defaults from a JSON string provided to
  386. * process(.)env(.)__FIREBASE_DEFAULTS__ or a JSON file whose path is in
  387. * process(.)env(.)__FIREBASE_DEFAULTS_PATH__
  388. * The dots are in parens because certain compilers (Vite?) cannot
  389. * handle seeing that variable in comments.
  390. * See https://github.com/firebase/firebase-js-sdk/issues/6838
  391. */
  392. const getDefaultsFromEnvVariable = () => {
  393. if (typeof process === 'undefined' || typeof process.env === 'undefined') {
  394. return;
  395. }
  396. const defaultsJsonString = process.env.__FIREBASE_DEFAULTS__;
  397. if (defaultsJsonString) {
  398. return JSON.parse(defaultsJsonString);
  399. }
  400. };
  401. const getDefaultsFromCookie = () => {
  402. if (typeof document === 'undefined') {
  403. return;
  404. }
  405. let match;
  406. try {
  407. match = document.cookie.match(/__FIREBASE_DEFAULTS__=([^;]+)/);
  408. }
  409. catch (e) {
  410. // Some environments such as Angular Universal SSR have a
  411. // `document` object but error on accessing `document.cookie`.
  412. return;
  413. }
  414. const decoded = match && base64Decode(match[1]);
  415. return decoded && JSON.parse(decoded);
  416. };
  417. /**
  418. * Get the __FIREBASE_DEFAULTS__ object. It checks in order:
  419. * (1) if such an object exists as a property of `globalThis`
  420. * (2) if such an object was provided on a shell environment variable
  421. * (3) if such an object exists in a cookie
  422. * @public
  423. */
  424. const getDefaults = () => {
  425. try {
  426. return (getDefaultsFromGlobal() ||
  427. getDefaultsFromEnvVariable() ||
  428. getDefaultsFromCookie());
  429. }
  430. catch (e) {
  431. /**
  432. * Catch-all for being unable to get __FIREBASE_DEFAULTS__ due
  433. * to any environment case we have not accounted for. Log to
  434. * info instead of swallowing so we can find these unknown cases
  435. * and add paths for them if needed.
  436. */
  437. console.info(`Unable to get __FIREBASE_DEFAULTS__ due to: ${e}`);
  438. return;
  439. }
  440. };
  441. /**
  442. * Returns Firebase app config stored in the __FIREBASE_DEFAULTS__ object.
  443. * @public
  444. */
  445. const getDefaultAppConfig = () => { var _a; return (_a = getDefaults()) === null || _a === void 0 ? void 0 : _a.config; };
  446. /**
  447. * @license
  448. * Copyright 2017 Google LLC
  449. *
  450. * Licensed under the Apache License, Version 2.0 (the "License");
  451. * you may not use this file except in compliance with the License.
  452. * You may obtain a copy of the License at
  453. *
  454. * http://www.apache.org/licenses/LICENSE-2.0
  455. *
  456. * Unless required by applicable law or agreed to in writing, software
  457. * distributed under the License is distributed on an "AS IS" BASIS,
  458. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  459. * See the License for the specific language governing permissions and
  460. * limitations under the License.
  461. */
  462. class Deferred {
  463. constructor() {
  464. this.reject = () => { };
  465. this.resolve = () => { };
  466. this.promise = new Promise((resolve, reject) => {
  467. this.resolve = resolve;
  468. this.reject = reject;
  469. });
  470. }
  471. /**
  472. * Our API internals are not promiseified and cannot because our callback APIs have subtle expectations around
  473. * invoking promises inline, which Promises are forbidden to do. This method accepts an optional node-style callback
  474. * and returns a node-style callback which will resolve or reject the Deferred's promise.
  475. */
  476. wrapCallback(callback) {
  477. return (error, value) => {
  478. if (error) {
  479. this.reject(error);
  480. }
  481. else {
  482. this.resolve(value);
  483. }
  484. if (typeof callback === 'function') {
  485. // Attaching noop handler just in case developer wasn't expecting
  486. // promises
  487. this.promise.catch(() => { });
  488. // Some of our callbacks don't expect a value and our own tests
  489. // assert that the parameter length is 1
  490. if (callback.length === 1) {
  491. callback(error);
  492. }
  493. else {
  494. callback(error, value);
  495. }
  496. }
  497. };
  498. }
  499. }
  500. /**
  501. * This method checks if indexedDB is supported by current browser/service worker context
  502. * @return true if indexedDB is supported by current browser/service worker context
  503. */
  504. function isIndexedDBAvailable() {
  505. try {
  506. return typeof indexedDB === 'object';
  507. }
  508. catch (e) {
  509. return false;
  510. }
  511. }
  512. /**
  513. * This method validates browser/sw context for indexedDB by opening a dummy indexedDB database and reject
  514. * if errors occur during the database open operation.
  515. *
  516. * @throws exception if current browser/sw context can't run idb.open (ex: Safari iframe, Firefox
  517. * private browsing)
  518. */
  519. function validateIndexedDBOpenable() {
  520. return new Promise((resolve, reject) => {
  521. try {
  522. let preExist = true;
  523. const DB_CHECK_NAME = 'validate-browser-context-for-indexeddb-analytics-module';
  524. const request = self.indexedDB.open(DB_CHECK_NAME);
  525. request.onsuccess = () => {
  526. request.result.close();
  527. // delete database only when it doesn't pre-exist
  528. if (!preExist) {
  529. self.indexedDB.deleteDatabase(DB_CHECK_NAME);
  530. }
  531. resolve(true);
  532. };
  533. request.onupgradeneeded = () => {
  534. preExist = false;
  535. };
  536. request.onerror = () => {
  537. var _a;
  538. reject(((_a = request.error) === null || _a === void 0 ? void 0 : _a.message) || '');
  539. };
  540. }
  541. catch (error) {
  542. reject(error);
  543. }
  544. });
  545. }
  546. /**
  547. * @license
  548. * Copyright 2017 Google LLC
  549. *
  550. * Licensed under the Apache License, Version 2.0 (the "License");
  551. * you may not use this file except in compliance with the License.
  552. * You may obtain a copy of the License at
  553. *
  554. * http://www.apache.org/licenses/LICENSE-2.0
  555. *
  556. * Unless required by applicable law or agreed to in writing, software
  557. * distributed under the License is distributed on an "AS IS" BASIS,
  558. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  559. * See the License for the specific language governing permissions and
  560. * limitations under the License.
  561. */
  562. /**
  563. * @fileoverview Standardized Firebase Error.
  564. *
  565. * Usage:
  566. *
  567. * // Typescript string literals for type-safe codes
  568. * type Err =
  569. * 'unknown' |
  570. * 'object-not-found'
  571. * ;
  572. *
  573. * // Closure enum for type-safe error codes
  574. * // at-enum {string}
  575. * var Err = {
  576. * UNKNOWN: 'unknown',
  577. * OBJECT_NOT_FOUND: 'object-not-found',
  578. * }
  579. *
  580. * let errors: Map<Err, string> = {
  581. * 'generic-error': "Unknown error",
  582. * 'file-not-found': "Could not find file: {$file}",
  583. * };
  584. *
  585. * // Type-safe function - must pass a valid error code as param.
  586. * let error = new ErrorFactory<Err>('service', 'Service', errors);
  587. *
  588. * ...
  589. * throw error.create(Err.GENERIC);
  590. * ...
  591. * throw error.create(Err.FILE_NOT_FOUND, {'file': fileName});
  592. * ...
  593. * // Service: Could not file file: foo.txt (service/file-not-found).
  594. *
  595. * catch (e) {
  596. * assert(e.message === "Could not find file: foo.txt.");
  597. * if ((e as FirebaseError)?.code === 'service/file-not-found') {
  598. * console.log("Could not read file: " + e['file']);
  599. * }
  600. * }
  601. */
  602. const ERROR_NAME = 'FirebaseError';
  603. // Based on code from:
  604. // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error#Custom_Error_Types
  605. class FirebaseError extends Error {
  606. constructor(
  607. /** The error code for this error. */
  608. code, message,
  609. /** Custom data for this error. */
  610. customData) {
  611. super(message);
  612. this.code = code;
  613. this.customData = customData;
  614. /** The custom name for all FirebaseErrors. */
  615. this.name = ERROR_NAME;
  616. // Fix For ES5
  617. // https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work
  618. Object.setPrototypeOf(this, FirebaseError.prototype);
  619. // Maintains proper stack trace for where our error was thrown.
  620. // Only available on V8.
  621. if (Error.captureStackTrace) {
  622. Error.captureStackTrace(this, ErrorFactory.prototype.create);
  623. }
  624. }
  625. }
  626. class ErrorFactory {
  627. constructor(service, serviceName, errors) {
  628. this.service = service;
  629. this.serviceName = serviceName;
  630. this.errors = errors;
  631. }
  632. create(code, ...data) {
  633. const customData = data[0] || {};
  634. const fullCode = `${this.service}/${code}`;
  635. const template = this.errors[code];
  636. const message = template ? replaceTemplate(template, customData) : 'Error';
  637. // Service Name: Error message (service/code).
  638. const fullMessage = `${this.serviceName}: ${message} (${fullCode}).`;
  639. const error = new FirebaseError(fullCode, fullMessage, customData);
  640. return error;
  641. }
  642. }
  643. function replaceTemplate(template, data) {
  644. return template.replace(PATTERN, (_, key) => {
  645. const value = data[key];
  646. return value != null ? String(value) : `<${key}?>`;
  647. });
  648. }
  649. const PATTERN = /\{\$([^}]+)}/g;
  650. /**
  651. * Deep equal two objects. Support Arrays and Objects.
  652. */
  653. function deepEqual(a, b) {
  654. if (a === b) {
  655. return true;
  656. }
  657. const aKeys = Object.keys(a);
  658. const bKeys = Object.keys(b);
  659. for (const k of aKeys) {
  660. if (!bKeys.includes(k)) {
  661. return false;
  662. }
  663. const aProp = a[k];
  664. const bProp = b[k];
  665. if (isObject(aProp) && isObject(bProp)) {
  666. if (!deepEqual(aProp, bProp)) {
  667. return false;
  668. }
  669. }
  670. else if (aProp !== bProp) {
  671. return false;
  672. }
  673. }
  674. for (const k of bKeys) {
  675. if (!aKeys.includes(k)) {
  676. return false;
  677. }
  678. }
  679. return true;
  680. }
  681. function isObject(thing) {
  682. return thing !== null && typeof thing === 'object';
  683. }
  684. /**
  685. * Component for service name T, e.g. `auth`, `auth-internal`
  686. */
  687. class Component {
  688. /**
  689. *
  690. * @param name The public service name, e.g. app, auth, firestore, database
  691. * @param instanceFactory Service factory responsible for creating the public interface
  692. * @param type whether the service provided by the component is public or private
  693. */
  694. constructor(name, instanceFactory, type) {
  695. this.name = name;
  696. this.instanceFactory = instanceFactory;
  697. this.type = type;
  698. this.multipleInstances = false;
  699. /**
  700. * Properties to be added to the service namespace
  701. */
  702. this.serviceProps = {};
  703. this.instantiationMode = "LAZY" /* InstantiationMode.LAZY */;
  704. this.onInstanceCreated = null;
  705. }
  706. setInstantiationMode(mode) {
  707. this.instantiationMode = mode;
  708. return this;
  709. }
  710. setMultipleInstances(multipleInstances) {
  711. this.multipleInstances = multipleInstances;
  712. return this;
  713. }
  714. setServiceProps(props) {
  715. this.serviceProps = props;
  716. return this;
  717. }
  718. setInstanceCreatedCallback(callback) {
  719. this.onInstanceCreated = callback;
  720. return this;
  721. }
  722. }
  723. /**
  724. * @license
  725. * Copyright 2019 Google LLC
  726. *
  727. * Licensed under the Apache License, Version 2.0 (the "License");
  728. * you may not use this file except in compliance with the License.
  729. * You may obtain a copy of the License at
  730. *
  731. * http://www.apache.org/licenses/LICENSE-2.0
  732. *
  733. * Unless required by applicable law or agreed to in writing, software
  734. * distributed under the License is distributed on an "AS IS" BASIS,
  735. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  736. * See the License for the specific language governing permissions and
  737. * limitations under the License.
  738. */
  739. const DEFAULT_ENTRY_NAME$1 = '[DEFAULT]';
  740. /**
  741. * @license
  742. * Copyright 2019 Google LLC
  743. *
  744. * Licensed under the Apache License, Version 2.0 (the "License");
  745. * you may not use this file except in compliance with the License.
  746. * You may obtain a copy of the License at
  747. *
  748. * http://www.apache.org/licenses/LICENSE-2.0
  749. *
  750. * Unless required by applicable law or agreed to in writing, software
  751. * distributed under the License is distributed on an "AS IS" BASIS,
  752. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  753. * See the License for the specific language governing permissions and
  754. * limitations under the License.
  755. */
  756. /**
  757. * Provider for instance for service name T, e.g. 'auth', 'auth-internal'
  758. * NameServiceMapping[T] is an alias for the type of the instance
  759. */
  760. class Provider {
  761. constructor(name, container) {
  762. this.name = name;
  763. this.container = container;
  764. this.component = null;
  765. this.instances = new Map();
  766. this.instancesDeferred = new Map();
  767. this.instancesOptions = new Map();
  768. this.onInitCallbacks = new Map();
  769. }
  770. /**
  771. * @param identifier A provider can provide mulitple instances of a service
  772. * if this.component.multipleInstances is true.
  773. */
  774. get(identifier) {
  775. // if multipleInstances is not supported, use the default name
  776. const normalizedIdentifier = this.normalizeInstanceIdentifier(identifier);
  777. if (!this.instancesDeferred.has(normalizedIdentifier)) {
  778. const deferred = new Deferred();
  779. this.instancesDeferred.set(normalizedIdentifier, deferred);
  780. if (this.isInitialized(normalizedIdentifier) ||
  781. this.shouldAutoInitialize()) {
  782. // initialize the service if it can be auto-initialized
  783. try {
  784. const instance = this.getOrInitializeService({
  785. instanceIdentifier: normalizedIdentifier
  786. });
  787. if (instance) {
  788. deferred.resolve(instance);
  789. }
  790. }
  791. catch (e) {
  792. // when the instance factory throws an exception during get(), it should not cause
  793. // a fatal error. We just return the unresolved promise in this case.
  794. }
  795. }
  796. }
  797. return this.instancesDeferred.get(normalizedIdentifier).promise;
  798. }
  799. getImmediate(options) {
  800. var _a;
  801. // if multipleInstances is not supported, use the default name
  802. const normalizedIdentifier = this.normalizeInstanceIdentifier(options === null || options === void 0 ? void 0 : options.identifier);
  803. const optional = (_a = options === null || options === void 0 ? void 0 : options.optional) !== null && _a !== void 0 ? _a : false;
  804. if (this.isInitialized(normalizedIdentifier) ||
  805. this.shouldAutoInitialize()) {
  806. try {
  807. return this.getOrInitializeService({
  808. instanceIdentifier: normalizedIdentifier
  809. });
  810. }
  811. catch (e) {
  812. if (optional) {
  813. return null;
  814. }
  815. else {
  816. throw e;
  817. }
  818. }
  819. }
  820. else {
  821. // In case a component is not initialized and should/can not be auto-initialized at the moment, return null if the optional flag is set, or throw
  822. if (optional) {
  823. return null;
  824. }
  825. else {
  826. throw Error(`Service ${this.name} is not available`);
  827. }
  828. }
  829. }
  830. getComponent() {
  831. return this.component;
  832. }
  833. setComponent(component) {
  834. if (component.name !== this.name) {
  835. throw Error(`Mismatching Component ${component.name} for Provider ${this.name}.`);
  836. }
  837. if (this.component) {
  838. throw Error(`Component for ${this.name} has already been provided`);
  839. }
  840. this.component = component;
  841. // return early without attempting to initialize the component if the component requires explicit initialization (calling `Provider.initialize()`)
  842. if (!this.shouldAutoInitialize()) {
  843. return;
  844. }
  845. // if the service is eager, initialize the default instance
  846. if (isComponentEager(component)) {
  847. try {
  848. this.getOrInitializeService({ instanceIdentifier: DEFAULT_ENTRY_NAME$1 });
  849. }
  850. catch (e) {
  851. // when the instance factory for an eager Component throws an exception during the eager
  852. // initialization, it should not cause a fatal error.
  853. // TODO: Investigate if we need to make it configurable, because some component may want to cause
  854. // a fatal error in this case?
  855. }
  856. }
  857. // Create service instances for the pending promises and resolve them
  858. // NOTE: if this.multipleInstances is false, only the default instance will be created
  859. // and all promises with resolve with it regardless of the identifier.
  860. for (const [instanceIdentifier, instanceDeferred] of this.instancesDeferred.entries()) {
  861. const normalizedIdentifier = this.normalizeInstanceIdentifier(instanceIdentifier);
  862. try {
  863. // `getOrInitializeService()` should always return a valid instance since a component is guaranteed. use ! to make typescript happy.
  864. const instance = this.getOrInitializeService({
  865. instanceIdentifier: normalizedIdentifier
  866. });
  867. instanceDeferred.resolve(instance);
  868. }
  869. catch (e) {
  870. // when the instance factory throws an exception, it should not cause
  871. // a fatal error. We just leave the promise unresolved.
  872. }
  873. }
  874. }
  875. clearInstance(identifier = DEFAULT_ENTRY_NAME$1) {
  876. this.instancesDeferred.delete(identifier);
  877. this.instancesOptions.delete(identifier);
  878. this.instances.delete(identifier);
  879. }
  880. // app.delete() will call this method on every provider to delete the services
  881. // TODO: should we mark the provider as deleted?
  882. async delete() {
  883. const services = Array.from(this.instances.values());
  884. await Promise.all([
  885. ...services
  886. .filter(service => 'INTERNAL' in service) // legacy services
  887. // eslint-disable-next-line @typescript-eslint/no-explicit-any
  888. .map(service => service.INTERNAL.delete()),
  889. ...services
  890. .filter(service => '_delete' in service) // modularized services
  891. // eslint-disable-next-line @typescript-eslint/no-explicit-any
  892. .map(service => service._delete())
  893. ]);
  894. }
  895. isComponentSet() {
  896. return this.component != null;
  897. }
  898. isInitialized(identifier = DEFAULT_ENTRY_NAME$1) {
  899. return this.instances.has(identifier);
  900. }
  901. getOptions(identifier = DEFAULT_ENTRY_NAME$1) {
  902. return this.instancesOptions.get(identifier) || {};
  903. }
  904. initialize(opts = {}) {
  905. const { options = {} } = opts;
  906. const normalizedIdentifier = this.normalizeInstanceIdentifier(opts.instanceIdentifier);
  907. if (this.isInitialized(normalizedIdentifier)) {
  908. throw Error(`${this.name}(${normalizedIdentifier}) has already been initialized`);
  909. }
  910. if (!this.isComponentSet()) {
  911. throw Error(`Component ${this.name} has not been registered yet`);
  912. }
  913. const instance = this.getOrInitializeService({
  914. instanceIdentifier: normalizedIdentifier,
  915. options
  916. });
  917. // resolve any pending promise waiting for the service instance
  918. for (const [instanceIdentifier, instanceDeferred] of this.instancesDeferred.entries()) {
  919. const normalizedDeferredIdentifier = this.normalizeInstanceIdentifier(instanceIdentifier);
  920. if (normalizedIdentifier === normalizedDeferredIdentifier) {
  921. instanceDeferred.resolve(instance);
  922. }
  923. }
  924. return instance;
  925. }
  926. /**
  927. *
  928. * @param callback - a function that will be invoked after the provider has been initialized by calling provider.initialize().
  929. * The function is invoked SYNCHRONOUSLY, so it should not execute any longrunning tasks in order to not block the program.
  930. *
  931. * @param identifier An optional instance identifier
  932. * @returns a function to unregister the callback
  933. */
  934. onInit(callback, identifier) {
  935. var _a;
  936. const normalizedIdentifier = this.normalizeInstanceIdentifier(identifier);
  937. const existingCallbacks = (_a = this.onInitCallbacks.get(normalizedIdentifier)) !== null && _a !== void 0 ? _a : new Set();
  938. existingCallbacks.add(callback);
  939. this.onInitCallbacks.set(normalizedIdentifier, existingCallbacks);
  940. const existingInstance = this.instances.get(normalizedIdentifier);
  941. if (existingInstance) {
  942. callback(existingInstance, normalizedIdentifier);
  943. }
  944. return () => {
  945. existingCallbacks.delete(callback);
  946. };
  947. }
  948. /**
  949. * Invoke onInit callbacks synchronously
  950. * @param instance the service instance`
  951. */
  952. invokeOnInitCallbacks(instance, identifier) {
  953. const callbacks = this.onInitCallbacks.get(identifier);
  954. if (!callbacks) {
  955. return;
  956. }
  957. for (const callback of callbacks) {
  958. try {
  959. callback(instance, identifier);
  960. }
  961. catch (_a) {
  962. // ignore errors in the onInit callback
  963. }
  964. }
  965. }
  966. getOrInitializeService({ instanceIdentifier, options = {} }) {
  967. let instance = this.instances.get(instanceIdentifier);
  968. if (!instance && this.component) {
  969. instance = this.component.instanceFactory(this.container, {
  970. instanceIdentifier: normalizeIdentifierForFactory(instanceIdentifier),
  971. options
  972. });
  973. this.instances.set(instanceIdentifier, instance);
  974. this.instancesOptions.set(instanceIdentifier, options);
  975. /**
  976. * Invoke onInit listeners.
  977. * Note this.component.onInstanceCreated is different, which is used by the component creator,
  978. * while onInit listeners are registered by consumers of the provider.
  979. */
  980. this.invokeOnInitCallbacks(instance, instanceIdentifier);
  981. /**
  982. * Order is important
  983. * onInstanceCreated() should be called after this.instances.set(instanceIdentifier, instance); which
  984. * makes `isInitialized()` return true.
  985. */
  986. if (this.component.onInstanceCreated) {
  987. try {
  988. this.component.onInstanceCreated(this.container, instanceIdentifier, instance);
  989. }
  990. catch (_a) {
  991. // ignore errors in the onInstanceCreatedCallback
  992. }
  993. }
  994. }
  995. return instance || null;
  996. }
  997. normalizeInstanceIdentifier(identifier = DEFAULT_ENTRY_NAME$1) {
  998. if (this.component) {
  999. return this.component.multipleInstances ? identifier : DEFAULT_ENTRY_NAME$1;
  1000. }
  1001. else {
  1002. return identifier; // assume multiple instances are supported before the component is provided.
  1003. }
  1004. }
  1005. shouldAutoInitialize() {
  1006. return (!!this.component &&
  1007. this.component.instantiationMode !== "EXPLICIT" /* InstantiationMode.EXPLICIT */);
  1008. }
  1009. }
  1010. // undefined should be passed to the service factory for the default instance
  1011. function normalizeIdentifierForFactory(identifier) {
  1012. return identifier === DEFAULT_ENTRY_NAME$1 ? undefined : identifier;
  1013. }
  1014. function isComponentEager(component) {
  1015. return component.instantiationMode === "EAGER" /* InstantiationMode.EAGER */;
  1016. }
  1017. /**
  1018. * @license
  1019. * Copyright 2019 Google LLC
  1020. *
  1021. * Licensed under the Apache License, Version 2.0 (the "License");
  1022. * you may not use this file except in compliance with the License.
  1023. * You may obtain a copy of the License at
  1024. *
  1025. * http://www.apache.org/licenses/LICENSE-2.0
  1026. *
  1027. * Unless required by applicable law or agreed to in writing, software
  1028. * distributed under the License is distributed on an "AS IS" BASIS,
  1029. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  1030. * See the License for the specific language governing permissions and
  1031. * limitations under the License.
  1032. */
  1033. /**
  1034. * ComponentContainer that provides Providers for service name T, e.g. `auth`, `auth-internal`
  1035. */
  1036. class ComponentContainer {
  1037. constructor(name) {
  1038. this.name = name;
  1039. this.providers = new Map();
  1040. }
  1041. /**
  1042. *
  1043. * @param component Component being added
  1044. * @param overwrite When a component with the same name has already been registered,
  1045. * if overwrite is true: overwrite the existing component with the new component and create a new
  1046. * provider with the new component. It can be useful in tests where you want to use different mocks
  1047. * for different tests.
  1048. * if overwrite is false: throw an exception
  1049. */
  1050. addComponent(component) {
  1051. const provider = this.getProvider(component.name);
  1052. if (provider.isComponentSet()) {
  1053. throw new Error(`Component ${component.name} has already been registered with ${this.name}`);
  1054. }
  1055. provider.setComponent(component);
  1056. }
  1057. addOrOverwriteComponent(component) {
  1058. const provider = this.getProvider(component.name);
  1059. if (provider.isComponentSet()) {
  1060. // delete the existing provider from the container, so we can register the new component
  1061. this.providers.delete(component.name);
  1062. }
  1063. this.addComponent(component);
  1064. }
  1065. /**
  1066. * getProvider provides a type safe interface where it can only be called with a field name
  1067. * present in NameServiceMapping interface.
  1068. *
  1069. * Firebase SDKs providing services should extend NameServiceMapping interface to register
  1070. * themselves.
  1071. */
  1072. getProvider(name) {
  1073. if (this.providers.has(name)) {
  1074. return this.providers.get(name);
  1075. }
  1076. // create a Provider for a service that hasn't registered with Firebase
  1077. const provider = new Provider(name, this);
  1078. this.providers.set(name, provider);
  1079. return provider;
  1080. }
  1081. getProviders() {
  1082. return Array.from(this.providers.values());
  1083. }
  1084. }
  1085. /**
  1086. * @license
  1087. * Copyright 2017 Google LLC
  1088. *
  1089. * Licensed under the Apache License, Version 2.0 (the "License");
  1090. * you may not use this file except in compliance with the License.
  1091. * You may obtain a copy of the License at
  1092. *
  1093. * http://www.apache.org/licenses/LICENSE-2.0
  1094. *
  1095. * Unless required by applicable law or agreed to in writing, software
  1096. * distributed under the License is distributed on an "AS IS" BASIS,
  1097. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  1098. * See the License for the specific language governing permissions and
  1099. * limitations under the License.
  1100. */
  1101. /**
  1102. * A container for all of the Logger instances
  1103. */
  1104. const instances = [];
  1105. /**
  1106. * The JS SDK supports 5 log levels and also allows a user the ability to
  1107. * silence the logs altogether.
  1108. *
  1109. * The order is a follows:
  1110. * DEBUG < VERBOSE < INFO < WARN < ERROR
  1111. *
  1112. * All of the log types above the current log level will be captured (i.e. if
  1113. * you set the log level to `INFO`, errors will still be logged, but `DEBUG` and
  1114. * `VERBOSE` logs will not)
  1115. */
  1116. var LogLevel;
  1117. (function (LogLevel) {
  1118. LogLevel[LogLevel["DEBUG"] = 0] = "DEBUG";
  1119. LogLevel[LogLevel["VERBOSE"] = 1] = "VERBOSE";
  1120. LogLevel[LogLevel["INFO"] = 2] = "INFO";
  1121. LogLevel[LogLevel["WARN"] = 3] = "WARN";
  1122. LogLevel[LogLevel["ERROR"] = 4] = "ERROR";
  1123. LogLevel[LogLevel["SILENT"] = 5] = "SILENT";
  1124. })(LogLevel || (LogLevel = {}));
  1125. const levelStringToEnum = {
  1126. 'debug': LogLevel.DEBUG,
  1127. 'verbose': LogLevel.VERBOSE,
  1128. 'info': LogLevel.INFO,
  1129. 'warn': LogLevel.WARN,
  1130. 'error': LogLevel.ERROR,
  1131. 'silent': LogLevel.SILENT
  1132. };
  1133. /**
  1134. * The default log level
  1135. */
  1136. const defaultLogLevel = LogLevel.INFO;
  1137. /**
  1138. * By default, `console.debug` is not displayed in the developer console (in
  1139. * chrome). To avoid forcing users to have to opt-in to these logs twice
  1140. * (i.e. once for firebase, and once in the console), we are sending `DEBUG`
  1141. * logs to the `console.log` function.
  1142. */
  1143. const ConsoleMethod = {
  1144. [LogLevel.DEBUG]: 'log',
  1145. [LogLevel.VERBOSE]: 'log',
  1146. [LogLevel.INFO]: 'info',
  1147. [LogLevel.WARN]: 'warn',
  1148. [LogLevel.ERROR]: 'error'
  1149. };
  1150. /**
  1151. * The default log handler will forward DEBUG, VERBOSE, INFO, WARN, and ERROR
  1152. * messages on to their corresponding console counterparts (if the log method
  1153. * is supported by the current log level)
  1154. */
  1155. const defaultLogHandler = (instance, logType, ...args) => {
  1156. if (logType < instance.logLevel) {
  1157. return;
  1158. }
  1159. const now = new Date().toISOString();
  1160. const method = ConsoleMethod[logType];
  1161. if (method) {
  1162. console[method](`[${now}] ${instance.name}:`, ...args);
  1163. }
  1164. else {
  1165. throw new Error(`Attempted to log a message with an invalid logType (value: ${logType})`);
  1166. }
  1167. };
  1168. class Logger {
  1169. /**
  1170. * Gives you an instance of a Logger to capture messages according to
  1171. * Firebase's logging scheme.
  1172. *
  1173. * @param name The name that the logs will be associated with
  1174. */
  1175. constructor(name) {
  1176. this.name = name;
  1177. /**
  1178. * The log level of the given Logger instance.
  1179. */
  1180. this._logLevel = defaultLogLevel;
  1181. /**
  1182. * The main (internal) log handler for the Logger instance.
  1183. * Can be set to a new function in internal package code but not by user.
  1184. */
  1185. this._logHandler = defaultLogHandler;
  1186. /**
  1187. * The optional, additional, user-defined log handler for the Logger instance.
  1188. */
  1189. this._userLogHandler = null;
  1190. /**
  1191. * Capture the current instance for later use
  1192. */
  1193. instances.push(this);
  1194. }
  1195. get logLevel() {
  1196. return this._logLevel;
  1197. }
  1198. set logLevel(val) {
  1199. if (!(val in LogLevel)) {
  1200. throw new TypeError(`Invalid value "${val}" assigned to \`logLevel\``);
  1201. }
  1202. this._logLevel = val;
  1203. }
  1204. // Workaround for setter/getter having to be the same type.
  1205. setLogLevel(val) {
  1206. this._logLevel = typeof val === 'string' ? levelStringToEnum[val] : val;
  1207. }
  1208. get logHandler() {
  1209. return this._logHandler;
  1210. }
  1211. set logHandler(val) {
  1212. if (typeof val !== 'function') {
  1213. throw new TypeError('Value assigned to `logHandler` must be a function');
  1214. }
  1215. this._logHandler = val;
  1216. }
  1217. get userLogHandler() {
  1218. return this._userLogHandler;
  1219. }
  1220. set userLogHandler(val) {
  1221. this._userLogHandler = val;
  1222. }
  1223. /**
  1224. * The functions below are all based on the `console` interface
  1225. */
  1226. debug(...args) {
  1227. this._userLogHandler && this._userLogHandler(this, LogLevel.DEBUG, ...args);
  1228. this._logHandler(this, LogLevel.DEBUG, ...args);
  1229. }
  1230. log(...args) {
  1231. this._userLogHandler &&
  1232. this._userLogHandler(this, LogLevel.VERBOSE, ...args);
  1233. this._logHandler(this, LogLevel.VERBOSE, ...args);
  1234. }
  1235. info(...args) {
  1236. this._userLogHandler && this._userLogHandler(this, LogLevel.INFO, ...args);
  1237. this._logHandler(this, LogLevel.INFO, ...args);
  1238. }
  1239. warn(...args) {
  1240. this._userLogHandler && this._userLogHandler(this, LogLevel.WARN, ...args);
  1241. this._logHandler(this, LogLevel.WARN, ...args);
  1242. }
  1243. error(...args) {
  1244. this._userLogHandler && this._userLogHandler(this, LogLevel.ERROR, ...args);
  1245. this._logHandler(this, LogLevel.ERROR, ...args);
  1246. }
  1247. }
  1248. function setLogLevel$1(level) {
  1249. instances.forEach(inst => {
  1250. inst.setLogLevel(level);
  1251. });
  1252. }
  1253. function setUserLogHandler(logCallback, options) {
  1254. for (const instance of instances) {
  1255. let customLogLevel = null;
  1256. if (options && options.level) {
  1257. customLogLevel = levelStringToEnum[options.level];
  1258. }
  1259. if (logCallback === null) {
  1260. instance.userLogHandler = null;
  1261. }
  1262. else {
  1263. instance.userLogHandler = (instance, level, ...args) => {
  1264. const message = args
  1265. .map(arg => {
  1266. if (arg == null) {
  1267. return null;
  1268. }
  1269. else if (typeof arg === 'string') {
  1270. return arg;
  1271. }
  1272. else if (typeof arg === 'number' || typeof arg === 'boolean') {
  1273. return arg.toString();
  1274. }
  1275. else if (arg instanceof Error) {
  1276. return arg.message;
  1277. }
  1278. else {
  1279. try {
  1280. return JSON.stringify(arg);
  1281. }
  1282. catch (ignored) {
  1283. return null;
  1284. }
  1285. }
  1286. })
  1287. .filter(arg => arg)
  1288. .join(' ');
  1289. if (level >= (customLogLevel !== null && customLogLevel !== void 0 ? customLogLevel : instance.logLevel)) {
  1290. logCallback({
  1291. level: LogLevel[level].toLowerCase(),
  1292. message,
  1293. args,
  1294. type: instance.name
  1295. });
  1296. }
  1297. };
  1298. }
  1299. }
  1300. }
  1301. const instanceOfAny = (object, constructors) => constructors.some((c) => object instanceof c);
  1302. let idbProxyableTypes;
  1303. let cursorAdvanceMethods;
  1304. // This is a function to prevent it throwing up in node environments.
  1305. function getIdbProxyableTypes() {
  1306. return (idbProxyableTypes ||
  1307. (idbProxyableTypes = [
  1308. IDBDatabase,
  1309. IDBObjectStore,
  1310. IDBIndex,
  1311. IDBCursor,
  1312. IDBTransaction,
  1313. ]));
  1314. }
  1315. // This is a function to prevent it throwing up in node environments.
  1316. function getCursorAdvanceMethods() {
  1317. return (cursorAdvanceMethods ||
  1318. (cursorAdvanceMethods = [
  1319. IDBCursor.prototype.advance,
  1320. IDBCursor.prototype.continue,
  1321. IDBCursor.prototype.continuePrimaryKey,
  1322. ]));
  1323. }
  1324. const cursorRequestMap = new WeakMap();
  1325. const transactionDoneMap = new WeakMap();
  1326. const transactionStoreNamesMap = new WeakMap();
  1327. const transformCache = new WeakMap();
  1328. const reverseTransformCache = new WeakMap();
  1329. function promisifyRequest(request) {
  1330. const promise = new Promise((resolve, reject) => {
  1331. const unlisten = () => {
  1332. request.removeEventListener('success', success);
  1333. request.removeEventListener('error', error);
  1334. };
  1335. const success = () => {
  1336. resolve(wrap(request.result));
  1337. unlisten();
  1338. };
  1339. const error = () => {
  1340. reject(request.error);
  1341. unlisten();
  1342. };
  1343. request.addEventListener('success', success);
  1344. request.addEventListener('error', error);
  1345. });
  1346. promise
  1347. .then((value) => {
  1348. // Since cursoring reuses the IDBRequest (*sigh*), we cache it for later retrieval
  1349. // (see wrapFunction).
  1350. if (value instanceof IDBCursor) {
  1351. cursorRequestMap.set(value, request);
  1352. }
  1353. // Catching to avoid "Uncaught Promise exceptions"
  1354. })
  1355. .catch(() => { });
  1356. // This mapping exists in reverseTransformCache but doesn't doesn't exist in transformCache. This
  1357. // is because we create many promises from a single IDBRequest.
  1358. reverseTransformCache.set(promise, request);
  1359. return promise;
  1360. }
  1361. function cacheDonePromiseForTransaction(tx) {
  1362. // Early bail if we've already created a done promise for this transaction.
  1363. if (transactionDoneMap.has(tx))
  1364. return;
  1365. const done = new Promise((resolve, reject) => {
  1366. const unlisten = () => {
  1367. tx.removeEventListener('complete', complete);
  1368. tx.removeEventListener('error', error);
  1369. tx.removeEventListener('abort', error);
  1370. };
  1371. const complete = () => {
  1372. resolve();
  1373. unlisten();
  1374. };
  1375. const error = () => {
  1376. reject(tx.error || new DOMException('AbortError', 'AbortError'));
  1377. unlisten();
  1378. };
  1379. tx.addEventListener('complete', complete);
  1380. tx.addEventListener('error', error);
  1381. tx.addEventListener('abort', error);
  1382. });
  1383. // Cache it for later retrieval.
  1384. transactionDoneMap.set(tx, done);
  1385. }
  1386. let idbProxyTraps = {
  1387. get(target, prop, receiver) {
  1388. if (target instanceof IDBTransaction) {
  1389. // Special handling for transaction.done.
  1390. if (prop === 'done')
  1391. return transactionDoneMap.get(target);
  1392. // Polyfill for objectStoreNames because of Edge.
  1393. if (prop === 'objectStoreNames') {
  1394. return target.objectStoreNames || transactionStoreNamesMap.get(target);
  1395. }
  1396. // Make tx.store return the only store in the transaction, or undefined if there are many.
  1397. if (prop === 'store') {
  1398. return receiver.objectStoreNames[1]
  1399. ? undefined
  1400. : receiver.objectStore(receiver.objectStoreNames[0]);
  1401. }
  1402. }
  1403. // Else transform whatever we get back.
  1404. return wrap(target[prop]);
  1405. },
  1406. set(target, prop, value) {
  1407. target[prop] = value;
  1408. return true;
  1409. },
  1410. has(target, prop) {
  1411. if (target instanceof IDBTransaction &&
  1412. (prop === 'done' || prop === 'store')) {
  1413. return true;
  1414. }
  1415. return prop in target;
  1416. },
  1417. };
  1418. function replaceTraps(callback) {
  1419. idbProxyTraps = callback(idbProxyTraps);
  1420. }
  1421. function wrapFunction(func) {
  1422. // Due to expected object equality (which is enforced by the caching in `wrap`), we
  1423. // only create one new func per func.
  1424. // Edge doesn't support objectStoreNames (booo), so we polyfill it here.
  1425. if (func === IDBDatabase.prototype.transaction &&
  1426. !('objectStoreNames' in IDBTransaction.prototype)) {
  1427. return function (storeNames, ...args) {
  1428. const tx = func.call(unwrap(this), storeNames, ...args);
  1429. transactionStoreNamesMap.set(tx, storeNames.sort ? storeNames.sort() : [storeNames]);
  1430. return wrap(tx);
  1431. };
  1432. }
  1433. // Cursor methods are special, as the behaviour is a little more different to standard IDB. In
  1434. // IDB, you advance the cursor and wait for a new 'success' on the IDBRequest that gave you the
  1435. // cursor. It's kinda like a promise that can resolve with many values. That doesn't make sense
  1436. // with real promises, so each advance methods returns a new promise for the cursor object, or
  1437. // undefined if the end of the cursor has been reached.
  1438. if (getCursorAdvanceMethods().includes(func)) {
  1439. return function (...args) {
  1440. // Calling the original function with the proxy as 'this' causes ILLEGAL INVOCATION, so we use
  1441. // the original object.
  1442. func.apply(unwrap(this), args);
  1443. return wrap(cursorRequestMap.get(this));
  1444. };
  1445. }
  1446. return function (...args) {
  1447. // Calling the original function with the proxy as 'this' causes ILLEGAL INVOCATION, so we use
  1448. // the original object.
  1449. return wrap(func.apply(unwrap(this), args));
  1450. };
  1451. }
  1452. function transformCachableValue(value) {
  1453. if (typeof value === 'function')
  1454. return wrapFunction(value);
  1455. // This doesn't return, it just creates a 'done' promise for the transaction,
  1456. // which is later returned for transaction.done (see idbObjectHandler).
  1457. if (value instanceof IDBTransaction)
  1458. cacheDonePromiseForTransaction(value);
  1459. if (instanceOfAny(value, getIdbProxyableTypes()))
  1460. return new Proxy(value, idbProxyTraps);
  1461. // Return the same value back if we're not going to transform it.
  1462. return value;
  1463. }
  1464. function wrap(value) {
  1465. // We sometimes generate multiple promises from a single IDBRequest (eg when cursoring), because
  1466. // IDB is weird and a single IDBRequest can yield many responses, so these can't be cached.
  1467. if (value instanceof IDBRequest)
  1468. return promisifyRequest(value);
  1469. // If we've already transformed this value before, reuse the transformed value.
  1470. // This is faster, but it also provides object equality.
  1471. if (transformCache.has(value))
  1472. return transformCache.get(value);
  1473. const newValue = transformCachableValue(value);
  1474. // Not all types are transformed.
  1475. // These may be primitive types, so they can't be WeakMap keys.
  1476. if (newValue !== value) {
  1477. transformCache.set(value, newValue);
  1478. reverseTransformCache.set(newValue, value);
  1479. }
  1480. return newValue;
  1481. }
  1482. const unwrap = (value) => reverseTransformCache.get(value);
  1483. /**
  1484. * Open a database.
  1485. *
  1486. * @param name Name of the database.
  1487. * @param version Schema version.
  1488. * @param callbacks Additional callbacks.
  1489. */
  1490. function openDB(name, version, { blocked, upgrade, blocking, terminated } = {}) {
  1491. const request = indexedDB.open(name, version);
  1492. const openPromise = wrap(request);
  1493. if (upgrade) {
  1494. request.addEventListener('upgradeneeded', (event) => {
  1495. upgrade(wrap(request.result), event.oldVersion, event.newVersion, wrap(request.transaction), event);
  1496. });
  1497. }
  1498. if (blocked) {
  1499. request.addEventListener('blocked', (event) => blocked(
  1500. // Casting due to https://github.com/microsoft/TypeScript-DOM-lib-generator/pull/1405
  1501. event.oldVersion, event.newVersion, event));
  1502. }
  1503. openPromise
  1504. .then((db) => {
  1505. if (terminated)
  1506. db.addEventListener('close', () => terminated());
  1507. if (blocking) {
  1508. db.addEventListener('versionchange', (event) => blocking(event.oldVersion, event.newVersion, event));
  1509. }
  1510. })
  1511. .catch(() => { });
  1512. return openPromise;
  1513. }
  1514. const readMethods = ['get', 'getKey', 'getAll', 'getAllKeys', 'count'];
  1515. const writeMethods = ['put', 'add', 'delete', 'clear'];
  1516. const cachedMethods = new Map();
  1517. function getMethod(target, prop) {
  1518. if (!(target instanceof IDBDatabase &&
  1519. !(prop in target) &&
  1520. typeof prop === 'string')) {
  1521. return;
  1522. }
  1523. if (cachedMethods.get(prop))
  1524. return cachedMethods.get(prop);
  1525. const targetFuncName = prop.replace(/FromIndex$/, '');
  1526. const useIndex = prop !== targetFuncName;
  1527. const isWrite = writeMethods.includes(targetFuncName);
  1528. if (
  1529. // Bail if the target doesn't exist on the target. Eg, getAll isn't in Edge.
  1530. !(targetFuncName in (useIndex ? IDBIndex : IDBObjectStore).prototype) ||
  1531. !(isWrite || readMethods.includes(targetFuncName))) {
  1532. return;
  1533. }
  1534. const method = async function (storeName, ...args) {
  1535. // isWrite ? 'readwrite' : undefined gzipps better, but fails in Edge :(
  1536. const tx = this.transaction(storeName, isWrite ? 'readwrite' : 'readonly');
  1537. let target = tx.store;
  1538. if (useIndex)
  1539. target = target.index(args.shift());
  1540. // Must reject if op rejects.
  1541. // If it's a write operation, must reject if tx.done rejects.
  1542. // Must reject with op rejection first.
  1543. // Must resolve with op value.
  1544. // Must handle both promises (no unhandled rejections)
  1545. return (await Promise.all([
  1546. target[targetFuncName](...args),
  1547. isWrite && tx.done,
  1548. ]))[0];
  1549. };
  1550. cachedMethods.set(prop, method);
  1551. return method;
  1552. }
  1553. replaceTraps((oldTraps) => ({
  1554. ...oldTraps,
  1555. get: (target, prop, receiver) => getMethod(target, prop) || oldTraps.get(target, prop, receiver),
  1556. has: (target, prop) => !!getMethod(target, prop) || oldTraps.has(target, prop),
  1557. }));
  1558. /**
  1559. * @license
  1560. * Copyright 2019 Google LLC
  1561. *
  1562. * Licensed under the Apache License, Version 2.0 (the "License");
  1563. * you may not use this file except in compliance with the License.
  1564. * You may obtain a copy of the License at
  1565. *
  1566. * http://www.apache.org/licenses/LICENSE-2.0
  1567. *
  1568. * Unless required by applicable law or agreed to in writing, software
  1569. * distributed under the License is distributed on an "AS IS" BASIS,
  1570. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  1571. * See the License for the specific language governing permissions and
  1572. * limitations under the License.
  1573. */
  1574. class PlatformLoggerServiceImpl {
  1575. constructor(container) {
  1576. this.container = container;
  1577. }
  1578. // In initial implementation, this will be called by installations on
  1579. // auth token refresh, and installations will send this string.
  1580. getPlatformInfoString() {
  1581. const providers = this.container.getProviders();
  1582. // Loop through providers and get library/version pairs from any that are
  1583. // version components.
  1584. return providers
  1585. .map(provider => {
  1586. if (isVersionServiceProvider(provider)) {
  1587. const service = provider.getImmediate();
  1588. return `${service.library}/${service.version}`;
  1589. }
  1590. else {
  1591. return null;
  1592. }
  1593. })
  1594. .filter(logString => logString)
  1595. .join(' ');
  1596. }
  1597. }
  1598. /**
  1599. *
  1600. * @param provider check if this provider provides a VersionService
  1601. *
  1602. * NOTE: Using Provider<'app-version'> is a hack to indicate that the provider
  1603. * provides VersionService. The provider is not necessarily a 'app-version'
  1604. * provider.
  1605. */
  1606. function isVersionServiceProvider(provider) {
  1607. const component = provider.getComponent();
  1608. return (component === null || component === void 0 ? void 0 : component.type) === "VERSION" /* ComponentType.VERSION */;
  1609. }
  1610. const name$o = "https://www.gstatic.com/firebasejs/9.23.0/firebase-app.js";
  1611. const version$1 = "0.9.13";
  1612. /**
  1613. * @license
  1614. * Copyright 2019 Google LLC
  1615. *
  1616. * Licensed under the Apache License, Version 2.0 (the "License");
  1617. * you may not use this file except in compliance with the License.
  1618. * You may obtain a copy of the License at
  1619. *
  1620. * http://www.apache.org/licenses/LICENSE-2.0
  1621. *
  1622. * Unless required by applicable law or agreed to in writing, software
  1623. * distributed under the License is distributed on an "AS IS" BASIS,
  1624. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  1625. * See the License for the specific language governing permissions and
  1626. * limitations under the License.
  1627. */
  1628. const logger = new Logger('https://www.gstatic.com/firebasejs/9.23.0/firebase-app.js');
  1629. const name$n = "@firebase/app-compat";
  1630. const name$m = "@firebase/analytics-compat";
  1631. const name$l = "@firebase/analytics";
  1632. const name$k = "@firebase/app-check-compat";
  1633. const name$j = "@firebase/app-check";
  1634. const name$i = "@firebase/auth";
  1635. const name$h = "@firebase/auth-compat";
  1636. const name$g = "@firebase/database";
  1637. const name$f = "@firebase/database-compat";
  1638. const name$e = "@firebase/functions";
  1639. const name$d = "@firebase/functions-compat";
  1640. const name$c = "@firebase/installations";
  1641. const name$b = "@firebase/installations-compat";
  1642. const name$a = "@firebase/messaging";
  1643. const name$9 = "@firebase/messaging-compat";
  1644. const name$8 = "@firebase/performance";
  1645. const name$7 = "@firebase/performance-compat";
  1646. const name$6 = "@firebase/remote-config";
  1647. const name$5 = "@firebase/remote-config-compat";
  1648. const name$4 = "@firebase/storage";
  1649. const name$3 = "@firebase/storage-compat";
  1650. const name$2 = "@firebase/firestore";
  1651. const name$1 = "@firebase/firestore-compat";
  1652. const name$p = "firebase";
  1653. const version$2 = "9.23.0";
  1654. /**
  1655. * @license
  1656. * Copyright 2019 Google LLC
  1657. *
  1658. * Licensed under the Apache License, Version 2.0 (the "License");
  1659. * you may not use this file except in compliance with the License.
  1660. * You may obtain a copy of the License at
  1661. *
  1662. * http://www.apache.org/licenses/LICENSE-2.0
  1663. *
  1664. * Unless required by applicable law or agreed to in writing, software
  1665. * distributed under the License is distributed on an "AS IS" BASIS,
  1666. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  1667. * See the License for the specific language governing permissions and
  1668. * limitations under the License.
  1669. */
  1670. /**
  1671. * The default app name
  1672. *
  1673. * @internal
  1674. */
  1675. const DEFAULT_ENTRY_NAME = '[DEFAULT]';
  1676. const PLATFORM_LOG_STRING = {
  1677. [name$o]: 'fire-core',
  1678. [name$n]: 'fire-core-compat',
  1679. [name$l]: 'fire-analytics',
  1680. [name$m]: 'fire-analytics-compat',
  1681. [name$j]: 'fire-app-check',
  1682. [name$k]: 'fire-app-check-compat',
  1683. [name$i]: 'fire-auth',
  1684. [name$h]: 'fire-auth-compat',
  1685. [name$g]: 'fire-rtdb',
  1686. [name$f]: 'fire-rtdb-compat',
  1687. [name$e]: 'fire-fn',
  1688. [name$d]: 'fire-fn-compat',
  1689. [name$c]: 'fire-iid',
  1690. [name$b]: 'fire-iid-compat',
  1691. [name$a]: 'fire-fcm',
  1692. [name$9]: 'fire-fcm-compat',
  1693. [name$8]: 'fire-perf',
  1694. [name$7]: 'fire-perf-compat',
  1695. [name$6]: 'fire-rc',
  1696. [name$5]: 'fire-rc-compat',
  1697. [name$4]: 'fire-gcs',
  1698. [name$3]: 'fire-gcs-compat',
  1699. [name$2]: 'fire-fst',
  1700. [name$1]: 'fire-fst-compat',
  1701. 'fire-js': 'fire-js',
  1702. [name$p]: 'fire-js-all'
  1703. };
  1704. /**
  1705. * @license
  1706. * Copyright 2019 Google LLC
  1707. *
  1708. * Licensed under the Apache License, Version 2.0 (the "License");
  1709. * you may not use this file except in compliance with the License.
  1710. * You may obtain a copy of the License at
  1711. *
  1712. * http://www.apache.org/licenses/LICENSE-2.0
  1713. *
  1714. * Unless required by applicable law or agreed to in writing, software
  1715. * distributed under the License is distributed on an "AS IS" BASIS,
  1716. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  1717. * See the License for the specific language governing permissions and
  1718. * limitations under the License.
  1719. */
  1720. /**
  1721. * @internal
  1722. */
  1723. const _apps = new Map();
  1724. /**
  1725. * Registered components.
  1726. *
  1727. * @internal
  1728. */
  1729. // eslint-disable-next-line @typescript-eslint/no-explicit-any
  1730. const _components = new Map();
  1731. /**
  1732. * @param component - the component being added to this app's container
  1733. *
  1734. * @internal
  1735. */
  1736. function _addComponent(app, component) {
  1737. try {
  1738. app.container.addComponent(component);
  1739. }
  1740. catch (e) {
  1741. logger.debug(`Component ${component.name} failed to register with FirebaseApp ${app.name}`, e);
  1742. }
  1743. }
  1744. /**
  1745. *
  1746. * @internal
  1747. */
  1748. function _addOrOverwriteComponent(app, component) {
  1749. app.container.addOrOverwriteComponent(component);
  1750. }
  1751. /**
  1752. *
  1753. * @param component - the component to register
  1754. * @returns whether or not the component is registered successfully
  1755. *
  1756. * @internal
  1757. */
  1758. function _registerComponent(component) {
  1759. const componentName = component.name;
  1760. if (_components.has(componentName)) {
  1761. logger.debug(`There were multiple attempts to register component ${componentName}.`);
  1762. return false;
  1763. }
  1764. _components.set(componentName, component);
  1765. // add the component to existing app instances
  1766. for (const app of _apps.values()) {
  1767. _addComponent(app, component);
  1768. }
  1769. return true;
  1770. }
  1771. /**
  1772. *
  1773. * @param app - FirebaseApp instance
  1774. * @param name - service name
  1775. *
  1776. * @returns the provider for the service with the matching name
  1777. *
  1778. * @internal
  1779. */
  1780. function _getProvider(app, name) {
  1781. const heartbeatController = app.container
  1782. .getProvider('heartbeat')
  1783. .getImmediate({ optional: true });
  1784. if (heartbeatController) {
  1785. void heartbeatController.triggerHeartbeat();
  1786. }
  1787. return app.container.getProvider(name);
  1788. }
  1789. /**
  1790. *
  1791. * @param app - FirebaseApp instance
  1792. * @param name - service name
  1793. * @param instanceIdentifier - service instance identifier in case the service supports multiple instances
  1794. *
  1795. * @internal
  1796. */
  1797. function _removeServiceInstance(app, name, instanceIdentifier = DEFAULT_ENTRY_NAME) {
  1798. _getProvider(app, name).clearInstance(instanceIdentifier);
  1799. }
  1800. /**
  1801. * Test only
  1802. *
  1803. * @internal
  1804. */
  1805. function _clearComponents() {
  1806. _components.clear();
  1807. }
  1808. /**
  1809. * @license
  1810. * Copyright 2019 Google LLC
  1811. *
  1812. * Licensed under the Apache License, Version 2.0 (the "License");
  1813. * you may not use this file except in compliance with the License.
  1814. * You may obtain a copy of the License at
  1815. *
  1816. * http://www.apache.org/licenses/LICENSE-2.0
  1817. *
  1818. * Unless required by applicable law or agreed to in writing, software
  1819. * distributed under the License is distributed on an "AS IS" BASIS,
  1820. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  1821. * See the License for the specific language governing permissions and
  1822. * limitations under the License.
  1823. */
  1824. const ERRORS = {
  1825. ["no-app" /* AppError.NO_APP */]: "No Firebase App '{$appName}' has been created - " +
  1826. 'call initializeApp() first',
  1827. ["bad-app-name" /* AppError.BAD_APP_NAME */]: "Illegal App name: '{$appName}",
  1828. ["duplicate-app" /* AppError.DUPLICATE_APP */]: "Firebase App named '{$appName}' already exists with different options or config",
  1829. ["app-deleted" /* AppError.APP_DELETED */]: "Firebase App named '{$appName}' already deleted",
  1830. ["no-options" /* AppError.NO_OPTIONS */]: 'Need to provide options, when not being deployed to hosting via source.',
  1831. ["invalid-app-argument" /* AppError.INVALID_APP_ARGUMENT */]: 'firebase.{$appName}() takes either no argument or a ' +
  1832. 'Firebase App instance.',
  1833. ["invalid-log-argument" /* AppError.INVALID_LOG_ARGUMENT */]: 'First argument to `onLog` must be null or a function.',
  1834. ["idb-open" /* AppError.IDB_OPEN */]: 'Error thrown when opening IndexedDB. Original error: {$originalErrorMessage}.',
  1835. ["idb-get" /* AppError.IDB_GET */]: 'Error thrown when reading from IndexedDB. Original error: {$originalErrorMessage}.',
  1836. ["idb-set" /* AppError.IDB_WRITE */]: 'Error thrown when writing to IndexedDB. Original error: {$originalErrorMessage}.',
  1837. ["idb-delete" /* AppError.IDB_DELETE */]: 'Error thrown when deleting from IndexedDB. Original error: {$originalErrorMessage}.'
  1838. };
  1839. const ERROR_FACTORY = new ErrorFactory('app', 'Firebase', ERRORS);
  1840. /**
  1841. * @license
  1842. * Copyright 2019 Google LLC
  1843. *
  1844. * Licensed under the Apache License, Version 2.0 (the "License");
  1845. * you may not use this file except in compliance with the License.
  1846. * You may obtain a copy of the License at
  1847. *
  1848. * http://www.apache.org/licenses/LICENSE-2.0
  1849. *
  1850. * Unless required by applicable law or agreed to in writing, software
  1851. * distributed under the License is distributed on an "AS IS" BASIS,
  1852. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  1853. * See the License for the specific language governing permissions and
  1854. * limitations under the License.
  1855. */
  1856. class FirebaseAppImpl {
  1857. constructor(options, config, container) {
  1858. this._isDeleted = false;
  1859. this._options = Object.assign({}, options);
  1860. this._config = Object.assign({}, config);
  1861. this._name = config.name;
  1862. this._automaticDataCollectionEnabled =
  1863. config.automaticDataCollectionEnabled;
  1864. this._container = container;
  1865. this.container.addComponent(new Component('app', () => this, "PUBLIC" /* ComponentType.PUBLIC */));
  1866. }
  1867. get automaticDataCollectionEnabled() {
  1868. this.checkDestroyed();
  1869. return this._automaticDataCollectionEnabled;
  1870. }
  1871. set automaticDataCollectionEnabled(val) {
  1872. this.checkDestroyed();
  1873. this._automaticDataCollectionEnabled = val;
  1874. }
  1875. get name() {
  1876. this.checkDestroyed();
  1877. return this._name;
  1878. }
  1879. get options() {
  1880. this.checkDestroyed();
  1881. return this._options;
  1882. }
  1883. get config() {
  1884. this.checkDestroyed();
  1885. return this._config;
  1886. }
  1887. get container() {
  1888. return this._container;
  1889. }
  1890. get isDeleted() {
  1891. return this._isDeleted;
  1892. }
  1893. set isDeleted(val) {
  1894. this._isDeleted = val;
  1895. }
  1896. /**
  1897. * This function will throw an Error if the App has already been deleted -
  1898. * use before performing API actions on the App.
  1899. */
  1900. checkDestroyed() {
  1901. if (this.isDeleted) {
  1902. throw ERROR_FACTORY.create("app-deleted" /* AppError.APP_DELETED */, { appName: this._name });
  1903. }
  1904. }
  1905. }
  1906. /**
  1907. * @license
  1908. * Copyright 2019 Google LLC
  1909. *
  1910. * Licensed under the Apache License, Version 2.0 (the "License");
  1911. * you may not use this file except in compliance with the License.
  1912. * You may obtain a copy of the License at
  1913. *
  1914. * http://www.apache.org/licenses/LICENSE-2.0
  1915. *
  1916. * Unless required by applicable law or agreed to in writing, software
  1917. * distributed under the License is distributed on an "AS IS" BASIS,
  1918. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  1919. * See the License for the specific language governing permissions and
  1920. * limitations under the License.
  1921. */
  1922. /**
  1923. * The current SDK version.
  1924. *
  1925. * @public
  1926. */
  1927. const SDK_VERSION = version$2;
  1928. function initializeApp(_options, rawConfig = {}) {
  1929. let options = _options;
  1930. if (typeof rawConfig !== 'object') {
  1931. const name = rawConfig;
  1932. rawConfig = { name };
  1933. }
  1934. const config = Object.assign({ name: DEFAULT_ENTRY_NAME, automaticDataCollectionEnabled: false }, rawConfig);
  1935. const name = config.name;
  1936. if (typeof name !== 'string' || !name) {
  1937. throw ERROR_FACTORY.create("bad-app-name" /* AppError.BAD_APP_NAME */, {
  1938. appName: String(name)
  1939. });
  1940. }
  1941. options || (options = getDefaultAppConfig());
  1942. if (!options) {
  1943. throw ERROR_FACTORY.create("no-options" /* AppError.NO_OPTIONS */);
  1944. }
  1945. const existingApp = _apps.get(name);
  1946. if (existingApp) {
  1947. // return the existing app if options and config deep equal the ones in the existing app.
  1948. if (deepEqual(options, existingApp.options) &&
  1949. deepEqual(config, existingApp.config)) {
  1950. return existingApp;
  1951. }
  1952. else {
  1953. throw ERROR_FACTORY.create("duplicate-app" /* AppError.DUPLICATE_APP */, { appName: name });
  1954. }
  1955. }
  1956. const container = new ComponentContainer(name);
  1957. for (const component of _components.values()) {
  1958. container.addComponent(component);
  1959. }
  1960. const newApp = new FirebaseAppImpl(options, config, container);
  1961. _apps.set(name, newApp);
  1962. return newApp;
  1963. }
  1964. /**
  1965. * Retrieves a {@link @firebase/app#FirebaseApp} instance.
  1966. *
  1967. * When called with no arguments, the default app is returned. When an app name
  1968. * is provided, the app corresponding to that name is returned.
  1969. *
  1970. * An exception is thrown if the app being retrieved has not yet been
  1971. * initialized.
  1972. *
  1973. * @example
  1974. * ```javascript
  1975. * // Return the default app
  1976. * const app = getApp();
  1977. * ```
  1978. *
  1979. * @example
  1980. * ```javascript
  1981. * // Return a named app
  1982. * const otherApp = getApp("otherApp");
  1983. * ```
  1984. *
  1985. * @param name - Optional name of the app to return. If no name is
  1986. * provided, the default is `"[DEFAULT]"`.
  1987. *
  1988. * @returns The app corresponding to the provided app name.
  1989. * If no app name is provided, the default app is returned.
  1990. *
  1991. * @public
  1992. */
  1993. function getApp(name = DEFAULT_ENTRY_NAME) {
  1994. const app = _apps.get(name);
  1995. if (!app && name === DEFAULT_ENTRY_NAME && getDefaultAppConfig()) {
  1996. return initializeApp();
  1997. }
  1998. if (!app) {
  1999. throw ERROR_FACTORY.create("no-app" /* AppError.NO_APP */, { appName: name });
  2000. }
  2001. return app;
  2002. }
  2003. /**
  2004. * A (read-only) array of all initialized apps.
  2005. * @public
  2006. */
  2007. function getApps() {
  2008. return Array.from(_apps.values());
  2009. }
  2010. /**
  2011. * Renders this app unusable and frees the resources of all associated
  2012. * services.
  2013. *
  2014. * @example
  2015. * ```javascript
  2016. * deleteApp(app)
  2017. * .then(function() {
  2018. * console.log("App deleted successfully");
  2019. * })
  2020. * .catch(function(error) {
  2021. * console.log("Error deleting app:", error);
  2022. * });
  2023. * ```
  2024. *
  2025. * @public
  2026. */
  2027. async function deleteApp(app) {
  2028. const name = app.name;
  2029. if (_apps.has(name)) {
  2030. _apps.delete(name);
  2031. await Promise.all(app.container
  2032. .getProviders()
  2033. .map(provider => provider.delete()));
  2034. app.isDeleted = true;
  2035. }
  2036. }
  2037. /**
  2038. * Registers a library's name and version for platform logging purposes.
  2039. * @param library - Name of 1p or 3p library (e.g. firestore, angularfire)
  2040. * @param version - Current version of that library.
  2041. * @param variant - Bundle variant, e.g., node, rn, etc.
  2042. *
  2043. * @public
  2044. */
  2045. function registerVersion(libraryKeyOrName, version, variant) {
  2046. var _a;
  2047. // TODO: We can use this check to whitelist strings when/if we set up
  2048. // a good whitelist system.
  2049. let library = (_a = PLATFORM_LOG_STRING[libraryKeyOrName]) !== null && _a !== void 0 ? _a : libraryKeyOrName;
  2050. if (variant) {
  2051. library += `-${variant}`;
  2052. }
  2053. const libraryMismatch = library.match(/\s|\//);
  2054. const versionMismatch = version.match(/\s|\//);
  2055. if (libraryMismatch || versionMismatch) {
  2056. const warning = [
  2057. `Unable to register library "${library}" with version "${version}":`
  2058. ];
  2059. if (libraryMismatch) {
  2060. warning.push(`library name "${library}" contains illegal characters (whitespace or "/")`);
  2061. }
  2062. if (libraryMismatch && versionMismatch) {
  2063. warning.push('and');
  2064. }
  2065. if (versionMismatch) {
  2066. warning.push(`version name "${version}" contains illegal characters (whitespace or "/")`);
  2067. }
  2068. logger.warn(warning.join(' '));
  2069. return;
  2070. }
  2071. _registerComponent(new Component(`${library}-version`, () => ({ library, version }), "VERSION" /* ComponentType.VERSION */));
  2072. }
  2073. /**
  2074. * Sets log handler for all Firebase SDKs.
  2075. * @param logCallback - An optional custom log handler that executes user code whenever
  2076. * the Firebase SDK makes a logging call.
  2077. *
  2078. * @public
  2079. */
  2080. function onLog(logCallback, options) {
  2081. if (logCallback !== null && typeof logCallback !== 'function') {
  2082. throw ERROR_FACTORY.create("invalid-log-argument" /* AppError.INVALID_LOG_ARGUMENT */);
  2083. }
  2084. setUserLogHandler(logCallback, options);
  2085. }
  2086. /**
  2087. * Sets log level for all Firebase SDKs.
  2088. *
  2089. * All of the log types above the current log level are captured (i.e. if
  2090. * you set the log level to `info`, errors are logged, but `debug` and
  2091. * `verbose` logs are not).
  2092. *
  2093. * @public
  2094. */
  2095. function setLogLevel(logLevel) {
  2096. setLogLevel$1(logLevel);
  2097. }
  2098. /**
  2099. * @license
  2100. * Copyright 2021 Google LLC
  2101. *
  2102. * Licensed under the Apache License, Version 2.0 (the "License");
  2103. * you may not use this file except in compliance with the License.
  2104. * You may obtain a copy of the License at
  2105. *
  2106. * http://www.apache.org/licenses/LICENSE-2.0
  2107. *
  2108. * Unless required by applicable law or agreed to in writing, software
  2109. * distributed under the License is distributed on an "AS IS" BASIS,
  2110. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  2111. * See the License for the specific language governing permissions and
  2112. * limitations under the License.
  2113. */
  2114. const DB_NAME = 'firebase-heartbeat-database';
  2115. const DB_VERSION = 1;
  2116. const STORE_NAME = 'firebase-heartbeat-store';
  2117. let dbPromise = null;
  2118. function getDbPromise() {
  2119. if (!dbPromise) {
  2120. dbPromise = openDB(DB_NAME, DB_VERSION, {
  2121. upgrade: (db, oldVersion) => {
  2122. // We don't use 'break' in this switch statement, the fall-through
  2123. // behavior is what we want, because if there are multiple versions between
  2124. // the old version and the current version, we want ALL the migrations
  2125. // that correspond to those versions to run, not only the last one.
  2126. // eslint-disable-next-line default-case
  2127. switch (oldVersion) {
  2128. case 0:
  2129. db.createObjectStore(STORE_NAME);
  2130. }
  2131. }
  2132. }).catch(e => {
  2133. throw ERROR_FACTORY.create("idb-open" /* AppError.IDB_OPEN */, {
  2134. originalErrorMessage: e.message
  2135. });
  2136. });
  2137. }
  2138. return dbPromise;
  2139. }
  2140. async function readHeartbeatsFromIndexedDB(app) {
  2141. try {
  2142. const db = await getDbPromise();
  2143. const result = await db
  2144. .transaction(STORE_NAME)
  2145. .objectStore(STORE_NAME)
  2146. .get(computeKey(app));
  2147. return result;
  2148. }
  2149. catch (e) {
  2150. if (e instanceof FirebaseError) {
  2151. logger.warn(e.message);
  2152. }
  2153. else {
  2154. const idbGetError = ERROR_FACTORY.create("idb-get" /* AppError.IDB_GET */, {
  2155. originalErrorMessage: e === null || e === void 0 ? void 0 : e.message
  2156. });
  2157. logger.warn(idbGetError.message);
  2158. }
  2159. }
  2160. }
  2161. async function writeHeartbeatsToIndexedDB(app, heartbeatObject) {
  2162. try {
  2163. const db = await getDbPromise();
  2164. const tx = db.transaction(STORE_NAME, 'readwrite');
  2165. const objectStore = tx.objectStore(STORE_NAME);
  2166. await objectStore.put(heartbeatObject, computeKey(app));
  2167. await tx.done;
  2168. }
  2169. catch (e) {
  2170. if (e instanceof FirebaseError) {
  2171. logger.warn(e.message);
  2172. }
  2173. else {
  2174. const idbGetError = ERROR_FACTORY.create("idb-set" /* AppError.IDB_WRITE */, {
  2175. originalErrorMessage: e === null || e === void 0 ? void 0 : e.message
  2176. });
  2177. logger.warn(idbGetError.message);
  2178. }
  2179. }
  2180. }
  2181. function computeKey(app) {
  2182. return `${app.name}!${app.options.appId}`;
  2183. }
  2184. /**
  2185. * @license
  2186. * Copyright 2021 Google LLC
  2187. *
  2188. * Licensed under the Apache License, Version 2.0 (the "License");
  2189. * you may not use this file except in compliance with the License.
  2190. * You may obtain a copy of the License at
  2191. *
  2192. * http://www.apache.org/licenses/LICENSE-2.0
  2193. *
  2194. * Unless required by applicable law or agreed to in writing, software
  2195. * distributed under the License is distributed on an "AS IS" BASIS,
  2196. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  2197. * See the License for the specific language governing permissions and
  2198. * limitations under the License.
  2199. */
  2200. const MAX_HEADER_BYTES = 1024;
  2201. // 30 days
  2202. const STORED_HEARTBEAT_RETENTION_MAX_MILLIS = 30 * 24 * 60 * 60 * 1000;
  2203. class HeartbeatServiceImpl {
  2204. constructor(container) {
  2205. this.container = container;
  2206. /**
  2207. * In-memory cache for heartbeats, used by getHeartbeatsHeader() to generate
  2208. * the header string.
  2209. * Stores one record per date. This will be consolidated into the standard
  2210. * format of one record per user agent string before being sent as a header.
  2211. * Populated from indexedDB when the controller is instantiated and should
  2212. * be kept in sync with indexedDB.
  2213. * Leave public for easier testing.
  2214. */
  2215. this._heartbeatsCache = null;
  2216. const app = this.container.getProvider('app').getImmediate();
  2217. this._storage = new HeartbeatStorageImpl(app);
  2218. this._heartbeatsCachePromise = this._storage.read().then(result => {
  2219. this._heartbeatsCache = result;
  2220. return result;
  2221. });
  2222. }
  2223. /**
  2224. * Called to report a heartbeat. The function will generate
  2225. * a HeartbeatsByUserAgent object, update heartbeatsCache, and persist it
  2226. * to IndexedDB.
  2227. * Note that we only store one heartbeat per day. So if a heartbeat for today is
  2228. * already logged, subsequent calls to this function in the same day will be ignored.
  2229. */
  2230. async triggerHeartbeat() {
  2231. const platformLogger = this.container
  2232. .getProvider('platform-logger')
  2233. .getImmediate();
  2234. // This is the "Firebase user agent" string from the platform logger
  2235. // service, not the browser user agent.
  2236. const agent = platformLogger.getPlatformInfoString();
  2237. const date = getUTCDateString();
  2238. if (this._heartbeatsCache === null) {
  2239. this._heartbeatsCache = await this._heartbeatsCachePromise;
  2240. }
  2241. // Do not store a heartbeat if one is already stored for this day
  2242. // or if a header has already been sent today.
  2243. if (this._heartbeatsCache.lastSentHeartbeatDate === date ||
  2244. this._heartbeatsCache.heartbeats.some(singleDateHeartbeat => singleDateHeartbeat.date === date)) {
  2245. return;
  2246. }
  2247. else {
  2248. // There is no entry for this date. Create one.
  2249. this._heartbeatsCache.heartbeats.push({ date, agent });
  2250. }
  2251. // Remove entries older than 30 days.
  2252. this._heartbeatsCache.heartbeats = this._heartbeatsCache.heartbeats.filter(singleDateHeartbeat => {
  2253. const hbTimestamp = new Date(singleDateHeartbeat.date).valueOf();
  2254. const now = Date.now();
  2255. return now - hbTimestamp <= STORED_HEARTBEAT_RETENTION_MAX_MILLIS;
  2256. });
  2257. return this._storage.overwrite(this._heartbeatsCache);
  2258. }
  2259. /**
  2260. * Returns a base64 encoded string which can be attached to the heartbeat-specific header directly.
  2261. * It also clears all heartbeats from memory as well as in IndexedDB.
  2262. *
  2263. * NOTE: Consuming product SDKs should not send the header if this method
  2264. * returns an empty string.
  2265. */
  2266. async getHeartbeatsHeader() {
  2267. if (this._heartbeatsCache === null) {
  2268. await this._heartbeatsCachePromise;
  2269. }
  2270. // If it's still null or the array is empty, there is no data to send.
  2271. if (this._heartbeatsCache === null ||
  2272. this._heartbeatsCache.heartbeats.length === 0) {
  2273. return '';
  2274. }
  2275. const date = getUTCDateString();
  2276. // Extract as many heartbeats from the cache as will fit under the size limit.
  2277. const { heartbeatsToSend, unsentEntries } = extractHeartbeatsForHeader(this._heartbeatsCache.heartbeats);
  2278. const headerString = base64urlEncodeWithoutPadding(JSON.stringify({ version: 2, heartbeats: heartbeatsToSend }));
  2279. // Store last sent date to prevent another being logged/sent for the same day.
  2280. this._heartbeatsCache.lastSentHeartbeatDate = date;
  2281. if (unsentEntries.length > 0) {
  2282. // Store any unsent entries if they exist.
  2283. this._heartbeatsCache.heartbeats = unsentEntries;
  2284. // This seems more likely than emptying the array (below) to lead to some odd state
  2285. // since the cache isn't empty and this will be called again on the next request,
  2286. // and is probably safest if we await it.
  2287. await this._storage.overwrite(this._heartbeatsCache);
  2288. }
  2289. else {
  2290. this._heartbeatsCache.heartbeats = [];
  2291. // Do not wait for this, to reduce latency.
  2292. void this._storage.overwrite(this._heartbeatsCache);
  2293. }
  2294. return headerString;
  2295. }
  2296. }
  2297. function getUTCDateString() {
  2298. const today = new Date();
  2299. // Returns date format 'YYYY-MM-DD'
  2300. return today.toISOString().substring(0, 10);
  2301. }
  2302. function extractHeartbeatsForHeader(heartbeatsCache, maxSize = MAX_HEADER_BYTES) {
  2303. // Heartbeats grouped by user agent in the standard format to be sent in
  2304. // the header.
  2305. const heartbeatsToSend = [];
  2306. // Single date format heartbeats that are not sent.
  2307. let unsentEntries = heartbeatsCache.slice();
  2308. for (const singleDateHeartbeat of heartbeatsCache) {
  2309. // Look for an existing entry with the same user agent.
  2310. const heartbeatEntry = heartbeatsToSend.find(hb => hb.agent === singleDateHeartbeat.agent);
  2311. if (!heartbeatEntry) {
  2312. // If no entry for this user agent exists, create one.
  2313. heartbeatsToSend.push({
  2314. agent: singleDateHeartbeat.agent,
  2315. dates: [singleDateHeartbeat.date]
  2316. });
  2317. if (countBytes(heartbeatsToSend) > maxSize) {
  2318. // If the header would exceed max size, remove the added heartbeat
  2319. // entry and stop adding to the header.
  2320. heartbeatsToSend.pop();
  2321. break;
  2322. }
  2323. }
  2324. else {
  2325. heartbeatEntry.dates.push(singleDateHeartbeat.date);
  2326. // If the header would exceed max size, remove the added date
  2327. // and stop adding to the header.
  2328. if (countBytes(heartbeatsToSend) > maxSize) {
  2329. heartbeatEntry.dates.pop();
  2330. break;
  2331. }
  2332. }
  2333. // Pop unsent entry from queue. (Skipped if adding the entry exceeded
  2334. // quota and the loop breaks early.)
  2335. unsentEntries = unsentEntries.slice(1);
  2336. }
  2337. return {
  2338. heartbeatsToSend,
  2339. unsentEntries
  2340. };
  2341. }
  2342. class HeartbeatStorageImpl {
  2343. constructor(app) {
  2344. this.app = app;
  2345. this._canUseIndexedDBPromise = this.runIndexedDBEnvironmentCheck();
  2346. }
  2347. async runIndexedDBEnvironmentCheck() {
  2348. if (!isIndexedDBAvailable()) {
  2349. return false;
  2350. }
  2351. else {
  2352. return validateIndexedDBOpenable()
  2353. .then(() => true)
  2354. .catch(() => false);
  2355. }
  2356. }
  2357. /**
  2358. * Read all heartbeats.
  2359. */
  2360. async read() {
  2361. const canUseIndexedDB = await this._canUseIndexedDBPromise;
  2362. if (!canUseIndexedDB) {
  2363. return { heartbeats: [] };
  2364. }
  2365. else {
  2366. const idbHeartbeatObject = await readHeartbeatsFromIndexedDB(this.app);
  2367. return idbHeartbeatObject || { heartbeats: [] };
  2368. }
  2369. }
  2370. // overwrite the storage with the provided heartbeats
  2371. async overwrite(heartbeatsObject) {
  2372. var _a;
  2373. const canUseIndexedDB = await this._canUseIndexedDBPromise;
  2374. if (!canUseIndexedDB) {
  2375. return;
  2376. }
  2377. else {
  2378. const existingHeartbeatsObject = await this.read();
  2379. return writeHeartbeatsToIndexedDB(this.app, {
  2380. lastSentHeartbeatDate: (_a = heartbeatsObject.lastSentHeartbeatDate) !== null && _a !== void 0 ? _a : existingHeartbeatsObject.lastSentHeartbeatDate,
  2381. heartbeats: heartbeatsObject.heartbeats
  2382. });
  2383. }
  2384. }
  2385. // add heartbeats
  2386. async add(heartbeatsObject) {
  2387. var _a;
  2388. const canUseIndexedDB = await this._canUseIndexedDBPromise;
  2389. if (!canUseIndexedDB) {
  2390. return;
  2391. }
  2392. else {
  2393. const existingHeartbeatsObject = await this.read();
  2394. return writeHeartbeatsToIndexedDB(this.app, {
  2395. lastSentHeartbeatDate: (_a = heartbeatsObject.lastSentHeartbeatDate) !== null && _a !== void 0 ? _a : existingHeartbeatsObject.lastSentHeartbeatDate,
  2396. heartbeats: [
  2397. ...existingHeartbeatsObject.heartbeats,
  2398. ...heartbeatsObject.heartbeats
  2399. ]
  2400. });
  2401. }
  2402. }
  2403. }
  2404. /**
  2405. * Calculate bytes of a HeartbeatsByUserAgent array after being wrapped
  2406. * in a platform logging header JSON object, stringified, and converted
  2407. * to base 64.
  2408. */
  2409. function countBytes(heartbeatsCache) {
  2410. // base64 has a restricted set of characters, all of which should be 1 byte.
  2411. return base64urlEncodeWithoutPadding(
  2412. // heartbeatsCache wrapper properties
  2413. JSON.stringify({ version: 2, heartbeats: heartbeatsCache })).length;
  2414. }
  2415. /**
  2416. * @license
  2417. * Copyright 2019 Google LLC
  2418. *
  2419. * Licensed under the Apache License, Version 2.0 (the "License");
  2420. * you may not use this file except in compliance with the License.
  2421. * You may obtain a copy of the License at
  2422. *
  2423. * http://www.apache.org/licenses/LICENSE-2.0
  2424. *
  2425. * Unless required by applicable law or agreed to in writing, software
  2426. * distributed under the License is distributed on an "AS IS" BASIS,
  2427. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  2428. * See the License for the specific language governing permissions and
  2429. * limitations under the License.
  2430. */
  2431. function registerCoreComponents(variant) {
  2432. _registerComponent(new Component('platform-logger', container => new PlatformLoggerServiceImpl(container), "PRIVATE" /* ComponentType.PRIVATE */));
  2433. _registerComponent(new Component('heartbeat', container => new HeartbeatServiceImpl(container), "PRIVATE" /* ComponentType.PRIVATE */));
  2434. // Register `app` package.
  2435. registerVersion(name$o, version$1, variant);
  2436. // BUILD_TARGET will be replaced by values like esm5, esm2017, cjs5, etc during the compilation
  2437. registerVersion(name$o, version$1, 'esm2017');
  2438. // Register platform SDK identifier (no version).
  2439. registerVersion('fire-js', '');
  2440. }
  2441. /**
  2442. * Firebase App
  2443. *
  2444. * @remarks This package coordinates the communication between the different Firebase components
  2445. * @packageDocumentation
  2446. */
  2447. registerCoreComponents('');
  2448. var name = "firebase";
  2449. var version = "9.23.0";
  2450. /**
  2451. * @license
  2452. * Copyright 2020 Google LLC
  2453. *
  2454. * Licensed under the Apache License, Version 2.0 (the "License");
  2455. * you may not use this file except in compliance with the License.
  2456. * You may obtain a copy of the License at
  2457. *
  2458. * http://www.apache.org/licenses/LICENSE-2.0
  2459. *
  2460. * Unless required by applicable law or agreed to in writing, software
  2461. * distributed under the License is distributed on an "AS IS" BASIS,
  2462. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  2463. * See the License for the specific language governing permissions and
  2464. * limitations under the License.
  2465. */
  2466. registerVersion(name, version, 'cdn');
  2467. export { FirebaseError, SDK_VERSION, DEFAULT_ENTRY_NAME as _DEFAULT_ENTRY_NAME, _addComponent, _addOrOverwriteComponent, _apps, _clearComponents, _components, _getProvider, _registerComponent, _removeServiceInstance, deleteApp, getApp, getApps, initializeApp, onLog, registerVersion, setLogLevel };
  2468. //# sourceMappingURL=firebase-app.js.map