@firebase/remote-config 0.7.0-canary.f06cbf99b → 0.7.0-canary.f5fc6bf76
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.
- package/dist/esm/index.esm.js +6 -85
- package/dist/esm/index.esm.js.map +1 -1
- package/dist/esm/src/errors.d.ts +1 -5
- package/dist/esm/src/public_types.d.ts +0 -19
- package/dist/esm/src/remote_config.d.ts +1 -11
- package/dist/esm/src/storage/storage.d.ts +1 -3
- package/dist/index.cjs.js +6 -85
- package/dist/index.cjs.js.map +1 -1
- package/dist/remote-config-public.d.ts +0 -20
- package/dist/remote-config.d.ts +0 -20
- package/dist/src/errors.d.ts +1 -5
- package/dist/src/global_index.d.ts +1 -20
- package/dist/src/public_types.d.ts +0 -19
- package/dist/src/remote_config.d.ts +1 -11
- package/dist/src/storage/storage.d.ts +1 -3
- package/package.json +7 -7
- package/dist/esm/src/abt/experiment.d.ts +0 -13
- package/dist/src/abt/experiment.d.ts +0 -13
package/dist/esm/src/errors.d.ts
CHANGED
|
@@ -35,8 +35,7 @@ export declare const enum ErrorCode {
|
|
|
35
35
|
CONFIG_UPDATE_STREAM_ERROR = "stream-error",
|
|
36
36
|
CONFIG_UPDATE_UNAVAILABLE = "realtime-unavailable",
|
|
37
37
|
CONFIG_UPDATE_MESSAGE_INVALID = "update-message-invalid",
|
|
38
|
-
CONFIG_UPDATE_NOT_FETCHED = "update-not-fetched"
|
|
39
|
-
ANALYTICS_UNAVAILABLE = "analytics-unavailable"
|
|
38
|
+
CONFIG_UPDATE_NOT_FETCHED = "update-not-fetched"
|
|
40
39
|
}
|
|
41
40
|
interface ErrorParams {
|
|
42
41
|
[ErrorCode.STORAGE_OPEN]: {
|
|
@@ -78,9 +77,6 @@ interface ErrorParams {
|
|
|
78
77
|
[ErrorCode.CONFIG_UPDATE_NOT_FETCHED]: {
|
|
79
78
|
originalErrorMessage: string;
|
|
80
79
|
};
|
|
81
|
-
[ErrorCode.ANALYTICS_UNAVAILABLE]: {
|
|
82
|
-
originalErrorMessage: string;
|
|
83
|
-
};
|
|
84
80
|
}
|
|
85
81
|
export declare const ERROR_FACTORY: ErrorFactory<ErrorCode, ErrorParams>;
|
|
86
82
|
export declare function hasErrorCode(e: Error, errorCode: ErrorCode): boolean;
|
|
@@ -54,19 +54,6 @@ export interface RemoteConfig {
|
|
|
54
54
|
export interface FirebaseRemoteConfigObject {
|
|
55
55
|
[key: string]: string;
|
|
56
56
|
}
|
|
57
|
-
/**
|
|
58
|
-
* Defines experiment and variant attached to a config parameter.
|
|
59
|
-
*
|
|
60
|
-
* @public
|
|
61
|
-
*/
|
|
62
|
-
export interface FirebaseExperimentDescription {
|
|
63
|
-
experimentId: string;
|
|
64
|
-
variantId: string;
|
|
65
|
-
experimentStartTime: string;
|
|
66
|
-
triggerTimeoutMillis: string;
|
|
67
|
-
timeToLiveMillis: string;
|
|
68
|
-
affectedParameterKeys?: string[];
|
|
69
|
-
}
|
|
70
57
|
/**
|
|
71
58
|
* Defines a successful response (200 or 304).
|
|
72
59
|
*
|
|
@@ -103,12 +90,6 @@ export interface FetchResponse {
|
|
|
103
90
|
* The version number of the config template fetched from the server.
|
|
104
91
|
*/
|
|
105
92
|
templateVersion?: number;
|
|
106
|
-
/**
|
|
107
|
-
* Metadata for A/B testing and Remote Config Rollout experiments.
|
|
108
|
-
*
|
|
109
|
-
* @remarks Only defined for 200 responses.
|
|
110
|
-
*/
|
|
111
|
-
experiments?: FirebaseExperimentDescription[];
|
|
112
93
|
}
|
|
113
94
|
/**
|
|
114
95
|
* Options for Remote Config initialization.
|
|
@@ -20,8 +20,6 @@ import { StorageCache } from './storage/storage_cache';
|
|
|
20
20
|
import { RemoteConfigFetchClient } from './client/remote_config_fetch_client';
|
|
21
21
|
import { Storage } from './storage/storage';
|
|
22
22
|
import { Logger } from '@firebase/logger';
|
|
23
|
-
import { FirebaseAnalyticsInternalName } from '@firebase/analytics-interop-types';
|
|
24
|
-
import { Provider } from '@firebase/component';
|
|
25
23
|
import { RealtimeHandler } from './client/realtime_handler';
|
|
26
24
|
/**
|
|
27
25
|
* Encapsulates business logic mapping network and storage dependencies to the public SDK API.
|
|
@@ -50,10 +48,6 @@ export declare class RemoteConfig implements RemoteConfigType {
|
|
|
50
48
|
* @internal
|
|
51
49
|
*/
|
|
52
50
|
readonly _realtimeHandler: RealtimeHandler;
|
|
53
|
-
/**
|
|
54
|
-
* @internal
|
|
55
|
-
*/
|
|
56
|
-
readonly _analyticsProvider: Provider<FirebaseAnalyticsInternalName>;
|
|
57
51
|
/**
|
|
58
52
|
* Tracks completion of initialization promise.
|
|
59
53
|
* @internal
|
|
@@ -90,9 +84,5 @@ export declare class RemoteConfig implements RemoteConfigType {
|
|
|
90
84
|
/**
|
|
91
85
|
* @internal
|
|
92
86
|
*/
|
|
93
|
-
_realtimeHandler: RealtimeHandler
|
|
94
|
-
/**
|
|
95
|
-
* @internal
|
|
96
|
-
*/
|
|
97
|
-
_analyticsProvider: Provider<FirebaseAnalyticsInternalName>);
|
|
87
|
+
_realtimeHandler: RealtimeHandler);
|
|
98
88
|
}
|
|
@@ -43,7 +43,7 @@ export interface RealtimeBackoffMetadata {
|
|
|
43
43
|
*
|
|
44
44
|
* <p>This seems like a small price to avoid potentially subtle bugs caused by a typo.
|
|
45
45
|
*/
|
|
46
|
-
type ProjectNamespaceKeyFieldValue = 'active_config' | 'active_config_etag' | '
|
|
46
|
+
type ProjectNamespaceKeyFieldValue = 'active_config' | 'active_config_etag' | 'last_fetch_status' | 'last_successful_fetch_timestamp_millis' | 'last_successful_fetch_response' | 'settings' | 'throttle_metadata' | 'custom_signals' | 'realtime_backoff_metadata' | 'last_known_template_version';
|
|
47
47
|
export declare function openDatabase(): Promise<IDBDatabase>;
|
|
48
48
|
/**
|
|
49
49
|
* Abstracts data persistence.
|
|
@@ -59,8 +59,6 @@ export declare abstract class Storage {
|
|
|
59
59
|
setActiveConfig(config: FirebaseRemoteConfigObject): Promise<void>;
|
|
60
60
|
getActiveConfigEtag(): Promise<string | undefined>;
|
|
61
61
|
setActiveConfigEtag(etag: string): Promise<void>;
|
|
62
|
-
getActiveExperiments(): Promise<Set<string> | undefined>;
|
|
63
|
-
setActiveExperiments(experiments: Set<string>): Promise<void>;
|
|
64
62
|
getThrottleMetadata(): Promise<ThrottleMetadata | undefined>;
|
|
65
63
|
setThrottleMetadata(metadata: ThrottleMetadata): Promise<void>;
|
|
66
64
|
deleteThrottleMetadata(): Promise<void>;
|
package/dist/index.cjs.js
CHANGED
|
@@ -9,7 +9,7 @@ var logger = require('@firebase/logger');
|
|
|
9
9
|
require('@firebase/installations');
|
|
10
10
|
|
|
11
11
|
const name = "@firebase/remote-config";
|
|
12
|
-
const version = "0.7.0-canary.
|
|
12
|
+
const version = "0.7.0-canary.f5fc6bf76";
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* @license
|
|
@@ -109,8 +109,7 @@ const ERROR_DESCRIPTION_MAP = {
|
|
|
109
109
|
["stream-error" /* ErrorCode.CONFIG_UPDATE_STREAM_ERROR */]: 'The stream was not able to connect to the backend: {$originalErrorMessage}.',
|
|
110
110
|
["realtime-unavailable" /* ErrorCode.CONFIG_UPDATE_UNAVAILABLE */]: 'The Realtime service is unavailable: {$originalErrorMessage}',
|
|
111
111
|
["update-message-invalid" /* ErrorCode.CONFIG_UPDATE_MESSAGE_INVALID */]: 'The stream invalidation message was unparsable: {$originalErrorMessage}',
|
|
112
|
-
["update-not-fetched" /* ErrorCode.CONFIG_UPDATE_NOT_FETCHED */]: 'Unable to fetch the latest config: {$originalErrorMessage}'
|
|
113
|
-
["analytics-unavailable" /* ErrorCode.ANALYTICS_UNAVAILABLE */]: 'Connection to Firebase Analytics failed: {$originalErrorMessage}'
|
|
112
|
+
["update-not-fetched" /* ErrorCode.CONFIG_UPDATE_NOT_FETCHED */]: 'Unable to fetch the latest config: {$originalErrorMessage}'
|
|
114
113
|
};
|
|
115
114
|
const ERROR_FACTORY = new util.ErrorFactory('remoteconfig' /* service */, 'Remote Config' /* service name */, ERROR_DESCRIPTION_MAP);
|
|
116
115
|
// Note how this is like typeof/instanceof, but for ErrorCode.
|
|
@@ -167,64 +166,6 @@ class Value {
|
|
|
167
166
|
}
|
|
168
167
|
}
|
|
169
168
|
|
|
170
|
-
class Experiment {
|
|
171
|
-
constructor(rc) {
|
|
172
|
-
this.storage = rc._storage;
|
|
173
|
-
this.logger = rc._logger;
|
|
174
|
-
this.analyticsProvider = rc._analyticsProvider;
|
|
175
|
-
}
|
|
176
|
-
async updateActiveExperiments(latestExperiments) {
|
|
177
|
-
const currentActiveExperiments = (await this.storage.getActiveExperiments()) || new Set();
|
|
178
|
-
const experimentInfoMap = this.createExperimentInfoMap(latestExperiments);
|
|
179
|
-
this.addActiveExperiments(experimentInfoMap);
|
|
180
|
-
this.removeInactiveExperiments(currentActiveExperiments, experimentInfoMap);
|
|
181
|
-
return this.storage.setActiveExperiments(new Set(experimentInfoMap.keys()));
|
|
182
|
-
}
|
|
183
|
-
createExperimentInfoMap(latestExperiments) {
|
|
184
|
-
const experimentInfoMap = new Map();
|
|
185
|
-
for (const experiment of latestExperiments) {
|
|
186
|
-
experimentInfoMap.set(experiment.experimentId, experiment);
|
|
187
|
-
}
|
|
188
|
-
return experimentInfoMap;
|
|
189
|
-
}
|
|
190
|
-
addActiveExperiments(experimentInfoMap) {
|
|
191
|
-
const customProperty = {};
|
|
192
|
-
for (const [experimentId, experimentInfo] of experimentInfoMap.entries()) {
|
|
193
|
-
customProperty[`firebase${experimentId}`] = experimentInfo.variantId;
|
|
194
|
-
}
|
|
195
|
-
this.addExperimentToAnalytics(customProperty);
|
|
196
|
-
}
|
|
197
|
-
removeInactiveExperiments(currentActiveExperiments, experimentInfoMap) {
|
|
198
|
-
const customProperty = {};
|
|
199
|
-
for (const experimentId of currentActiveExperiments) {
|
|
200
|
-
if (!experimentInfoMap.has(experimentId)) {
|
|
201
|
-
customProperty[`firebase${experimentId}`] = null;
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
this.addExperimentToAnalytics(customProperty);
|
|
205
|
-
}
|
|
206
|
-
addExperimentToAnalytics(customProperty) {
|
|
207
|
-
if (Object.keys(customProperty).length === 0) {
|
|
208
|
-
return;
|
|
209
|
-
}
|
|
210
|
-
try {
|
|
211
|
-
const analytics = this.analyticsProvider.getImmediate({ optional: true });
|
|
212
|
-
if (analytics) {
|
|
213
|
-
analytics.setUserProperties(customProperty);
|
|
214
|
-
analytics.logEvent(`set_firebase_experiment_state`);
|
|
215
|
-
}
|
|
216
|
-
else {
|
|
217
|
-
this.logger.warn(`Analytics import failed. Verify if you have imported Firebase Analytics in your app code.`);
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
catch (error) {
|
|
221
|
-
throw ERROR_FACTORY.create("analytics-unavailable" /* ErrorCode.ANALYTICS_UNAVAILABLE */, {
|
|
222
|
-
originalErrorMessage: error?.message
|
|
223
|
-
});
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
|
|
228
169
|
/**
|
|
229
170
|
* @license
|
|
230
171
|
* Copyright 2020 Google LLC
|
|
@@ -302,15 +243,10 @@ async function activate(remoteConfig) {
|
|
|
302
243
|
// config.
|
|
303
244
|
return false;
|
|
304
245
|
}
|
|
305
|
-
const experiment = new Experiment(rc);
|
|
306
|
-
const updateActiveExperiments = lastSuccessfulFetchResponse.experiments
|
|
307
|
-
? experiment.updateActiveExperiments(lastSuccessfulFetchResponse.experiments)
|
|
308
|
-
: Promise.resolve();
|
|
309
246
|
await Promise.all([
|
|
310
247
|
rc._storageCache.setActiveConfig(lastSuccessfulFetchResponse.config),
|
|
311
248
|
rc._storage.setActiveConfigEtag(lastSuccessfulFetchResponse.eTag),
|
|
312
|
-
rc._storage.setActiveConfigTemplateVersion(lastSuccessfulFetchResponse.templateVersion)
|
|
313
|
-
updateActiveExperiments
|
|
249
|
+
rc._storage.setActiveConfigTemplateVersion(lastSuccessfulFetchResponse.templateVersion)
|
|
314
250
|
]);
|
|
315
251
|
return true;
|
|
316
252
|
}
|
|
@@ -765,7 +701,6 @@ class RestClient {
|
|
|
765
701
|
let config;
|
|
766
702
|
let state;
|
|
767
703
|
let templateVersion;
|
|
768
|
-
let experiments;
|
|
769
704
|
// JSON parsing throws SyntaxError if the response body isn't a JSON string.
|
|
770
705
|
// Requesting application/json and checking for a 200 ensures there's JSON data.
|
|
771
706
|
if (response.status === 200) {
|
|
@@ -781,7 +716,6 @@ class RestClient {
|
|
|
781
716
|
config = responseBody['entries'];
|
|
782
717
|
state = responseBody['state'];
|
|
783
718
|
templateVersion = responseBody['templateVersion'];
|
|
784
|
-
experiments = responseBody['experimentDescriptions'];
|
|
785
719
|
}
|
|
786
720
|
// Normalizes based on legacy state.
|
|
787
721
|
if (state === 'INSTANCE_STATE_UNSPECIFIED') {
|
|
@@ -793,7 +727,6 @@ class RestClient {
|
|
|
793
727
|
else if (state === 'NO_TEMPLATE' || state === 'EMPTY_CONFIG') {
|
|
794
728
|
// These cases can be fixed remotely, so normalize to safe value.
|
|
795
729
|
config = {};
|
|
796
|
-
experiments = [];
|
|
797
730
|
}
|
|
798
731
|
// Normalize to exception-based control flow for non-success cases.
|
|
799
732
|
// Encapsulates HTTP specifics in this class as much as possible. Status is still the best for
|
|
@@ -804,7 +737,7 @@ class RestClient {
|
|
|
804
737
|
httpStatus: status
|
|
805
738
|
});
|
|
806
739
|
}
|
|
807
|
-
return { status, eTag: responseEtag, config, templateVersion
|
|
740
|
+
return { status, eTag: responseEtag, config, templateVersion };
|
|
808
741
|
}
|
|
809
742
|
}
|
|
810
743
|
|
|
@@ -970,18 +903,13 @@ class RemoteConfig {
|
|
|
970
903
|
/**
|
|
971
904
|
* @internal
|
|
972
905
|
*/
|
|
973
|
-
_realtimeHandler
|
|
974
|
-
/**
|
|
975
|
-
* @internal
|
|
976
|
-
*/
|
|
977
|
-
_analyticsProvider) {
|
|
906
|
+
_realtimeHandler) {
|
|
978
907
|
this.app = app;
|
|
979
908
|
this._client = _client;
|
|
980
909
|
this._storageCache = _storageCache;
|
|
981
910
|
this._storage = _storage;
|
|
982
911
|
this._logger = _logger;
|
|
983
912
|
this._realtimeHandler = _realtimeHandler;
|
|
984
|
-
this._analyticsProvider = _analyticsProvider;
|
|
985
913
|
/**
|
|
986
914
|
* Tracks completion of initialization promise.
|
|
987
915
|
* @internal
|
|
@@ -1102,12 +1030,6 @@ class Storage {
|
|
|
1102
1030
|
setActiveConfigEtag(etag) {
|
|
1103
1031
|
return this.set('active_config_etag', etag);
|
|
1104
1032
|
}
|
|
1105
|
-
getActiveExperiments() {
|
|
1106
|
-
return this.get('active_experiments');
|
|
1107
|
-
}
|
|
1108
|
-
setActiveExperiments(experiments) {
|
|
1109
|
-
return this.set('active_experiments', experiments);
|
|
1110
|
-
}
|
|
1111
1033
|
getThrottleMetadata() {
|
|
1112
1034
|
return this.get('throttle_metadata');
|
|
1113
1035
|
}
|
|
@@ -2098,7 +2020,6 @@ function registerRemoteConfig() {
|
|
|
2098
2020
|
const installations = container
|
|
2099
2021
|
.getProvider('installations-internal')
|
|
2100
2022
|
.getImmediate();
|
|
2101
|
-
const analyticsProvider = container.getProvider('analytics-internal');
|
|
2102
2023
|
// Normalizes optional inputs.
|
|
2103
2024
|
const { projectId, apiKey, appId } = app$1.options;
|
|
2104
2025
|
if (!projectId) {
|
|
@@ -2125,7 +2046,7 @@ function registerRemoteConfig() {
|
|
|
2125
2046
|
const retryingClient = new RetryingClient(restClient, storage);
|
|
2126
2047
|
const cachingClient = new CachingClient(retryingClient, storage, storageCache, logger$1);
|
|
2127
2048
|
const realtimeHandler = new RealtimeHandler(installations, storage, app.SDK_VERSION, namespace, projectId, apiKey, appId, logger$1, storageCache, cachingClient);
|
|
2128
|
-
const remoteConfigInstance = new RemoteConfig(app$1, cachingClient, storageCache, storage, logger$1, realtimeHandler
|
|
2049
|
+
const remoteConfigInstance = new RemoteConfig(app$1, cachingClient, storageCache, storage, logger$1, realtimeHandler);
|
|
2129
2050
|
// Starts warming cache.
|
|
2130
2051
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
2131
2052
|
ensureInitialized(remoteConfigInstance);
|