No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

index.esm2017.js 42KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154
  1. import { _getProvider, getApp, _registerComponent, registerVersion } from '@firebase/app';
  2. import { Component } from '@firebase/component';
  3. import { ErrorFactory, FirebaseError } from '@firebase/util';
  4. import { openDB } from 'idb';
  5. const name = "@firebase/installations";
  6. const version = "0.6.1";
  7. /**
  8. * @license
  9. * Copyright 2019 Google LLC
  10. *
  11. * Licensed under the Apache License, Version 2.0 (the "License");
  12. * you may not use this file except in compliance with the License.
  13. * You may obtain a copy of the License at
  14. *
  15. * http://www.apache.org/licenses/LICENSE-2.0
  16. *
  17. * Unless required by applicable law or agreed to in writing, software
  18. * distributed under the License is distributed on an "AS IS" BASIS,
  19. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  20. * See the License for the specific language governing permissions and
  21. * limitations under the License.
  22. */
  23. const PENDING_TIMEOUT_MS = 10000;
  24. const PACKAGE_VERSION = `w:${version}`;
  25. const INTERNAL_AUTH_VERSION = 'FIS_v2';
  26. const INSTALLATIONS_API_URL = 'https://firebaseinstallations.googleapis.com/v1';
  27. const TOKEN_EXPIRATION_BUFFER = 60 * 60 * 1000; // One hour
  28. const SERVICE = 'installations';
  29. const SERVICE_NAME = 'Installations';
  30. /**
  31. * @license
  32. * Copyright 2019 Google LLC
  33. *
  34. * Licensed under the Apache License, Version 2.0 (the "License");
  35. * you may not use this file except in compliance with the License.
  36. * You may obtain a copy of the License at
  37. *
  38. * http://www.apache.org/licenses/LICENSE-2.0
  39. *
  40. * Unless required by applicable law or agreed to in writing, software
  41. * distributed under the License is distributed on an "AS IS" BASIS,
  42. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  43. * See the License for the specific language governing permissions and
  44. * limitations under the License.
  45. */
  46. const ERROR_DESCRIPTION_MAP = {
  47. ["missing-app-config-values" /* ErrorCode.MISSING_APP_CONFIG_VALUES */]: 'Missing App configuration value: "{$valueName}"',
  48. ["not-registered" /* ErrorCode.NOT_REGISTERED */]: 'Firebase Installation is not registered.',
  49. ["installation-not-found" /* ErrorCode.INSTALLATION_NOT_FOUND */]: 'Firebase Installation not found.',
  50. ["request-failed" /* ErrorCode.REQUEST_FAILED */]: '{$requestName} request failed with error "{$serverCode} {$serverStatus}: {$serverMessage}"',
  51. ["app-offline" /* ErrorCode.APP_OFFLINE */]: 'Could not process request. Application offline.',
  52. ["delete-pending-registration" /* ErrorCode.DELETE_PENDING_REGISTRATION */]: "Can't delete installation while there is a pending registration request."
  53. };
  54. const ERROR_FACTORY = new ErrorFactory(SERVICE, SERVICE_NAME, ERROR_DESCRIPTION_MAP);
  55. /** Returns true if error is a FirebaseError that is based on an error from the server. */
  56. function isServerError(error) {
  57. return (error instanceof FirebaseError &&
  58. error.code.includes("request-failed" /* ErrorCode.REQUEST_FAILED */));
  59. }
  60. /**
  61. * @license
  62. * Copyright 2019 Google LLC
  63. *
  64. * Licensed under the Apache License, Version 2.0 (the "License");
  65. * you may not use this file except in compliance with the License.
  66. * You may obtain a copy of the License at
  67. *
  68. * http://www.apache.org/licenses/LICENSE-2.0
  69. *
  70. * Unless required by applicable law or agreed to in writing, software
  71. * distributed under the License is distributed on an "AS IS" BASIS,
  72. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  73. * See the License for the specific language governing permissions and
  74. * limitations under the License.
  75. */
  76. function getInstallationsEndpoint({ projectId }) {
  77. return `${INSTALLATIONS_API_URL}/projects/${projectId}/installations`;
  78. }
  79. function extractAuthTokenInfoFromResponse(response) {
  80. return {
  81. token: response.token,
  82. requestStatus: 2 /* RequestStatus.COMPLETED */,
  83. expiresIn: getExpiresInFromResponseExpiresIn(response.expiresIn),
  84. creationTime: Date.now()
  85. };
  86. }
  87. async function getErrorFromResponse(requestName, response) {
  88. const responseJson = await response.json();
  89. const errorData = responseJson.error;
  90. return ERROR_FACTORY.create("request-failed" /* ErrorCode.REQUEST_FAILED */, {
  91. requestName,
  92. serverCode: errorData.code,
  93. serverMessage: errorData.message,
  94. serverStatus: errorData.status
  95. });
  96. }
  97. function getHeaders({ apiKey }) {
  98. return new Headers({
  99. 'Content-Type': 'application/json',
  100. Accept: 'application/json',
  101. 'x-goog-api-key': apiKey
  102. });
  103. }
  104. function getHeadersWithAuth(appConfig, { refreshToken }) {
  105. const headers = getHeaders(appConfig);
  106. headers.append('Authorization', getAuthorizationHeader(refreshToken));
  107. return headers;
  108. }
  109. /**
  110. * Calls the passed in fetch wrapper and returns the response.
  111. * If the returned response has a status of 5xx, re-runs the function once and
  112. * returns the response.
  113. */
  114. async function retryIfServerError(fn) {
  115. const result = await fn();
  116. if (result.status >= 500 && result.status < 600) {
  117. // Internal Server Error. Retry request.
  118. return fn();
  119. }
  120. return result;
  121. }
  122. function getExpiresInFromResponseExpiresIn(responseExpiresIn) {
  123. // This works because the server will never respond with fractions of a second.
  124. return Number(responseExpiresIn.replace('s', '000'));
  125. }
  126. function getAuthorizationHeader(refreshToken) {
  127. return `${INTERNAL_AUTH_VERSION} ${refreshToken}`;
  128. }
  129. /**
  130. * @license
  131. * Copyright 2019 Google LLC
  132. *
  133. * Licensed under the Apache License, Version 2.0 (the "License");
  134. * you may not use this file except in compliance with the License.
  135. * You may obtain a copy of the License at
  136. *
  137. * http://www.apache.org/licenses/LICENSE-2.0
  138. *
  139. * Unless required by applicable law or agreed to in writing, software
  140. * distributed under the License is distributed on an "AS IS" BASIS,
  141. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  142. * See the License for the specific language governing permissions and
  143. * limitations under the License.
  144. */
  145. async function createInstallationRequest({ appConfig, heartbeatServiceProvider }, { fid }) {
  146. const endpoint = getInstallationsEndpoint(appConfig);
  147. const headers = getHeaders(appConfig);
  148. // If heartbeat service exists, add the heartbeat string to the header.
  149. const heartbeatService = heartbeatServiceProvider.getImmediate({
  150. optional: true
  151. });
  152. if (heartbeatService) {
  153. const heartbeatsHeader = await heartbeatService.getHeartbeatsHeader();
  154. if (heartbeatsHeader) {
  155. headers.append('x-firebase-client', heartbeatsHeader);
  156. }
  157. }
  158. const body = {
  159. fid,
  160. authVersion: INTERNAL_AUTH_VERSION,
  161. appId: appConfig.appId,
  162. sdkVersion: PACKAGE_VERSION
  163. };
  164. const request = {
  165. method: 'POST',
  166. headers,
  167. body: JSON.stringify(body)
  168. };
  169. const response = await retryIfServerError(() => fetch(endpoint, request));
  170. if (response.ok) {
  171. const responseValue = await response.json();
  172. const registeredInstallationEntry = {
  173. fid: responseValue.fid || fid,
  174. registrationStatus: 2 /* RequestStatus.COMPLETED */,
  175. refreshToken: responseValue.refreshToken,
  176. authToken: extractAuthTokenInfoFromResponse(responseValue.authToken)
  177. };
  178. return registeredInstallationEntry;
  179. }
  180. else {
  181. throw await getErrorFromResponse('Create Installation', response);
  182. }
  183. }
  184. /**
  185. * @license
  186. * Copyright 2019 Google LLC
  187. *
  188. * Licensed under the Apache License, Version 2.0 (the "License");
  189. * you may not use this file except in compliance with the License.
  190. * You may obtain a copy of the License at
  191. *
  192. * http://www.apache.org/licenses/LICENSE-2.0
  193. *
  194. * Unless required by applicable law or agreed to in writing, software
  195. * distributed under the License is distributed on an "AS IS" BASIS,
  196. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  197. * See the License for the specific language governing permissions and
  198. * limitations under the License.
  199. */
  200. /** Returns a promise that resolves after given time passes. */
  201. function sleep(ms) {
  202. return new Promise(resolve => {
  203. setTimeout(resolve, ms);
  204. });
  205. }
  206. /**
  207. * @license
  208. * Copyright 2019 Google LLC
  209. *
  210. * Licensed under the Apache License, Version 2.0 (the "License");
  211. * you may not use this file except in compliance with the License.
  212. * You may obtain a copy of the License at
  213. *
  214. * http://www.apache.org/licenses/LICENSE-2.0
  215. *
  216. * Unless required by applicable law or agreed to in writing, software
  217. * distributed under the License is distributed on an "AS IS" BASIS,
  218. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  219. * See the License for the specific language governing permissions and
  220. * limitations under the License.
  221. */
  222. function bufferToBase64UrlSafe(array) {
  223. const b64 = btoa(String.fromCharCode(...array));
  224. return b64.replace(/\+/g, '-').replace(/\//g, '_');
  225. }
  226. /**
  227. * @license
  228. * Copyright 2019 Google LLC
  229. *
  230. * Licensed under the Apache License, Version 2.0 (the "License");
  231. * you may not use this file except in compliance with the License.
  232. * You may obtain a copy of the License at
  233. *
  234. * http://www.apache.org/licenses/LICENSE-2.0
  235. *
  236. * Unless required by applicable law or agreed to in writing, software
  237. * distributed under the License is distributed on an "AS IS" BASIS,
  238. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  239. * See the License for the specific language governing permissions and
  240. * limitations under the License.
  241. */
  242. const VALID_FID_PATTERN = /^[cdef][\w-]{21}$/;
  243. const INVALID_FID = '';
  244. /**
  245. * Generates a new FID using random values from Web Crypto API.
  246. * Returns an empty string if FID generation fails for any reason.
  247. */
  248. function generateFid() {
  249. try {
  250. // A valid FID has exactly 22 base64 characters, which is 132 bits, or 16.5
  251. // bytes. our implementation generates a 17 byte array instead.
  252. const fidByteArray = new Uint8Array(17);
  253. const crypto = self.crypto || self.msCrypto;
  254. crypto.getRandomValues(fidByteArray);
  255. // Replace the first 4 random bits with the constant FID header of 0b0111.
  256. fidByteArray[0] = 0b01110000 + (fidByteArray[0] % 0b00010000);
  257. const fid = encode(fidByteArray);
  258. return VALID_FID_PATTERN.test(fid) ? fid : INVALID_FID;
  259. }
  260. catch (_a) {
  261. // FID generation errored
  262. return INVALID_FID;
  263. }
  264. }
  265. /** Converts a FID Uint8Array to a base64 string representation. */
  266. function encode(fidByteArray) {
  267. const b64String = bufferToBase64UrlSafe(fidByteArray);
  268. // Remove the 23rd character that was added because of the extra 4 bits at the
  269. // end of our 17 byte array, and the '=' padding.
  270. return b64String.substr(0, 22);
  271. }
  272. /**
  273. * @license
  274. * Copyright 2019 Google LLC
  275. *
  276. * Licensed under the Apache License, Version 2.0 (the "License");
  277. * you may not use this file except in compliance with the License.
  278. * You may obtain a copy of the License at
  279. *
  280. * http://www.apache.org/licenses/LICENSE-2.0
  281. *
  282. * Unless required by applicable law or agreed to in writing, software
  283. * distributed under the License is distributed on an "AS IS" BASIS,
  284. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  285. * See the License for the specific language governing permissions and
  286. * limitations under the License.
  287. */
  288. /** Returns a string key that can be used to identify the app. */
  289. function getKey(appConfig) {
  290. return `${appConfig.appName}!${appConfig.appId}`;
  291. }
  292. /**
  293. * @license
  294. * Copyright 2019 Google LLC
  295. *
  296. * Licensed under the Apache License, Version 2.0 (the "License");
  297. * you may not use this file except in compliance with the License.
  298. * You may obtain a copy of the License at
  299. *
  300. * http://www.apache.org/licenses/LICENSE-2.0
  301. *
  302. * Unless required by applicable law or agreed to in writing, software
  303. * distributed under the License is distributed on an "AS IS" BASIS,
  304. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  305. * See the License for the specific language governing permissions and
  306. * limitations under the License.
  307. */
  308. const fidChangeCallbacks = new Map();
  309. /**
  310. * Calls the onIdChange callbacks with the new FID value, and broadcasts the
  311. * change to other tabs.
  312. */
  313. function fidChanged(appConfig, fid) {
  314. const key = getKey(appConfig);
  315. callFidChangeCallbacks(key, fid);
  316. broadcastFidChange(key, fid);
  317. }
  318. function addCallback(appConfig, callback) {
  319. // Open the broadcast channel if it's not already open,
  320. // to be able to listen to change events from other tabs.
  321. getBroadcastChannel();
  322. const key = getKey(appConfig);
  323. let callbackSet = fidChangeCallbacks.get(key);
  324. if (!callbackSet) {
  325. callbackSet = new Set();
  326. fidChangeCallbacks.set(key, callbackSet);
  327. }
  328. callbackSet.add(callback);
  329. }
  330. function removeCallback(appConfig, callback) {
  331. const key = getKey(appConfig);
  332. const callbackSet = fidChangeCallbacks.get(key);
  333. if (!callbackSet) {
  334. return;
  335. }
  336. callbackSet.delete(callback);
  337. if (callbackSet.size === 0) {
  338. fidChangeCallbacks.delete(key);
  339. }
  340. // Close broadcast channel if there are no more callbacks.
  341. closeBroadcastChannel();
  342. }
  343. function callFidChangeCallbacks(key, fid) {
  344. const callbacks = fidChangeCallbacks.get(key);
  345. if (!callbacks) {
  346. return;
  347. }
  348. for (const callback of callbacks) {
  349. callback(fid);
  350. }
  351. }
  352. function broadcastFidChange(key, fid) {
  353. const channel = getBroadcastChannel();
  354. if (channel) {
  355. channel.postMessage({ key, fid });
  356. }
  357. closeBroadcastChannel();
  358. }
  359. let broadcastChannel = null;
  360. /** Opens and returns a BroadcastChannel if it is supported by the browser. */
  361. function getBroadcastChannel() {
  362. if (!broadcastChannel && 'BroadcastChannel' in self) {
  363. broadcastChannel = new BroadcastChannel('[Firebase] FID Change');
  364. broadcastChannel.onmessage = e => {
  365. callFidChangeCallbacks(e.data.key, e.data.fid);
  366. };
  367. }
  368. return broadcastChannel;
  369. }
  370. function closeBroadcastChannel() {
  371. if (fidChangeCallbacks.size === 0 && broadcastChannel) {
  372. broadcastChannel.close();
  373. broadcastChannel = null;
  374. }
  375. }
  376. /**
  377. * @license
  378. * Copyright 2019 Google LLC
  379. *
  380. * Licensed under the Apache License, Version 2.0 (the "License");
  381. * you may not use this file except in compliance with the License.
  382. * You may obtain a copy of the License at
  383. *
  384. * http://www.apache.org/licenses/LICENSE-2.0
  385. *
  386. * Unless required by applicable law or agreed to in writing, software
  387. * distributed under the License is distributed on an "AS IS" BASIS,
  388. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  389. * See the License for the specific language governing permissions and
  390. * limitations under the License.
  391. */
  392. const DATABASE_NAME = 'firebase-installations-database';
  393. const DATABASE_VERSION = 1;
  394. const OBJECT_STORE_NAME = 'firebase-installations-store';
  395. let dbPromise = null;
  396. function getDbPromise() {
  397. if (!dbPromise) {
  398. dbPromise = openDB(DATABASE_NAME, DATABASE_VERSION, {
  399. upgrade: (db, oldVersion) => {
  400. // We don't use 'break' in this switch statement, the fall-through
  401. // behavior is what we want, because if there are multiple versions between
  402. // the old version and the current version, we want ALL the migrations
  403. // that correspond to those versions to run, not only the last one.
  404. // eslint-disable-next-line default-case
  405. switch (oldVersion) {
  406. case 0:
  407. db.createObjectStore(OBJECT_STORE_NAME);
  408. }
  409. }
  410. });
  411. }
  412. return dbPromise;
  413. }
  414. /** Assigns or overwrites the record for the given key with the given value. */
  415. async function set(appConfig, value) {
  416. const key = getKey(appConfig);
  417. const db = await getDbPromise();
  418. const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');
  419. const objectStore = tx.objectStore(OBJECT_STORE_NAME);
  420. const oldValue = (await objectStore.get(key));
  421. await objectStore.put(value, key);
  422. await tx.done;
  423. if (!oldValue || oldValue.fid !== value.fid) {
  424. fidChanged(appConfig, value.fid);
  425. }
  426. return value;
  427. }
  428. /** Removes record(s) from the objectStore that match the given key. */
  429. async function remove(appConfig) {
  430. const key = getKey(appConfig);
  431. const db = await getDbPromise();
  432. const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');
  433. await tx.objectStore(OBJECT_STORE_NAME).delete(key);
  434. await tx.done;
  435. }
  436. /**
  437. * Atomically updates a record with the result of updateFn, which gets
  438. * called with the current value. If newValue is undefined, the record is
  439. * deleted instead.
  440. * @return Updated value
  441. */
  442. async function update(appConfig, updateFn) {
  443. const key = getKey(appConfig);
  444. const db = await getDbPromise();
  445. const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');
  446. const store = tx.objectStore(OBJECT_STORE_NAME);
  447. const oldValue = (await store.get(key));
  448. const newValue = updateFn(oldValue);
  449. if (newValue === undefined) {
  450. await store.delete(key);
  451. }
  452. else {
  453. await store.put(newValue, key);
  454. }
  455. await tx.done;
  456. if (newValue && (!oldValue || oldValue.fid !== newValue.fid)) {
  457. fidChanged(appConfig, newValue.fid);
  458. }
  459. return newValue;
  460. }
  461. /**
  462. * @license
  463. * Copyright 2019 Google LLC
  464. *
  465. * Licensed under the Apache License, Version 2.0 (the "License");
  466. * you may not use this file except in compliance with the License.
  467. * You may obtain a copy of the License at
  468. *
  469. * http://www.apache.org/licenses/LICENSE-2.0
  470. *
  471. * Unless required by applicable law or agreed to in writing, software
  472. * distributed under the License is distributed on an "AS IS" BASIS,
  473. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  474. * See the License for the specific language governing permissions and
  475. * limitations under the License.
  476. */
  477. /**
  478. * Updates and returns the InstallationEntry from the database.
  479. * Also triggers a registration request if it is necessary and possible.
  480. */
  481. async function getInstallationEntry(installations) {
  482. let registrationPromise;
  483. const installationEntry = await update(installations.appConfig, oldEntry => {
  484. const installationEntry = updateOrCreateInstallationEntry(oldEntry);
  485. const entryWithPromise = triggerRegistrationIfNecessary(installations, installationEntry);
  486. registrationPromise = entryWithPromise.registrationPromise;
  487. return entryWithPromise.installationEntry;
  488. });
  489. if (installationEntry.fid === INVALID_FID) {
  490. // FID generation failed. Waiting for the FID from the server.
  491. return { installationEntry: await registrationPromise };
  492. }
  493. return {
  494. installationEntry,
  495. registrationPromise
  496. };
  497. }
  498. /**
  499. * Creates a new Installation Entry if one does not exist.
  500. * Also clears timed out pending requests.
  501. */
  502. function updateOrCreateInstallationEntry(oldEntry) {
  503. const entry = oldEntry || {
  504. fid: generateFid(),
  505. registrationStatus: 0 /* RequestStatus.NOT_STARTED */
  506. };
  507. return clearTimedOutRequest(entry);
  508. }
  509. /**
  510. * If the Firebase Installation is not registered yet, this will trigger the
  511. * registration and return an InProgressInstallationEntry.
  512. *
  513. * If registrationPromise does not exist, the installationEntry is guaranteed
  514. * to be registered.
  515. */
  516. function triggerRegistrationIfNecessary(installations, installationEntry) {
  517. if (installationEntry.registrationStatus === 0 /* RequestStatus.NOT_STARTED */) {
  518. if (!navigator.onLine) {
  519. // Registration required but app is offline.
  520. const registrationPromiseWithError = Promise.reject(ERROR_FACTORY.create("app-offline" /* ErrorCode.APP_OFFLINE */));
  521. return {
  522. installationEntry,
  523. registrationPromise: registrationPromiseWithError
  524. };
  525. }
  526. // Try registering. Change status to IN_PROGRESS.
  527. const inProgressEntry = {
  528. fid: installationEntry.fid,
  529. registrationStatus: 1 /* RequestStatus.IN_PROGRESS */,
  530. registrationTime: Date.now()
  531. };
  532. const registrationPromise = registerInstallation(installations, inProgressEntry);
  533. return { installationEntry: inProgressEntry, registrationPromise };
  534. }
  535. else if (installationEntry.registrationStatus === 1 /* RequestStatus.IN_PROGRESS */) {
  536. return {
  537. installationEntry,
  538. registrationPromise: waitUntilFidRegistration(installations)
  539. };
  540. }
  541. else {
  542. return { installationEntry };
  543. }
  544. }
  545. /** This will be executed only once for each new Firebase Installation. */
  546. async function registerInstallation(installations, installationEntry) {
  547. try {
  548. const registeredInstallationEntry = await createInstallationRequest(installations, installationEntry);
  549. return set(installations.appConfig, registeredInstallationEntry);
  550. }
  551. catch (e) {
  552. if (isServerError(e) && e.customData.serverCode === 409) {
  553. // Server returned a "FID can not be used" error.
  554. // Generate a new ID next time.
  555. await remove(installations.appConfig);
  556. }
  557. else {
  558. // Registration failed. Set FID as not registered.
  559. await set(installations.appConfig, {
  560. fid: installationEntry.fid,
  561. registrationStatus: 0 /* RequestStatus.NOT_STARTED */
  562. });
  563. }
  564. throw e;
  565. }
  566. }
  567. /** Call if FID registration is pending in another request. */
  568. async function waitUntilFidRegistration(installations) {
  569. // Unfortunately, there is no way of reliably observing when a value in
  570. // IndexedDB changes (yet, see https://github.com/WICG/indexed-db-observers),
  571. // so we need to poll.
  572. let entry = await updateInstallationRequest(installations.appConfig);
  573. while (entry.registrationStatus === 1 /* RequestStatus.IN_PROGRESS */) {
  574. // createInstallation request still in progress.
  575. await sleep(100);
  576. entry = await updateInstallationRequest(installations.appConfig);
  577. }
  578. if (entry.registrationStatus === 0 /* RequestStatus.NOT_STARTED */) {
  579. // The request timed out or failed in a different call. Try again.
  580. const { installationEntry, registrationPromise } = await getInstallationEntry(installations);
  581. if (registrationPromise) {
  582. return registrationPromise;
  583. }
  584. else {
  585. // if there is no registrationPromise, entry is registered.
  586. return installationEntry;
  587. }
  588. }
  589. return entry;
  590. }
  591. /**
  592. * Called only if there is a CreateInstallation request in progress.
  593. *
  594. * Updates the InstallationEntry in the DB based on the status of the
  595. * CreateInstallation request.
  596. *
  597. * Returns the updated InstallationEntry.
  598. */
  599. function updateInstallationRequest(appConfig) {
  600. return update(appConfig, oldEntry => {
  601. if (!oldEntry) {
  602. throw ERROR_FACTORY.create("installation-not-found" /* ErrorCode.INSTALLATION_NOT_FOUND */);
  603. }
  604. return clearTimedOutRequest(oldEntry);
  605. });
  606. }
  607. function clearTimedOutRequest(entry) {
  608. if (hasInstallationRequestTimedOut(entry)) {
  609. return {
  610. fid: entry.fid,
  611. registrationStatus: 0 /* RequestStatus.NOT_STARTED */
  612. };
  613. }
  614. return entry;
  615. }
  616. function hasInstallationRequestTimedOut(installationEntry) {
  617. return (installationEntry.registrationStatus === 1 /* RequestStatus.IN_PROGRESS */ &&
  618. installationEntry.registrationTime + PENDING_TIMEOUT_MS < Date.now());
  619. }
  620. /**
  621. * @license
  622. * Copyright 2019 Google LLC
  623. *
  624. * Licensed under the Apache License, Version 2.0 (the "License");
  625. * you may not use this file except in compliance with the License.
  626. * You may obtain a copy of the License at
  627. *
  628. * http://www.apache.org/licenses/LICENSE-2.0
  629. *
  630. * Unless required by applicable law or agreed to in writing, software
  631. * distributed under the License is distributed on an "AS IS" BASIS,
  632. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  633. * See the License for the specific language governing permissions and
  634. * limitations under the License.
  635. */
  636. async function generateAuthTokenRequest({ appConfig, heartbeatServiceProvider }, installationEntry) {
  637. const endpoint = getGenerateAuthTokenEndpoint(appConfig, installationEntry);
  638. const headers = getHeadersWithAuth(appConfig, installationEntry);
  639. // If heartbeat service exists, add the heartbeat string to the header.
  640. const heartbeatService = heartbeatServiceProvider.getImmediate({
  641. optional: true
  642. });
  643. if (heartbeatService) {
  644. const heartbeatsHeader = await heartbeatService.getHeartbeatsHeader();
  645. if (heartbeatsHeader) {
  646. headers.append('x-firebase-client', heartbeatsHeader);
  647. }
  648. }
  649. const body = {
  650. installation: {
  651. sdkVersion: PACKAGE_VERSION,
  652. appId: appConfig.appId
  653. }
  654. };
  655. const request = {
  656. method: 'POST',
  657. headers,
  658. body: JSON.stringify(body)
  659. };
  660. const response = await retryIfServerError(() => fetch(endpoint, request));
  661. if (response.ok) {
  662. const responseValue = await response.json();
  663. const completedAuthToken = extractAuthTokenInfoFromResponse(responseValue);
  664. return completedAuthToken;
  665. }
  666. else {
  667. throw await getErrorFromResponse('Generate Auth Token', response);
  668. }
  669. }
  670. function getGenerateAuthTokenEndpoint(appConfig, { fid }) {
  671. return `${getInstallationsEndpoint(appConfig)}/${fid}/authTokens:generate`;
  672. }
  673. /**
  674. * @license
  675. * Copyright 2019 Google LLC
  676. *
  677. * Licensed under the Apache License, Version 2.0 (the "License");
  678. * you may not use this file except in compliance with the License.
  679. * You may obtain a copy of the License at
  680. *
  681. * http://www.apache.org/licenses/LICENSE-2.0
  682. *
  683. * Unless required by applicable law or agreed to in writing, software
  684. * distributed under the License is distributed on an "AS IS" BASIS,
  685. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  686. * See the License for the specific language governing permissions and
  687. * limitations under the License.
  688. */
  689. /**
  690. * Returns a valid authentication token for the installation. Generates a new
  691. * token if one doesn't exist, is expired or about to expire.
  692. *
  693. * Should only be called if the Firebase Installation is registered.
  694. */
  695. async function refreshAuthToken(installations, forceRefresh = false) {
  696. let tokenPromise;
  697. const entry = await update(installations.appConfig, oldEntry => {
  698. if (!isEntryRegistered(oldEntry)) {
  699. throw ERROR_FACTORY.create("not-registered" /* ErrorCode.NOT_REGISTERED */);
  700. }
  701. const oldAuthToken = oldEntry.authToken;
  702. if (!forceRefresh && isAuthTokenValid(oldAuthToken)) {
  703. // There is a valid token in the DB.
  704. return oldEntry;
  705. }
  706. else if (oldAuthToken.requestStatus === 1 /* RequestStatus.IN_PROGRESS */) {
  707. // There already is a token request in progress.
  708. tokenPromise = waitUntilAuthTokenRequest(installations, forceRefresh);
  709. return oldEntry;
  710. }
  711. else {
  712. // No token or token expired.
  713. if (!navigator.onLine) {
  714. throw ERROR_FACTORY.create("app-offline" /* ErrorCode.APP_OFFLINE */);
  715. }
  716. const inProgressEntry = makeAuthTokenRequestInProgressEntry(oldEntry);
  717. tokenPromise = fetchAuthTokenFromServer(installations, inProgressEntry);
  718. return inProgressEntry;
  719. }
  720. });
  721. const authToken = tokenPromise
  722. ? await tokenPromise
  723. : entry.authToken;
  724. return authToken;
  725. }
  726. /**
  727. * Call only if FID is registered and Auth Token request is in progress.
  728. *
  729. * Waits until the current pending request finishes. If the request times out,
  730. * tries once in this thread as well.
  731. */
  732. async function waitUntilAuthTokenRequest(installations, forceRefresh) {
  733. // Unfortunately, there is no way of reliably observing when a value in
  734. // IndexedDB changes (yet, see https://github.com/WICG/indexed-db-observers),
  735. // so we need to poll.
  736. let entry = await updateAuthTokenRequest(installations.appConfig);
  737. while (entry.authToken.requestStatus === 1 /* RequestStatus.IN_PROGRESS */) {
  738. // generateAuthToken still in progress.
  739. await sleep(100);
  740. entry = await updateAuthTokenRequest(installations.appConfig);
  741. }
  742. const authToken = entry.authToken;
  743. if (authToken.requestStatus === 0 /* RequestStatus.NOT_STARTED */) {
  744. // The request timed out or failed in a different call. Try again.
  745. return refreshAuthToken(installations, forceRefresh);
  746. }
  747. else {
  748. return authToken;
  749. }
  750. }
  751. /**
  752. * Called only if there is a GenerateAuthToken request in progress.
  753. *
  754. * Updates the InstallationEntry in the DB based on the status of the
  755. * GenerateAuthToken request.
  756. *
  757. * Returns the updated InstallationEntry.
  758. */
  759. function updateAuthTokenRequest(appConfig) {
  760. return update(appConfig, oldEntry => {
  761. if (!isEntryRegistered(oldEntry)) {
  762. throw ERROR_FACTORY.create("not-registered" /* ErrorCode.NOT_REGISTERED */);
  763. }
  764. const oldAuthToken = oldEntry.authToken;
  765. if (hasAuthTokenRequestTimedOut(oldAuthToken)) {
  766. return Object.assign(Object.assign({}, oldEntry), { authToken: { requestStatus: 0 /* RequestStatus.NOT_STARTED */ } });
  767. }
  768. return oldEntry;
  769. });
  770. }
  771. async function fetchAuthTokenFromServer(installations, installationEntry) {
  772. try {
  773. const authToken = await generateAuthTokenRequest(installations, installationEntry);
  774. const updatedInstallationEntry = Object.assign(Object.assign({}, installationEntry), { authToken });
  775. await set(installations.appConfig, updatedInstallationEntry);
  776. return authToken;
  777. }
  778. catch (e) {
  779. if (isServerError(e) &&
  780. (e.customData.serverCode === 401 || e.customData.serverCode === 404)) {
  781. // Server returned a "FID not found" or a "Invalid authentication" error.
  782. // Generate a new ID next time.
  783. await remove(installations.appConfig);
  784. }
  785. else {
  786. const updatedInstallationEntry = Object.assign(Object.assign({}, installationEntry), { authToken: { requestStatus: 0 /* RequestStatus.NOT_STARTED */ } });
  787. await set(installations.appConfig, updatedInstallationEntry);
  788. }
  789. throw e;
  790. }
  791. }
  792. function isEntryRegistered(installationEntry) {
  793. return (installationEntry !== undefined &&
  794. installationEntry.registrationStatus === 2 /* RequestStatus.COMPLETED */);
  795. }
  796. function isAuthTokenValid(authToken) {
  797. return (authToken.requestStatus === 2 /* RequestStatus.COMPLETED */ &&
  798. !isAuthTokenExpired(authToken));
  799. }
  800. function isAuthTokenExpired(authToken) {
  801. const now = Date.now();
  802. return (now < authToken.creationTime ||
  803. authToken.creationTime + authToken.expiresIn < now + TOKEN_EXPIRATION_BUFFER);
  804. }
  805. /** Returns an updated InstallationEntry with an InProgressAuthToken. */
  806. function makeAuthTokenRequestInProgressEntry(oldEntry) {
  807. const inProgressAuthToken = {
  808. requestStatus: 1 /* RequestStatus.IN_PROGRESS */,
  809. requestTime: Date.now()
  810. };
  811. return Object.assign(Object.assign({}, oldEntry), { authToken: inProgressAuthToken });
  812. }
  813. function hasAuthTokenRequestTimedOut(authToken) {
  814. return (authToken.requestStatus === 1 /* RequestStatus.IN_PROGRESS */ &&
  815. authToken.requestTime + PENDING_TIMEOUT_MS < Date.now());
  816. }
  817. /**
  818. * @license
  819. * Copyright 2019 Google LLC
  820. *
  821. * Licensed under the Apache License, Version 2.0 (the "License");
  822. * you may not use this file except in compliance with the License.
  823. * You may obtain a copy of the License at
  824. *
  825. * http://www.apache.org/licenses/LICENSE-2.0
  826. *
  827. * Unless required by applicable law or agreed to in writing, software
  828. * distributed under the License is distributed on an "AS IS" BASIS,
  829. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  830. * See the License for the specific language governing permissions and
  831. * limitations under the License.
  832. */
  833. /**
  834. * Creates a Firebase Installation if there isn't one for the app and
  835. * returns the Installation ID.
  836. * @param installations - The `Installations` instance.
  837. *
  838. * @public
  839. */
  840. async function getId(installations) {
  841. const installationsImpl = installations;
  842. const { installationEntry, registrationPromise } = await getInstallationEntry(installationsImpl);
  843. if (registrationPromise) {
  844. registrationPromise.catch(console.error);
  845. }
  846. else {
  847. // If the installation is already registered, update the authentication
  848. // token if needed.
  849. refreshAuthToken(installationsImpl).catch(console.error);
  850. }
  851. return installationEntry.fid;
  852. }
  853. /**
  854. * @license
  855. * Copyright 2019 Google LLC
  856. *
  857. * Licensed under the Apache License, Version 2.0 (the "License");
  858. * you may not use this file except in compliance with the License.
  859. * You may obtain a copy of the License at
  860. *
  861. * http://www.apache.org/licenses/LICENSE-2.0
  862. *
  863. * Unless required by applicable law or agreed to in writing, software
  864. * distributed under the License is distributed on an "AS IS" BASIS,
  865. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  866. * See the License for the specific language governing permissions and
  867. * limitations under the License.
  868. */
  869. /**
  870. * Returns a Firebase Installations auth token, identifying the current
  871. * Firebase Installation.
  872. * @param installations - The `Installations` instance.
  873. * @param forceRefresh - Force refresh regardless of token expiration.
  874. *
  875. * @public
  876. */
  877. async function getToken(installations, forceRefresh = false) {
  878. const installationsImpl = installations;
  879. await completeInstallationRegistration(installationsImpl);
  880. // At this point we either have a Registered Installation in the DB, or we've
  881. // already thrown an error.
  882. const authToken = await refreshAuthToken(installationsImpl, forceRefresh);
  883. return authToken.token;
  884. }
  885. async function completeInstallationRegistration(installations) {
  886. const { registrationPromise } = await getInstallationEntry(installations);
  887. if (registrationPromise) {
  888. // A createInstallation request is in progress. Wait until it finishes.
  889. await registrationPromise;
  890. }
  891. }
  892. /**
  893. * @license
  894. * Copyright 2019 Google LLC
  895. *
  896. * Licensed under the Apache License, Version 2.0 (the "License");
  897. * you may not use this file except in compliance with the License.
  898. * You may obtain a copy of the License at
  899. *
  900. * http://www.apache.org/licenses/LICENSE-2.0
  901. *
  902. * Unless required by applicable law or agreed to in writing, software
  903. * distributed under the License is distributed on an "AS IS" BASIS,
  904. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  905. * See the License for the specific language governing permissions and
  906. * limitations under the License.
  907. */
  908. async function deleteInstallationRequest(appConfig, installationEntry) {
  909. const endpoint = getDeleteEndpoint(appConfig, installationEntry);
  910. const headers = getHeadersWithAuth(appConfig, installationEntry);
  911. const request = {
  912. method: 'DELETE',
  913. headers
  914. };
  915. const response = await retryIfServerError(() => fetch(endpoint, request));
  916. if (!response.ok) {
  917. throw await getErrorFromResponse('Delete Installation', response);
  918. }
  919. }
  920. function getDeleteEndpoint(appConfig, { fid }) {
  921. return `${getInstallationsEndpoint(appConfig)}/${fid}`;
  922. }
  923. /**
  924. * @license
  925. * Copyright 2019 Google LLC
  926. *
  927. * Licensed under the Apache License, Version 2.0 (the "License");
  928. * you may not use this file except in compliance with the License.
  929. * You may obtain a copy of the License at
  930. *
  931. * http://www.apache.org/licenses/LICENSE-2.0
  932. *
  933. * Unless required by applicable law or agreed to in writing, software
  934. * distributed under the License is distributed on an "AS IS" BASIS,
  935. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  936. * See the License for the specific language governing permissions and
  937. * limitations under the License.
  938. */
  939. /**
  940. * Deletes the Firebase Installation and all associated data.
  941. * @param installations - The `Installations` instance.
  942. *
  943. * @public
  944. */
  945. async function deleteInstallations(installations) {
  946. const { appConfig } = installations;
  947. const entry = await update(appConfig, oldEntry => {
  948. if (oldEntry && oldEntry.registrationStatus === 0 /* RequestStatus.NOT_STARTED */) {
  949. // Delete the unregistered entry without sending a deleteInstallation request.
  950. return undefined;
  951. }
  952. return oldEntry;
  953. });
  954. if (entry) {
  955. if (entry.registrationStatus === 1 /* RequestStatus.IN_PROGRESS */) {
  956. // Can't delete while trying to register.
  957. throw ERROR_FACTORY.create("delete-pending-registration" /* ErrorCode.DELETE_PENDING_REGISTRATION */);
  958. }
  959. else if (entry.registrationStatus === 2 /* RequestStatus.COMPLETED */) {
  960. if (!navigator.onLine) {
  961. throw ERROR_FACTORY.create("app-offline" /* ErrorCode.APP_OFFLINE */);
  962. }
  963. else {
  964. await deleteInstallationRequest(appConfig, entry);
  965. await remove(appConfig);
  966. }
  967. }
  968. }
  969. }
  970. /**
  971. * @license
  972. * Copyright 2019 Google LLC
  973. *
  974. * Licensed under the Apache License, Version 2.0 (the "License");
  975. * you may not use this file except in compliance with the License.
  976. * You may obtain a copy of the License at
  977. *
  978. * http://www.apache.org/licenses/LICENSE-2.0
  979. *
  980. * Unless required by applicable law or agreed to in writing, software
  981. * distributed under the License is distributed on an "AS IS" BASIS,
  982. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  983. * See the License for the specific language governing permissions and
  984. * limitations under the License.
  985. */
  986. /**
  987. * Sets a new callback that will get called when Installation ID changes.
  988. * Returns an unsubscribe function that will remove the callback when called.
  989. * @param installations - The `Installations` instance.
  990. * @param callback - The callback function that is invoked when FID changes.
  991. * @returns A function that can be called to unsubscribe.
  992. *
  993. * @public
  994. */
  995. function onIdChange(installations, callback) {
  996. const { appConfig } = installations;
  997. addCallback(appConfig, callback);
  998. return () => {
  999. removeCallback(appConfig, callback);
  1000. };
  1001. }
  1002. /**
  1003. * @license
  1004. * Copyright 2020 Google LLC
  1005. *
  1006. * Licensed under the Apache License, Version 2.0 (the "License");
  1007. * you may not use this file except in compliance with the License.
  1008. * You may obtain a copy of the License at
  1009. *
  1010. * http://www.apache.org/licenses/LICENSE-2.0
  1011. *
  1012. * Unless required by applicable law or agreed to in writing, software
  1013. * distributed under the License is distributed on an "AS IS" BASIS,
  1014. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  1015. * See the License for the specific language governing permissions and
  1016. * limitations under the License.
  1017. */
  1018. /**
  1019. * Returns an instance of {@link Installations} associated with the given
  1020. * {@link @firebase/app#FirebaseApp} instance.
  1021. * @param app - The {@link @firebase/app#FirebaseApp} instance.
  1022. *
  1023. * @public
  1024. */
  1025. function getInstallations(app = getApp()) {
  1026. const installationsImpl = _getProvider(app, 'installations').getImmediate();
  1027. return installationsImpl;
  1028. }
  1029. /**
  1030. * @license
  1031. * Copyright 2019 Google LLC
  1032. *
  1033. * Licensed under the Apache License, Version 2.0 (the "License");
  1034. * you may not use this file except in compliance with the License.
  1035. * You may obtain a copy of the License at
  1036. *
  1037. * http://www.apache.org/licenses/LICENSE-2.0
  1038. *
  1039. * Unless required by applicable law or agreed to in writing, software
  1040. * distributed under the License is distributed on an "AS IS" BASIS,
  1041. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  1042. * See the License for the specific language governing permissions and
  1043. * limitations under the License.
  1044. */
  1045. function extractAppConfig(app) {
  1046. if (!app || !app.options) {
  1047. throw getMissingValueError('App Configuration');
  1048. }
  1049. if (!app.name) {
  1050. throw getMissingValueError('App Name');
  1051. }
  1052. // Required app config keys
  1053. const configKeys = [
  1054. 'projectId',
  1055. 'apiKey',
  1056. 'appId'
  1057. ];
  1058. for (const keyName of configKeys) {
  1059. if (!app.options[keyName]) {
  1060. throw getMissingValueError(keyName);
  1061. }
  1062. }
  1063. return {
  1064. appName: app.name,
  1065. projectId: app.options.projectId,
  1066. apiKey: app.options.apiKey,
  1067. appId: app.options.appId
  1068. };
  1069. }
  1070. function getMissingValueError(valueName) {
  1071. return ERROR_FACTORY.create("missing-app-config-values" /* ErrorCode.MISSING_APP_CONFIG_VALUES */, {
  1072. valueName
  1073. });
  1074. }
  1075. /**
  1076. * @license
  1077. * Copyright 2020 Google LLC
  1078. *
  1079. * Licensed under the Apache License, Version 2.0 (the "License");
  1080. * you may not use this file except in compliance with the License.
  1081. * You may obtain a copy of the License at
  1082. *
  1083. * http://www.apache.org/licenses/LICENSE-2.0
  1084. *
  1085. * Unless required by applicable law or agreed to in writing, software
  1086. * distributed under the License is distributed on an "AS IS" BASIS,
  1087. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  1088. * See the License for the specific language governing permissions and
  1089. * limitations under the License.
  1090. */
  1091. const INSTALLATIONS_NAME = 'installations';
  1092. const INSTALLATIONS_NAME_INTERNAL = 'installations-internal';
  1093. const publicFactory = (container) => {
  1094. const app = container.getProvider('app').getImmediate();
  1095. // Throws if app isn't configured properly.
  1096. const appConfig = extractAppConfig(app);
  1097. const heartbeatServiceProvider = _getProvider(app, 'heartbeat');
  1098. const installationsImpl = {
  1099. app,
  1100. appConfig,
  1101. heartbeatServiceProvider,
  1102. _delete: () => Promise.resolve()
  1103. };
  1104. return installationsImpl;
  1105. };
  1106. const internalFactory = (container) => {
  1107. const app = container.getProvider('app').getImmediate();
  1108. // Internal FIS instance relies on public FIS instance.
  1109. const installations = _getProvider(app, INSTALLATIONS_NAME).getImmediate();
  1110. const installationsInternal = {
  1111. getId: () => getId(installations),
  1112. getToken: (forceRefresh) => getToken(installations, forceRefresh)
  1113. };
  1114. return installationsInternal;
  1115. };
  1116. function registerInstallations() {
  1117. _registerComponent(new Component(INSTALLATIONS_NAME, publicFactory, "PUBLIC" /* ComponentType.PUBLIC */));
  1118. _registerComponent(new Component(INSTALLATIONS_NAME_INTERNAL, internalFactory, "PRIVATE" /* ComponentType.PRIVATE */));
  1119. }
  1120. /**
  1121. * Firebase Installations
  1122. *
  1123. * @packageDocumentation
  1124. */
  1125. registerInstallations();
  1126. registerVersion(name, version);
  1127. // BUILD_TARGET will be replaced by values like esm5, esm2017, cjs5, etc during the compilation
  1128. registerVersion(name, version, 'esm2017');
  1129. export { deleteInstallations, getId, getInstallations, getToken, onIdChange };
  1130. //# sourceMappingURL=index.esm2017.js.map