firebase-app.js 90 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542
  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/10.8.0/firebase-app.js";
  1611. const version$1 = "0.9.27";
  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/10.8.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 = "10.8.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. try {
  2130. db.createObjectStore(STORE_NAME);
  2131. }
  2132. catch (e) {
  2133. // Safari/iOS browsers throw occasional exceptions on
  2134. // db.createObjectStore() that may be a bug. Avoid blocking
  2135. // the rest of the app functionality.
  2136. console.warn(e);
  2137. }
  2138. }
  2139. }
  2140. }).catch(e => {
  2141. throw ERROR_FACTORY.create("idb-open" /* AppError.IDB_OPEN */, {
  2142. originalErrorMessage: e.message
  2143. });
  2144. });
  2145. }
  2146. return dbPromise;
  2147. }
  2148. async function readHeartbeatsFromIndexedDB(app) {
  2149. try {
  2150. const db = await getDbPromise();
  2151. const tx = db.transaction(STORE_NAME);
  2152. const result = await tx.objectStore(STORE_NAME).get(computeKey(app));
  2153. // We already have the value but tx.done can throw,
  2154. // so we need to await it here to catch errors
  2155. await tx.done;
  2156. return result;
  2157. }
  2158. catch (e) {
  2159. if (e instanceof FirebaseError) {
  2160. logger.warn(e.message);
  2161. }
  2162. else {
  2163. const idbGetError = ERROR_FACTORY.create("idb-get" /* AppError.IDB_GET */, {
  2164. originalErrorMessage: e === null || e === void 0 ? void 0 : e.message
  2165. });
  2166. logger.warn(idbGetError.message);
  2167. }
  2168. }
  2169. }
  2170. async function writeHeartbeatsToIndexedDB(app, heartbeatObject) {
  2171. try {
  2172. const db = await getDbPromise();
  2173. const tx = db.transaction(STORE_NAME, 'readwrite');
  2174. const objectStore = tx.objectStore(STORE_NAME);
  2175. await objectStore.put(heartbeatObject, computeKey(app));
  2176. await tx.done;
  2177. }
  2178. catch (e) {
  2179. if (e instanceof FirebaseError) {
  2180. logger.warn(e.message);
  2181. }
  2182. else {
  2183. const idbGetError = ERROR_FACTORY.create("idb-set" /* AppError.IDB_WRITE */, {
  2184. originalErrorMessage: e === null || e === void 0 ? void 0 : e.message
  2185. });
  2186. logger.warn(idbGetError.message);
  2187. }
  2188. }
  2189. }
  2190. function computeKey(app) {
  2191. return `${app.name}!${app.options.appId}`;
  2192. }
  2193. /**
  2194. * @license
  2195. * Copyright 2021 Google LLC
  2196. *
  2197. * Licensed under the Apache License, Version 2.0 (the "License");
  2198. * you may not use this file except in compliance with the License.
  2199. * You may obtain a copy of the License at
  2200. *
  2201. * http://www.apache.org/licenses/LICENSE-2.0
  2202. *
  2203. * Unless required by applicable law or agreed to in writing, software
  2204. * distributed under the License is distributed on an "AS IS" BASIS,
  2205. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  2206. * See the License for the specific language governing permissions and
  2207. * limitations under the License.
  2208. */
  2209. const MAX_HEADER_BYTES = 1024;
  2210. // 30 days
  2211. const STORED_HEARTBEAT_RETENTION_MAX_MILLIS = 30 * 24 * 60 * 60 * 1000;
  2212. class HeartbeatServiceImpl {
  2213. constructor(container) {
  2214. this.container = container;
  2215. /**
  2216. * In-memory cache for heartbeats, used by getHeartbeatsHeader() to generate
  2217. * the header string.
  2218. * Stores one record per date. This will be consolidated into the standard
  2219. * format of one record per user agent string before being sent as a header.
  2220. * Populated from indexedDB when the controller is instantiated and should
  2221. * be kept in sync with indexedDB.
  2222. * Leave public for easier testing.
  2223. */
  2224. this._heartbeatsCache = null;
  2225. const app = this.container.getProvider('app').getImmediate();
  2226. this._storage = new HeartbeatStorageImpl(app);
  2227. this._heartbeatsCachePromise = this._storage.read().then(result => {
  2228. this._heartbeatsCache = result;
  2229. return result;
  2230. });
  2231. }
  2232. /**
  2233. * Called to report a heartbeat. The function will generate
  2234. * a HeartbeatsByUserAgent object, update heartbeatsCache, and persist it
  2235. * to IndexedDB.
  2236. * Note that we only store one heartbeat per day. So if a heartbeat for today is
  2237. * already logged, subsequent calls to this function in the same day will be ignored.
  2238. */
  2239. async triggerHeartbeat() {
  2240. var _a, _b;
  2241. const platformLogger = this.container
  2242. .getProvider('platform-logger')
  2243. .getImmediate();
  2244. // This is the "Firebase user agent" string from the platform logger
  2245. // service, not the browser user agent.
  2246. const agent = platformLogger.getPlatformInfoString();
  2247. const date = getUTCDateString();
  2248. if (((_a = this._heartbeatsCache) === null || _a === void 0 ? void 0 : _a.heartbeats) == null) {
  2249. this._heartbeatsCache = await this._heartbeatsCachePromise;
  2250. // If we failed to construct a heartbeats cache, then return immediately.
  2251. if (((_b = this._heartbeatsCache) === null || _b === void 0 ? void 0 : _b.heartbeats) == null) {
  2252. return;
  2253. }
  2254. }
  2255. // Do not store a heartbeat if one is already stored for this day
  2256. // or if a header has already been sent today.
  2257. if (this._heartbeatsCache.lastSentHeartbeatDate === date ||
  2258. this._heartbeatsCache.heartbeats.some(singleDateHeartbeat => singleDateHeartbeat.date === date)) {
  2259. return;
  2260. }
  2261. else {
  2262. // There is no entry for this date. Create one.
  2263. this._heartbeatsCache.heartbeats.push({ date, agent });
  2264. }
  2265. // Remove entries older than 30 days.
  2266. this._heartbeatsCache.heartbeats = this._heartbeatsCache.heartbeats.filter(singleDateHeartbeat => {
  2267. const hbTimestamp = new Date(singleDateHeartbeat.date).valueOf();
  2268. const now = Date.now();
  2269. return now - hbTimestamp <= STORED_HEARTBEAT_RETENTION_MAX_MILLIS;
  2270. });
  2271. return this._storage.overwrite(this._heartbeatsCache);
  2272. }
  2273. /**
  2274. * Returns a base64 encoded string which can be attached to the heartbeat-specific header directly.
  2275. * It also clears all heartbeats from memory as well as in IndexedDB.
  2276. *
  2277. * NOTE: Consuming product SDKs should not send the header if this method
  2278. * returns an empty string.
  2279. */
  2280. async getHeartbeatsHeader() {
  2281. var _a;
  2282. if (this._heartbeatsCache === null) {
  2283. await this._heartbeatsCachePromise;
  2284. }
  2285. // If it's still null or the array is empty, there is no data to send.
  2286. if (((_a = this._heartbeatsCache) === null || _a === void 0 ? void 0 : _a.heartbeats) == null ||
  2287. this._heartbeatsCache.heartbeats.length === 0) {
  2288. return '';
  2289. }
  2290. const date = getUTCDateString();
  2291. // Extract as many heartbeats from the cache as will fit under the size limit.
  2292. const { heartbeatsToSend, unsentEntries } = extractHeartbeatsForHeader(this._heartbeatsCache.heartbeats);
  2293. const headerString = base64urlEncodeWithoutPadding(JSON.stringify({ version: 2, heartbeats: heartbeatsToSend }));
  2294. // Store last sent date to prevent another being logged/sent for the same day.
  2295. this._heartbeatsCache.lastSentHeartbeatDate = date;
  2296. if (unsentEntries.length > 0) {
  2297. // Store any unsent entries if they exist.
  2298. this._heartbeatsCache.heartbeats = unsentEntries;
  2299. // This seems more likely than emptying the array (below) to lead to some odd state
  2300. // since the cache isn't empty and this will be called again on the next request,
  2301. // and is probably safest if we await it.
  2302. await this._storage.overwrite(this._heartbeatsCache);
  2303. }
  2304. else {
  2305. this._heartbeatsCache.heartbeats = [];
  2306. // Do not wait for this, to reduce latency.
  2307. void this._storage.overwrite(this._heartbeatsCache);
  2308. }
  2309. return headerString;
  2310. }
  2311. }
  2312. function getUTCDateString() {
  2313. const today = new Date();
  2314. // Returns date format 'YYYY-MM-DD'
  2315. return today.toISOString().substring(0, 10);
  2316. }
  2317. function extractHeartbeatsForHeader(heartbeatsCache, maxSize = MAX_HEADER_BYTES) {
  2318. // Heartbeats grouped by user agent in the standard format to be sent in
  2319. // the header.
  2320. const heartbeatsToSend = [];
  2321. // Single date format heartbeats that are not sent.
  2322. let unsentEntries = heartbeatsCache.slice();
  2323. for (const singleDateHeartbeat of heartbeatsCache) {
  2324. // Look for an existing entry with the same user agent.
  2325. const heartbeatEntry = heartbeatsToSend.find(hb => hb.agent === singleDateHeartbeat.agent);
  2326. if (!heartbeatEntry) {
  2327. // If no entry for this user agent exists, create one.
  2328. heartbeatsToSend.push({
  2329. agent: singleDateHeartbeat.agent,
  2330. dates: [singleDateHeartbeat.date]
  2331. });
  2332. if (countBytes(heartbeatsToSend) > maxSize) {
  2333. // If the header would exceed max size, remove the added heartbeat
  2334. // entry and stop adding to the header.
  2335. heartbeatsToSend.pop();
  2336. break;
  2337. }
  2338. }
  2339. else {
  2340. heartbeatEntry.dates.push(singleDateHeartbeat.date);
  2341. // If the header would exceed max size, remove the added date
  2342. // and stop adding to the header.
  2343. if (countBytes(heartbeatsToSend) > maxSize) {
  2344. heartbeatEntry.dates.pop();
  2345. break;
  2346. }
  2347. }
  2348. // Pop unsent entry from queue. (Skipped if adding the entry exceeded
  2349. // quota and the loop breaks early.)
  2350. unsentEntries = unsentEntries.slice(1);
  2351. }
  2352. return {
  2353. heartbeatsToSend,
  2354. unsentEntries
  2355. };
  2356. }
  2357. class HeartbeatStorageImpl {
  2358. constructor(app) {
  2359. this.app = app;
  2360. this._canUseIndexedDBPromise = this.runIndexedDBEnvironmentCheck();
  2361. }
  2362. async runIndexedDBEnvironmentCheck() {
  2363. if (!isIndexedDBAvailable()) {
  2364. return false;
  2365. }
  2366. else {
  2367. return validateIndexedDBOpenable()
  2368. .then(() => true)
  2369. .catch(() => false);
  2370. }
  2371. }
  2372. /**
  2373. * Read all heartbeats.
  2374. */
  2375. async read() {
  2376. const canUseIndexedDB = await this._canUseIndexedDBPromise;
  2377. if (!canUseIndexedDB) {
  2378. return { heartbeats: [] };
  2379. }
  2380. else {
  2381. const idbHeartbeatObject = await readHeartbeatsFromIndexedDB(this.app);
  2382. if (idbHeartbeatObject === null || idbHeartbeatObject === void 0 ? void 0 : idbHeartbeatObject.heartbeats) {
  2383. return idbHeartbeatObject;
  2384. }
  2385. else {
  2386. return { heartbeats: [] };
  2387. }
  2388. }
  2389. }
  2390. // overwrite the storage with the provided heartbeats
  2391. async overwrite(heartbeatsObject) {
  2392. var _a;
  2393. const canUseIndexedDB = await this._canUseIndexedDBPromise;
  2394. if (!canUseIndexedDB) {
  2395. return;
  2396. }
  2397. else {
  2398. const existingHeartbeatsObject = await this.read();
  2399. return writeHeartbeatsToIndexedDB(this.app, {
  2400. lastSentHeartbeatDate: (_a = heartbeatsObject.lastSentHeartbeatDate) !== null && _a !== void 0 ? _a : existingHeartbeatsObject.lastSentHeartbeatDate,
  2401. heartbeats: heartbeatsObject.heartbeats
  2402. });
  2403. }
  2404. }
  2405. // add heartbeats
  2406. async add(heartbeatsObject) {
  2407. var _a;
  2408. const canUseIndexedDB = await this._canUseIndexedDBPromise;
  2409. if (!canUseIndexedDB) {
  2410. return;
  2411. }
  2412. else {
  2413. const existingHeartbeatsObject = await this.read();
  2414. return writeHeartbeatsToIndexedDB(this.app, {
  2415. lastSentHeartbeatDate: (_a = heartbeatsObject.lastSentHeartbeatDate) !== null && _a !== void 0 ? _a : existingHeartbeatsObject.lastSentHeartbeatDate,
  2416. heartbeats: [
  2417. ...existingHeartbeatsObject.heartbeats,
  2418. ...heartbeatsObject.heartbeats
  2419. ]
  2420. });
  2421. }
  2422. }
  2423. }
  2424. /**
  2425. * Calculate bytes of a HeartbeatsByUserAgent array after being wrapped
  2426. * in a platform logging header JSON object, stringified, and converted
  2427. * to base 64.
  2428. */
  2429. function countBytes(heartbeatsCache) {
  2430. // base64 has a restricted set of characters, all of which should be 1 byte.
  2431. return base64urlEncodeWithoutPadding(
  2432. // heartbeatsCache wrapper properties
  2433. JSON.stringify({ version: 2, heartbeats: heartbeatsCache })).length;
  2434. }
  2435. /**
  2436. * @license
  2437. * Copyright 2019 Google LLC
  2438. *
  2439. * Licensed under the Apache License, Version 2.0 (the "License");
  2440. * you may not use this file except in compliance with the License.
  2441. * You may obtain a copy of the License at
  2442. *
  2443. * http://www.apache.org/licenses/LICENSE-2.0
  2444. *
  2445. * Unless required by applicable law or agreed to in writing, software
  2446. * distributed under the License is distributed on an "AS IS" BASIS,
  2447. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  2448. * See the License for the specific language governing permissions and
  2449. * limitations under the License.
  2450. */
  2451. function registerCoreComponents(variant) {
  2452. _registerComponent(new Component('platform-logger', container => new PlatformLoggerServiceImpl(container), "PRIVATE" /* ComponentType.PRIVATE */));
  2453. _registerComponent(new Component('heartbeat', container => new HeartbeatServiceImpl(container), "PRIVATE" /* ComponentType.PRIVATE */));
  2454. // Register `app` package.
  2455. registerVersion(name$o, version$1, variant);
  2456. // BUILD_TARGET will be replaced by values like esm5, esm2017, cjs5, etc during the compilation
  2457. registerVersion(name$o, version$1, 'esm2017');
  2458. // Register platform SDK identifier (no version).
  2459. registerVersion('fire-js', '');
  2460. }
  2461. /**
  2462. * Firebase App
  2463. *
  2464. * @remarks This package coordinates the communication between the different Firebase components
  2465. * @packageDocumentation
  2466. */
  2467. registerCoreComponents('');
  2468. var name = "firebase";
  2469. var version = "10.8.0";
  2470. /**
  2471. * @license
  2472. * Copyright 2020 Google LLC
  2473. *
  2474. * Licensed under the Apache License, Version 2.0 (the "License");
  2475. * you may not use this file except in compliance with the License.
  2476. * You may obtain a copy of the License at
  2477. *
  2478. * http://www.apache.org/licenses/LICENSE-2.0
  2479. *
  2480. * Unless required by applicable law or agreed to in writing, software
  2481. * distributed under the License is distributed on an "AS IS" BASIS,
  2482. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  2483. * See the License for the specific language governing permissions and
  2484. * limitations under the License.
  2485. */
  2486. registerVersion(name, version, 'cdn');
  2487. 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 };
  2488. //# sourceMappingURL=firebase-app.js.map