@firebase/remote-config 0.5.0 → 0.6.0-20250226000544

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 (45) hide show
  1. package/dist/esm/index.esm2017.js +96 -45
  2. package/dist/esm/index.esm2017.js.map +1 -1
  3. package/dist/esm/src/api.d.ts +4 -2
  4. package/dist/esm/src/client/caching_client.d.ts +2 -1
  5. package/dist/esm/src/client/remote_config_fetch_client.d.ts +1 -38
  6. package/dist/esm/src/client/rest_client.d.ts +2 -1
  7. package/dist/esm/src/client/retrying_client.d.ts +2 -1
  8. package/dist/esm/src/errors.d.ts +1 -0
  9. package/dist/esm/src/public_types.d.ts +52 -0
  10. package/dist/esm/src/remote_config.d.ts +1 -1
  11. package/dist/esm/src/storage/storage.d.ts +25 -12
  12. package/dist/esm/src/storage/storage_cache.d.ts +1 -1
  13. package/dist/index.cjs.js +95 -44
  14. package/dist/index.cjs.js.map +1 -1
  15. package/dist/remote-config-public.d.ts +58 -1
  16. package/dist/remote-config.d.ts +58 -1
  17. package/dist/src/api.d.ts +4 -2
  18. package/dist/src/client/caching_client.d.ts +2 -1
  19. package/dist/src/client/remote_config_fetch_client.d.ts +1 -38
  20. package/dist/src/client/rest_client.d.ts +2 -1
  21. package/dist/src/client/retrying_client.d.ts +2 -1
  22. package/dist/src/errors.d.ts +1 -0
  23. package/dist/src/public_types.d.ts +52 -0
  24. package/dist/src/remote_config.d.ts +1 -1
  25. package/dist/src/storage/storage.d.ts +25 -12
  26. package/dist/src/storage/storage_cache.d.ts +1 -1
  27. package/package.json +4 -4
  28. package/dist/esm/test/client/caching_client.test.d.ts +0 -17
  29. package/dist/esm/test/client/rest_client.test.d.ts +0 -17
  30. package/dist/esm/test/client/retrying_client.test.d.ts +0 -17
  31. package/dist/esm/test/errors.test.d.ts +0 -17
  32. package/dist/esm/test/language.test.d.ts +0 -17
  33. package/dist/esm/test/remote_config.test.d.ts +0 -17
  34. package/dist/esm/test/storage/storage.test.d.ts +0 -17
  35. package/dist/esm/test/storage/storage_cache.test.d.ts +0 -17
  36. package/dist/esm/test/value.test.d.ts +0 -17
  37. package/dist/test/client/caching_client.test.d.ts +0 -17
  38. package/dist/test/client/rest_client.test.d.ts +0 -17
  39. package/dist/test/client/retrying_client.test.d.ts +0 -17
  40. package/dist/test/errors.test.d.ts +0 -17
  41. package/dist/test/language.test.d.ts +0 -17
  42. package/dist/test/remote_config.test.d.ts +0 -17
  43. package/dist/test/storage/storage.test.d.ts +0 -17
  44. package/dist/test/storage/storage_cache.test.d.ts +0 -17
  45. package/dist/test/value.test.d.ts +0 -17
@@ -1,11 +1,11 @@
1
1
  import { _getProvider, getApp, _registerComponent, registerVersion, SDK_VERSION } from '@firebase/app';
2
- import { ErrorFactory, FirebaseError, getModularInstance, calculateBackoffMillis, isIndexedDBAvailable, validateIndexedDBOpenable } from '@firebase/util';
2
+ import { ErrorFactory, FirebaseError, getModularInstance, deepEqual, calculateBackoffMillis, isIndexedDBAvailable, validateIndexedDBOpenable } from '@firebase/util';
3
3
  import { Component } from '@firebase/component';
4
4
  import { LogLevel, Logger } from '@firebase/logger';
5
5
  import '@firebase/installations';
6
6
 
7
7
  const name = "@firebase/remote-config";
8
- const version = "0.5.0";
8
+ const version = "0.6.0-20250226000544";
9
9
 
10
10
  /**
11
11
  * @license
@@ -81,6 +81,7 @@ const RC_CUSTOM_SIGNAL_VALUE_MAX_LENGTH = 500;
81
81
  * limitations under the License.
82
82
  */
83
83
  const ERROR_DESCRIPTION_MAP = {
84
+ ["already-initialized" /* ErrorCode.ALREADY_INITIALIZED */]: 'Remote Config already initialized',
84
85
  ["registration-window" /* ErrorCode.REGISTRATION_WINDOW */]: 'Undefined window object. This SDK only supports usage in a browser environment.',
85
86
  ["registration-project-id" /* ErrorCode.REGISTRATION_PROJECT_ID */]: 'Undefined project identifier. Check Firebase app initialization.',
86
87
  ["registration-api-key" /* ErrorCode.REGISTRATION_API_KEY */]: 'Undefined API key. Check Firebase app initialization.',
@@ -176,14 +177,40 @@ class Value {
176
177
  /**
177
178
  *
178
179
  * @param app - The {@link @firebase/app#FirebaseApp} instance.
180
+ * @param options - Optional. The {@link RemoteConfigOptions} with which to instantiate the
181
+ * Remote Config instance.
179
182
  * @returns A {@link RemoteConfig} instance.
180
183
  *
181
184
  * @public
182
185
  */
183
- function getRemoteConfig(app = getApp()) {
186
+ function getRemoteConfig(app = getApp(), options = {}) {
187
+ var _a, _b;
184
188
  app = getModularInstance(app);
185
189
  const rcProvider = _getProvider(app, RC_COMPONENT_NAME);
186
- return rcProvider.getImmediate();
190
+ if (rcProvider.isInitialized()) {
191
+ const initialOptions = rcProvider.getOptions();
192
+ if (deepEqual(initialOptions, options)) {
193
+ return rcProvider.getImmediate();
194
+ }
195
+ throw ERROR_FACTORY.create("already-initialized" /* ErrorCode.ALREADY_INITIALIZED */);
196
+ }
197
+ rcProvider.initialize({ options });
198
+ const rc = rcProvider.getImmediate();
199
+ if (options.initialFetchResponse) {
200
+ // We use these initial writes as the initialization promise since they will hydrate the same
201
+ // fields that `storageCache.loadFromStorage` would set.
202
+ rc._initializePromise = Promise.all([
203
+ rc._storage.setLastSuccessfulFetchResponse(options.initialFetchResponse),
204
+ rc._storage.setActiveConfigEtag(((_a = options.initialFetchResponse) === null || _a === void 0 ? void 0 : _a.eTag) || ''),
205
+ rc._storageCache.setLastSuccessfulFetchTimestampMillis(Date.now()),
206
+ rc._storageCache.setLastFetchStatus('success'),
207
+ rc._storageCache.setActiveConfig(((_b = options.initialFetchResponse) === null || _b === void 0 ? void 0 : _b.config) || {})
208
+ ]).then();
209
+ // The `storageCache` methods above set their in-memory fields synchronously, so it's
210
+ // safe to declare our initialization complete at this point.
211
+ rc._isInitializationComplete = true;
212
+ }
213
+ return rc;
187
214
  }
188
215
  /**
189
216
  * Makes the last fetched config available to the getters.
@@ -805,7 +832,7 @@ const DEFAULT_CACHE_MAX_AGE_MILLIS = 12 * 60 * 60 * 1000; // Twelve hours.
805
832
  /**
806
833
  * Encapsulates business logic mapping network and storage dependencies to the public SDK API.
807
834
  *
808
- * See {@link https://github.com/firebase/firebase-js-sdk/blob/main/packages/firebase/index.d.ts|interface documentation} for method descriptions.
835
+ * See {@link https://github.com/firebase/firebase-js-sdk/blob/main/packages/firebase/compat/index.d.ts|interface documentation} for method descriptions.
809
836
  */
810
837
  class RemoteConfig {
811
838
  get fetchTimeMillis() {
@@ -929,17 +956,6 @@ function openDatabase() {
929
956
  * Abstracts data persistence.
930
957
  */
931
958
  class Storage {
932
- /**
933
- * @param appId enables storage segmentation by app (ID + name).
934
- * @param appName enables storage segmentation by app (ID + name).
935
- * @param namespace enables storage segmentation by namespace.
936
- */
937
- constructor(appId, appName, namespace, openDbPromise = openDatabase()) {
938
- this.appId = appId;
939
- this.appName = appName;
940
- this.namespace = namespace;
941
- this.openDbPromise = openDbPromise;
942
- }
943
959
  getLastFetchStatus() {
944
960
  return this.get('last_fetch_status');
945
961
  }
@@ -984,28 +1000,25 @@ class Storage {
984
1000
  getCustomSignals() {
985
1001
  return this.get('custom_signals');
986
1002
  }
1003
+ }
1004
+ class IndexedDbStorage extends Storage {
1005
+ /**
1006
+ * @param appId enables storage segmentation by app (ID + name).
1007
+ * @param appName enables storage segmentation by app (ID + name).
1008
+ * @param namespace enables storage segmentation by namespace.
1009
+ */
1010
+ constructor(appId, appName, namespace, openDbPromise = openDatabase()) {
1011
+ super();
1012
+ this.appId = appId;
1013
+ this.appName = appName;
1014
+ this.namespace = namespace;
1015
+ this.openDbPromise = openDbPromise;
1016
+ }
987
1017
  async setCustomSignals(customSignals) {
988
1018
  const db = await this.openDbPromise;
989
1019
  const transaction = db.transaction([APP_NAMESPACE_STORE], 'readwrite');
990
1020
  const storedSignals = await this.getWithTransaction('custom_signals', transaction);
991
- const combinedSignals = Object.assign(Object.assign({}, storedSignals), customSignals);
992
- // Filter out key-value assignments with null values since they are signals being unset
993
- const updatedSignals = Object.fromEntries(Object.entries(combinedSignals)
994
- .filter(([_, v]) => v !== null)
995
- .map(([k, v]) => {
996
- // Stringify numbers to store a map of string keys and values which can be sent
997
- // as-is in a fetch call.
998
- if (typeof v === 'number') {
999
- return [k, v.toString()];
1000
- }
1001
- return [k, v];
1002
- }));
1003
- // Throw an error if the number of custom signals to be stored exceeds the limit
1004
- if (Object.keys(updatedSignals).length > RC_CUSTOM_SIGNAL_MAX_ALLOWED_SIGNALS) {
1005
- throw ERROR_FACTORY.create("custom-signal-max-allowed-signals" /* ErrorCode.CUSTOM_SIGNAL_MAX_ALLOWED_SIGNALS */, {
1006
- maxSignals: RC_CUSTOM_SIGNAL_MAX_ALLOWED_SIGNALS
1007
- });
1008
- }
1021
+ const updatedSignals = mergeCustomSignals(customSignals, storedSignals || {});
1009
1022
  await this.setWithTransaction('custom_signals', updatedSignals, transaction);
1010
1023
  return updatedSignals;
1011
1024
  }
@@ -1110,6 +1123,50 @@ class Storage {
1110
1123
  return [this.appId, this.appName, this.namespace, key].join();
1111
1124
  }
1112
1125
  }
1126
+ class InMemoryStorage extends Storage {
1127
+ constructor() {
1128
+ super(...arguments);
1129
+ this.storage = {};
1130
+ }
1131
+ async get(key) {
1132
+ return Promise.resolve(this.storage[key]);
1133
+ }
1134
+ async set(key, value) {
1135
+ this.storage[key] = value;
1136
+ return Promise.resolve(undefined);
1137
+ }
1138
+ async delete(key) {
1139
+ this.storage[key] = undefined;
1140
+ return Promise.resolve();
1141
+ }
1142
+ async setCustomSignals(customSignals) {
1143
+ const storedSignals = (this.storage['custom_signals'] ||
1144
+ {});
1145
+ this.storage['custom_signals'] = mergeCustomSignals(customSignals, storedSignals);
1146
+ return Promise.resolve(this.storage['custom_signals']);
1147
+ }
1148
+ }
1149
+ function mergeCustomSignals(customSignals, storedSignals) {
1150
+ const combinedSignals = Object.assign(Object.assign({}, storedSignals), customSignals);
1151
+ // Filter out key-value assignments with null values since they are signals being unset
1152
+ const updatedSignals = Object.fromEntries(Object.entries(combinedSignals)
1153
+ .filter(([_, v]) => v !== null)
1154
+ .map(([k, v]) => {
1155
+ // Stringify numbers to store a map of string keys and values which can be sent
1156
+ // as-is in a fetch call.
1157
+ if (typeof v === 'number') {
1158
+ return [k, v.toString()];
1159
+ }
1160
+ return [k, v];
1161
+ }));
1162
+ // Throw an error if the number of custom signals to be stored exceeds the limit
1163
+ if (Object.keys(updatedSignals).length > RC_CUSTOM_SIGNAL_MAX_ALLOWED_SIGNALS) {
1164
+ throw ERROR_FACTORY.create("custom-signal-max-allowed-signals" /* ErrorCode.CUSTOM_SIGNAL_MAX_ALLOWED_SIGNALS */, {
1165
+ maxSignals: RC_CUSTOM_SIGNAL_MAX_ALLOWED_SIGNALS
1166
+ });
1167
+ }
1168
+ return updatedSignals;
1169
+ }
1113
1170
 
1114
1171
  /**
1115
1172
  * @license
@@ -1221,7 +1278,7 @@ function registerRemoteConfig() {
1221
1278
  registerVersion(name, version);
1222
1279
  // BUILD_TARGET will be replaced by values like esm2017, cjs2017, etc during the compilation
1223
1280
  registerVersion(name, version, 'esm2017');
1224
- function remoteConfigFactory(container, { instanceIdentifier: namespace }) {
1281
+ function remoteConfigFactory(container, { options }) {
1225
1282
  /* Dependencies */
1226
1283
  // getImmediate for FirebaseApp will always succeed
1227
1284
  const app = container.getProvider('app').getImmediate();
@@ -1229,14 +1286,6 @@ function registerRemoteConfig() {
1229
1286
  const installations = container
1230
1287
  .getProvider('installations-internal')
1231
1288
  .getImmediate();
1232
- // Guards against the SDK being used in non-browser environments.
1233
- if (typeof window === 'undefined') {
1234
- throw ERROR_FACTORY.create("registration-window" /* ErrorCode.REGISTRATION_WINDOW */);
1235
- }
1236
- // Guards against the SDK being used when indexedDB is not available.
1237
- if (!isIndexedDBAvailable()) {
1238
- throw ERROR_FACTORY.create("indexed-db-unavailable" /* ErrorCode.INDEXED_DB_UNAVAILABLE */);
1239
- }
1240
1289
  // Normalizes optional inputs.
1241
1290
  const { projectId, apiKey, appId } = app.options;
1242
1291
  if (!projectId) {
@@ -1248,8 +1297,10 @@ function registerRemoteConfig() {
1248
1297
  if (!appId) {
1249
1298
  throw ERROR_FACTORY.create("registration-app-id" /* ErrorCode.REGISTRATION_APP_ID */);
1250
1299
  }
1251
- namespace = namespace || 'firebase';
1252
- const storage = new Storage(appId, app.name, namespace);
1300
+ const namespace = (options === null || options === void 0 ? void 0 : options.templateId) || 'firebase';
1301
+ const storage = isIndexedDBAvailable()
1302
+ ? new IndexedDbStorage(appId, app.name, namespace)
1303
+ : new InMemoryStorage();
1253
1304
  const storageCache = new StorageCache(storage);
1254
1305
  const logger = new Logger(name);
1255
1306
  // Sets ERROR as the default log level.