@firebase/remote-config 0.8.4 → 0.8.5-20260615181107

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.
@@ -94,6 +94,9 @@ export declare class RealtimeHandler {
94
94
  * A key is considered changed if it's new, removed, or has a different value.
95
95
  */
96
96
  private getChangedParams;
97
+ private areExperimentsEqual;
98
+ /** Creates a map where the key is the config key and the value is the experiment description. */
99
+ private createExperimentsMap;
97
100
  private fetchLatestConfig;
98
101
  private autoFetch;
99
102
  /**
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.8.4";
12
+ const version = "0.8.5-20260615181107";
13
13
 
14
14
  /**
15
15
  * @license
@@ -1550,6 +1550,7 @@ const NO_FAILED_REALTIME_STREAMS = 0;
1550
1550
  const REALTIME_DISABLED_KEY = 'featureDisabled';
1551
1551
  const REALTIME_RETRY_INTERVAL = 'retryIntervalSeconds';
1552
1552
  const TEMPLATE_VERSION_KEY = 'latestTemplateVersionNumber';
1553
+ const ROLLOUT_ID_PREFIX = '_exp_rollout';
1553
1554
  class RealtimeHandler {
1554
1555
  constructor(firebaseInstallations, storage, sdkVersion, namespace, projectId, apiKey, appId, logger, storageCache, cachingClient) {
1555
1556
  this.firebaseInstallations = firebaseInstallations;
@@ -1767,14 +1768,29 @@ class RealtimeHandler {
1767
1768
  * Compares two configuration objects and returns a set of keys that have changed.
1768
1769
  * A key is considered changed if it's new, removed, or has a different value.
1769
1770
  */
1770
- getChangedParams(newConfig, oldConfig) {
1771
+ getChangedParams(newConfig, oldConfig, newFetchResponse, oldFetchResponse) {
1771
1772
  const changedKeys = new Set();
1772
1773
  const newKeys = new Set(Object.keys(newConfig || {}));
1773
1774
  const oldKeys = new Set(Object.keys(oldConfig || {}));
1775
+ const newExperiments = newFetchResponse.experiments || [];
1776
+ const oldExperiments = oldFetchResponse?.experiments || [];
1777
+ const newExperimentsMap = this.createExperimentsMap(newExperiments);
1778
+ const oldExperimentsMap = this.createExperimentsMap(oldExperiments);
1774
1779
  for (const key of newKeys) {
1775
1780
  if (!oldKeys.has(key) || newConfig[key] !== oldConfig[key]) {
1776
1781
  changedKeys.add(key);
1777
1782
  }
1783
+ if (newExperimentsMap.has(key) !== oldExperimentsMap.has(key)) {
1784
+ changedKeys.add(key);
1785
+ continue;
1786
+ }
1787
+ const newExperiment = newExperimentsMap.get(key);
1788
+ const oldExperiment = oldExperimentsMap.get(key);
1789
+ if (newExperiment &&
1790
+ oldExperiment &&
1791
+ !this.areExperimentsEqual(newExperiment, oldExperiment)) {
1792
+ changedKeys.add(key);
1793
+ }
1778
1794
  }
1779
1795
  for (const key of oldKeys) {
1780
1796
  if (!newKeys.has(key)) {
@@ -1783,6 +1799,26 @@ class RealtimeHandler {
1783
1799
  }
1784
1800
  return changedKeys;
1785
1801
  }
1802
+ areExperimentsEqual(newExperiment, oldExperiment) {
1803
+ return (newExperiment.experimentId === oldExperiment.experimentId &&
1804
+ newExperiment.variantId === oldExperiment.variantId &&
1805
+ newExperiment.timeToLiveMillis === oldExperiment.timeToLiveMillis &&
1806
+ newExperiment.triggerTimeoutMillis === oldExperiment.triggerTimeoutMillis);
1807
+ }
1808
+ /** Creates a map where the key is the config key and the value is the experiment description. */
1809
+ createExperimentsMap(experimentDescriptions) {
1810
+ const experimentsMap = new Map();
1811
+ for (const experimentDescription of experimentDescriptions) {
1812
+ if (!experimentDescription.affectedParameterKeys ||
1813
+ experimentDescription.experimentId.startsWith(ROLLOUT_ID_PREFIX)) {
1814
+ continue;
1815
+ }
1816
+ for (const key of experimentDescription.affectedParameterKeys) {
1817
+ experimentsMap.set(key, experimentDescription);
1818
+ }
1819
+ }
1820
+ return experimentsMap;
1821
+ }
1786
1822
  async fetchLatestConfig(remainingAttempts, targetVersion) {
1787
1823
  const remainingAttemptsAfterFetch = remainingAttempts - 1;
1788
1824
  const currentAttempt = MAXIMUM_FETCH_ATTEMPTS - remainingAttemptsAfterFetch;
@@ -1799,6 +1835,7 @@ class RealtimeHandler {
1799
1835
  fetchType: 'REALTIME',
1800
1836
  fetchAttempt: currentAttempt
1801
1837
  };
1838
+ const lastFetchResponse = await this.storage.getLastSuccessfulFetchResponse();
1802
1839
  const fetchResponse = await this.cachingClient.fetch(fetchRequest);
1803
1840
  let activatedConfigs = await this.storage.getActiveConfig();
1804
1841
  if (!this.fetchResponseIsUpToDate(fetchResponse, targetVersion)) {
@@ -1815,7 +1852,7 @@ class RealtimeHandler {
1815
1852
  if (activatedConfigs == null) {
1816
1853
  activatedConfigs = {};
1817
1854
  }
1818
- const updatedKeys = this.getChangedParams(fetchResponse.config, activatedConfigs);
1855
+ const updatedKeys = this.getChangedParams(fetchResponse.config, activatedConfigs, fetchResponse, lastFetchResponse);
1819
1856
  if (updatedKeys.size === 0) {
1820
1857
  this.logger.debug('Config was fetched, but no params changed.');
1821
1858
  return;