Aucune description
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

firebase-app.js 89KB

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