mixpanel-browser 2.77.0 → 2.78.0

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 (41) hide show
  1. package/.claude/settings.local.json +3 -1
  2. package/CHANGELOG.md +4 -0
  3. package/dist/async-modules/{mixpanel-recorder-wIWnMDLA.min.js → mixpanel-recorder-BjSlYaNJ.min.js} +2 -2
  4. package/dist/async-modules/{mixpanel-recorder-wIWnMDLA.min.js.map → mixpanel-recorder-BjSlYaNJ.min.js.map} +1 -1
  5. package/dist/async-modules/{mixpanel-recorder-DLKbUIEE.js → mixpanel-recorder-zMBXIyeG.js} +1 -1
  6. package/dist/async-modules/{mixpanel-targeting-CTcftSJC.min.js → mixpanel-targeting-BSHal4N9.min.js} +2 -2
  7. package/dist/async-modules/{mixpanel-targeting-CTcftSJC.min.js.map → mixpanel-targeting-BSHal4N9.min.js.map} +1 -1
  8. package/dist/async-modules/{mixpanel-targeting-CmVvUyFM.js → mixpanel-targeting-UHf4eBfC.js} +1 -1
  9. package/dist/mixpanel-core.cjs.d.ts +1 -0
  10. package/dist/mixpanel-core.cjs.js +111 -80
  11. package/dist/mixpanel-recorder.js +1 -1
  12. package/dist/mixpanel-recorder.min.js +1 -1
  13. package/dist/mixpanel-recorder.min.js.map +1 -1
  14. package/dist/mixpanel-targeting.js +1 -1
  15. package/dist/mixpanel-targeting.min.js +1 -1
  16. package/dist/mixpanel-targeting.min.js.map +1 -1
  17. package/dist/mixpanel-with-async-modules.cjs.d.ts +1 -0
  18. package/dist/mixpanel-with-async-modules.cjs.js +113 -82
  19. package/dist/mixpanel-with-async-recorder.cjs.d.ts +1 -0
  20. package/dist/mixpanel-with-async-recorder.cjs.js +113 -82
  21. package/dist/mixpanel-with-recorder.d.ts +1 -0
  22. package/dist/mixpanel-with-recorder.js +111 -80
  23. package/dist/mixpanel-with-recorder.min.d.ts +1 -0
  24. package/dist/mixpanel-with-recorder.min.js +1 -1
  25. package/dist/mixpanel.amd.d.ts +1 -0
  26. package/dist/mixpanel.amd.js +111 -80
  27. package/dist/mixpanel.cjs.d.ts +1 -0
  28. package/dist/mixpanel.cjs.js +111 -80
  29. package/dist/mixpanel.globals.js +113 -82
  30. package/dist/mixpanel.min.js +180 -179
  31. package/dist/mixpanel.module.d.ts +1 -0
  32. package/dist/mixpanel.module.js +111 -80
  33. package/dist/mixpanel.umd.d.ts +1 -0
  34. package/dist/mixpanel.umd.js +111 -80
  35. package/package.json +1 -1
  36. package/src/config.js +1 -1
  37. package/src/flags/CLAUDE.md +24 -0
  38. package/src/flags/index.js +109 -80
  39. package/src/index.d.ts +1 -0
  40. package/src/mixpanel-core.js +3 -1
  41. package/testServer.js +2 -0
@@ -28,7 +28,7 @@
28
28
 
29
29
  var Config = {
30
30
  DEBUG: false,
31
- LIB_VERSION: '2.77.0'
31
+ LIB_VERSION: '2.78.0'
32
32
  };
33
33
 
34
34
  // Window global names for async modules
@@ -25663,7 +25663,9 @@
25663
25663
  }
25664
25664
 
25665
25665
  this.flags = null;
25666
- this.fetchFlags();
25666
+ this.fetchFlags().catch(function() {
25667
+ logger$1.error('Error fetching flags during init');
25668
+ });
25667
25669
 
25668
25670
  this.trackedFeatures = new Set();
25669
25671
  this.pendingFirstTimeEvents = {};
@@ -25704,8 +25706,12 @@
25704
25706
  var oldContext = (options && options['replace']) ? {} : this.getConfig(CONFIG_CONTEXT);
25705
25707
  ffConfig[CONFIG_CONTEXT] = _.extend({}, oldContext, newContext);
25706
25708
 
25707
- this.setMpConfig(FLAGS_CONFIG_KEY, ffConfig);
25708
- return this.fetchFlags();
25709
+ var configUpdate = {};
25710
+ configUpdate[FLAGS_CONFIG_KEY] = ffConfig;
25711
+ this.setMpConfig(configUpdate);
25712
+ return this.fetchFlags().catch(function() {
25713
+ logger$1.error('Error fetching flags during updateContext');
25714
+ });
25709
25715
  };
25710
25716
 
25711
25717
  FeatureFlagManager.prototype.areFlagsReady = function() {
@@ -25742,96 +25748,110 @@
25742
25748
  }
25743
25749
  }).then(function(response) {
25744
25750
  this.markFetchComplete();
25745
- return response.json().then(function(responseBody) {
25746
- var responseFlags = responseBody['flags'];
25747
- if (!responseFlags) {
25748
- throw new Error('No flags in API response');
25749
- }
25750
- var flags = new Map();
25751
- var pendingFirstTimeEvents = {};
25752
-
25753
- // Process flags from response
25754
- _.each(responseFlags, function(data, key) {
25755
- // Check if this flag has any activated first-time events this session
25756
- var hasActivatedEvent = false;
25757
- var prefix = key + ':';
25758
- _.each(this.activatedFirstTimeEvents, function(activated, eventKey) {
25759
- if (eventKey.startsWith(prefix)) {
25760
- hasActivatedEvent = true;
25761
- }
25762
- });
25751
+ return response.json();
25752
+ }.bind(this)).then(function(responseBody) {
25753
+ var responseFlags = responseBody['flags'];
25754
+ if (!responseFlags) {
25755
+ throw new Error('No flags in API response');
25756
+ }
25757
+ var flags = new Map();
25758
+ var pendingFirstTimeEvents = {};
25759
+
25760
+ // Process flags from response
25761
+ _.each(responseFlags, function(data, key) {
25762
+ // Check if this flag has any activated first-time events this session
25763
+ var hasActivatedEvent = false;
25764
+ var prefix = key + ':';
25765
+ _.each(this.activatedFirstTimeEvents, function(activated, eventKey) {
25766
+ if (eventKey.startsWith(prefix)) {
25767
+ hasActivatedEvent = true;
25768
+ }
25769
+ });
25763
25770
 
25764
- if (hasActivatedEvent) {
25765
- // Preserve the activated variant, don't overwrite with server's current variant
25766
- var currentFlag = this.flags && this.flags.get(key);
25767
- if (currentFlag) {
25768
- flags.set(key, currentFlag);
25769
- }
25770
- } else {
25771
- // Use server's current variant
25772
- flags.set(key, {
25773
- 'key': data['variant_key'],
25774
- 'value': data['variant_value'],
25775
- 'experiment_id': data['experiment_id'],
25776
- 'is_experiment_active': data['is_experiment_active'],
25777
- 'is_qa_tester': data['is_qa_tester']
25778
- });
25771
+ if (hasActivatedEvent) {
25772
+ // Preserve the activated variant, don't overwrite with server's current variant
25773
+ var currentFlag = this.flags && this.flags.get(key);
25774
+ if (currentFlag) {
25775
+ flags.set(key, currentFlag);
25779
25776
  }
25780
- }, this);
25777
+ } else {
25778
+ // Use server's current variant
25779
+ flags.set(key, {
25780
+ 'key': data['variant_key'],
25781
+ 'value': data['variant_value'],
25782
+ 'experiment_id': data['experiment_id'],
25783
+ 'is_experiment_active': data['is_experiment_active'],
25784
+ 'is_qa_tester': data['is_qa_tester']
25785
+ });
25786
+ }
25787
+ }, this);
25781
25788
 
25782
- // Process top-level pending_first_time_events array
25783
- var topLevelDefinitions = responseBody['pending_first_time_events'];
25784
- if (topLevelDefinitions && topLevelDefinitions.length > 0) {
25785
- _.each(topLevelDefinitions, function(def) {
25786
- var flagKey = def['flag_key'];
25787
- var eventKey = getPendingEventKey(flagKey, def['first_time_event_hash']);
25789
+ // Process top-level pending_first_time_events array
25790
+ var topLevelDefinitions = responseBody['pending_first_time_events'];
25791
+ if (topLevelDefinitions && topLevelDefinitions.length > 0) {
25792
+ _.each(topLevelDefinitions, function(def) {
25793
+ var flagKey = def['flag_key'];
25794
+ var eventKey = getPendingEventKey(flagKey, def['first_time_event_hash']);
25788
25795
 
25789
- // Skip if this specific event has already been activated this session
25790
- if (this.activatedFirstTimeEvents[eventKey]) {
25791
- return;
25792
- }
25796
+ // Skip if this specific event has already been activated this session
25797
+ if (this.activatedFirstTimeEvents[eventKey]) {
25798
+ return;
25799
+ }
25793
25800
 
25794
- // Store pending event definition using composite key
25795
- pendingFirstTimeEvents[eventKey] = {
25796
- 'flag_key': flagKey,
25797
- 'flag_id': def['flag_id'],
25798
- 'project_id': def['project_id'],
25799
- 'first_time_event_hash': def['first_time_event_hash'],
25800
- 'event_name': def['event_name'],
25801
- 'property_filters': def['property_filters'],
25802
- 'pending_variant': def['pending_variant']
25803
- };
25804
- }, this);
25805
- }
25801
+ // Store pending event definition using composite key
25802
+ pendingFirstTimeEvents[eventKey] = {
25803
+ 'flag_key': flagKey,
25804
+ 'flag_id': def['flag_id'],
25805
+ 'project_id': def['project_id'],
25806
+ 'first_time_event_hash': def['first_time_event_hash'],
25807
+ 'event_name': def['event_name'],
25808
+ 'property_filters': def['property_filters'],
25809
+ 'pending_variant': def['pending_variant']
25810
+ };
25811
+ }, this);
25812
+ }
25806
25813
 
25807
- // Preserve any activated orphaned flags (flags that were activated but are no longer in response)
25808
- if (this.activatedFirstTimeEvents) {
25809
- _.each(this.activatedFirstTimeEvents, function(activated, eventKey) {
25810
- var flagKey = getFlagKeyFromPendingEventKey(eventKey);
25811
- if (activated && !flags.has(flagKey) && this.flags && this.flags.has(flagKey)) {
25812
- // Keep the activated flag even though it's not in the new response
25813
- flags.set(flagKey, this.flags.get(flagKey));
25814
- }
25815
- }, this);
25816
- }
25814
+ // Preserve any activated orphaned flags (flags that were activated but are no longer in response)
25815
+ if (this.activatedFirstTimeEvents) {
25816
+ _.each(this.activatedFirstTimeEvents, function(activated, eventKey) {
25817
+ var flagKey = getFlagKeyFromPendingEventKey(eventKey);
25818
+ if (activated && !flags.has(flagKey) && this.flags && this.flags.has(flagKey)) {
25819
+ // Keep the activated flag even though it's not in the new response
25820
+ flags.set(flagKey, this.flags.get(flagKey));
25821
+ }
25822
+ }, this);
25823
+ }
25817
25824
 
25818
- this.flags = flags;
25819
- this.pendingFirstTimeEvents = pendingFirstTimeEvents;
25820
- this._traceparent = traceparent;
25825
+ this.flags = flags;
25826
+ this.pendingFirstTimeEvents = pendingFirstTimeEvents;
25827
+ this._traceparent = traceparent;
25821
25828
 
25822
- this._loadTargetingIfNeeded();
25823
- }.bind(this)).catch(function(error) {
25824
- this.markFetchComplete();
25825
- logger$1.error(error);
25826
- }.bind(this));
25829
+ this._loadTargetingIfNeeded();
25827
25830
  }.bind(this)).catch(function(error) {
25828
- this.markFetchComplete();
25831
+ if (this._fetchInProgressStartTime) {
25832
+ this.markFetchComplete();
25833
+ }
25829
25834
  logger$1.error(error);
25835
+ throw error;
25830
25836
  }.bind(this));
25831
25837
 
25832
25838
  return this.fetchPromise;
25833
25839
  };
25834
25840
 
25841
+ FeatureFlagManager.prototype.loadFlags = function() {
25842
+ if (!this.isSystemEnabled()) {
25843
+ return Promise.resolve();
25844
+ }
25845
+ if (!this.trackedFeatures) {
25846
+ logger$1.error('loadFlags called before init');
25847
+ return Promise.resolve();
25848
+ }
25849
+ if (this._fetchInProgressStartTime) {
25850
+ return this.fetchPromise;
25851
+ }
25852
+ return this.fetchFlags();
25853
+ };
25854
+
25835
25855
  FeatureFlagManager.prototype.markFetchComplete = function() {
25836
25856
  if (!this._fetchInProgressStartTime) {
25837
25857
  logger$1.error('Fetch in progress started time not set, cannot mark fetch complete');
@@ -26111,6 +26131,13 @@
26111
26131
  this.track('$experiment_started', trackingProperties);
26112
26132
  };
26113
26133
 
26134
+ FeatureFlagManager.prototype.whenReady = function() {
26135
+ if (this.fetchPromise) {
26136
+ return this.fetchPromise;
26137
+ }
26138
+ return Promise.resolve();
26139
+ };
26140
+
26114
26141
  FeatureFlagManager.prototype.minApisSupported = function() {
26115
26142
  return !!this.fetch &&
26116
26143
  typeof Promise !== 'undefined' &&
@@ -26127,7 +26154,9 @@
26127
26154
  FeatureFlagManager.prototype['get_variant_value_sync'] = FeatureFlagManager.prototype.getVariantValueSync;
26128
26155
  FeatureFlagManager.prototype['is_enabled'] = FeatureFlagManager.prototype.isEnabled;
26129
26156
  FeatureFlagManager.prototype['is_enabled_sync'] = FeatureFlagManager.prototype.isEnabledSync;
26157
+ FeatureFlagManager.prototype['load_flags'] = FeatureFlagManager.prototype.loadFlags;
26130
26158
  FeatureFlagManager.prototype['update_context'] = FeatureFlagManager.prototype.updateContext;
26159
+ FeatureFlagManager.prototype['when_ready'] = FeatureFlagManager.prototype.whenReady;
26131
26160
 
26132
26161
  // Deprecated method
26133
26162
  FeatureFlagManager.prototype['get_feature_data'] = FeatureFlagManager.prototype.getFeatureData;
@@ -29483,7 +29512,9 @@
29483
29512
 
29484
29513
  // check feature flags again if distinct id has changed
29485
29514
  if (new_distinct_id !== previous_distinct_id) {
29486
- this.flags.fetchFlags();
29515
+ this.flags.fetchFlags().catch(function() {
29516
+ console$1.error('[flags] Error fetching flags during identify');
29517
+ });
29487
29518
  }
29488
29519
  };
29489
29520
 
@@ -357,6 +357,7 @@ export interface FlagsUpdateContextOptions {
357
357
 
358
358
  export interface FlagsManager {
359
359
  are_flags_ready(): boolean;
360
+ load_flags(): Promise<void>;
360
361
  get_variant(
361
362
  featureName: string,
362
363
  fallback: FlagsVariant