@firebase/remote-config 0.8.4 → 0.8.5-20260616165109

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.
@@ -5,7 +5,7 @@ import { LogLevel, Logger } from '@firebase/logger';
5
5
  import '@firebase/installations';
6
6
 
7
7
  const name = "@firebase/remote-config";
8
- const version = "0.8.4";
8
+ const version = "0.8.5-20260616165109";
9
9
 
10
10
  /**
11
11
  * @license
@@ -1546,6 +1546,7 @@ const NO_FAILED_REALTIME_STREAMS = 0;
1546
1546
  const REALTIME_DISABLED_KEY = 'featureDisabled';
1547
1547
  const REALTIME_RETRY_INTERVAL = 'retryIntervalSeconds';
1548
1548
  const TEMPLATE_VERSION_KEY = 'latestTemplateVersionNumber';
1549
+ const ROLLOUT_ID_PREFIX = '_exp_rollout';
1549
1550
  class RealtimeHandler {
1550
1551
  constructor(firebaseInstallations, storage, sdkVersion, namespace, projectId, apiKey, appId, logger, storageCache, cachingClient) {
1551
1552
  this.firebaseInstallations = firebaseInstallations;
@@ -1763,14 +1764,29 @@ class RealtimeHandler {
1763
1764
  * Compares two configuration objects and returns a set of keys that have changed.
1764
1765
  * A key is considered changed if it's new, removed, or has a different value.
1765
1766
  */
1766
- getChangedParams(newConfig, oldConfig) {
1767
+ getChangedParams(newConfig, oldConfig, newFetchResponse, oldFetchResponse) {
1767
1768
  const changedKeys = new Set();
1768
1769
  const newKeys = new Set(Object.keys(newConfig || {}));
1769
1770
  const oldKeys = new Set(Object.keys(oldConfig || {}));
1771
+ const newExperiments = newFetchResponse.experiments || [];
1772
+ const oldExperiments = oldFetchResponse?.experiments || [];
1773
+ const newExperimentsMap = this.createExperimentsMap(newExperiments);
1774
+ const oldExperimentsMap = this.createExperimentsMap(oldExperiments);
1770
1775
  for (const key of newKeys) {
1771
1776
  if (!oldKeys.has(key) || newConfig[key] !== oldConfig[key]) {
1772
1777
  changedKeys.add(key);
1773
1778
  }
1779
+ if (newExperimentsMap.has(key) !== oldExperimentsMap.has(key)) {
1780
+ changedKeys.add(key);
1781
+ continue;
1782
+ }
1783
+ const newExperiment = newExperimentsMap.get(key);
1784
+ const oldExperiment = oldExperimentsMap.get(key);
1785
+ if (newExperiment &&
1786
+ oldExperiment &&
1787
+ !this.areExperimentsEqual(newExperiment, oldExperiment)) {
1788
+ changedKeys.add(key);
1789
+ }
1774
1790
  }
1775
1791
  for (const key of oldKeys) {
1776
1792
  if (!newKeys.has(key)) {
@@ -1779,6 +1795,26 @@ class RealtimeHandler {
1779
1795
  }
1780
1796
  return changedKeys;
1781
1797
  }
1798
+ areExperimentsEqual(newExperiment, oldExperiment) {
1799
+ return (newExperiment.experimentId === oldExperiment.experimentId &&
1800
+ newExperiment.variantId === oldExperiment.variantId &&
1801
+ newExperiment.timeToLiveMillis === oldExperiment.timeToLiveMillis &&
1802
+ newExperiment.triggerTimeoutMillis === oldExperiment.triggerTimeoutMillis);
1803
+ }
1804
+ /** Creates a map where the key is the config key and the value is the experiment description. */
1805
+ createExperimentsMap(experimentDescriptions) {
1806
+ const experimentsMap = new Map();
1807
+ for (const experimentDescription of experimentDescriptions) {
1808
+ if (!experimentDescription.affectedParameterKeys ||
1809
+ experimentDescription.experimentId.startsWith(ROLLOUT_ID_PREFIX)) {
1810
+ continue;
1811
+ }
1812
+ for (const key of experimentDescription.affectedParameterKeys) {
1813
+ experimentsMap.set(key, experimentDescription);
1814
+ }
1815
+ }
1816
+ return experimentsMap;
1817
+ }
1782
1818
  async fetchLatestConfig(remainingAttempts, targetVersion) {
1783
1819
  const remainingAttemptsAfterFetch = remainingAttempts - 1;
1784
1820
  const currentAttempt = MAXIMUM_FETCH_ATTEMPTS - remainingAttemptsAfterFetch;
@@ -1795,6 +1831,7 @@ class RealtimeHandler {
1795
1831
  fetchType: 'REALTIME',
1796
1832
  fetchAttempt: currentAttempt
1797
1833
  };
1834
+ const lastFetchResponse = await this.storage.getLastSuccessfulFetchResponse();
1798
1835
  const fetchResponse = await this.cachingClient.fetch(fetchRequest);
1799
1836
  let activatedConfigs = await this.storage.getActiveConfig();
1800
1837
  if (!this.fetchResponseIsUpToDate(fetchResponse, targetVersion)) {
@@ -1811,7 +1848,7 @@ class RealtimeHandler {
1811
1848
  if (activatedConfigs == null) {
1812
1849
  activatedConfigs = {};
1813
1850
  }
1814
- const updatedKeys = this.getChangedParams(fetchResponse.config, activatedConfigs);
1851
+ const updatedKeys = this.getChangedParams(fetchResponse.config, activatedConfigs, fetchResponse, lastFetchResponse);
1815
1852
  if (updatedKeys.size === 0) {
1816
1853
  this.logger.debug('Config was fetched, but no params changed.');
1817
1854
  return;