@firebase/remote-config 0.4.9 → 0.4.10

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.
@@ -1,1398 +0,0 @@
1
- import { getApp, _getProvider, _registerComponent, registerVersion, SDK_VERSION } from '@firebase/app';
2
- import { ErrorFactory, FirebaseError, getModularInstance, calculateBackoffMillis, isIndexedDBAvailable, validateIndexedDBOpenable } from '@firebase/util';
3
- import { Component } from '@firebase/component';
4
- import { LogLevel, Logger } from '@firebase/logger';
5
- import { __awaiter, __generator, __assign } from 'tslib';
6
- import '@firebase/installations';
7
-
8
- var name = "@firebase/remote-config";
9
- var version = "0.4.9";
10
-
11
- /**
12
- * @license
13
- * Copyright 2019 Google LLC
14
- *
15
- * Licensed under the Apache License, Version 2.0 (the "License");
16
- * you may not use this file except in compliance with the License.
17
- * You may obtain a copy of the License at
18
- *
19
- * http://www.apache.org/licenses/LICENSE-2.0
20
- *
21
- * Unless required by applicable law or agreed to in writing, software
22
- * distributed under the License is distributed on an "AS IS" BASIS,
23
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24
- * See the License for the specific language governing permissions and
25
- * limitations under the License.
26
- */
27
- /**
28
- * Shims a minimal AbortSignal.
29
- *
30
- * <p>AbortController's AbortSignal conveniently decouples fetch timeout logic from other aspects
31
- * of networking, such as retries. Firebase doesn't use AbortController enough to justify a
32
- * polyfill recommendation, like we do with the Fetch API, but this minimal shim can easily be
33
- * swapped out if/when we do.
34
- */
35
- var RemoteConfigAbortSignal = /** @class */ (function () {
36
- function RemoteConfigAbortSignal() {
37
- this.listeners = [];
38
- }
39
- RemoteConfigAbortSignal.prototype.addEventListener = function (listener) {
40
- this.listeners.push(listener);
41
- };
42
- RemoteConfigAbortSignal.prototype.abort = function () {
43
- this.listeners.forEach(function (listener) { return listener(); });
44
- };
45
- return RemoteConfigAbortSignal;
46
- }());
47
-
48
- /**
49
- * @license
50
- * Copyright 2020 Google LLC
51
- *
52
- * Licensed under the Apache License, Version 2.0 (the "License");
53
- * you may not use this file except in compliance with the License.
54
- * You may obtain a copy of the License at
55
- *
56
- * http://www.apache.org/licenses/LICENSE-2.0
57
- *
58
- * Unless required by applicable law or agreed to in writing, software
59
- * distributed under the License is distributed on an "AS IS" BASIS,
60
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
61
- * See the License for the specific language governing permissions and
62
- * limitations under the License.
63
- */
64
- var RC_COMPONENT_NAME = 'remote-config';
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
- */
82
- var _a;
83
- var ERROR_DESCRIPTION_MAP = (_a = {},
84
- _a["registration-window" /* ErrorCode.REGISTRATION_WINDOW */] = 'Undefined window object. This SDK only supports usage in a browser environment.',
85
- _a["registration-project-id" /* ErrorCode.REGISTRATION_PROJECT_ID */] = 'Undefined project identifier. Check Firebase app initialization.',
86
- _a["registration-api-key" /* ErrorCode.REGISTRATION_API_KEY */] = 'Undefined API key. Check Firebase app initialization.',
87
- _a["registration-app-id" /* ErrorCode.REGISTRATION_APP_ID */] = 'Undefined app identifier. Check Firebase app initialization.',
88
- _a["storage-open" /* ErrorCode.STORAGE_OPEN */] = 'Error thrown when opening storage. Original error: {$originalErrorMessage}.',
89
- _a["storage-get" /* ErrorCode.STORAGE_GET */] = 'Error thrown when reading from storage. Original error: {$originalErrorMessage}.',
90
- _a["storage-set" /* ErrorCode.STORAGE_SET */] = 'Error thrown when writing to storage. Original error: {$originalErrorMessage}.',
91
- _a["storage-delete" /* ErrorCode.STORAGE_DELETE */] = 'Error thrown when deleting from storage. Original error: {$originalErrorMessage}.',
92
- _a["fetch-client-network" /* ErrorCode.FETCH_NETWORK */] = 'Fetch client failed to connect to a network. Check Internet connection.' +
93
- ' Original error: {$originalErrorMessage}.',
94
- _a["fetch-timeout" /* ErrorCode.FETCH_TIMEOUT */] = 'The config fetch request timed out. ' +
95
- ' Configure timeout using "fetchTimeoutMillis" SDK setting.',
96
- _a["fetch-throttle" /* ErrorCode.FETCH_THROTTLE */] = 'The config fetch request timed out while in an exponential backoff state.' +
97
- ' Configure timeout using "fetchTimeoutMillis" SDK setting.' +
98
- ' Unix timestamp in milliseconds when fetch request throttling ends: {$throttleEndTimeMillis}.',
99
- _a["fetch-client-parse" /* ErrorCode.FETCH_PARSE */] = 'Fetch client could not parse response.' +
100
- ' Original error: {$originalErrorMessage}.',
101
- _a["fetch-status" /* ErrorCode.FETCH_STATUS */] = 'Fetch server returned an HTTP error status. HTTP status: {$httpStatus}.',
102
- _a["indexed-db-unavailable" /* ErrorCode.INDEXED_DB_UNAVAILABLE */] = 'Indexed DB is not supported by current browser',
103
- _a);
104
- var ERROR_FACTORY = new ErrorFactory('remoteconfig' /* service */, 'Remote Config' /* service name */, ERROR_DESCRIPTION_MAP);
105
- // Note how this is like typeof/instanceof, but for ErrorCode.
106
- function hasErrorCode(e, errorCode) {
107
- return e instanceof FirebaseError && e.code.indexOf(errorCode) !== -1;
108
- }
109
-
110
- /**
111
- * @license
112
- * Copyright 2019 Google LLC
113
- *
114
- * Licensed under the Apache License, Version 2.0 (the "License");
115
- * you may not use this file except in compliance with the License.
116
- * You may obtain a copy of the License at
117
- *
118
- * http://www.apache.org/licenses/LICENSE-2.0
119
- *
120
- * Unless required by applicable law or agreed to in writing, software
121
- * distributed under the License is distributed on an "AS IS" BASIS,
122
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
123
- * See the License for the specific language governing permissions and
124
- * limitations under the License.
125
- */
126
- var DEFAULT_VALUE_FOR_BOOLEAN = false;
127
- var DEFAULT_VALUE_FOR_STRING = '';
128
- var DEFAULT_VALUE_FOR_NUMBER = 0;
129
- var BOOLEAN_TRUTHY_VALUES = ['1', 'true', 't', 'yes', 'y', 'on'];
130
- var Value = /** @class */ (function () {
131
- function Value(_source, _value) {
132
- if (_value === void 0) { _value = DEFAULT_VALUE_FOR_STRING; }
133
- this._source = _source;
134
- this._value = _value;
135
- }
136
- Value.prototype.asString = function () {
137
- return this._value;
138
- };
139
- Value.prototype.asBoolean = function () {
140
- if (this._source === 'static') {
141
- return DEFAULT_VALUE_FOR_BOOLEAN;
142
- }
143
- return BOOLEAN_TRUTHY_VALUES.indexOf(this._value.toLowerCase()) >= 0;
144
- };
145
- Value.prototype.asNumber = function () {
146
- if (this._source === 'static') {
147
- return DEFAULT_VALUE_FOR_NUMBER;
148
- }
149
- var num = Number(this._value);
150
- if (isNaN(num)) {
151
- num = DEFAULT_VALUE_FOR_NUMBER;
152
- }
153
- return num;
154
- };
155
- Value.prototype.getSource = function () {
156
- return this._source;
157
- };
158
- return Value;
159
- }());
160
-
161
- /**
162
- * @license
163
- * Copyright 2020 Google LLC
164
- *
165
- * Licensed under the Apache License, Version 2.0 (the "License");
166
- * you may not use this file except in compliance with the License.
167
- * You may obtain a copy of the License at
168
- *
169
- * http://www.apache.org/licenses/LICENSE-2.0
170
- *
171
- * Unless required by applicable law or agreed to in writing, software
172
- * distributed under the License is distributed on an "AS IS" BASIS,
173
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
174
- * See the License for the specific language governing permissions and
175
- * limitations under the License.
176
- */
177
- /**
178
- *
179
- * @param app - The {@link @firebase/app#FirebaseApp} instance.
180
- * @returns A {@link RemoteConfig} instance.
181
- *
182
- * @public
183
- */
184
- function getRemoteConfig(app) {
185
- if (app === void 0) { app = getApp(); }
186
- app = getModularInstance(app);
187
- var rcProvider = _getProvider(app, RC_COMPONENT_NAME);
188
- return rcProvider.getImmediate();
189
- }
190
- /**
191
- * Makes the last fetched config available to the getters.
192
- * @param remoteConfig - The {@link RemoteConfig} instance.
193
- * @returns A `Promise` which resolves to true if the current call activated the fetched configs.
194
- * If the fetched configs were already activated, the `Promise` will resolve to false.
195
- *
196
- * @public
197
- */
198
- function activate(remoteConfig) {
199
- return __awaiter(this, void 0, void 0, function () {
200
- var rc, _a, lastSuccessfulFetchResponse, activeConfigEtag;
201
- return __generator(this, function (_b) {
202
- switch (_b.label) {
203
- case 0:
204
- rc = getModularInstance(remoteConfig);
205
- return [4 /*yield*/, Promise.all([
206
- rc._storage.getLastSuccessfulFetchResponse(),
207
- rc._storage.getActiveConfigEtag()
208
- ])];
209
- case 1:
210
- _a = _b.sent(), lastSuccessfulFetchResponse = _a[0], activeConfigEtag = _a[1];
211
- if (!lastSuccessfulFetchResponse ||
212
- !lastSuccessfulFetchResponse.config ||
213
- !lastSuccessfulFetchResponse.eTag ||
214
- lastSuccessfulFetchResponse.eTag === activeConfigEtag) {
215
- // Either there is no successful fetched config, or is the same as current active
216
- // config.
217
- return [2 /*return*/, false];
218
- }
219
- return [4 /*yield*/, Promise.all([
220
- rc._storageCache.setActiveConfig(lastSuccessfulFetchResponse.config),
221
- rc._storage.setActiveConfigEtag(lastSuccessfulFetchResponse.eTag)
222
- ])];
223
- case 2:
224
- _b.sent();
225
- return [2 /*return*/, true];
226
- }
227
- });
228
- });
229
- }
230
- /**
231
- * Ensures the last activated config are available to the getters.
232
- * @param remoteConfig - The {@link RemoteConfig} instance.
233
- *
234
- * @returns A `Promise` that resolves when the last activated config is available to the getters.
235
- * @public
236
- */
237
- function ensureInitialized(remoteConfig) {
238
- var rc = getModularInstance(remoteConfig);
239
- if (!rc._initializePromise) {
240
- rc._initializePromise = rc._storageCache.loadFromStorage().then(function () {
241
- rc._isInitializationComplete = true;
242
- });
243
- }
244
- return rc._initializePromise;
245
- }
246
- /**
247
- * Fetches and caches configuration from the Remote Config service.
248
- * @param remoteConfig - The {@link RemoteConfig} instance.
249
- * @public
250
- */
251
- function fetchConfig(remoteConfig) {
252
- return __awaiter(this, void 0, void 0, function () {
253
- var rc, abortSignal, e_1, lastFetchStatus;
254
- var _this = this;
255
- return __generator(this, function (_a) {
256
- switch (_a.label) {
257
- case 0:
258
- rc = getModularInstance(remoteConfig);
259
- abortSignal = new RemoteConfigAbortSignal();
260
- setTimeout(function () { return __awaiter(_this, void 0, void 0, function () {
261
- return __generator(this, function (_a) {
262
- // Note a very low delay, eg < 10ms, can elapse before listeners are initialized.
263
- abortSignal.abort();
264
- return [2 /*return*/];
265
- });
266
- }); }, rc.settings.fetchTimeoutMillis);
267
- _a.label = 1;
268
- case 1:
269
- _a.trys.push([1, 4, , 6]);
270
- return [4 /*yield*/, rc._client.fetch({
271
- cacheMaxAgeMillis: rc.settings.minimumFetchIntervalMillis,
272
- signal: abortSignal
273
- })];
274
- case 2:
275
- _a.sent();
276
- return [4 /*yield*/, rc._storageCache.setLastFetchStatus('success')];
277
- case 3:
278
- _a.sent();
279
- return [3 /*break*/, 6];
280
- case 4:
281
- e_1 = _a.sent();
282
- lastFetchStatus = hasErrorCode(e_1, "fetch-throttle" /* ErrorCode.FETCH_THROTTLE */)
283
- ? 'throttle'
284
- : 'failure';
285
- return [4 /*yield*/, rc._storageCache.setLastFetchStatus(lastFetchStatus)];
286
- case 5:
287
- _a.sent();
288
- throw e_1;
289
- case 6: return [2 /*return*/];
290
- }
291
- });
292
- });
293
- }
294
- /**
295
- * Gets all config.
296
- *
297
- * @param remoteConfig - The {@link RemoteConfig} instance.
298
- * @returns All config.
299
- *
300
- * @public
301
- */
302
- function getAll(remoteConfig) {
303
- var rc = getModularInstance(remoteConfig);
304
- return getAllKeys(rc._storageCache.getActiveConfig(), rc.defaultConfig).reduce(function (allConfigs, key) {
305
- allConfigs[key] = getValue(remoteConfig, key);
306
- return allConfigs;
307
- }, {});
308
- }
309
- /**
310
- * Gets the value for the given key as a boolean.
311
- *
312
- * Convenience method for calling <code>remoteConfig.getValue(key).asBoolean()</code>.
313
- *
314
- * @param remoteConfig - The {@link RemoteConfig} instance.
315
- * @param key - The name of the parameter.
316
- *
317
- * @returns The value for the given key as a boolean.
318
- * @public
319
- */
320
- function getBoolean(remoteConfig, key) {
321
- return getValue(getModularInstance(remoteConfig), key).asBoolean();
322
- }
323
- /**
324
- * Gets the value for the given key as a number.
325
- *
326
- * Convenience method for calling <code>remoteConfig.getValue(key).asNumber()</code>.
327
- *
328
- * @param remoteConfig - The {@link RemoteConfig} instance.
329
- * @param key - The name of the parameter.
330
- *
331
- * @returns The value for the given key as a number.
332
- *
333
- * @public
334
- */
335
- function getNumber(remoteConfig, key) {
336
- return getValue(getModularInstance(remoteConfig), key).asNumber();
337
- }
338
- /**
339
- * Gets the value for the given key as a string.
340
- * Convenience method for calling <code>remoteConfig.getValue(key).asString()</code>.
341
- *
342
- * @param remoteConfig - The {@link RemoteConfig} instance.
343
- * @param key - The name of the parameter.
344
- *
345
- * @returns The value for the given key as a string.
346
- *
347
- * @public
348
- */
349
- function getString(remoteConfig, key) {
350
- return getValue(getModularInstance(remoteConfig), key).asString();
351
- }
352
- /**
353
- * Gets the {@link Value} for the given key.
354
- *
355
- * @param remoteConfig - The {@link RemoteConfig} instance.
356
- * @param key - The name of the parameter.
357
- *
358
- * @returns The value for the given key.
359
- *
360
- * @public
361
- */
362
- function getValue(remoteConfig, key) {
363
- var rc = getModularInstance(remoteConfig);
364
- if (!rc._isInitializationComplete) {
365
- rc._logger.debug("A value was requested for key \"".concat(key, "\" before SDK initialization completed.") +
366
- ' Await on ensureInitialized if the intent was to get a previously activated value.');
367
- }
368
- var activeConfig = rc._storageCache.getActiveConfig();
369
- if (activeConfig && activeConfig[key] !== undefined) {
370
- return new Value('remote', activeConfig[key]);
371
- }
372
- else if (rc.defaultConfig && rc.defaultConfig[key] !== undefined) {
373
- return new Value('default', String(rc.defaultConfig[key]));
374
- }
375
- rc._logger.debug("Returning static value for key \"".concat(key, "\".") +
376
- ' Define a default or remote value if this is unintentional.');
377
- return new Value('static');
378
- }
379
- /**
380
- * Defines the log level to use.
381
- *
382
- * @param remoteConfig - The {@link RemoteConfig} instance.
383
- * @param logLevel - The log level to set.
384
- *
385
- * @public
386
- */
387
- function setLogLevel(remoteConfig, logLevel) {
388
- var rc = getModularInstance(remoteConfig);
389
- switch (logLevel) {
390
- case 'debug':
391
- rc._logger.logLevel = LogLevel.DEBUG;
392
- break;
393
- case 'silent':
394
- rc._logger.logLevel = LogLevel.SILENT;
395
- break;
396
- default:
397
- rc._logger.logLevel = LogLevel.ERROR;
398
- }
399
- }
400
- /**
401
- * Dedupes and returns an array of all the keys of the received objects.
402
- */
403
- function getAllKeys(obj1, obj2) {
404
- if (obj1 === void 0) { obj1 = {}; }
405
- if (obj2 === void 0) { obj2 = {}; }
406
- return Object.keys(__assign(__assign({}, obj1), obj2));
407
- }
408
-
409
- /**
410
- * @license
411
- * Copyright 2019 Google LLC
412
- *
413
- * Licensed under the Apache License, Version 2.0 (the "License");
414
- * you may not use this file except in compliance with the License.
415
- * You may obtain a copy of the License at
416
- *
417
- * http://www.apache.org/licenses/LICENSE-2.0
418
- *
419
- * Unless required by applicable law or agreed to in writing, software
420
- * distributed under the License is distributed on an "AS IS" BASIS,
421
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
422
- * See the License for the specific language governing permissions and
423
- * limitations under the License.
424
- */
425
- /**
426
- * Implements the {@link RemoteConfigClient} abstraction with success response caching.
427
- *
428
- * <p>Comparable to the browser's Cache API for responses, but the Cache API requires a Service
429
- * Worker, which requires HTTPS, which would significantly complicate SDK installation. Also, the
430
- * Cache API doesn't support matching entries by time.
431
- */
432
- var CachingClient = /** @class */ (function () {
433
- function CachingClient(client, storage, storageCache, logger) {
434
- this.client = client;
435
- this.storage = storage;
436
- this.storageCache = storageCache;
437
- this.logger = logger;
438
- }
439
- /**
440
- * Returns true if the age of the cached fetched configs is less than or equal to
441
- * {@link Settings#minimumFetchIntervalInSeconds}.
442
- *
443
- * <p>This is comparable to passing `headers = { 'Cache-Control': max-age <maxAge> }` to the
444
- * native Fetch API.
445
- *
446
- * <p>Visible for testing.
447
- */
448
- CachingClient.prototype.isCachedDataFresh = function (cacheMaxAgeMillis, lastSuccessfulFetchTimestampMillis) {
449
- // Cache can only be fresh if it's populated.
450
- if (!lastSuccessfulFetchTimestampMillis) {
451
- this.logger.debug('Config fetch cache check. Cache unpopulated.');
452
- return false;
453
- }
454
- // Calculates age of cache entry.
455
- var cacheAgeMillis = Date.now() - lastSuccessfulFetchTimestampMillis;
456
- var isCachedDataFresh = cacheAgeMillis <= cacheMaxAgeMillis;
457
- this.logger.debug('Config fetch cache check.' +
458
- " Cache age millis: ".concat(cacheAgeMillis, ".") +
459
- " Cache max age millis (minimumFetchIntervalMillis setting): ".concat(cacheMaxAgeMillis, ".") +
460
- " Is cache hit: ".concat(isCachedDataFresh, "."));
461
- return isCachedDataFresh;
462
- };
463
- CachingClient.prototype.fetch = function (request) {
464
- return __awaiter(this, void 0, void 0, function () {
465
- var _a, lastSuccessfulFetchTimestampMillis, lastSuccessfulFetchResponse, response, storageOperations;
466
- return __generator(this, function (_b) {
467
- switch (_b.label) {
468
- case 0: return [4 /*yield*/, Promise.all([
469
- this.storage.getLastSuccessfulFetchTimestampMillis(),
470
- this.storage.getLastSuccessfulFetchResponse()
471
- ])];
472
- case 1:
473
- _a = _b.sent(), lastSuccessfulFetchTimestampMillis = _a[0], lastSuccessfulFetchResponse = _a[1];
474
- // Exits early on cache hit.
475
- if (lastSuccessfulFetchResponse &&
476
- this.isCachedDataFresh(request.cacheMaxAgeMillis, lastSuccessfulFetchTimestampMillis)) {
477
- return [2 /*return*/, lastSuccessfulFetchResponse];
478
- }
479
- // Deviates from pure decorator by not honoring a passed ETag since we don't have a public API
480
- // that allows the caller to pass an ETag.
481
- request.eTag =
482
- lastSuccessfulFetchResponse && lastSuccessfulFetchResponse.eTag;
483
- return [4 /*yield*/, this.client.fetch(request)];
484
- case 2:
485
- response = _b.sent();
486
- storageOperations = [
487
- // Uses write-through cache for consistency with synchronous public API.
488
- this.storageCache.setLastSuccessfulFetchTimestampMillis(Date.now())
489
- ];
490
- if (response.status === 200) {
491
- // Caches response only if it has changed, ie non-304 responses.
492
- storageOperations.push(this.storage.setLastSuccessfulFetchResponse(response));
493
- }
494
- return [4 /*yield*/, Promise.all(storageOperations)];
495
- case 3:
496
- _b.sent();
497
- return [2 /*return*/, response];
498
- }
499
- });
500
- });
501
- };
502
- return CachingClient;
503
- }());
504
-
505
- /**
506
- * @license
507
- * Copyright 2019 Google LLC
508
- *
509
- * Licensed under the Apache License, Version 2.0 (the "License");
510
- * you may not use this file except in compliance with the License.
511
- * You may obtain a copy of the License at
512
- *
513
- * http://www.apache.org/licenses/LICENSE-2.0
514
- *
515
- * Unless required by applicable law or agreed to in writing, software
516
- * distributed under the License is distributed on an "AS IS" BASIS,
517
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
518
- * See the License for the specific language governing permissions and
519
- * limitations under the License.
520
- */
521
- /**
522
- * Attempts to get the most accurate browser language setting.
523
- *
524
- * <p>Adapted from getUserLanguage in packages/auth/src/utils.js for TypeScript.
525
- *
526
- * <p>Defers default language specification to server logic for consistency.
527
- *
528
- * @param navigatorLanguage Enables tests to override read-only {@link NavigatorLanguage}.
529
- */
530
- function getUserLanguage(navigatorLanguage) {
531
- if (navigatorLanguage === void 0) { navigatorLanguage = navigator; }
532
- return (
533
- // Most reliable, but only supported in Chrome/Firefox.
534
- (navigatorLanguage.languages && navigatorLanguage.languages[0]) ||
535
- // Supported in most browsers, but returns the language of the browser
536
- // UI, not the language set in browser settings.
537
- navigatorLanguage.language
538
- // Polyfill otherwise.
539
- );
540
- }
541
-
542
- /**
543
- * @license
544
- * Copyright 2019 Google LLC
545
- *
546
- * Licensed under the Apache License, Version 2.0 (the "License");
547
- * you may not use this file except in compliance with the License.
548
- * You may obtain a copy of the License at
549
- *
550
- * http://www.apache.org/licenses/LICENSE-2.0
551
- *
552
- * Unless required by applicable law or agreed to in writing, software
553
- * distributed under the License is distributed on an "AS IS" BASIS,
554
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
555
- * See the License for the specific language governing permissions and
556
- * limitations under the License.
557
- */
558
- /**
559
- * Implements the Client abstraction for the Remote Config REST API.
560
- */
561
- var RestClient = /** @class */ (function () {
562
- function RestClient(firebaseInstallations, sdkVersion, namespace, projectId, apiKey, appId) {
563
- this.firebaseInstallations = firebaseInstallations;
564
- this.sdkVersion = sdkVersion;
565
- this.namespace = namespace;
566
- this.projectId = projectId;
567
- this.apiKey = apiKey;
568
- this.appId = appId;
569
- }
570
- /**
571
- * Fetches from the Remote Config REST API.
572
- *
573
- * @throws a {@link ErrorCode.FETCH_NETWORK} error if {@link GlobalFetch#fetch} can't
574
- * connect to the network.
575
- * @throws a {@link ErrorCode.FETCH_PARSE} error if {@link Response#json} can't parse the
576
- * fetch response.
577
- * @throws a {@link ErrorCode.FETCH_STATUS} error if the service returns an HTTP error status.
578
- */
579
- RestClient.prototype.fetch = function (request) {
580
- return __awaiter(this, void 0, void 0, function () {
581
- var _a, installationId, installationToken, urlBase, url, headers, requestBody, options, fetchPromise, timeoutPromise, response, originalError_1, errorCode, status, responseEtag, config, state, responseBody, originalError_2;
582
- return __generator(this, function (_b) {
583
- switch (_b.label) {
584
- case 0: return [4 /*yield*/, Promise.all([
585
- this.firebaseInstallations.getId(),
586
- this.firebaseInstallations.getToken()
587
- ])];
588
- case 1:
589
- _a = _b.sent(), installationId = _a[0], installationToken = _a[1];
590
- urlBase = window.FIREBASE_REMOTE_CONFIG_URL_BASE ||
591
- 'https://firebaseremoteconfig.googleapis.com';
592
- url = "".concat(urlBase, "/v1/projects/").concat(this.projectId, "/namespaces/").concat(this.namespace, ":fetch?key=").concat(this.apiKey);
593
- headers = {
594
- 'Content-Type': 'application/json',
595
- 'Content-Encoding': 'gzip',
596
- // Deviates from pure decorator by not passing max-age header since we don't currently have
597
- // service behavior using that header.
598
- 'If-None-Match': request.eTag || '*'
599
- };
600
- requestBody = {
601
- /* eslint-disable camelcase */
602
- sdk_version: this.sdkVersion,
603
- app_instance_id: installationId,
604
- app_instance_id_token: installationToken,
605
- app_id: this.appId,
606
- language_code: getUserLanguage()
607
- /* eslint-enable camelcase */
608
- };
609
- options = {
610
- method: 'POST',
611
- headers: headers,
612
- body: JSON.stringify(requestBody)
613
- };
614
- fetchPromise = fetch(url, options);
615
- timeoutPromise = new Promise(function (_resolve, reject) {
616
- // Maps async event listener to Promise API.
617
- request.signal.addEventListener(function () {
618
- // Emulates https://heycam.github.io/webidl/#aborterror
619
- var error = new Error('The operation was aborted.');
620
- error.name = 'AbortError';
621
- reject(error);
622
- });
623
- });
624
- _b.label = 2;
625
- case 2:
626
- _b.trys.push([2, 5, , 6]);
627
- return [4 /*yield*/, Promise.race([fetchPromise, timeoutPromise])];
628
- case 3:
629
- _b.sent();
630
- return [4 /*yield*/, fetchPromise];
631
- case 4:
632
- response = _b.sent();
633
- return [3 /*break*/, 6];
634
- case 5:
635
- originalError_1 = _b.sent();
636
- errorCode = "fetch-client-network" /* ErrorCode.FETCH_NETWORK */;
637
- if ((originalError_1 === null || originalError_1 === void 0 ? void 0 : originalError_1.name) === 'AbortError') {
638
- errorCode = "fetch-timeout" /* ErrorCode.FETCH_TIMEOUT */;
639
- }
640
- throw ERROR_FACTORY.create(errorCode, {
641
- originalErrorMessage: originalError_1 === null || originalError_1 === void 0 ? void 0 : originalError_1.message
642
- });
643
- case 6:
644
- status = response.status;
645
- responseEtag = response.headers.get('ETag') || undefined;
646
- if (!(response.status === 200)) return [3 /*break*/, 11];
647
- responseBody = void 0;
648
- _b.label = 7;
649
- case 7:
650
- _b.trys.push([7, 9, , 10]);
651
- return [4 /*yield*/, response.json()];
652
- case 8:
653
- responseBody = _b.sent();
654
- return [3 /*break*/, 10];
655
- case 9:
656
- originalError_2 = _b.sent();
657
- throw ERROR_FACTORY.create("fetch-client-parse" /* ErrorCode.FETCH_PARSE */, {
658
- originalErrorMessage: originalError_2 === null || originalError_2 === void 0 ? void 0 : originalError_2.message
659
- });
660
- case 10:
661
- config = responseBody['entries'];
662
- state = responseBody['state'];
663
- _b.label = 11;
664
- case 11:
665
- // Normalizes based on legacy state.
666
- if (state === 'INSTANCE_STATE_UNSPECIFIED') {
667
- status = 500;
668
- }
669
- else if (state === 'NO_CHANGE') {
670
- status = 304;
671
- }
672
- else if (state === 'NO_TEMPLATE' || state === 'EMPTY_CONFIG') {
673
- // These cases can be fixed remotely, so normalize to safe value.
674
- config = {};
675
- }
676
- // Normalize to exception-based control flow for non-success cases.
677
- // Encapsulates HTTP specifics in this class as much as possible. Status is still the best for
678
- // differentiating success states (200 from 304; the state body param is undefined in a
679
- // standard 304).
680
- if (status !== 304 && status !== 200) {
681
- throw ERROR_FACTORY.create("fetch-status" /* ErrorCode.FETCH_STATUS */, {
682
- httpStatus: status
683
- });
684
- }
685
- return [2 /*return*/, { status: status, eTag: responseEtag, config: config }];
686
- }
687
- });
688
- });
689
- };
690
- return RestClient;
691
- }());
692
-
693
- /**
694
- * @license
695
- * Copyright 2019 Google LLC
696
- *
697
- * Licensed under the Apache License, Version 2.0 (the "License");
698
- * you may not use this file except in compliance with the License.
699
- * You may obtain a copy of the License at
700
- *
701
- * http://www.apache.org/licenses/LICENSE-2.0
702
- *
703
- * Unless required by applicable law or agreed to in writing, software
704
- * distributed under the License is distributed on an "AS IS" BASIS,
705
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
706
- * See the License for the specific language governing permissions and
707
- * limitations under the License.
708
- */
709
- /**
710
- * Supports waiting on a backoff by:
711
- *
712
- * <ul>
713
- * <li>Promisifying setTimeout, so we can set a timeout in our Promise chain</li>
714
- * <li>Listening on a signal bus for abort events, just like the Fetch API</li>
715
- * <li>Failing in the same way the Fetch API fails, so timing out a live request and a throttled
716
- * request appear the same.</li>
717
- * </ul>
718
- *
719
- * <p>Visible for testing.
720
- */
721
- function setAbortableTimeout(signal, throttleEndTimeMillis) {
722
- return new Promise(function (resolve, reject) {
723
- // Derives backoff from given end time, normalizing negative numbers to zero.
724
- var backoffMillis = Math.max(throttleEndTimeMillis - Date.now(), 0);
725
- var timeout = setTimeout(resolve, backoffMillis);
726
- // Adds listener, rather than sets onabort, because signal is a shared object.
727
- signal.addEventListener(function () {
728
- clearTimeout(timeout);
729
- // If the request completes before this timeout, the rejection has no effect.
730
- reject(ERROR_FACTORY.create("fetch-throttle" /* ErrorCode.FETCH_THROTTLE */, {
731
- throttleEndTimeMillis: throttleEndTimeMillis
732
- }));
733
- });
734
- });
735
- }
736
- /**
737
- * Returns true if the {@link Error} indicates a fetch request may succeed later.
738
- */
739
- function isRetriableError(e) {
740
- if (!(e instanceof FirebaseError) || !e.customData) {
741
- return false;
742
- }
743
- // Uses string index defined by ErrorData, which FirebaseError implements.
744
- var httpStatus = Number(e.customData['httpStatus']);
745
- return (httpStatus === 429 ||
746
- httpStatus === 500 ||
747
- httpStatus === 503 ||
748
- httpStatus === 504);
749
- }
750
- /**
751
- * Decorates a Client with retry logic.
752
- *
753
- * <p>Comparable to CachingClient, but uses backoff logic instead of cache max age and doesn't cache
754
- * responses (because the SDK has no use for error responses).
755
- */
756
- var RetryingClient = /** @class */ (function () {
757
- function RetryingClient(client, storage) {
758
- this.client = client;
759
- this.storage = storage;
760
- }
761
- RetryingClient.prototype.fetch = function (request) {
762
- return __awaiter(this, void 0, void 0, function () {
763
- var throttleMetadata;
764
- return __generator(this, function (_a) {
765
- switch (_a.label) {
766
- case 0: return [4 /*yield*/, this.storage.getThrottleMetadata()];
767
- case 1:
768
- throttleMetadata = (_a.sent()) || {
769
- backoffCount: 0,
770
- throttleEndTimeMillis: Date.now()
771
- };
772
- return [2 /*return*/, this.attemptFetch(request, throttleMetadata)];
773
- }
774
- });
775
- });
776
- };
777
- /**
778
- * A recursive helper for attempting a fetch request repeatedly.
779
- *
780
- * @throws any non-retriable errors.
781
- */
782
- RetryingClient.prototype.attemptFetch = function (request, _a) {
783
- var throttleEndTimeMillis = _a.throttleEndTimeMillis, backoffCount = _a.backoffCount;
784
- return __awaiter(this, void 0, void 0, function () {
785
- var response, e_1, throttleMetadata;
786
- return __generator(this, function (_b) {
787
- switch (_b.label) {
788
- case 0:
789
- // Starts with a (potentially zero) timeout to support resumption from stored state.
790
- // Ensures the throttle end time is honored if the last attempt timed out.
791
- // Note the SDK will never make a request if the fetch timeout expires at this point.
792
- return [4 /*yield*/, setAbortableTimeout(request.signal, throttleEndTimeMillis)];
793
- case 1:
794
- // Starts with a (potentially zero) timeout to support resumption from stored state.
795
- // Ensures the throttle end time is honored if the last attempt timed out.
796
- // Note the SDK will never make a request if the fetch timeout expires at this point.
797
- _b.sent();
798
- _b.label = 2;
799
- case 2:
800
- _b.trys.push([2, 5, , 7]);
801
- return [4 /*yield*/, this.client.fetch(request)];
802
- case 3:
803
- response = _b.sent();
804
- // Note the SDK only clears throttle state if response is success or non-retriable.
805
- return [4 /*yield*/, this.storage.deleteThrottleMetadata()];
806
- case 4:
807
- // Note the SDK only clears throttle state if response is success or non-retriable.
808
- _b.sent();
809
- return [2 /*return*/, response];
810
- case 5:
811
- e_1 = _b.sent();
812
- if (!isRetriableError(e_1)) {
813
- throw e_1;
814
- }
815
- throttleMetadata = {
816
- throttleEndTimeMillis: Date.now() + calculateBackoffMillis(backoffCount),
817
- backoffCount: backoffCount + 1
818
- };
819
- // Persists state.
820
- return [4 /*yield*/, this.storage.setThrottleMetadata(throttleMetadata)];
821
- case 6:
822
- // Persists state.
823
- _b.sent();
824
- return [2 /*return*/, this.attemptFetch(request, throttleMetadata)];
825
- case 7: return [2 /*return*/];
826
- }
827
- });
828
- });
829
- };
830
- return RetryingClient;
831
- }());
832
-
833
- /**
834
- * @license
835
- * Copyright 2019 Google LLC
836
- *
837
- * Licensed under the Apache License, Version 2.0 (the "License");
838
- * you may not use this file except in compliance with the License.
839
- * You may obtain a copy of the License at
840
- *
841
- * http://www.apache.org/licenses/LICENSE-2.0
842
- *
843
- * Unless required by applicable law or agreed to in writing, software
844
- * distributed under the License is distributed on an "AS IS" BASIS,
845
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
846
- * See the License for the specific language governing permissions and
847
- * limitations under the License.
848
- */
849
- var DEFAULT_FETCH_TIMEOUT_MILLIS = 60 * 1000; // One minute
850
- var DEFAULT_CACHE_MAX_AGE_MILLIS = 12 * 60 * 60 * 1000; // Twelve hours.
851
- /**
852
- * Encapsulates business logic mapping network and storage dependencies to the public SDK API.
853
- *
854
- * See {@link https://github.com/firebase/firebase-js-sdk/blob/main/packages/firebase/index.d.ts|interface documentation} for method descriptions.
855
- */
856
- var RemoteConfig = /** @class */ (function () {
857
- function RemoteConfig(
858
- // Required by FirebaseServiceFactory interface.
859
- app,
860
- // JS doesn't support private yet
861
- // (https://github.com/tc39/proposal-class-fields#private-fields), so we hint using an
862
- // underscore prefix.
863
- /**
864
- * @internal
865
- */
866
- _client,
867
- /**
868
- * @internal
869
- */
870
- _storageCache,
871
- /**
872
- * @internal
873
- */
874
- _storage,
875
- /**
876
- * @internal
877
- */
878
- _logger) {
879
- this.app = app;
880
- this._client = _client;
881
- this._storageCache = _storageCache;
882
- this._storage = _storage;
883
- this._logger = _logger;
884
- /**
885
- * Tracks completion of initialization promise.
886
- * @internal
887
- */
888
- this._isInitializationComplete = false;
889
- this.settings = {
890
- fetchTimeoutMillis: DEFAULT_FETCH_TIMEOUT_MILLIS,
891
- minimumFetchIntervalMillis: DEFAULT_CACHE_MAX_AGE_MILLIS
892
- };
893
- this.defaultConfig = {};
894
- }
895
- Object.defineProperty(RemoteConfig.prototype, "fetchTimeMillis", {
896
- get: function () {
897
- return this._storageCache.getLastSuccessfulFetchTimestampMillis() || -1;
898
- },
899
- enumerable: false,
900
- configurable: true
901
- });
902
- Object.defineProperty(RemoteConfig.prototype, "lastFetchStatus", {
903
- get: function () {
904
- return this._storageCache.getLastFetchStatus() || 'no-fetch-yet';
905
- },
906
- enumerable: false,
907
- configurable: true
908
- });
909
- return RemoteConfig;
910
- }());
911
-
912
- /**
913
- * @license
914
- * Copyright 2019 Google LLC
915
- *
916
- * Licensed under the Apache License, Version 2.0 (the "License");
917
- * you may not use this file except in compliance with the License.
918
- * You may obtain a copy of the License at
919
- *
920
- * http://www.apache.org/licenses/LICENSE-2.0
921
- *
922
- * Unless required by applicable law or agreed to in writing, software
923
- * distributed under the License is distributed on an "AS IS" BASIS,
924
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
925
- * See the License for the specific language governing permissions and
926
- * limitations under the License.
927
- */
928
- /**
929
- * Converts an error event associated with a {@link IDBRequest} to a {@link FirebaseError}.
930
- */
931
- function toFirebaseError(event, errorCode) {
932
- var originalError = event.target.error || undefined;
933
- return ERROR_FACTORY.create(errorCode, {
934
- originalErrorMessage: originalError && (originalError === null || originalError === void 0 ? void 0 : originalError.message)
935
- });
936
- }
937
- /**
938
- * A general-purpose store keyed by app + namespace + {@link
939
- * ProjectNamespaceKeyFieldValue}.
940
- *
941
- * <p>The Remote Config SDK can be used with multiple app installations, and each app can interact
942
- * with multiple namespaces, so this store uses app (ID + name) and namespace as common parent keys
943
- * for a set of key-value pairs. See {@link Storage#createCompositeKey}.
944
- *
945
- * <p>Visible for testing.
946
- */
947
- var APP_NAMESPACE_STORE = 'app_namespace_store';
948
- var DB_NAME = 'firebase_remote_config';
949
- var DB_VERSION = 1;
950
- // Visible for testing.
951
- function openDatabase() {
952
- return new Promise(function (resolve, reject) {
953
- try {
954
- var request = indexedDB.open(DB_NAME, DB_VERSION);
955
- request.onerror = function (event) {
956
- reject(toFirebaseError(event, "storage-open" /* ErrorCode.STORAGE_OPEN */));
957
- };
958
- request.onsuccess = function (event) {
959
- resolve(event.target.result);
960
- };
961
- request.onupgradeneeded = function (event) {
962
- var db = event.target.result;
963
- // We don't use 'break' in this switch statement, the fall-through
964
- // behavior is what we want, because if there are multiple versions between
965
- // the old version and the current version, we want ALL the migrations
966
- // that correspond to those versions to run, not only the last one.
967
- // eslint-disable-next-line default-case
968
- switch (event.oldVersion) {
969
- case 0:
970
- db.createObjectStore(APP_NAMESPACE_STORE, {
971
- keyPath: 'compositeKey'
972
- });
973
- }
974
- };
975
- }
976
- catch (error) {
977
- reject(ERROR_FACTORY.create("storage-open" /* ErrorCode.STORAGE_OPEN */, {
978
- originalErrorMessage: error === null || error === void 0 ? void 0 : error.message
979
- }));
980
- }
981
- });
982
- }
983
- /**
984
- * Abstracts data persistence.
985
- */
986
- var Storage = /** @class */ (function () {
987
- /**
988
- * @param appId enables storage segmentation by app (ID + name).
989
- * @param appName enables storage segmentation by app (ID + name).
990
- * @param namespace enables storage segmentation by namespace.
991
- */
992
- function Storage(appId, appName, namespace, openDbPromise) {
993
- if (openDbPromise === void 0) { openDbPromise = openDatabase(); }
994
- this.appId = appId;
995
- this.appName = appName;
996
- this.namespace = namespace;
997
- this.openDbPromise = openDbPromise;
998
- }
999
- Storage.prototype.getLastFetchStatus = function () {
1000
- return this.get('last_fetch_status');
1001
- };
1002
- Storage.prototype.setLastFetchStatus = function (status) {
1003
- return this.set('last_fetch_status', status);
1004
- };
1005
- // This is comparable to a cache entry timestamp. If we need to expire other data, we could
1006
- // consider adding timestamp to all storage records and an optional max age arg to getters.
1007
- Storage.prototype.getLastSuccessfulFetchTimestampMillis = function () {
1008
- return this.get('last_successful_fetch_timestamp_millis');
1009
- };
1010
- Storage.prototype.setLastSuccessfulFetchTimestampMillis = function (timestamp) {
1011
- return this.set('last_successful_fetch_timestamp_millis', timestamp);
1012
- };
1013
- Storage.prototype.getLastSuccessfulFetchResponse = function () {
1014
- return this.get('last_successful_fetch_response');
1015
- };
1016
- Storage.prototype.setLastSuccessfulFetchResponse = function (response) {
1017
- return this.set('last_successful_fetch_response', response);
1018
- };
1019
- Storage.prototype.getActiveConfig = function () {
1020
- return this.get('active_config');
1021
- };
1022
- Storage.prototype.setActiveConfig = function (config) {
1023
- return this.set('active_config', config);
1024
- };
1025
- Storage.prototype.getActiveConfigEtag = function () {
1026
- return this.get('active_config_etag');
1027
- };
1028
- Storage.prototype.setActiveConfigEtag = function (etag) {
1029
- return this.set('active_config_etag', etag);
1030
- };
1031
- Storage.prototype.getThrottleMetadata = function () {
1032
- return this.get('throttle_metadata');
1033
- };
1034
- Storage.prototype.setThrottleMetadata = function (metadata) {
1035
- return this.set('throttle_metadata', metadata);
1036
- };
1037
- Storage.prototype.deleteThrottleMetadata = function () {
1038
- return this.delete('throttle_metadata');
1039
- };
1040
- Storage.prototype.get = function (key) {
1041
- return __awaiter(this, void 0, void 0, function () {
1042
- var db;
1043
- var _this = this;
1044
- return __generator(this, function (_a) {
1045
- switch (_a.label) {
1046
- case 0: return [4 /*yield*/, this.openDbPromise];
1047
- case 1:
1048
- db = _a.sent();
1049
- return [2 /*return*/, new Promise(function (resolve, reject) {
1050
- var transaction = db.transaction([APP_NAMESPACE_STORE], 'readonly');
1051
- var objectStore = transaction.objectStore(APP_NAMESPACE_STORE);
1052
- var compositeKey = _this.createCompositeKey(key);
1053
- try {
1054
- var request = objectStore.get(compositeKey);
1055
- request.onerror = function (event) {
1056
- reject(toFirebaseError(event, "storage-get" /* ErrorCode.STORAGE_GET */));
1057
- };
1058
- request.onsuccess = function (event) {
1059
- var result = event.target.result;
1060
- if (result) {
1061
- resolve(result.value);
1062
- }
1063
- else {
1064
- resolve(undefined);
1065
- }
1066
- };
1067
- }
1068
- catch (e) {
1069
- reject(ERROR_FACTORY.create("storage-get" /* ErrorCode.STORAGE_GET */, {
1070
- originalErrorMessage: e === null || e === void 0 ? void 0 : e.message
1071
- }));
1072
- }
1073
- })];
1074
- }
1075
- });
1076
- });
1077
- };
1078
- Storage.prototype.set = function (key, value) {
1079
- return __awaiter(this, void 0, void 0, function () {
1080
- var db;
1081
- var _this = this;
1082
- return __generator(this, function (_a) {
1083
- switch (_a.label) {
1084
- case 0: return [4 /*yield*/, this.openDbPromise];
1085
- case 1:
1086
- db = _a.sent();
1087
- return [2 /*return*/, new Promise(function (resolve, reject) {
1088
- var transaction = db.transaction([APP_NAMESPACE_STORE], 'readwrite');
1089
- var objectStore = transaction.objectStore(APP_NAMESPACE_STORE);
1090
- var compositeKey = _this.createCompositeKey(key);
1091
- try {
1092
- var request = objectStore.put({
1093
- compositeKey: compositeKey,
1094
- value: value
1095
- });
1096
- request.onerror = function (event) {
1097
- reject(toFirebaseError(event, "storage-set" /* ErrorCode.STORAGE_SET */));
1098
- };
1099
- request.onsuccess = function () {
1100
- resolve();
1101
- };
1102
- }
1103
- catch (e) {
1104
- reject(ERROR_FACTORY.create("storage-set" /* ErrorCode.STORAGE_SET */, {
1105
- originalErrorMessage: e === null || e === void 0 ? void 0 : e.message
1106
- }));
1107
- }
1108
- })];
1109
- }
1110
- });
1111
- });
1112
- };
1113
- Storage.prototype.delete = function (key) {
1114
- return __awaiter(this, void 0, void 0, function () {
1115
- var db;
1116
- var _this = this;
1117
- return __generator(this, function (_a) {
1118
- switch (_a.label) {
1119
- case 0: return [4 /*yield*/, this.openDbPromise];
1120
- case 1:
1121
- db = _a.sent();
1122
- return [2 /*return*/, new Promise(function (resolve, reject) {
1123
- var transaction = db.transaction([APP_NAMESPACE_STORE], 'readwrite');
1124
- var objectStore = transaction.objectStore(APP_NAMESPACE_STORE);
1125
- var compositeKey = _this.createCompositeKey(key);
1126
- try {
1127
- var request = objectStore.delete(compositeKey);
1128
- request.onerror = function (event) {
1129
- reject(toFirebaseError(event, "storage-delete" /* ErrorCode.STORAGE_DELETE */));
1130
- };
1131
- request.onsuccess = function () {
1132
- resolve();
1133
- };
1134
- }
1135
- catch (e) {
1136
- reject(ERROR_FACTORY.create("storage-delete" /* ErrorCode.STORAGE_DELETE */, {
1137
- originalErrorMessage: e === null || e === void 0 ? void 0 : e.message
1138
- }));
1139
- }
1140
- })];
1141
- }
1142
- });
1143
- });
1144
- };
1145
- // Facilitates composite key functionality (which is unsupported in IE).
1146
- Storage.prototype.createCompositeKey = function (key) {
1147
- return [this.appId, this.appName, this.namespace, key].join();
1148
- };
1149
- return Storage;
1150
- }());
1151
-
1152
- /**
1153
- * @license
1154
- * Copyright 2019 Google LLC
1155
- *
1156
- * Licensed under the Apache License, Version 2.0 (the "License");
1157
- * you may not use this file except in compliance with the License.
1158
- * You may obtain a copy of the License at
1159
- *
1160
- * http://www.apache.org/licenses/LICENSE-2.0
1161
- *
1162
- * Unless required by applicable law or agreed to in writing, software
1163
- * distributed under the License is distributed on an "AS IS" BASIS,
1164
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1165
- * See the License for the specific language governing permissions and
1166
- * limitations under the License.
1167
- */
1168
- /**
1169
- * A memory cache layer over storage to support the SDK's synchronous read requirements.
1170
- */
1171
- var StorageCache = /** @class */ (function () {
1172
- function StorageCache(storage) {
1173
- this.storage = storage;
1174
- }
1175
- /**
1176
- * Memory-only getters
1177
- */
1178
- StorageCache.prototype.getLastFetchStatus = function () {
1179
- return this.lastFetchStatus;
1180
- };
1181
- StorageCache.prototype.getLastSuccessfulFetchTimestampMillis = function () {
1182
- return this.lastSuccessfulFetchTimestampMillis;
1183
- };
1184
- StorageCache.prototype.getActiveConfig = function () {
1185
- return this.activeConfig;
1186
- };
1187
- /**
1188
- * Read-ahead getter
1189
- */
1190
- StorageCache.prototype.loadFromStorage = function () {
1191
- return __awaiter(this, void 0, void 0, function () {
1192
- var lastFetchStatusPromise, lastSuccessfulFetchTimestampMillisPromise, activeConfigPromise, lastFetchStatus, lastSuccessfulFetchTimestampMillis, activeConfig;
1193
- return __generator(this, function (_a) {
1194
- switch (_a.label) {
1195
- case 0:
1196
- lastFetchStatusPromise = this.storage.getLastFetchStatus();
1197
- lastSuccessfulFetchTimestampMillisPromise = this.storage.getLastSuccessfulFetchTimestampMillis();
1198
- activeConfigPromise = this.storage.getActiveConfig();
1199
- return [4 /*yield*/, lastFetchStatusPromise];
1200
- case 1:
1201
- lastFetchStatus = _a.sent();
1202
- if (lastFetchStatus) {
1203
- this.lastFetchStatus = lastFetchStatus;
1204
- }
1205
- return [4 /*yield*/, lastSuccessfulFetchTimestampMillisPromise];
1206
- case 2:
1207
- lastSuccessfulFetchTimestampMillis = _a.sent();
1208
- if (lastSuccessfulFetchTimestampMillis) {
1209
- this.lastSuccessfulFetchTimestampMillis =
1210
- lastSuccessfulFetchTimestampMillis;
1211
- }
1212
- return [4 /*yield*/, activeConfigPromise];
1213
- case 3:
1214
- activeConfig = _a.sent();
1215
- if (activeConfig) {
1216
- this.activeConfig = activeConfig;
1217
- }
1218
- return [2 /*return*/];
1219
- }
1220
- });
1221
- });
1222
- };
1223
- /**
1224
- * Write-through setters
1225
- */
1226
- StorageCache.prototype.setLastFetchStatus = function (status) {
1227
- this.lastFetchStatus = status;
1228
- return this.storage.setLastFetchStatus(status);
1229
- };
1230
- StorageCache.prototype.setLastSuccessfulFetchTimestampMillis = function (timestampMillis) {
1231
- this.lastSuccessfulFetchTimestampMillis = timestampMillis;
1232
- return this.storage.setLastSuccessfulFetchTimestampMillis(timestampMillis);
1233
- };
1234
- StorageCache.prototype.setActiveConfig = function (activeConfig) {
1235
- this.activeConfig = activeConfig;
1236
- return this.storage.setActiveConfig(activeConfig);
1237
- };
1238
- return StorageCache;
1239
- }());
1240
-
1241
- /**
1242
- * @license
1243
- * Copyright 2020 Google LLC
1244
- *
1245
- * Licensed under the Apache License, Version 2.0 (the "License");
1246
- * you may not use this file except in compliance with the License.
1247
- * You may obtain a copy of the License at
1248
- *
1249
- * http://www.apache.org/licenses/LICENSE-2.0
1250
- *
1251
- * Unless required by applicable law or agreed to in writing, software
1252
- * distributed under the License is distributed on an "AS IS" BASIS,
1253
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1254
- * See the License for the specific language governing permissions and
1255
- * limitations under the License.
1256
- */
1257
- function registerRemoteConfig() {
1258
- _registerComponent(new Component(RC_COMPONENT_NAME, remoteConfigFactory, "PUBLIC" /* ComponentType.PUBLIC */).setMultipleInstances(true));
1259
- registerVersion(name, version);
1260
- // BUILD_TARGET will be replaced by values like esm5, esm2017, cjs5, etc during the compilation
1261
- registerVersion(name, version, 'esm5');
1262
- function remoteConfigFactory(container, _a) {
1263
- var namespace = _a.instanceIdentifier;
1264
- /* Dependencies */
1265
- // getImmediate for FirebaseApp will always succeed
1266
- var app = container.getProvider('app').getImmediate();
1267
- // The following call will always succeed because rc has `import '@firebase/installations'`
1268
- var installations = container
1269
- .getProvider('installations-internal')
1270
- .getImmediate();
1271
- // Guards against the SDK being used in non-browser environments.
1272
- if (typeof window === 'undefined') {
1273
- throw ERROR_FACTORY.create("registration-window" /* ErrorCode.REGISTRATION_WINDOW */);
1274
- }
1275
- // Guards against the SDK being used when indexedDB is not available.
1276
- if (!isIndexedDBAvailable()) {
1277
- throw ERROR_FACTORY.create("indexed-db-unavailable" /* ErrorCode.INDEXED_DB_UNAVAILABLE */);
1278
- }
1279
- // Normalizes optional inputs.
1280
- var _b = app.options, projectId = _b.projectId, apiKey = _b.apiKey, appId = _b.appId;
1281
- if (!projectId) {
1282
- throw ERROR_FACTORY.create("registration-project-id" /* ErrorCode.REGISTRATION_PROJECT_ID */);
1283
- }
1284
- if (!apiKey) {
1285
- throw ERROR_FACTORY.create("registration-api-key" /* ErrorCode.REGISTRATION_API_KEY */);
1286
- }
1287
- if (!appId) {
1288
- throw ERROR_FACTORY.create("registration-app-id" /* ErrorCode.REGISTRATION_APP_ID */);
1289
- }
1290
- namespace = namespace || 'firebase';
1291
- var storage = new Storage(appId, app.name, namespace);
1292
- var storageCache = new StorageCache(storage);
1293
- var logger = new Logger(name);
1294
- // Sets ERROR as the default log level.
1295
- // See RemoteConfig#setLogLevel for corresponding normalization to ERROR log level.
1296
- logger.logLevel = LogLevel.ERROR;
1297
- var restClient = new RestClient(installations,
1298
- // Uses the JS SDK version, by which the RC package version can be deduced, if necessary.
1299
- SDK_VERSION, namespace, projectId, apiKey, appId);
1300
- var retryingClient = new RetryingClient(restClient, storage);
1301
- var cachingClient = new CachingClient(retryingClient, storage, storageCache, logger);
1302
- var remoteConfigInstance = new RemoteConfig(app, cachingClient, storageCache, storage, logger);
1303
- // Starts warming cache.
1304
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
1305
- ensureInitialized(remoteConfigInstance);
1306
- return remoteConfigInstance;
1307
- }
1308
- }
1309
-
1310
- /**
1311
- * @license
1312
- * Copyright 2020 Google LLC
1313
- *
1314
- * Licensed under the Apache License, Version 2.0 (the "License");
1315
- * you may not use this file except in compliance with the License.
1316
- * You may obtain a copy of the License at
1317
- *
1318
- * http://www.apache.org/licenses/LICENSE-2.0
1319
- *
1320
- * Unless required by applicable law or agreed to in writing, software
1321
- * distributed under the License is distributed on an "AS IS" BASIS,
1322
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1323
- * See the License for the specific language governing permissions and
1324
- * limitations under the License.
1325
- */
1326
- // This API is put in a separate file, so we can stub fetchConfig and activate in tests.
1327
- // It's not possible to stub standalone functions from the same module.
1328
- /**
1329
- *
1330
- * Performs fetch and activate operations, as a convenience.
1331
- *
1332
- * @param remoteConfig - The {@link RemoteConfig} instance.
1333
- *
1334
- * @returns A `Promise` which resolves to true if the current call activated the fetched configs.
1335
- * If the fetched configs were already activated, the `Promise` will resolve to false.
1336
- *
1337
- * @public
1338
- */
1339
- function fetchAndActivate(remoteConfig) {
1340
- return __awaiter(this, void 0, void 0, function () {
1341
- return __generator(this, function (_a) {
1342
- switch (_a.label) {
1343
- case 0:
1344
- remoteConfig = getModularInstance(remoteConfig);
1345
- return [4 /*yield*/, fetchConfig(remoteConfig)];
1346
- case 1:
1347
- _a.sent();
1348
- return [2 /*return*/, activate(remoteConfig)];
1349
- }
1350
- });
1351
- });
1352
- }
1353
- /**
1354
- * This method provides two different checks:
1355
- *
1356
- * 1. Check if IndexedDB exists in the browser environment.
1357
- * 2. Check if the current browser context allows IndexedDB `open()` calls.
1358
- *
1359
- * @returns A `Promise` which resolves to true if a {@link RemoteConfig} instance
1360
- * can be initialized in this environment, or false if it cannot.
1361
- * @public
1362
- */
1363
- function isSupported() {
1364
- return __awaiter(this, void 0, void 0, function () {
1365
- var isDBOpenable;
1366
- return __generator(this, function (_a) {
1367
- switch (_a.label) {
1368
- case 0:
1369
- if (!isIndexedDBAvailable()) {
1370
- return [2 /*return*/, false];
1371
- }
1372
- _a.label = 1;
1373
- case 1:
1374
- _a.trys.push([1, 3, , 4]);
1375
- return [4 /*yield*/, validateIndexedDBOpenable()];
1376
- case 2:
1377
- isDBOpenable = _a.sent();
1378
- return [2 /*return*/, isDBOpenable];
1379
- case 3:
1380
- _a.sent();
1381
- return [2 /*return*/, false];
1382
- case 4: return [2 /*return*/];
1383
- }
1384
- });
1385
- });
1386
- }
1387
-
1388
- /**
1389
- * The Firebase Remote Config Web SDK.
1390
- * This SDK does not work in a Node.js environment.
1391
- *
1392
- * @packageDocumentation
1393
- */
1394
- /** register component and version */
1395
- registerRemoteConfig();
1396
-
1397
- export { activate, ensureInitialized, fetchAndActivate, fetchConfig, getAll, getBoolean, getNumber, getRemoteConfig, getString, getValue, isSupported, setLogLevel };
1398
- //# sourceMappingURL=index.esm.js.map