@firebase/app 0.10.15 → 0.10.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/dist/app/src/api.d.ts +207 -207
  2. package/dist/app/src/api.test.d.ts +22 -22
  3. package/dist/app/src/constants.d.ts +26 -26
  4. package/dist/app/src/errors.d.ts +67 -67
  5. package/dist/app/src/firebaseApp.d.ts +46 -46
  6. package/dist/app/src/firebaseApp.test.d.ts +17 -17
  7. package/dist/app/src/firebaseServerApp.d.ts +36 -36
  8. package/dist/app/src/firebaseServerApp.test.d.ts +17 -17
  9. package/dist/app/src/global_index.d.ts +868 -868
  10. package/dist/app/src/heartbeatService.d.ts +83 -83
  11. package/dist/app/src/heartbeatService.test.d.ts +23 -23
  12. package/dist/app/src/index.d.ts +9 -9
  13. package/dist/app/src/indexeddb.d.ts +20 -20
  14. package/dist/app/src/indexeddb.test.d.ts +17 -17
  15. package/dist/app/src/internal.d.ts +99 -99
  16. package/dist/app/src/internal.test.d.ts +23 -23
  17. package/dist/app/src/logger.d.ts +18 -18
  18. package/dist/app/src/platformLoggerService.d.ts +23 -23
  19. package/dist/app/src/platformLoggerService.test.d.ts +24 -24
  20. package/dist/app/src/public-types.d.ts +231 -231
  21. package/dist/app/src/registerCoreComponents.d.ts +17 -17
  22. package/dist/app/src/types.d.ts +55 -55
  23. package/dist/app/test/setup.d.ts +17 -17
  24. package/dist/app/test/util.d.ts +26 -26
  25. package/dist/esm/app/src/api.d.ts +207 -207
  26. package/dist/esm/app/src/api.test.d.ts +22 -22
  27. package/dist/esm/app/src/constants.d.ts +26 -26
  28. package/dist/esm/app/src/errors.d.ts +67 -67
  29. package/dist/esm/app/src/firebaseApp.d.ts +46 -46
  30. package/dist/esm/app/src/firebaseApp.test.d.ts +17 -17
  31. package/dist/esm/app/src/firebaseServerApp.d.ts +36 -36
  32. package/dist/esm/app/src/firebaseServerApp.test.d.ts +17 -17
  33. package/dist/esm/app/src/heartbeatService.d.ts +83 -83
  34. package/dist/esm/app/src/heartbeatService.test.d.ts +23 -23
  35. package/dist/esm/app/src/index.d.ts +9 -9
  36. package/dist/esm/app/src/indexeddb.d.ts +20 -20
  37. package/dist/esm/app/src/indexeddb.test.d.ts +17 -17
  38. package/dist/esm/app/src/internal.d.ts +99 -99
  39. package/dist/esm/app/src/internal.test.d.ts +23 -23
  40. package/dist/esm/app/src/logger.d.ts +18 -18
  41. package/dist/esm/app/src/platformLoggerService.d.ts +23 -23
  42. package/dist/esm/app/src/platformLoggerService.test.d.ts +24 -24
  43. package/dist/esm/app/src/public-types.d.ts +231 -231
  44. package/dist/esm/app/src/registerCoreComponents.d.ts +17 -17
  45. package/dist/esm/app/src/types.d.ts +55 -55
  46. package/dist/esm/app/test/setup.d.ts +17 -17
  47. package/dist/esm/app/test/util.d.ts +26 -26
  48. package/dist/esm/index.esm2017.js +1069 -1069
  49. package/dist/esm/index.esm2017.js.map +1 -1
  50. package/dist/index.cjs.js +1069 -1069
  51. package/dist/index.cjs.js.map +1 -1
  52. package/package.json +5 -5
package/dist/index.cjs.js CHANGED
@@ -7,78 +7,78 @@ var logger$1 = require('@firebase/logger');
7
7
  var util = require('@firebase/util');
8
8
  var idb = require('idb');
9
9
 
10
- /**
11
- * @license
12
- * Copyright 2019 Google LLC
13
- *
14
- * Licensed under the Apache License, Version 2.0 (the "License");
15
- * you may not use this file except in compliance with the License.
16
- * You may obtain a copy of the License at
17
- *
18
- * http://www.apache.org/licenses/LICENSE-2.0
19
- *
20
- * Unless required by applicable law or agreed to in writing, software
21
- * distributed under the License is distributed on an "AS IS" BASIS,
22
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23
- * See the License for the specific language governing permissions and
24
- * limitations under the License.
25
- */
26
- class PlatformLoggerServiceImpl {
27
- constructor(container) {
28
- this.container = container;
29
- }
30
- // In initial implementation, this will be called by installations on
31
- // auth token refresh, and installations will send this string.
32
- getPlatformInfoString() {
33
- const providers = this.container.getProviders();
34
- // Loop through providers and get library/version pairs from any that are
35
- // version components.
36
- return providers
37
- .map(provider => {
38
- if (isVersionServiceProvider(provider)) {
39
- const service = provider.getImmediate();
40
- return `${service.library}/${service.version}`;
41
- }
42
- else {
43
- return null;
44
- }
45
- })
46
- .filter(logString => logString)
47
- .join(' ');
48
- }
49
- }
50
- /**
51
- *
52
- * @param provider check if this provider provides a VersionService
53
- *
54
- * NOTE: Using Provider<'app-version'> is a hack to indicate that the provider
55
- * provides VersionService. The provider is not necessarily a 'app-version'
56
- * provider.
57
- */
58
- function isVersionServiceProvider(provider) {
59
- const component = provider.getComponent();
60
- return (component === null || component === void 0 ? void 0 : component.type) === "VERSION" /* ComponentType.VERSION */;
10
+ /**
11
+ * @license
12
+ * Copyright 2019 Google LLC
13
+ *
14
+ * Licensed under the Apache License, Version 2.0 (the "License");
15
+ * you may not use this file except in compliance with the License.
16
+ * You may obtain a copy of the License at
17
+ *
18
+ * http://www.apache.org/licenses/LICENSE-2.0
19
+ *
20
+ * Unless required by applicable law or agreed to in writing, software
21
+ * distributed under the License is distributed on an "AS IS" BASIS,
22
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23
+ * See the License for the specific language governing permissions and
24
+ * limitations under the License.
25
+ */
26
+ class PlatformLoggerServiceImpl {
27
+ constructor(container) {
28
+ this.container = container;
29
+ }
30
+ // In initial implementation, this will be called by installations on
31
+ // auth token refresh, and installations will send this string.
32
+ getPlatformInfoString() {
33
+ const providers = this.container.getProviders();
34
+ // Loop through providers and get library/version pairs from any that are
35
+ // version components.
36
+ return providers
37
+ .map(provider => {
38
+ if (isVersionServiceProvider(provider)) {
39
+ const service = provider.getImmediate();
40
+ return `${service.library}/${service.version}`;
41
+ }
42
+ else {
43
+ return null;
44
+ }
45
+ })
46
+ .filter(logString => logString)
47
+ .join(' ');
48
+ }
49
+ }
50
+ /**
51
+ *
52
+ * @param provider check if this provider provides a VersionService
53
+ *
54
+ * NOTE: Using Provider<'app-version'> is a hack to indicate that the provider
55
+ * provides VersionService. The provider is not necessarily a 'app-version'
56
+ * provider.
57
+ */
58
+ function isVersionServiceProvider(provider) {
59
+ const component = provider.getComponent();
60
+ return (component === null || component === void 0 ? void 0 : component.type) === "VERSION" /* ComponentType.VERSION */;
61
61
  }
62
62
 
63
63
  const name$q = "@firebase/app";
64
- const version$1 = "0.10.15";
64
+ const version$1 = "0.10.16";
65
65
 
66
- /**
67
- * @license
68
- * Copyright 2019 Google LLC
69
- *
70
- * Licensed under the Apache License, Version 2.0 (the "License");
71
- * you may not use this file except in compliance with the License.
72
- * You may obtain a copy of the License at
73
- *
74
- * http://www.apache.org/licenses/LICENSE-2.0
75
- *
76
- * Unless required by applicable law or agreed to in writing, software
77
- * distributed under the License is distributed on an "AS IS" BASIS,
78
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
79
- * See the License for the specific language governing permissions and
80
- * limitations under the License.
81
- */
66
+ /**
67
+ * @license
68
+ * Copyright 2019 Google LLC
69
+ *
70
+ * Licensed under the Apache License, Version 2.0 (the "License");
71
+ * you may not use this file except in compliance with the License.
72
+ * You may obtain a copy of the License at
73
+ *
74
+ * http://www.apache.org/licenses/LICENSE-2.0
75
+ *
76
+ * Unless required by applicable law or agreed to in writing, software
77
+ * distributed under the License is distributed on an "AS IS" BASIS,
78
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
79
+ * See the License for the specific language governing permissions and
80
+ * limitations under the License.
81
+ */
82
82
  const logger = new logger$1.Logger('@firebase/app');
83
83
 
84
84
  const name$p = "@firebase/app-compat";
@@ -132,1026 +132,1026 @@ const name$2 = "@firebase/vertexai";
132
132
  const name$1 = "@firebase/firestore-compat";
133
133
 
134
134
  const name = "firebase";
135
- const version = "11.0.1";
135
+ const version = "11.0.2";
136
136
 
137
- /**
138
- * @license
139
- * Copyright 2019 Google LLC
140
- *
141
- * Licensed under the Apache License, Version 2.0 (the "License");
142
- * you may not use this file except in compliance with the License.
143
- * You may obtain a copy of the License at
144
- *
145
- * http://www.apache.org/licenses/LICENSE-2.0
146
- *
147
- * Unless required by applicable law or agreed to in writing, software
148
- * distributed under the License is distributed on an "AS IS" BASIS,
149
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
150
- * See the License for the specific language governing permissions and
151
- * limitations under the License.
152
- */
153
- /**
154
- * The default app name
155
- *
156
- * @internal
157
- */
158
- const DEFAULT_ENTRY_NAME = '[DEFAULT]';
159
- const PLATFORM_LOG_STRING = {
160
- [name$q]: 'fire-core',
161
- [name$p]: 'fire-core-compat',
162
- [name$n]: 'fire-analytics',
163
- [name$o]: 'fire-analytics-compat',
164
- [name$l]: 'fire-app-check',
165
- [name$m]: 'fire-app-check-compat',
166
- [name$k]: 'fire-auth',
167
- [name$j]: 'fire-auth-compat',
168
- [name$i]: 'fire-rtdb',
169
- [name$h]: 'fire-data-connect',
170
- [name$g]: 'fire-rtdb-compat',
171
- [name$f]: 'fire-fn',
172
- [name$e]: 'fire-fn-compat',
173
- [name$d]: 'fire-iid',
174
- [name$c]: 'fire-iid-compat',
175
- [name$b]: 'fire-fcm',
176
- [name$a]: 'fire-fcm-compat',
177
- [name$9]: 'fire-perf',
178
- [name$8]: 'fire-perf-compat',
179
- [name$7]: 'fire-rc',
180
- [name$6]: 'fire-rc-compat',
181
- [name$5]: 'fire-gcs',
182
- [name$4]: 'fire-gcs-compat',
183
- [name$3]: 'fire-fst',
184
- [name$1]: 'fire-fst-compat',
185
- [name$2]: 'fire-vertex',
186
- 'fire-js': 'fire-js',
187
- [name]: 'fire-js-all'
137
+ /**
138
+ * @license
139
+ * Copyright 2019 Google LLC
140
+ *
141
+ * Licensed under the Apache License, Version 2.0 (the "License");
142
+ * you may not use this file except in compliance with the License.
143
+ * You may obtain a copy of the License at
144
+ *
145
+ * http://www.apache.org/licenses/LICENSE-2.0
146
+ *
147
+ * Unless required by applicable law or agreed to in writing, software
148
+ * distributed under the License is distributed on an "AS IS" BASIS,
149
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
150
+ * See the License for the specific language governing permissions and
151
+ * limitations under the License.
152
+ */
153
+ /**
154
+ * The default app name
155
+ *
156
+ * @internal
157
+ */
158
+ const DEFAULT_ENTRY_NAME = '[DEFAULT]';
159
+ const PLATFORM_LOG_STRING = {
160
+ [name$q]: 'fire-core',
161
+ [name$p]: 'fire-core-compat',
162
+ [name$n]: 'fire-analytics',
163
+ [name$o]: 'fire-analytics-compat',
164
+ [name$l]: 'fire-app-check',
165
+ [name$m]: 'fire-app-check-compat',
166
+ [name$k]: 'fire-auth',
167
+ [name$j]: 'fire-auth-compat',
168
+ [name$i]: 'fire-rtdb',
169
+ [name$h]: 'fire-data-connect',
170
+ [name$g]: 'fire-rtdb-compat',
171
+ [name$f]: 'fire-fn',
172
+ [name$e]: 'fire-fn-compat',
173
+ [name$d]: 'fire-iid',
174
+ [name$c]: 'fire-iid-compat',
175
+ [name$b]: 'fire-fcm',
176
+ [name$a]: 'fire-fcm-compat',
177
+ [name$9]: 'fire-perf',
178
+ [name$8]: 'fire-perf-compat',
179
+ [name$7]: 'fire-rc',
180
+ [name$6]: 'fire-rc-compat',
181
+ [name$5]: 'fire-gcs',
182
+ [name$4]: 'fire-gcs-compat',
183
+ [name$3]: 'fire-fst',
184
+ [name$1]: 'fire-fst-compat',
185
+ [name$2]: 'fire-vertex',
186
+ 'fire-js': 'fire-js', // Platform identifier for JS SDK.
187
+ [name]: 'fire-js-all'
188
188
  };
189
189
 
190
- /**
191
- * @license
192
- * Copyright 2019 Google LLC
193
- *
194
- * Licensed under the Apache License, Version 2.0 (the "License");
195
- * you may not use this file except in compliance with the License.
196
- * You may obtain a copy of the License at
197
- *
198
- * http://www.apache.org/licenses/LICENSE-2.0
199
- *
200
- * Unless required by applicable law or agreed to in writing, software
201
- * distributed under the License is distributed on an "AS IS" BASIS,
202
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
203
- * See the License for the specific language governing permissions and
204
- * limitations under the License.
205
- */
206
- /**
207
- * @internal
208
- */
209
- const _apps = new Map();
210
- /**
211
- * @internal
212
- */
213
- const _serverApps = new Map();
214
- /**
215
- * Registered components.
216
- *
217
- * @internal
218
- */
219
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
220
- const _components = new Map();
221
- /**
222
- * @param component - the component being added to this app's container
223
- *
224
- * @internal
225
- */
226
- function _addComponent(app, component) {
227
- try {
228
- app.container.addComponent(component);
229
- }
230
- catch (e) {
231
- logger.debug(`Component ${component.name} failed to register with FirebaseApp ${app.name}`, e);
232
- }
233
- }
234
- /**
235
- *
236
- * @internal
237
- */
238
- function _addOrOverwriteComponent(app, component) {
239
- app.container.addOrOverwriteComponent(component);
240
- }
241
- /**
242
- *
243
- * @param component - the component to register
244
- * @returns whether or not the component is registered successfully
245
- *
246
- * @internal
247
- */
248
- function _registerComponent(component) {
249
- const componentName = component.name;
250
- if (_components.has(componentName)) {
251
- logger.debug(`There were multiple attempts to register component ${componentName}.`);
252
- return false;
253
- }
254
- _components.set(componentName, component);
255
- // add the component to existing app instances
256
- for (const app of _apps.values()) {
257
- _addComponent(app, component);
258
- }
259
- for (const serverApp of _serverApps.values()) {
260
- _addComponent(serverApp, component);
261
- }
262
- return true;
263
- }
264
- /**
265
- *
266
- * @param app - FirebaseApp instance
267
- * @param name - service name
268
- *
269
- * @returns the provider for the service with the matching name
270
- *
271
- * @internal
272
- */
273
- function _getProvider(app, name) {
274
- const heartbeatController = app.container
275
- .getProvider('heartbeat')
276
- .getImmediate({ optional: true });
277
- if (heartbeatController) {
278
- void heartbeatController.triggerHeartbeat();
279
- }
280
- return app.container.getProvider(name);
281
- }
282
- /**
283
- *
284
- * @param app - FirebaseApp instance
285
- * @param name - service name
286
- * @param instanceIdentifier - service instance identifier in case the service supports multiple instances
287
- *
288
- * @internal
289
- */
290
- function _removeServiceInstance(app, name, instanceIdentifier = DEFAULT_ENTRY_NAME) {
291
- _getProvider(app, name).clearInstance(instanceIdentifier);
292
- }
293
- /**
294
- *
295
- * @param obj - an object of type FirebaseApp or FirebaseOptions.
296
- *
297
- * @returns true if the provide object is of type FirebaseApp.
298
- *
299
- * @internal
300
- */
301
- function _isFirebaseApp(obj) {
302
- return obj.options !== undefined;
303
- }
304
- /**
305
- *
306
- * @param obj - an object of type FirebaseApp.
307
- *
308
- * @returns true if the provided object is of type FirebaseServerAppImpl.
309
- *
310
- * @internal
311
- */
312
- function _isFirebaseServerApp(obj) {
313
- return obj.settings !== undefined;
314
- }
315
- /**
316
- * Test only
317
- *
318
- * @internal
319
- */
320
- function _clearComponents() {
321
- _components.clear();
190
+ /**
191
+ * @license
192
+ * Copyright 2019 Google LLC
193
+ *
194
+ * Licensed under the Apache License, Version 2.0 (the "License");
195
+ * you may not use this file except in compliance with the License.
196
+ * You may obtain a copy of the License at
197
+ *
198
+ * http://www.apache.org/licenses/LICENSE-2.0
199
+ *
200
+ * Unless required by applicable law or agreed to in writing, software
201
+ * distributed under the License is distributed on an "AS IS" BASIS,
202
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
203
+ * See the License for the specific language governing permissions and
204
+ * limitations under the License.
205
+ */
206
+ /**
207
+ * @internal
208
+ */
209
+ const _apps = new Map();
210
+ /**
211
+ * @internal
212
+ */
213
+ const _serverApps = new Map();
214
+ /**
215
+ * Registered components.
216
+ *
217
+ * @internal
218
+ */
219
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
220
+ const _components = new Map();
221
+ /**
222
+ * @param component - the component being added to this app's container
223
+ *
224
+ * @internal
225
+ */
226
+ function _addComponent(app, component) {
227
+ try {
228
+ app.container.addComponent(component);
229
+ }
230
+ catch (e) {
231
+ logger.debug(`Component ${component.name} failed to register with FirebaseApp ${app.name}`, e);
232
+ }
233
+ }
234
+ /**
235
+ *
236
+ * @internal
237
+ */
238
+ function _addOrOverwriteComponent(app, component) {
239
+ app.container.addOrOverwriteComponent(component);
240
+ }
241
+ /**
242
+ *
243
+ * @param component - the component to register
244
+ * @returns whether or not the component is registered successfully
245
+ *
246
+ * @internal
247
+ */
248
+ function _registerComponent(component) {
249
+ const componentName = component.name;
250
+ if (_components.has(componentName)) {
251
+ logger.debug(`There were multiple attempts to register component ${componentName}.`);
252
+ return false;
253
+ }
254
+ _components.set(componentName, component);
255
+ // add the component to existing app instances
256
+ for (const app of _apps.values()) {
257
+ _addComponent(app, component);
258
+ }
259
+ for (const serverApp of _serverApps.values()) {
260
+ _addComponent(serverApp, component);
261
+ }
262
+ return true;
263
+ }
264
+ /**
265
+ *
266
+ * @param app - FirebaseApp instance
267
+ * @param name - service name
268
+ *
269
+ * @returns the provider for the service with the matching name
270
+ *
271
+ * @internal
272
+ */
273
+ function _getProvider(app, name) {
274
+ const heartbeatController = app.container
275
+ .getProvider('heartbeat')
276
+ .getImmediate({ optional: true });
277
+ if (heartbeatController) {
278
+ void heartbeatController.triggerHeartbeat();
279
+ }
280
+ return app.container.getProvider(name);
281
+ }
282
+ /**
283
+ *
284
+ * @param app - FirebaseApp instance
285
+ * @param name - service name
286
+ * @param instanceIdentifier - service instance identifier in case the service supports multiple instances
287
+ *
288
+ * @internal
289
+ */
290
+ function _removeServiceInstance(app, name, instanceIdentifier = DEFAULT_ENTRY_NAME) {
291
+ _getProvider(app, name).clearInstance(instanceIdentifier);
292
+ }
293
+ /**
294
+ *
295
+ * @param obj - an object of type FirebaseApp or FirebaseOptions.
296
+ *
297
+ * @returns true if the provide object is of type FirebaseApp.
298
+ *
299
+ * @internal
300
+ */
301
+ function _isFirebaseApp(obj) {
302
+ return obj.options !== undefined;
303
+ }
304
+ /**
305
+ *
306
+ * @param obj - an object of type FirebaseApp.
307
+ *
308
+ * @returns true if the provided object is of type FirebaseServerAppImpl.
309
+ *
310
+ * @internal
311
+ */
312
+ function _isFirebaseServerApp(obj) {
313
+ return obj.settings !== undefined;
314
+ }
315
+ /**
316
+ * Test only
317
+ *
318
+ * @internal
319
+ */
320
+ function _clearComponents() {
321
+ _components.clear();
322
322
  }
323
323
 
324
- /**
325
- * @license
326
- * Copyright 2019 Google LLC
327
- *
328
- * Licensed under the Apache License, Version 2.0 (the "License");
329
- * you may not use this file except in compliance with the License.
330
- * You may obtain a copy of the License at
331
- *
332
- * http://www.apache.org/licenses/LICENSE-2.0
333
- *
334
- * Unless required by applicable law or agreed to in writing, software
335
- * distributed under the License is distributed on an "AS IS" BASIS,
336
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
337
- * See the License for the specific language governing permissions and
338
- * limitations under the License.
339
- */
340
- const ERRORS = {
341
- ["no-app" /* AppError.NO_APP */]: "No Firebase App '{$appName}' has been created - " +
342
- 'call initializeApp() first',
343
- ["bad-app-name" /* AppError.BAD_APP_NAME */]: "Illegal App name: '{$appName}'",
344
- ["duplicate-app" /* AppError.DUPLICATE_APP */]: "Firebase App named '{$appName}' already exists with different options or config",
345
- ["app-deleted" /* AppError.APP_DELETED */]: "Firebase App named '{$appName}' already deleted",
346
- ["server-app-deleted" /* AppError.SERVER_APP_DELETED */]: 'Firebase Server App has been deleted',
347
- ["no-options" /* AppError.NO_OPTIONS */]: 'Need to provide options, when not being deployed to hosting via source.',
348
- ["invalid-app-argument" /* AppError.INVALID_APP_ARGUMENT */]: 'firebase.{$appName}() takes either no argument or a ' +
349
- 'Firebase App instance.',
350
- ["invalid-log-argument" /* AppError.INVALID_LOG_ARGUMENT */]: 'First argument to `onLog` must be null or a function.',
351
- ["idb-open" /* AppError.IDB_OPEN */]: 'Error thrown when opening IndexedDB. Original error: {$originalErrorMessage}.',
352
- ["idb-get" /* AppError.IDB_GET */]: 'Error thrown when reading from IndexedDB. Original error: {$originalErrorMessage}.',
353
- ["idb-set" /* AppError.IDB_WRITE */]: 'Error thrown when writing to IndexedDB. Original error: {$originalErrorMessage}.',
354
- ["idb-delete" /* AppError.IDB_DELETE */]: 'Error thrown when deleting from IndexedDB. Original error: {$originalErrorMessage}.',
355
- ["finalization-registry-not-supported" /* AppError.FINALIZATION_REGISTRY_NOT_SUPPORTED */]: 'FirebaseServerApp deleteOnDeref field defined but the JS runtime does not support FinalizationRegistry.',
356
- ["invalid-server-app-environment" /* AppError.INVALID_SERVER_APP_ENVIRONMENT */]: 'FirebaseServerApp is not for use in browser environments.'
357
- };
324
+ /**
325
+ * @license
326
+ * Copyright 2019 Google LLC
327
+ *
328
+ * Licensed under the Apache License, Version 2.0 (the "License");
329
+ * you may not use this file except in compliance with the License.
330
+ * You may obtain a copy of the License at
331
+ *
332
+ * http://www.apache.org/licenses/LICENSE-2.0
333
+ *
334
+ * Unless required by applicable law or agreed to in writing, software
335
+ * distributed under the License is distributed on an "AS IS" BASIS,
336
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
337
+ * See the License for the specific language governing permissions and
338
+ * limitations under the License.
339
+ */
340
+ const ERRORS = {
341
+ ["no-app" /* AppError.NO_APP */]: "No Firebase App '{$appName}' has been created - " +
342
+ 'call initializeApp() first',
343
+ ["bad-app-name" /* AppError.BAD_APP_NAME */]: "Illegal App name: '{$appName}'",
344
+ ["duplicate-app" /* AppError.DUPLICATE_APP */]: "Firebase App named '{$appName}' already exists with different options or config",
345
+ ["app-deleted" /* AppError.APP_DELETED */]: "Firebase App named '{$appName}' already deleted",
346
+ ["server-app-deleted" /* AppError.SERVER_APP_DELETED */]: 'Firebase Server App has been deleted',
347
+ ["no-options" /* AppError.NO_OPTIONS */]: 'Need to provide options, when not being deployed to hosting via source.',
348
+ ["invalid-app-argument" /* AppError.INVALID_APP_ARGUMENT */]: 'firebase.{$appName}() takes either no argument or a ' +
349
+ 'Firebase App instance.',
350
+ ["invalid-log-argument" /* AppError.INVALID_LOG_ARGUMENT */]: 'First argument to `onLog` must be null or a function.',
351
+ ["idb-open" /* AppError.IDB_OPEN */]: 'Error thrown when opening IndexedDB. Original error: {$originalErrorMessage}.',
352
+ ["idb-get" /* AppError.IDB_GET */]: 'Error thrown when reading from IndexedDB. Original error: {$originalErrorMessage}.',
353
+ ["idb-set" /* AppError.IDB_WRITE */]: 'Error thrown when writing to IndexedDB. Original error: {$originalErrorMessage}.',
354
+ ["idb-delete" /* AppError.IDB_DELETE */]: 'Error thrown when deleting from IndexedDB. Original error: {$originalErrorMessage}.',
355
+ ["finalization-registry-not-supported" /* AppError.FINALIZATION_REGISTRY_NOT_SUPPORTED */]: 'FirebaseServerApp deleteOnDeref field defined but the JS runtime does not support FinalizationRegistry.',
356
+ ["invalid-server-app-environment" /* AppError.INVALID_SERVER_APP_ENVIRONMENT */]: 'FirebaseServerApp is not for use in browser environments.'
357
+ };
358
358
  const ERROR_FACTORY = new util.ErrorFactory('app', 'Firebase', ERRORS);
359
359
 
360
- /**
361
- * @license
362
- * Copyright 2019 Google LLC
363
- *
364
- * Licensed under the Apache License, Version 2.0 (the "License");
365
- * you may not use this file except in compliance with the License.
366
- * You may obtain a copy of the License at
367
- *
368
- * http://www.apache.org/licenses/LICENSE-2.0
369
- *
370
- * Unless required by applicable law or agreed to in writing, software
371
- * distributed under the License is distributed on an "AS IS" BASIS,
372
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
373
- * See the License for the specific language governing permissions and
374
- * limitations under the License.
375
- */
376
- class FirebaseAppImpl {
377
- constructor(options, config, container) {
378
- this._isDeleted = false;
379
- this._options = Object.assign({}, options);
380
- this._config = Object.assign({}, config);
381
- this._name = config.name;
382
- this._automaticDataCollectionEnabled =
383
- config.automaticDataCollectionEnabled;
384
- this._container = container;
385
- this.container.addComponent(new component.Component('app', () => this, "PUBLIC" /* ComponentType.PUBLIC */));
386
- }
387
- get automaticDataCollectionEnabled() {
388
- this.checkDestroyed();
389
- return this._automaticDataCollectionEnabled;
390
- }
391
- set automaticDataCollectionEnabled(val) {
392
- this.checkDestroyed();
393
- this._automaticDataCollectionEnabled = val;
394
- }
395
- get name() {
396
- this.checkDestroyed();
397
- return this._name;
398
- }
399
- get options() {
400
- this.checkDestroyed();
401
- return this._options;
402
- }
403
- get config() {
404
- this.checkDestroyed();
405
- return this._config;
406
- }
407
- get container() {
408
- return this._container;
409
- }
410
- get isDeleted() {
411
- return this._isDeleted;
412
- }
413
- set isDeleted(val) {
414
- this._isDeleted = val;
415
- }
416
- /**
417
- * This function will throw an Error if the App has already been deleted -
418
- * use before performing API actions on the App.
419
- */
420
- checkDestroyed() {
421
- if (this.isDeleted) {
422
- throw ERROR_FACTORY.create("app-deleted" /* AppError.APP_DELETED */, { appName: this._name });
423
- }
424
- }
360
+ /**
361
+ * @license
362
+ * Copyright 2019 Google LLC
363
+ *
364
+ * Licensed under the Apache License, Version 2.0 (the "License");
365
+ * you may not use this file except in compliance with the License.
366
+ * You may obtain a copy of the License at
367
+ *
368
+ * http://www.apache.org/licenses/LICENSE-2.0
369
+ *
370
+ * Unless required by applicable law or agreed to in writing, software
371
+ * distributed under the License is distributed on an "AS IS" BASIS,
372
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
373
+ * See the License for the specific language governing permissions and
374
+ * limitations under the License.
375
+ */
376
+ class FirebaseAppImpl {
377
+ constructor(options, config, container) {
378
+ this._isDeleted = false;
379
+ this._options = Object.assign({}, options);
380
+ this._config = Object.assign({}, config);
381
+ this._name = config.name;
382
+ this._automaticDataCollectionEnabled =
383
+ config.automaticDataCollectionEnabled;
384
+ this._container = container;
385
+ this.container.addComponent(new component.Component('app', () => this, "PUBLIC" /* ComponentType.PUBLIC */));
386
+ }
387
+ get automaticDataCollectionEnabled() {
388
+ this.checkDestroyed();
389
+ return this._automaticDataCollectionEnabled;
390
+ }
391
+ set automaticDataCollectionEnabled(val) {
392
+ this.checkDestroyed();
393
+ this._automaticDataCollectionEnabled = val;
394
+ }
395
+ get name() {
396
+ this.checkDestroyed();
397
+ return this._name;
398
+ }
399
+ get options() {
400
+ this.checkDestroyed();
401
+ return this._options;
402
+ }
403
+ get config() {
404
+ this.checkDestroyed();
405
+ return this._config;
406
+ }
407
+ get container() {
408
+ return this._container;
409
+ }
410
+ get isDeleted() {
411
+ return this._isDeleted;
412
+ }
413
+ set isDeleted(val) {
414
+ this._isDeleted = val;
415
+ }
416
+ /**
417
+ * This function will throw an Error if the App has already been deleted -
418
+ * use before performing API actions on the App.
419
+ */
420
+ checkDestroyed() {
421
+ if (this.isDeleted) {
422
+ throw ERROR_FACTORY.create("app-deleted" /* AppError.APP_DELETED */, { appName: this._name });
423
+ }
424
+ }
425
425
  }
426
426
 
427
- /**
428
- * @license
429
- * Copyright 2023 Google LLC
430
- *
431
- * Licensed under the Apache License, Version 2.0 (the "License");
432
- * you may not use this file except in compliance with the License.
433
- * You may obtain a copy of the License at
434
- *
435
- * http://www.apache.org/licenses/LICENSE-2.0
436
- *
437
- * Unless required by applicable law or agreed to in writing, software
438
- * distributed under the License is distributed on an "AS IS" BASIS,
439
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
440
- * See the License for the specific language governing permissions and
441
- * limitations under the License.
442
- */
443
- class FirebaseServerAppImpl extends FirebaseAppImpl {
444
- constructor(options, serverConfig, name, container) {
445
- // Build configuration parameters for the FirebaseAppImpl base class.
446
- const automaticDataCollectionEnabled = serverConfig.automaticDataCollectionEnabled !== undefined
447
- ? serverConfig.automaticDataCollectionEnabled
448
- : false;
449
- // Create the FirebaseAppSettings object for the FirebaseAppImp constructor.
450
- const config = {
451
- name,
452
- automaticDataCollectionEnabled
453
- };
454
- if (options.apiKey !== undefined) {
455
- // Construct the parent FirebaseAppImp object.
456
- super(options, config, container);
457
- }
458
- else {
459
- const appImpl = options;
460
- super(appImpl.options, config, container);
461
- }
462
- // Now construct the data for the FirebaseServerAppImpl.
463
- this._serverConfig = Object.assign({ automaticDataCollectionEnabled }, serverConfig);
464
- this._finalizationRegistry = null;
465
- if (typeof FinalizationRegistry !== 'undefined') {
466
- this._finalizationRegistry = new FinalizationRegistry(() => {
467
- this.automaticCleanup();
468
- });
469
- }
470
- this._refCount = 0;
471
- this.incRefCount(this._serverConfig.releaseOnDeref);
472
- // Do not retain a hard reference to the dref object, otherwise the FinalizationRegistry
473
- // will never trigger.
474
- this._serverConfig.releaseOnDeref = undefined;
475
- serverConfig.releaseOnDeref = undefined;
476
- registerVersion(name$q, version$1, 'serverapp');
477
- }
478
- toJSON() {
479
- return undefined;
480
- }
481
- get refCount() {
482
- return this._refCount;
483
- }
484
- // Increment the reference count of this server app. If an object is provided, register it
485
- // with the finalization registry.
486
- incRefCount(obj) {
487
- if (this.isDeleted) {
488
- return;
489
- }
490
- this._refCount++;
491
- if (obj !== undefined && this._finalizationRegistry !== null) {
492
- this._finalizationRegistry.register(obj, this);
493
- }
494
- }
495
- // Decrement the reference count.
496
- decRefCount() {
497
- if (this.isDeleted) {
498
- return 0;
499
- }
500
- return --this._refCount;
501
- }
502
- // Invoked by the FinalizationRegistry callback to note that this app should go through its
503
- // reference counts and delete itself if no reference count remain. The coordinating logic that
504
- // handles this is in deleteApp(...).
505
- automaticCleanup() {
506
- void deleteApp(this);
507
- }
508
- get settings() {
509
- this.checkDestroyed();
510
- return this._serverConfig;
511
- }
512
- /**
513
- * This function will throw an Error if the App has already been deleted -
514
- * use before performing API actions on the App.
515
- */
516
- checkDestroyed() {
517
- if (this.isDeleted) {
518
- throw ERROR_FACTORY.create("server-app-deleted" /* AppError.SERVER_APP_DELETED */);
519
- }
520
- }
427
+ /**
428
+ * @license
429
+ * Copyright 2023 Google LLC
430
+ *
431
+ * Licensed under the Apache License, Version 2.0 (the "License");
432
+ * you may not use this file except in compliance with the License.
433
+ * You may obtain a copy of the License at
434
+ *
435
+ * http://www.apache.org/licenses/LICENSE-2.0
436
+ *
437
+ * Unless required by applicable law or agreed to in writing, software
438
+ * distributed under the License is distributed on an "AS IS" BASIS,
439
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
440
+ * See the License for the specific language governing permissions and
441
+ * limitations under the License.
442
+ */
443
+ class FirebaseServerAppImpl extends FirebaseAppImpl {
444
+ constructor(options, serverConfig, name, container) {
445
+ // Build configuration parameters for the FirebaseAppImpl base class.
446
+ const automaticDataCollectionEnabled = serverConfig.automaticDataCollectionEnabled !== undefined
447
+ ? serverConfig.automaticDataCollectionEnabled
448
+ : false;
449
+ // Create the FirebaseAppSettings object for the FirebaseAppImp constructor.
450
+ const config = {
451
+ name,
452
+ automaticDataCollectionEnabled
453
+ };
454
+ if (options.apiKey !== undefined) {
455
+ // Construct the parent FirebaseAppImp object.
456
+ super(options, config, container);
457
+ }
458
+ else {
459
+ const appImpl = options;
460
+ super(appImpl.options, config, container);
461
+ }
462
+ // Now construct the data for the FirebaseServerAppImpl.
463
+ this._serverConfig = Object.assign({ automaticDataCollectionEnabled }, serverConfig);
464
+ this._finalizationRegistry = null;
465
+ if (typeof FinalizationRegistry !== 'undefined') {
466
+ this._finalizationRegistry = new FinalizationRegistry(() => {
467
+ this.automaticCleanup();
468
+ });
469
+ }
470
+ this._refCount = 0;
471
+ this.incRefCount(this._serverConfig.releaseOnDeref);
472
+ // Do not retain a hard reference to the dref object, otherwise the FinalizationRegistry
473
+ // will never trigger.
474
+ this._serverConfig.releaseOnDeref = undefined;
475
+ serverConfig.releaseOnDeref = undefined;
476
+ registerVersion(name$q, version$1, 'serverapp');
477
+ }
478
+ toJSON() {
479
+ return undefined;
480
+ }
481
+ get refCount() {
482
+ return this._refCount;
483
+ }
484
+ // Increment the reference count of this server app. If an object is provided, register it
485
+ // with the finalization registry.
486
+ incRefCount(obj) {
487
+ if (this.isDeleted) {
488
+ return;
489
+ }
490
+ this._refCount++;
491
+ if (obj !== undefined && this._finalizationRegistry !== null) {
492
+ this._finalizationRegistry.register(obj, this);
493
+ }
494
+ }
495
+ // Decrement the reference count.
496
+ decRefCount() {
497
+ if (this.isDeleted) {
498
+ return 0;
499
+ }
500
+ return --this._refCount;
501
+ }
502
+ // Invoked by the FinalizationRegistry callback to note that this app should go through its
503
+ // reference counts and delete itself if no reference count remain. The coordinating logic that
504
+ // handles this is in deleteApp(...).
505
+ automaticCleanup() {
506
+ void deleteApp(this);
507
+ }
508
+ get settings() {
509
+ this.checkDestroyed();
510
+ return this._serverConfig;
511
+ }
512
+ /**
513
+ * This function will throw an Error if the App has already been deleted -
514
+ * use before performing API actions on the App.
515
+ */
516
+ checkDestroyed() {
517
+ if (this.isDeleted) {
518
+ throw ERROR_FACTORY.create("server-app-deleted" /* AppError.SERVER_APP_DELETED */);
519
+ }
520
+ }
521
521
  }
522
522
 
523
- /**
524
- * @license
525
- * Copyright 2019 Google LLC
526
- *
527
- * Licensed under the Apache License, Version 2.0 (the "License");
528
- * you may not use this file except in compliance with the License.
529
- * You may obtain a copy of the License at
530
- *
531
- * http://www.apache.org/licenses/LICENSE-2.0
532
- *
533
- * Unless required by applicable law or agreed to in writing, software
534
- * distributed under the License is distributed on an "AS IS" BASIS,
535
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
536
- * See the License for the specific language governing permissions and
537
- * limitations under the License.
538
- */
539
- /**
540
- * The current SDK version.
541
- *
542
- * @public
543
- */
544
- const SDK_VERSION = version;
545
- function initializeApp(_options, rawConfig = {}) {
546
- let options = _options;
547
- if (typeof rawConfig !== 'object') {
548
- const name = rawConfig;
549
- rawConfig = { name };
550
- }
551
- const config = Object.assign({ name: DEFAULT_ENTRY_NAME, automaticDataCollectionEnabled: false }, rawConfig);
552
- const name = config.name;
553
- if (typeof name !== 'string' || !name) {
554
- throw ERROR_FACTORY.create("bad-app-name" /* AppError.BAD_APP_NAME */, {
555
- appName: String(name)
556
- });
557
- }
558
- options || (options = util.getDefaultAppConfig());
559
- if (!options) {
560
- throw ERROR_FACTORY.create("no-options" /* AppError.NO_OPTIONS */);
561
- }
562
- const existingApp = _apps.get(name);
563
- if (existingApp) {
564
- // return the existing app if options and config deep equal the ones in the existing app.
565
- if (util.deepEqual(options, existingApp.options) &&
566
- util.deepEqual(config, existingApp.config)) {
567
- return existingApp;
568
- }
569
- else {
570
- throw ERROR_FACTORY.create("duplicate-app" /* AppError.DUPLICATE_APP */, { appName: name });
571
- }
572
- }
573
- const container = new component.ComponentContainer(name);
574
- for (const component of _components.values()) {
575
- container.addComponent(component);
576
- }
577
- const newApp = new FirebaseAppImpl(options, config, container);
578
- _apps.set(name, newApp);
579
- return newApp;
580
- }
581
- function initializeServerApp(_options, _serverAppConfig) {
582
- if (util.isBrowser() && !util.isWebWorker()) {
583
- // FirebaseServerApp isn't designed to be run in browsers.
584
- throw ERROR_FACTORY.create("invalid-server-app-environment" /* AppError.INVALID_SERVER_APP_ENVIRONMENT */);
585
- }
586
- if (_serverAppConfig.automaticDataCollectionEnabled === undefined) {
587
- _serverAppConfig.automaticDataCollectionEnabled = false;
588
- }
589
- let appOptions;
590
- if (_isFirebaseApp(_options)) {
591
- appOptions = _options.options;
592
- }
593
- else {
594
- appOptions = _options;
595
- }
596
- // Build an app name based on a hash of the configuration options.
597
- const nameObj = Object.assign(Object.assign({}, _serverAppConfig), appOptions);
598
- // However, Do not mangle the name based on releaseOnDeref, since it will vary between the
599
- // construction of FirebaseServerApp instances. For example, if the object is the request headers.
600
- if (nameObj.releaseOnDeref !== undefined) {
601
- delete nameObj.releaseOnDeref;
602
- }
603
- const hashCode = (s) => {
604
- return [...s].reduce((hash, c) => (Math.imul(31, hash) + c.charCodeAt(0)) | 0, 0);
605
- };
606
- if (_serverAppConfig.releaseOnDeref !== undefined) {
607
- if (typeof FinalizationRegistry === 'undefined') {
608
- throw ERROR_FACTORY.create("finalization-registry-not-supported" /* AppError.FINALIZATION_REGISTRY_NOT_SUPPORTED */, {});
609
- }
610
- }
611
- const nameString = '' + hashCode(JSON.stringify(nameObj));
612
- const existingApp = _serverApps.get(nameString);
613
- if (existingApp) {
614
- existingApp.incRefCount(_serverAppConfig.releaseOnDeref);
615
- return existingApp;
616
- }
617
- const container = new component.ComponentContainer(nameString);
618
- for (const component of _components.values()) {
619
- container.addComponent(component);
620
- }
621
- const newApp = new FirebaseServerAppImpl(appOptions, _serverAppConfig, nameString, container);
622
- _serverApps.set(nameString, newApp);
623
- return newApp;
624
- }
625
- /**
626
- * Retrieves a {@link @firebase/app#FirebaseApp} instance.
627
- *
628
- * When called with no arguments, the default app is returned. When an app name
629
- * is provided, the app corresponding to that name is returned.
630
- *
631
- * An exception is thrown if the app being retrieved has not yet been
632
- * initialized.
633
- *
634
- * @example
635
- * ```javascript
636
- * // Return the default app
637
- * const app = getApp();
638
- * ```
639
- *
640
- * @example
641
- * ```javascript
642
- * // Return a named app
643
- * const otherApp = getApp("otherApp");
644
- * ```
645
- *
646
- * @param name - Optional name of the app to return. If no name is
647
- * provided, the default is `"[DEFAULT]"`.
648
- *
649
- * @returns The app corresponding to the provided app name.
650
- * If no app name is provided, the default app is returned.
651
- *
652
- * @public
653
- */
654
- function getApp(name = DEFAULT_ENTRY_NAME) {
655
- const app = _apps.get(name);
656
- if (!app && name === DEFAULT_ENTRY_NAME && util.getDefaultAppConfig()) {
657
- return initializeApp();
658
- }
659
- if (!app) {
660
- throw ERROR_FACTORY.create("no-app" /* AppError.NO_APP */, { appName: name });
661
- }
662
- return app;
663
- }
664
- /**
665
- * A (read-only) array of all initialized apps.
666
- * @public
667
- */
668
- function getApps() {
669
- return Array.from(_apps.values());
670
- }
671
- /**
672
- * Renders this app unusable and frees the resources of all associated
673
- * services.
674
- *
675
- * @example
676
- * ```javascript
677
- * deleteApp(app)
678
- * .then(function() {
679
- * console.log("App deleted successfully");
680
- * })
681
- * .catch(function(error) {
682
- * console.log("Error deleting app:", error);
683
- * });
684
- * ```
685
- *
686
- * @public
687
- */
688
- async function deleteApp(app) {
689
- let cleanupProviders = false;
690
- const name = app.name;
691
- if (_apps.has(name)) {
692
- cleanupProviders = true;
693
- _apps.delete(name);
694
- }
695
- else if (_serverApps.has(name)) {
696
- const firebaseServerApp = app;
697
- if (firebaseServerApp.decRefCount() <= 0) {
698
- _serverApps.delete(name);
699
- cleanupProviders = true;
700
- }
701
- }
702
- if (cleanupProviders) {
703
- await Promise.all(app.container
704
- .getProviders()
705
- .map(provider => provider.delete()));
706
- app.isDeleted = true;
707
- }
708
- }
709
- /**
710
- * Registers a library's name and version for platform logging purposes.
711
- * @param library - Name of 1p or 3p library (e.g. firestore, angularfire)
712
- * @param version - Current version of that library.
713
- * @param variant - Bundle variant, e.g., node, rn, etc.
714
- *
715
- * @public
716
- */
717
- function registerVersion(libraryKeyOrName, version, variant) {
718
- var _a;
719
- // TODO: We can use this check to whitelist strings when/if we set up
720
- // a good whitelist system.
721
- let library = (_a = PLATFORM_LOG_STRING[libraryKeyOrName]) !== null && _a !== void 0 ? _a : libraryKeyOrName;
722
- if (variant) {
723
- library += `-${variant}`;
724
- }
725
- const libraryMismatch = library.match(/\s|\//);
726
- const versionMismatch = version.match(/\s|\//);
727
- if (libraryMismatch || versionMismatch) {
728
- const warning = [
729
- `Unable to register library "${library}" with version "${version}":`
730
- ];
731
- if (libraryMismatch) {
732
- warning.push(`library name "${library}" contains illegal characters (whitespace or "/")`);
733
- }
734
- if (libraryMismatch && versionMismatch) {
735
- warning.push('and');
736
- }
737
- if (versionMismatch) {
738
- warning.push(`version name "${version}" contains illegal characters (whitespace or "/")`);
739
- }
740
- logger.warn(warning.join(' '));
741
- return;
742
- }
743
- _registerComponent(new component.Component(`${library}-version`, () => ({ library, version }), "VERSION" /* ComponentType.VERSION */));
744
- }
745
- /**
746
- * Sets log handler for all Firebase SDKs.
747
- * @param logCallback - An optional custom log handler that executes user code whenever
748
- * the Firebase SDK makes a logging call.
749
- *
750
- * @public
751
- */
752
- function onLog(logCallback, options) {
753
- if (logCallback !== null && typeof logCallback !== 'function') {
754
- throw ERROR_FACTORY.create("invalid-log-argument" /* AppError.INVALID_LOG_ARGUMENT */);
755
- }
756
- logger$1.setUserLogHandler(logCallback, options);
757
- }
758
- /**
759
- * Sets log level for all Firebase SDKs.
760
- *
761
- * All of the log types above the current log level are captured (i.e. if
762
- * you set the log level to `info`, errors are logged, but `debug` and
763
- * `verbose` logs are not).
764
- *
765
- * @public
766
- */
767
- function setLogLevel(logLevel) {
768
- logger$1.setLogLevel(logLevel);
523
+ /**
524
+ * @license
525
+ * Copyright 2019 Google LLC
526
+ *
527
+ * Licensed under the Apache License, Version 2.0 (the "License");
528
+ * you may not use this file except in compliance with the License.
529
+ * You may obtain a copy of the License at
530
+ *
531
+ * http://www.apache.org/licenses/LICENSE-2.0
532
+ *
533
+ * Unless required by applicable law or agreed to in writing, software
534
+ * distributed under the License is distributed on an "AS IS" BASIS,
535
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
536
+ * See the License for the specific language governing permissions and
537
+ * limitations under the License.
538
+ */
539
+ /**
540
+ * The current SDK version.
541
+ *
542
+ * @public
543
+ */
544
+ const SDK_VERSION = version;
545
+ function initializeApp(_options, rawConfig = {}) {
546
+ let options = _options;
547
+ if (typeof rawConfig !== 'object') {
548
+ const name = rawConfig;
549
+ rawConfig = { name };
550
+ }
551
+ const config = Object.assign({ name: DEFAULT_ENTRY_NAME, automaticDataCollectionEnabled: false }, rawConfig);
552
+ const name = config.name;
553
+ if (typeof name !== 'string' || !name) {
554
+ throw ERROR_FACTORY.create("bad-app-name" /* AppError.BAD_APP_NAME */, {
555
+ appName: String(name)
556
+ });
557
+ }
558
+ options || (options = util.getDefaultAppConfig());
559
+ if (!options) {
560
+ throw ERROR_FACTORY.create("no-options" /* AppError.NO_OPTIONS */);
561
+ }
562
+ const existingApp = _apps.get(name);
563
+ if (existingApp) {
564
+ // return the existing app if options and config deep equal the ones in the existing app.
565
+ if (util.deepEqual(options, existingApp.options) &&
566
+ util.deepEqual(config, existingApp.config)) {
567
+ return existingApp;
568
+ }
569
+ else {
570
+ throw ERROR_FACTORY.create("duplicate-app" /* AppError.DUPLICATE_APP */, { appName: name });
571
+ }
572
+ }
573
+ const container = new component.ComponentContainer(name);
574
+ for (const component of _components.values()) {
575
+ container.addComponent(component);
576
+ }
577
+ const newApp = new FirebaseAppImpl(options, config, container);
578
+ _apps.set(name, newApp);
579
+ return newApp;
580
+ }
581
+ function initializeServerApp(_options, _serverAppConfig) {
582
+ if (util.isBrowser() && !util.isWebWorker()) {
583
+ // FirebaseServerApp isn't designed to be run in browsers.
584
+ throw ERROR_FACTORY.create("invalid-server-app-environment" /* AppError.INVALID_SERVER_APP_ENVIRONMENT */);
585
+ }
586
+ if (_serverAppConfig.automaticDataCollectionEnabled === undefined) {
587
+ _serverAppConfig.automaticDataCollectionEnabled = false;
588
+ }
589
+ let appOptions;
590
+ if (_isFirebaseApp(_options)) {
591
+ appOptions = _options.options;
592
+ }
593
+ else {
594
+ appOptions = _options;
595
+ }
596
+ // Build an app name based on a hash of the configuration options.
597
+ const nameObj = Object.assign(Object.assign({}, _serverAppConfig), appOptions);
598
+ // However, Do not mangle the name based on releaseOnDeref, since it will vary between the
599
+ // construction of FirebaseServerApp instances. For example, if the object is the request headers.
600
+ if (nameObj.releaseOnDeref !== undefined) {
601
+ delete nameObj.releaseOnDeref;
602
+ }
603
+ const hashCode = (s) => {
604
+ return [...s].reduce((hash, c) => (Math.imul(31, hash) + c.charCodeAt(0)) | 0, 0);
605
+ };
606
+ if (_serverAppConfig.releaseOnDeref !== undefined) {
607
+ if (typeof FinalizationRegistry === 'undefined') {
608
+ throw ERROR_FACTORY.create("finalization-registry-not-supported" /* AppError.FINALIZATION_REGISTRY_NOT_SUPPORTED */, {});
609
+ }
610
+ }
611
+ const nameString = '' + hashCode(JSON.stringify(nameObj));
612
+ const existingApp = _serverApps.get(nameString);
613
+ if (existingApp) {
614
+ existingApp.incRefCount(_serverAppConfig.releaseOnDeref);
615
+ return existingApp;
616
+ }
617
+ const container = new component.ComponentContainer(nameString);
618
+ for (const component of _components.values()) {
619
+ container.addComponent(component);
620
+ }
621
+ const newApp = new FirebaseServerAppImpl(appOptions, _serverAppConfig, nameString, container);
622
+ _serverApps.set(nameString, newApp);
623
+ return newApp;
624
+ }
625
+ /**
626
+ * Retrieves a {@link @firebase/app#FirebaseApp} instance.
627
+ *
628
+ * When called with no arguments, the default app is returned. When an app name
629
+ * is provided, the app corresponding to that name is returned.
630
+ *
631
+ * An exception is thrown if the app being retrieved has not yet been
632
+ * initialized.
633
+ *
634
+ * @example
635
+ * ```javascript
636
+ * // Return the default app
637
+ * const app = getApp();
638
+ * ```
639
+ *
640
+ * @example
641
+ * ```javascript
642
+ * // Return a named app
643
+ * const otherApp = getApp("otherApp");
644
+ * ```
645
+ *
646
+ * @param name - Optional name of the app to return. If no name is
647
+ * provided, the default is `"[DEFAULT]"`.
648
+ *
649
+ * @returns The app corresponding to the provided app name.
650
+ * If no app name is provided, the default app is returned.
651
+ *
652
+ * @public
653
+ */
654
+ function getApp(name = DEFAULT_ENTRY_NAME) {
655
+ const app = _apps.get(name);
656
+ if (!app && name === DEFAULT_ENTRY_NAME && util.getDefaultAppConfig()) {
657
+ return initializeApp();
658
+ }
659
+ if (!app) {
660
+ throw ERROR_FACTORY.create("no-app" /* AppError.NO_APP */, { appName: name });
661
+ }
662
+ return app;
663
+ }
664
+ /**
665
+ * A (read-only) array of all initialized apps.
666
+ * @public
667
+ */
668
+ function getApps() {
669
+ return Array.from(_apps.values());
670
+ }
671
+ /**
672
+ * Renders this app unusable and frees the resources of all associated
673
+ * services.
674
+ *
675
+ * @example
676
+ * ```javascript
677
+ * deleteApp(app)
678
+ * .then(function() {
679
+ * console.log("App deleted successfully");
680
+ * })
681
+ * .catch(function(error) {
682
+ * console.log("Error deleting app:", error);
683
+ * });
684
+ * ```
685
+ *
686
+ * @public
687
+ */
688
+ async function deleteApp(app) {
689
+ let cleanupProviders = false;
690
+ const name = app.name;
691
+ if (_apps.has(name)) {
692
+ cleanupProviders = true;
693
+ _apps.delete(name);
694
+ }
695
+ else if (_serverApps.has(name)) {
696
+ const firebaseServerApp = app;
697
+ if (firebaseServerApp.decRefCount() <= 0) {
698
+ _serverApps.delete(name);
699
+ cleanupProviders = true;
700
+ }
701
+ }
702
+ if (cleanupProviders) {
703
+ await Promise.all(app.container
704
+ .getProviders()
705
+ .map(provider => provider.delete()));
706
+ app.isDeleted = true;
707
+ }
708
+ }
709
+ /**
710
+ * Registers a library's name and version for platform logging purposes.
711
+ * @param library - Name of 1p or 3p library (e.g. firestore, angularfire)
712
+ * @param version - Current version of that library.
713
+ * @param variant - Bundle variant, e.g., node, rn, etc.
714
+ *
715
+ * @public
716
+ */
717
+ function registerVersion(libraryKeyOrName, version, variant) {
718
+ var _a;
719
+ // TODO: We can use this check to whitelist strings when/if we set up
720
+ // a good whitelist system.
721
+ let library = (_a = PLATFORM_LOG_STRING[libraryKeyOrName]) !== null && _a !== void 0 ? _a : libraryKeyOrName;
722
+ if (variant) {
723
+ library += `-${variant}`;
724
+ }
725
+ const libraryMismatch = library.match(/\s|\//);
726
+ const versionMismatch = version.match(/\s|\//);
727
+ if (libraryMismatch || versionMismatch) {
728
+ const warning = [
729
+ `Unable to register library "${library}" with version "${version}":`
730
+ ];
731
+ if (libraryMismatch) {
732
+ warning.push(`library name "${library}" contains illegal characters (whitespace or "/")`);
733
+ }
734
+ if (libraryMismatch && versionMismatch) {
735
+ warning.push('and');
736
+ }
737
+ if (versionMismatch) {
738
+ warning.push(`version name "${version}" contains illegal characters (whitespace or "/")`);
739
+ }
740
+ logger.warn(warning.join(' '));
741
+ return;
742
+ }
743
+ _registerComponent(new component.Component(`${library}-version`, () => ({ library, version }), "VERSION" /* ComponentType.VERSION */));
744
+ }
745
+ /**
746
+ * Sets log handler for all Firebase SDKs.
747
+ * @param logCallback - An optional custom log handler that executes user code whenever
748
+ * the Firebase SDK makes a logging call.
749
+ *
750
+ * @public
751
+ */
752
+ function onLog(logCallback, options) {
753
+ if (logCallback !== null && typeof logCallback !== 'function') {
754
+ throw ERROR_FACTORY.create("invalid-log-argument" /* AppError.INVALID_LOG_ARGUMENT */);
755
+ }
756
+ logger$1.setUserLogHandler(logCallback, options);
757
+ }
758
+ /**
759
+ * Sets log level for all Firebase SDKs.
760
+ *
761
+ * All of the log types above the current log level are captured (i.e. if
762
+ * you set the log level to `info`, errors are logged, but `debug` and
763
+ * `verbose` logs are not).
764
+ *
765
+ * @public
766
+ */
767
+ function setLogLevel(logLevel) {
768
+ logger$1.setLogLevel(logLevel);
769
769
  }
770
770
 
771
- /**
772
- * @license
773
- * Copyright 2021 Google LLC
774
- *
775
- * Licensed under the Apache License, Version 2.0 (the "License");
776
- * you may not use this file except in compliance with the License.
777
- * You may obtain a copy of the License at
778
- *
779
- * http://www.apache.org/licenses/LICENSE-2.0
780
- *
781
- * Unless required by applicable law or agreed to in writing, software
782
- * distributed under the License is distributed on an "AS IS" BASIS,
783
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
784
- * See the License for the specific language governing permissions and
785
- * limitations under the License.
786
- */
787
- const DB_NAME = 'firebase-heartbeat-database';
788
- const DB_VERSION = 1;
789
- const STORE_NAME = 'firebase-heartbeat-store';
790
- let dbPromise = null;
791
- function getDbPromise() {
792
- if (!dbPromise) {
793
- dbPromise = idb.openDB(DB_NAME, DB_VERSION, {
794
- upgrade: (db, oldVersion) => {
795
- // We don't use 'break' in this switch statement, the fall-through
796
- // behavior is what we want, because if there are multiple versions between
797
- // the old version and the current version, we want ALL the migrations
798
- // that correspond to those versions to run, not only the last one.
799
- // eslint-disable-next-line default-case
800
- switch (oldVersion) {
801
- case 0:
802
- try {
803
- db.createObjectStore(STORE_NAME);
804
- }
805
- catch (e) {
806
- // Safari/iOS browsers throw occasional exceptions on
807
- // db.createObjectStore() that may be a bug. Avoid blocking
808
- // the rest of the app functionality.
809
- console.warn(e);
810
- }
811
- }
812
- }
813
- }).catch(e => {
814
- throw ERROR_FACTORY.create("idb-open" /* AppError.IDB_OPEN */, {
815
- originalErrorMessage: e.message
816
- });
817
- });
818
- }
819
- return dbPromise;
820
- }
821
- async function readHeartbeatsFromIndexedDB(app) {
822
- try {
823
- const db = await getDbPromise();
824
- const tx = db.transaction(STORE_NAME);
825
- const result = await tx.objectStore(STORE_NAME).get(computeKey(app));
826
- // We already have the value but tx.done can throw,
827
- // so we need to await it here to catch errors
828
- await tx.done;
829
- return result;
830
- }
831
- catch (e) {
832
- if (e instanceof util.FirebaseError) {
833
- logger.warn(e.message);
834
- }
835
- else {
836
- const idbGetError = ERROR_FACTORY.create("idb-get" /* AppError.IDB_GET */, {
837
- originalErrorMessage: e === null || e === void 0 ? void 0 : e.message
838
- });
839
- logger.warn(idbGetError.message);
840
- }
841
- }
842
- }
843
- async function writeHeartbeatsToIndexedDB(app, heartbeatObject) {
844
- try {
845
- const db = await getDbPromise();
846
- const tx = db.transaction(STORE_NAME, 'readwrite');
847
- const objectStore = tx.objectStore(STORE_NAME);
848
- await objectStore.put(heartbeatObject, computeKey(app));
849
- await tx.done;
850
- }
851
- catch (e) {
852
- if (e instanceof util.FirebaseError) {
853
- logger.warn(e.message);
854
- }
855
- else {
856
- const idbGetError = ERROR_FACTORY.create("idb-set" /* AppError.IDB_WRITE */, {
857
- originalErrorMessage: e === null || e === void 0 ? void 0 : e.message
858
- });
859
- logger.warn(idbGetError.message);
860
- }
861
- }
862
- }
863
- function computeKey(app) {
864
- return `${app.name}!${app.options.appId}`;
771
+ /**
772
+ * @license
773
+ * Copyright 2021 Google LLC
774
+ *
775
+ * Licensed under the Apache License, Version 2.0 (the "License");
776
+ * you may not use this file except in compliance with the License.
777
+ * You may obtain a copy of the License at
778
+ *
779
+ * http://www.apache.org/licenses/LICENSE-2.0
780
+ *
781
+ * Unless required by applicable law or agreed to in writing, software
782
+ * distributed under the License is distributed on an "AS IS" BASIS,
783
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
784
+ * See the License for the specific language governing permissions and
785
+ * limitations under the License.
786
+ */
787
+ const DB_NAME = 'firebase-heartbeat-database';
788
+ const DB_VERSION = 1;
789
+ const STORE_NAME = 'firebase-heartbeat-store';
790
+ let dbPromise = null;
791
+ function getDbPromise() {
792
+ if (!dbPromise) {
793
+ dbPromise = idb.openDB(DB_NAME, DB_VERSION, {
794
+ upgrade: (db, oldVersion) => {
795
+ // We don't use 'break' in this switch statement, the fall-through
796
+ // behavior is what we want, because if there are multiple versions between
797
+ // the old version and the current version, we want ALL the migrations
798
+ // that correspond to those versions to run, not only the last one.
799
+ // eslint-disable-next-line default-case
800
+ switch (oldVersion) {
801
+ case 0:
802
+ try {
803
+ db.createObjectStore(STORE_NAME);
804
+ }
805
+ catch (e) {
806
+ // Safari/iOS browsers throw occasional exceptions on
807
+ // db.createObjectStore() that may be a bug. Avoid blocking
808
+ // the rest of the app functionality.
809
+ console.warn(e);
810
+ }
811
+ }
812
+ }
813
+ }).catch(e => {
814
+ throw ERROR_FACTORY.create("idb-open" /* AppError.IDB_OPEN */, {
815
+ originalErrorMessage: e.message
816
+ });
817
+ });
818
+ }
819
+ return dbPromise;
820
+ }
821
+ async function readHeartbeatsFromIndexedDB(app) {
822
+ try {
823
+ const db = await getDbPromise();
824
+ const tx = db.transaction(STORE_NAME);
825
+ const result = await tx.objectStore(STORE_NAME).get(computeKey(app));
826
+ // We already have the value but tx.done can throw,
827
+ // so we need to await it here to catch errors
828
+ await tx.done;
829
+ return result;
830
+ }
831
+ catch (e) {
832
+ if (e instanceof util.FirebaseError) {
833
+ logger.warn(e.message);
834
+ }
835
+ else {
836
+ const idbGetError = ERROR_FACTORY.create("idb-get" /* AppError.IDB_GET */, {
837
+ originalErrorMessage: e === null || e === void 0 ? void 0 : e.message
838
+ });
839
+ logger.warn(idbGetError.message);
840
+ }
841
+ }
842
+ }
843
+ async function writeHeartbeatsToIndexedDB(app, heartbeatObject) {
844
+ try {
845
+ const db = await getDbPromise();
846
+ const tx = db.transaction(STORE_NAME, 'readwrite');
847
+ const objectStore = tx.objectStore(STORE_NAME);
848
+ await objectStore.put(heartbeatObject, computeKey(app));
849
+ await tx.done;
850
+ }
851
+ catch (e) {
852
+ if (e instanceof util.FirebaseError) {
853
+ logger.warn(e.message);
854
+ }
855
+ else {
856
+ const idbGetError = ERROR_FACTORY.create("idb-set" /* AppError.IDB_WRITE */, {
857
+ originalErrorMessage: e === null || e === void 0 ? void 0 : e.message
858
+ });
859
+ logger.warn(idbGetError.message);
860
+ }
861
+ }
862
+ }
863
+ function computeKey(app) {
864
+ return `${app.name}!${app.options.appId}`;
865
865
  }
866
866
 
867
- /**
868
- * @license
869
- * Copyright 2021 Google LLC
870
- *
871
- * Licensed under the Apache License, Version 2.0 (the "License");
872
- * you may not use this file except in compliance with the License.
873
- * You may obtain a copy of the License at
874
- *
875
- * http://www.apache.org/licenses/LICENSE-2.0
876
- *
877
- * Unless required by applicable law or agreed to in writing, software
878
- * distributed under the License is distributed on an "AS IS" BASIS,
879
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
880
- * See the License for the specific language governing permissions and
881
- * limitations under the License.
882
- */
883
- const MAX_HEADER_BYTES = 1024;
884
- // 30 days
885
- const STORED_HEARTBEAT_RETENTION_MAX_MILLIS = 30 * 24 * 60 * 60 * 1000;
886
- class HeartbeatServiceImpl {
887
- constructor(container) {
888
- this.container = container;
889
- /**
890
- * In-memory cache for heartbeats, used by getHeartbeatsHeader() to generate
891
- * the header string.
892
- * Stores one record per date. This will be consolidated into the standard
893
- * format of one record per user agent string before being sent as a header.
894
- * Populated from indexedDB when the controller is instantiated and should
895
- * be kept in sync with indexedDB.
896
- * Leave public for easier testing.
897
- */
898
- this._heartbeatsCache = null;
899
- const app = this.container.getProvider('app').getImmediate();
900
- this._storage = new HeartbeatStorageImpl(app);
901
- this._heartbeatsCachePromise = this._storage.read().then(result => {
902
- this._heartbeatsCache = result;
903
- return result;
904
- });
905
- }
906
- /**
907
- * Called to report a heartbeat. The function will generate
908
- * a HeartbeatsByUserAgent object, update heartbeatsCache, and persist it
909
- * to IndexedDB.
910
- * Note that we only store one heartbeat per day. So if a heartbeat for today is
911
- * already logged, subsequent calls to this function in the same day will be ignored.
912
- */
913
- async triggerHeartbeat() {
914
- var _a, _b;
915
- try {
916
- const platformLogger = this.container
917
- .getProvider('platform-logger')
918
- .getImmediate();
919
- // This is the "Firebase user agent" string from the platform logger
920
- // service, not the browser user agent.
921
- const agent = platformLogger.getPlatformInfoString();
922
- const date = getUTCDateString();
923
- if (((_a = this._heartbeatsCache) === null || _a === void 0 ? void 0 : _a.heartbeats) == null) {
924
- this._heartbeatsCache = await this._heartbeatsCachePromise;
925
- // If we failed to construct a heartbeats cache, then return immediately.
926
- if (((_b = this._heartbeatsCache) === null || _b === void 0 ? void 0 : _b.heartbeats) == null) {
927
- return;
928
- }
929
- }
930
- // Do not store a heartbeat if one is already stored for this day
931
- // or if a header has already been sent today.
932
- if (this._heartbeatsCache.lastSentHeartbeatDate === date ||
933
- this._heartbeatsCache.heartbeats.some(singleDateHeartbeat => singleDateHeartbeat.date === date)) {
934
- return;
935
- }
936
- else {
937
- // There is no entry for this date. Create one.
938
- this._heartbeatsCache.heartbeats.push({ date, agent });
939
- }
940
- // Remove entries older than 30 days.
941
- this._heartbeatsCache.heartbeats =
942
- this._heartbeatsCache.heartbeats.filter(singleDateHeartbeat => {
943
- const hbTimestamp = new Date(singleDateHeartbeat.date).valueOf();
944
- const now = Date.now();
945
- return now - hbTimestamp <= STORED_HEARTBEAT_RETENTION_MAX_MILLIS;
946
- });
947
- return this._storage.overwrite(this._heartbeatsCache);
948
- }
949
- catch (e) {
950
- logger.warn(e);
951
- }
952
- }
953
- /**
954
- * Returns a base64 encoded string which can be attached to the heartbeat-specific header directly.
955
- * It also clears all heartbeats from memory as well as in IndexedDB.
956
- *
957
- * NOTE: Consuming product SDKs should not send the header if this method
958
- * returns an empty string.
959
- */
960
- async getHeartbeatsHeader() {
961
- var _a;
962
- try {
963
- if (this._heartbeatsCache === null) {
964
- await this._heartbeatsCachePromise;
965
- }
966
- // If it's still null or the array is empty, there is no data to send.
967
- if (((_a = this._heartbeatsCache) === null || _a === void 0 ? void 0 : _a.heartbeats) == null ||
968
- this._heartbeatsCache.heartbeats.length === 0) {
969
- return '';
970
- }
971
- const date = getUTCDateString();
972
- // Extract as many heartbeats from the cache as will fit under the size limit.
973
- const { heartbeatsToSend, unsentEntries } = extractHeartbeatsForHeader(this._heartbeatsCache.heartbeats);
974
- const headerString = util.base64urlEncodeWithoutPadding(JSON.stringify({ version: 2, heartbeats: heartbeatsToSend }));
975
- // Store last sent date to prevent another being logged/sent for the same day.
976
- this._heartbeatsCache.lastSentHeartbeatDate = date;
977
- if (unsentEntries.length > 0) {
978
- // Store any unsent entries if they exist.
979
- this._heartbeatsCache.heartbeats = unsentEntries;
980
- // This seems more likely than emptying the array (below) to lead to some odd state
981
- // since the cache isn't empty and this will be called again on the next request,
982
- // and is probably safest if we await it.
983
- await this._storage.overwrite(this._heartbeatsCache);
984
- }
985
- else {
986
- this._heartbeatsCache.heartbeats = [];
987
- // Do not wait for this, to reduce latency.
988
- void this._storage.overwrite(this._heartbeatsCache);
989
- }
990
- return headerString;
991
- }
992
- catch (e) {
993
- logger.warn(e);
994
- return '';
995
- }
996
- }
997
- }
998
- function getUTCDateString() {
999
- const today = new Date();
1000
- // Returns date format 'YYYY-MM-DD'
1001
- return today.toISOString().substring(0, 10);
1002
- }
1003
- function extractHeartbeatsForHeader(heartbeatsCache, maxSize = MAX_HEADER_BYTES) {
1004
- // Heartbeats grouped by user agent in the standard format to be sent in
1005
- // the header.
1006
- const heartbeatsToSend = [];
1007
- // Single date format heartbeats that are not sent.
1008
- let unsentEntries = heartbeatsCache.slice();
1009
- for (const singleDateHeartbeat of heartbeatsCache) {
1010
- // Look for an existing entry with the same user agent.
1011
- const heartbeatEntry = heartbeatsToSend.find(hb => hb.agent === singleDateHeartbeat.agent);
1012
- if (!heartbeatEntry) {
1013
- // If no entry for this user agent exists, create one.
1014
- heartbeatsToSend.push({
1015
- agent: singleDateHeartbeat.agent,
1016
- dates: [singleDateHeartbeat.date]
1017
- });
1018
- if (countBytes(heartbeatsToSend) > maxSize) {
1019
- // If the header would exceed max size, remove the added heartbeat
1020
- // entry and stop adding to the header.
1021
- heartbeatsToSend.pop();
1022
- break;
1023
- }
1024
- }
1025
- else {
1026
- heartbeatEntry.dates.push(singleDateHeartbeat.date);
1027
- // If the header would exceed max size, remove the added date
1028
- // and stop adding to the header.
1029
- if (countBytes(heartbeatsToSend) > maxSize) {
1030
- heartbeatEntry.dates.pop();
1031
- break;
1032
- }
1033
- }
1034
- // Pop unsent entry from queue. (Skipped if adding the entry exceeded
1035
- // quota and the loop breaks early.)
1036
- unsentEntries = unsentEntries.slice(1);
1037
- }
1038
- return {
1039
- heartbeatsToSend,
1040
- unsentEntries
1041
- };
1042
- }
1043
- class HeartbeatStorageImpl {
1044
- constructor(app) {
1045
- this.app = app;
1046
- this._canUseIndexedDBPromise = this.runIndexedDBEnvironmentCheck();
1047
- }
1048
- async runIndexedDBEnvironmentCheck() {
1049
- if (!util.isIndexedDBAvailable()) {
1050
- return false;
1051
- }
1052
- else {
1053
- return util.validateIndexedDBOpenable()
1054
- .then(() => true)
1055
- .catch(() => false);
1056
- }
1057
- }
1058
- /**
1059
- * Read all heartbeats.
1060
- */
1061
- async read() {
1062
- const canUseIndexedDB = await this._canUseIndexedDBPromise;
1063
- if (!canUseIndexedDB) {
1064
- return { heartbeats: [] };
1065
- }
1066
- else {
1067
- const idbHeartbeatObject = await readHeartbeatsFromIndexedDB(this.app);
1068
- if (idbHeartbeatObject === null || idbHeartbeatObject === void 0 ? void 0 : idbHeartbeatObject.heartbeats) {
1069
- return idbHeartbeatObject;
1070
- }
1071
- else {
1072
- return { heartbeats: [] };
1073
- }
1074
- }
1075
- }
1076
- // overwrite the storage with the provided heartbeats
1077
- async overwrite(heartbeatsObject) {
1078
- var _a;
1079
- const canUseIndexedDB = await this._canUseIndexedDBPromise;
1080
- if (!canUseIndexedDB) {
1081
- return;
1082
- }
1083
- else {
1084
- const existingHeartbeatsObject = await this.read();
1085
- return writeHeartbeatsToIndexedDB(this.app, {
1086
- lastSentHeartbeatDate: (_a = heartbeatsObject.lastSentHeartbeatDate) !== null && _a !== void 0 ? _a : existingHeartbeatsObject.lastSentHeartbeatDate,
1087
- heartbeats: heartbeatsObject.heartbeats
1088
- });
1089
- }
1090
- }
1091
- // add heartbeats
1092
- async add(heartbeatsObject) {
1093
- var _a;
1094
- const canUseIndexedDB = await this._canUseIndexedDBPromise;
1095
- if (!canUseIndexedDB) {
1096
- return;
1097
- }
1098
- else {
1099
- const existingHeartbeatsObject = await this.read();
1100
- return writeHeartbeatsToIndexedDB(this.app, {
1101
- lastSentHeartbeatDate: (_a = heartbeatsObject.lastSentHeartbeatDate) !== null && _a !== void 0 ? _a : existingHeartbeatsObject.lastSentHeartbeatDate,
1102
- heartbeats: [
1103
- ...existingHeartbeatsObject.heartbeats,
1104
- ...heartbeatsObject.heartbeats
1105
- ]
1106
- });
1107
- }
1108
- }
1109
- }
1110
- /**
1111
- * Calculate bytes of a HeartbeatsByUserAgent array after being wrapped
1112
- * in a platform logging header JSON object, stringified, and converted
1113
- * to base 64.
1114
- */
1115
- function countBytes(heartbeatsCache) {
1116
- // base64 has a restricted set of characters, all of which should be 1 byte.
1117
- return util.base64urlEncodeWithoutPadding(
1118
- // heartbeatsCache wrapper properties
1119
- JSON.stringify({ version: 2, heartbeats: heartbeatsCache })).length;
867
+ /**
868
+ * @license
869
+ * Copyright 2021 Google LLC
870
+ *
871
+ * Licensed under the Apache License, Version 2.0 (the "License");
872
+ * you may not use this file except in compliance with the License.
873
+ * You may obtain a copy of the License at
874
+ *
875
+ * http://www.apache.org/licenses/LICENSE-2.0
876
+ *
877
+ * Unless required by applicable law or agreed to in writing, software
878
+ * distributed under the License is distributed on an "AS IS" BASIS,
879
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
880
+ * See the License for the specific language governing permissions and
881
+ * limitations under the License.
882
+ */
883
+ const MAX_HEADER_BYTES = 1024;
884
+ // 30 days
885
+ const STORED_HEARTBEAT_RETENTION_MAX_MILLIS = 30 * 24 * 60 * 60 * 1000;
886
+ class HeartbeatServiceImpl {
887
+ constructor(container) {
888
+ this.container = container;
889
+ /**
890
+ * In-memory cache for heartbeats, used by getHeartbeatsHeader() to generate
891
+ * the header string.
892
+ * Stores one record per date. This will be consolidated into the standard
893
+ * format of one record per user agent string before being sent as a header.
894
+ * Populated from indexedDB when the controller is instantiated and should
895
+ * be kept in sync with indexedDB.
896
+ * Leave public for easier testing.
897
+ */
898
+ this._heartbeatsCache = null;
899
+ const app = this.container.getProvider('app').getImmediate();
900
+ this._storage = new HeartbeatStorageImpl(app);
901
+ this._heartbeatsCachePromise = this._storage.read().then(result => {
902
+ this._heartbeatsCache = result;
903
+ return result;
904
+ });
905
+ }
906
+ /**
907
+ * Called to report a heartbeat. The function will generate
908
+ * a HeartbeatsByUserAgent object, update heartbeatsCache, and persist it
909
+ * to IndexedDB.
910
+ * Note that we only store one heartbeat per day. So if a heartbeat for today is
911
+ * already logged, subsequent calls to this function in the same day will be ignored.
912
+ */
913
+ async triggerHeartbeat() {
914
+ var _a, _b;
915
+ try {
916
+ const platformLogger = this.container
917
+ .getProvider('platform-logger')
918
+ .getImmediate();
919
+ // This is the "Firebase user agent" string from the platform logger
920
+ // service, not the browser user agent.
921
+ const agent = platformLogger.getPlatformInfoString();
922
+ const date = getUTCDateString();
923
+ if (((_a = this._heartbeatsCache) === null || _a === void 0 ? void 0 : _a.heartbeats) == null) {
924
+ this._heartbeatsCache = await this._heartbeatsCachePromise;
925
+ // If we failed to construct a heartbeats cache, then return immediately.
926
+ if (((_b = this._heartbeatsCache) === null || _b === void 0 ? void 0 : _b.heartbeats) == null) {
927
+ return;
928
+ }
929
+ }
930
+ // Do not store a heartbeat if one is already stored for this day
931
+ // or if a header has already been sent today.
932
+ if (this._heartbeatsCache.lastSentHeartbeatDate === date ||
933
+ this._heartbeatsCache.heartbeats.some(singleDateHeartbeat => singleDateHeartbeat.date === date)) {
934
+ return;
935
+ }
936
+ else {
937
+ // There is no entry for this date. Create one.
938
+ this._heartbeatsCache.heartbeats.push({ date, agent });
939
+ }
940
+ // Remove entries older than 30 days.
941
+ this._heartbeatsCache.heartbeats =
942
+ this._heartbeatsCache.heartbeats.filter(singleDateHeartbeat => {
943
+ const hbTimestamp = new Date(singleDateHeartbeat.date).valueOf();
944
+ const now = Date.now();
945
+ return now - hbTimestamp <= STORED_HEARTBEAT_RETENTION_MAX_MILLIS;
946
+ });
947
+ return this._storage.overwrite(this._heartbeatsCache);
948
+ }
949
+ catch (e) {
950
+ logger.warn(e);
951
+ }
952
+ }
953
+ /**
954
+ * Returns a base64 encoded string which can be attached to the heartbeat-specific header directly.
955
+ * It also clears all heartbeats from memory as well as in IndexedDB.
956
+ *
957
+ * NOTE: Consuming product SDKs should not send the header if this method
958
+ * returns an empty string.
959
+ */
960
+ async getHeartbeatsHeader() {
961
+ var _a;
962
+ try {
963
+ if (this._heartbeatsCache === null) {
964
+ await this._heartbeatsCachePromise;
965
+ }
966
+ // If it's still null or the array is empty, there is no data to send.
967
+ if (((_a = this._heartbeatsCache) === null || _a === void 0 ? void 0 : _a.heartbeats) == null ||
968
+ this._heartbeatsCache.heartbeats.length === 0) {
969
+ return '';
970
+ }
971
+ const date = getUTCDateString();
972
+ // Extract as many heartbeats from the cache as will fit under the size limit.
973
+ const { heartbeatsToSend, unsentEntries } = extractHeartbeatsForHeader(this._heartbeatsCache.heartbeats);
974
+ const headerString = util.base64urlEncodeWithoutPadding(JSON.stringify({ version: 2, heartbeats: heartbeatsToSend }));
975
+ // Store last sent date to prevent another being logged/sent for the same day.
976
+ this._heartbeatsCache.lastSentHeartbeatDate = date;
977
+ if (unsentEntries.length > 0) {
978
+ // Store any unsent entries if they exist.
979
+ this._heartbeatsCache.heartbeats = unsentEntries;
980
+ // This seems more likely than emptying the array (below) to lead to some odd state
981
+ // since the cache isn't empty and this will be called again on the next request,
982
+ // and is probably safest if we await it.
983
+ await this._storage.overwrite(this._heartbeatsCache);
984
+ }
985
+ else {
986
+ this._heartbeatsCache.heartbeats = [];
987
+ // Do not wait for this, to reduce latency.
988
+ void this._storage.overwrite(this._heartbeatsCache);
989
+ }
990
+ return headerString;
991
+ }
992
+ catch (e) {
993
+ logger.warn(e);
994
+ return '';
995
+ }
996
+ }
997
+ }
998
+ function getUTCDateString() {
999
+ const today = new Date();
1000
+ // Returns date format 'YYYY-MM-DD'
1001
+ return today.toISOString().substring(0, 10);
1002
+ }
1003
+ function extractHeartbeatsForHeader(heartbeatsCache, maxSize = MAX_HEADER_BYTES) {
1004
+ // Heartbeats grouped by user agent in the standard format to be sent in
1005
+ // the header.
1006
+ const heartbeatsToSend = [];
1007
+ // Single date format heartbeats that are not sent.
1008
+ let unsentEntries = heartbeatsCache.slice();
1009
+ for (const singleDateHeartbeat of heartbeatsCache) {
1010
+ // Look for an existing entry with the same user agent.
1011
+ const heartbeatEntry = heartbeatsToSend.find(hb => hb.agent === singleDateHeartbeat.agent);
1012
+ if (!heartbeatEntry) {
1013
+ // If no entry for this user agent exists, create one.
1014
+ heartbeatsToSend.push({
1015
+ agent: singleDateHeartbeat.agent,
1016
+ dates: [singleDateHeartbeat.date]
1017
+ });
1018
+ if (countBytes(heartbeatsToSend) > maxSize) {
1019
+ // If the header would exceed max size, remove the added heartbeat
1020
+ // entry and stop adding to the header.
1021
+ heartbeatsToSend.pop();
1022
+ break;
1023
+ }
1024
+ }
1025
+ else {
1026
+ heartbeatEntry.dates.push(singleDateHeartbeat.date);
1027
+ // If the header would exceed max size, remove the added date
1028
+ // and stop adding to the header.
1029
+ if (countBytes(heartbeatsToSend) > maxSize) {
1030
+ heartbeatEntry.dates.pop();
1031
+ break;
1032
+ }
1033
+ }
1034
+ // Pop unsent entry from queue. (Skipped if adding the entry exceeded
1035
+ // quota and the loop breaks early.)
1036
+ unsentEntries = unsentEntries.slice(1);
1037
+ }
1038
+ return {
1039
+ heartbeatsToSend,
1040
+ unsentEntries
1041
+ };
1042
+ }
1043
+ class HeartbeatStorageImpl {
1044
+ constructor(app) {
1045
+ this.app = app;
1046
+ this._canUseIndexedDBPromise = this.runIndexedDBEnvironmentCheck();
1047
+ }
1048
+ async runIndexedDBEnvironmentCheck() {
1049
+ if (!util.isIndexedDBAvailable()) {
1050
+ return false;
1051
+ }
1052
+ else {
1053
+ return util.validateIndexedDBOpenable()
1054
+ .then(() => true)
1055
+ .catch(() => false);
1056
+ }
1057
+ }
1058
+ /**
1059
+ * Read all heartbeats.
1060
+ */
1061
+ async read() {
1062
+ const canUseIndexedDB = await this._canUseIndexedDBPromise;
1063
+ if (!canUseIndexedDB) {
1064
+ return { heartbeats: [] };
1065
+ }
1066
+ else {
1067
+ const idbHeartbeatObject = await readHeartbeatsFromIndexedDB(this.app);
1068
+ if (idbHeartbeatObject === null || idbHeartbeatObject === void 0 ? void 0 : idbHeartbeatObject.heartbeats) {
1069
+ return idbHeartbeatObject;
1070
+ }
1071
+ else {
1072
+ return { heartbeats: [] };
1073
+ }
1074
+ }
1075
+ }
1076
+ // overwrite the storage with the provided heartbeats
1077
+ async overwrite(heartbeatsObject) {
1078
+ var _a;
1079
+ const canUseIndexedDB = await this._canUseIndexedDBPromise;
1080
+ if (!canUseIndexedDB) {
1081
+ return;
1082
+ }
1083
+ else {
1084
+ const existingHeartbeatsObject = await this.read();
1085
+ return writeHeartbeatsToIndexedDB(this.app, {
1086
+ lastSentHeartbeatDate: (_a = heartbeatsObject.lastSentHeartbeatDate) !== null && _a !== void 0 ? _a : existingHeartbeatsObject.lastSentHeartbeatDate,
1087
+ heartbeats: heartbeatsObject.heartbeats
1088
+ });
1089
+ }
1090
+ }
1091
+ // add heartbeats
1092
+ async add(heartbeatsObject) {
1093
+ var _a;
1094
+ const canUseIndexedDB = await this._canUseIndexedDBPromise;
1095
+ if (!canUseIndexedDB) {
1096
+ return;
1097
+ }
1098
+ else {
1099
+ const existingHeartbeatsObject = await this.read();
1100
+ return writeHeartbeatsToIndexedDB(this.app, {
1101
+ lastSentHeartbeatDate: (_a = heartbeatsObject.lastSentHeartbeatDate) !== null && _a !== void 0 ? _a : existingHeartbeatsObject.lastSentHeartbeatDate,
1102
+ heartbeats: [
1103
+ ...existingHeartbeatsObject.heartbeats,
1104
+ ...heartbeatsObject.heartbeats
1105
+ ]
1106
+ });
1107
+ }
1108
+ }
1109
+ }
1110
+ /**
1111
+ * Calculate bytes of a HeartbeatsByUserAgent array after being wrapped
1112
+ * in a platform logging header JSON object, stringified, and converted
1113
+ * to base 64.
1114
+ */
1115
+ function countBytes(heartbeatsCache) {
1116
+ // base64 has a restricted set of characters, all of which should be 1 byte.
1117
+ return util.base64urlEncodeWithoutPadding(
1118
+ // heartbeatsCache wrapper properties
1119
+ JSON.stringify({ version: 2, heartbeats: heartbeatsCache })).length;
1120
1120
  }
1121
1121
 
1122
- /**
1123
- * @license
1124
- * Copyright 2019 Google LLC
1125
- *
1126
- * Licensed under the Apache License, Version 2.0 (the "License");
1127
- * you may not use this file except in compliance with the License.
1128
- * You may obtain a copy of the License at
1129
- *
1130
- * http://www.apache.org/licenses/LICENSE-2.0
1131
- *
1132
- * Unless required by applicable law or agreed to in writing, software
1133
- * distributed under the License is distributed on an "AS IS" BASIS,
1134
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1135
- * See the License for the specific language governing permissions and
1136
- * limitations under the License.
1137
- */
1138
- function registerCoreComponents(variant) {
1139
- _registerComponent(new component.Component('platform-logger', container => new PlatformLoggerServiceImpl(container), "PRIVATE" /* ComponentType.PRIVATE */));
1140
- _registerComponent(new component.Component('heartbeat', container => new HeartbeatServiceImpl(container), "PRIVATE" /* ComponentType.PRIVATE */));
1141
- // Register `app` package.
1142
- registerVersion(name$q, version$1, variant);
1143
- // BUILD_TARGET will be replaced by values like esm2017, cjs2017, etc during the compilation
1144
- registerVersion(name$q, version$1, 'cjs2017');
1145
- // Register platform SDK identifier (no version).
1146
- registerVersion('fire-js', '');
1122
+ /**
1123
+ * @license
1124
+ * Copyright 2019 Google LLC
1125
+ *
1126
+ * Licensed under the Apache License, Version 2.0 (the "License");
1127
+ * you may not use this file except in compliance with the License.
1128
+ * You may obtain a copy of the License at
1129
+ *
1130
+ * http://www.apache.org/licenses/LICENSE-2.0
1131
+ *
1132
+ * Unless required by applicable law or agreed to in writing, software
1133
+ * distributed under the License is distributed on an "AS IS" BASIS,
1134
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1135
+ * See the License for the specific language governing permissions and
1136
+ * limitations under the License.
1137
+ */
1138
+ function registerCoreComponents(variant) {
1139
+ _registerComponent(new component.Component('platform-logger', container => new PlatformLoggerServiceImpl(container), "PRIVATE" /* ComponentType.PRIVATE */));
1140
+ _registerComponent(new component.Component('heartbeat', container => new HeartbeatServiceImpl(container), "PRIVATE" /* ComponentType.PRIVATE */));
1141
+ // Register `app` package.
1142
+ registerVersion(name$q, version$1, variant);
1143
+ // BUILD_TARGET will be replaced by values like esm2017, cjs2017, etc during the compilation
1144
+ registerVersion(name$q, version$1, 'cjs2017');
1145
+ // Register platform SDK identifier (no version).
1146
+ registerVersion('fire-js', '');
1147
1147
  }
1148
1148
 
1149
- /**
1150
- * Firebase App
1151
- *
1152
- * @remarks This package coordinates the communication between the different Firebase components
1153
- * @packageDocumentation
1154
- */
1149
+ /**
1150
+ * Firebase App
1151
+ *
1152
+ * @remarks This package coordinates the communication between the different Firebase components
1153
+ * @packageDocumentation
1154
+ */
1155
1155
  registerCoreComponents('node');
1156
1156
 
1157
1157
  Object.defineProperty(exports, 'FirebaseError', {