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
@@ -3,7 +3,7 @@
3
3
 
4
4
  var Config = {
5
5
  DEBUG: false,
6
- LIB_VERSION: '2.77.0'
6
+ LIB_VERSION: '2.78.0'
7
7
  };
8
8
 
9
9
  // Window global names for async modules
@@ -11,8 +11,8 @@
11
11
  var RECORDER_GLOBAL_NAME = '__mp_recorder';
12
12
 
13
13
  // Constants that are injected at build-time for the names of async modules.
14
- var RECORDER_FILENAME = 'mixpanel-recorder-DLKbUIEE.js';
15
- var TARGETING_FILENAME = 'mixpanel-targeting-CmVvUyFM.js';
14
+ var RECORDER_FILENAME = 'mixpanel-recorder-zMBXIyeG.js';
15
+ var TARGETING_FILENAME = 'mixpanel-targeting-UHf4eBfC.js';
16
16
 
17
17
  // since es6 imports are static and we run unit tests from the console, window won't be defined when importing this file
18
18
  var win;
@@ -3972,7 +3972,9 @@
3972
3972
  }
3973
3973
 
3974
3974
  this.flags = null;
3975
- this.fetchFlags();
3975
+ this.fetchFlags().catch(function() {
3976
+ logger$4.error('Error fetching flags during init');
3977
+ });
3976
3978
 
3977
3979
  this.trackedFeatures = new Set();
3978
3980
  this.pendingFirstTimeEvents = {};
@@ -4013,8 +4015,12 @@
4013
4015
  var oldContext = (options && options['replace']) ? {} : this.getConfig(CONFIG_CONTEXT);
4014
4016
  ffConfig[CONFIG_CONTEXT] = _.extend({}, oldContext, newContext);
4015
4017
 
4016
- this.setMpConfig(FLAGS_CONFIG_KEY, ffConfig);
4017
- return this.fetchFlags();
4018
+ var configUpdate = {};
4019
+ configUpdate[FLAGS_CONFIG_KEY] = ffConfig;
4020
+ this.setMpConfig(configUpdate);
4021
+ return this.fetchFlags().catch(function() {
4022
+ logger$4.error('Error fetching flags during updateContext');
4023
+ });
4018
4024
  };
4019
4025
 
4020
4026
  FeatureFlagManager.prototype.areFlagsReady = function() {
@@ -4051,96 +4057,110 @@
4051
4057
  }
4052
4058
  }).then(function(response) {
4053
4059
  this.markFetchComplete();
4054
- return response.json().then(function(responseBody) {
4055
- var responseFlags = responseBody['flags'];
4056
- if (!responseFlags) {
4057
- throw new Error('No flags in API response');
4058
- }
4059
- var flags = new Map();
4060
- var pendingFirstTimeEvents = {};
4061
-
4062
- // Process flags from response
4063
- _.each(responseFlags, function(data, key) {
4064
- // Check if this flag has any activated first-time events this session
4065
- var hasActivatedEvent = false;
4066
- var prefix = key + ':';
4067
- _.each(this.activatedFirstTimeEvents, function(activated, eventKey) {
4068
- if (eventKey.startsWith(prefix)) {
4069
- hasActivatedEvent = true;
4070
- }
4071
- });
4060
+ return response.json();
4061
+ }.bind(this)).then(function(responseBody) {
4062
+ var responseFlags = responseBody['flags'];
4063
+ if (!responseFlags) {
4064
+ throw new Error('No flags in API response');
4065
+ }
4066
+ var flags = new Map();
4067
+ var pendingFirstTimeEvents = {};
4068
+
4069
+ // Process flags from response
4070
+ _.each(responseFlags, function(data, key) {
4071
+ // Check if this flag has any activated first-time events this session
4072
+ var hasActivatedEvent = false;
4073
+ var prefix = key + ':';
4074
+ _.each(this.activatedFirstTimeEvents, function(activated, eventKey) {
4075
+ if (eventKey.startsWith(prefix)) {
4076
+ hasActivatedEvent = true;
4077
+ }
4078
+ });
4072
4079
 
4073
- if (hasActivatedEvent) {
4074
- // Preserve the activated variant, don't overwrite with server's current variant
4075
- var currentFlag = this.flags && this.flags.get(key);
4076
- if (currentFlag) {
4077
- flags.set(key, currentFlag);
4078
- }
4079
- } else {
4080
- // Use server's current variant
4081
- flags.set(key, {
4082
- 'key': data['variant_key'],
4083
- 'value': data['variant_value'],
4084
- 'experiment_id': data['experiment_id'],
4085
- 'is_experiment_active': data['is_experiment_active'],
4086
- 'is_qa_tester': data['is_qa_tester']
4087
- });
4080
+ if (hasActivatedEvent) {
4081
+ // Preserve the activated variant, don't overwrite with server's current variant
4082
+ var currentFlag = this.flags && this.flags.get(key);
4083
+ if (currentFlag) {
4084
+ flags.set(key, currentFlag);
4088
4085
  }
4089
- }, this);
4086
+ } else {
4087
+ // Use server's current variant
4088
+ flags.set(key, {
4089
+ 'key': data['variant_key'],
4090
+ 'value': data['variant_value'],
4091
+ 'experiment_id': data['experiment_id'],
4092
+ 'is_experiment_active': data['is_experiment_active'],
4093
+ 'is_qa_tester': data['is_qa_tester']
4094
+ });
4095
+ }
4096
+ }, this);
4090
4097
 
4091
- // Process top-level pending_first_time_events array
4092
- var topLevelDefinitions = responseBody['pending_first_time_events'];
4093
- if (topLevelDefinitions && topLevelDefinitions.length > 0) {
4094
- _.each(topLevelDefinitions, function(def) {
4095
- var flagKey = def['flag_key'];
4096
- var eventKey = getPendingEventKey(flagKey, def['first_time_event_hash']);
4098
+ // Process top-level pending_first_time_events array
4099
+ var topLevelDefinitions = responseBody['pending_first_time_events'];
4100
+ if (topLevelDefinitions && topLevelDefinitions.length > 0) {
4101
+ _.each(topLevelDefinitions, function(def) {
4102
+ var flagKey = def['flag_key'];
4103
+ var eventKey = getPendingEventKey(flagKey, def['first_time_event_hash']);
4097
4104
 
4098
- // Skip if this specific event has already been activated this session
4099
- if (this.activatedFirstTimeEvents[eventKey]) {
4100
- return;
4101
- }
4105
+ // Skip if this specific event has already been activated this session
4106
+ if (this.activatedFirstTimeEvents[eventKey]) {
4107
+ return;
4108
+ }
4102
4109
 
4103
- // Store pending event definition using composite key
4104
- pendingFirstTimeEvents[eventKey] = {
4105
- 'flag_key': flagKey,
4106
- 'flag_id': def['flag_id'],
4107
- 'project_id': def['project_id'],
4108
- 'first_time_event_hash': def['first_time_event_hash'],
4109
- 'event_name': def['event_name'],
4110
- 'property_filters': def['property_filters'],
4111
- 'pending_variant': def['pending_variant']
4112
- };
4113
- }, this);
4114
- }
4110
+ // Store pending event definition using composite key
4111
+ pendingFirstTimeEvents[eventKey] = {
4112
+ 'flag_key': flagKey,
4113
+ 'flag_id': def['flag_id'],
4114
+ 'project_id': def['project_id'],
4115
+ 'first_time_event_hash': def['first_time_event_hash'],
4116
+ 'event_name': def['event_name'],
4117
+ 'property_filters': def['property_filters'],
4118
+ 'pending_variant': def['pending_variant']
4119
+ };
4120
+ }, this);
4121
+ }
4115
4122
 
4116
- // Preserve any activated orphaned flags (flags that were activated but are no longer in response)
4117
- if (this.activatedFirstTimeEvents) {
4118
- _.each(this.activatedFirstTimeEvents, function(activated, eventKey) {
4119
- var flagKey = getFlagKeyFromPendingEventKey(eventKey);
4120
- if (activated && !flags.has(flagKey) && this.flags && this.flags.has(flagKey)) {
4121
- // Keep the activated flag even though it's not in the new response
4122
- flags.set(flagKey, this.flags.get(flagKey));
4123
- }
4124
- }, this);
4125
- }
4123
+ // Preserve any activated orphaned flags (flags that were activated but are no longer in response)
4124
+ if (this.activatedFirstTimeEvents) {
4125
+ _.each(this.activatedFirstTimeEvents, function(activated, eventKey) {
4126
+ var flagKey = getFlagKeyFromPendingEventKey(eventKey);
4127
+ if (activated && !flags.has(flagKey) && this.flags && this.flags.has(flagKey)) {
4128
+ // Keep the activated flag even though it's not in the new response
4129
+ flags.set(flagKey, this.flags.get(flagKey));
4130
+ }
4131
+ }, this);
4132
+ }
4126
4133
 
4127
- this.flags = flags;
4128
- this.pendingFirstTimeEvents = pendingFirstTimeEvents;
4129
- this._traceparent = traceparent;
4134
+ this.flags = flags;
4135
+ this.pendingFirstTimeEvents = pendingFirstTimeEvents;
4136
+ this._traceparent = traceparent;
4130
4137
 
4131
- this._loadTargetingIfNeeded();
4132
- }.bind(this)).catch(function(error) {
4133
- this.markFetchComplete();
4134
- logger$4.error(error);
4135
- }.bind(this));
4138
+ this._loadTargetingIfNeeded();
4136
4139
  }.bind(this)).catch(function(error) {
4137
- this.markFetchComplete();
4140
+ if (this._fetchInProgressStartTime) {
4141
+ this.markFetchComplete();
4142
+ }
4138
4143
  logger$4.error(error);
4144
+ throw error;
4139
4145
  }.bind(this));
4140
4146
 
4141
4147
  return this.fetchPromise;
4142
4148
  };
4143
4149
 
4150
+ FeatureFlagManager.prototype.loadFlags = function() {
4151
+ if (!this.isSystemEnabled()) {
4152
+ return Promise.resolve();
4153
+ }
4154
+ if (!this.trackedFeatures) {
4155
+ logger$4.error('loadFlags called before init');
4156
+ return Promise.resolve();
4157
+ }
4158
+ if (this._fetchInProgressStartTime) {
4159
+ return this.fetchPromise;
4160
+ }
4161
+ return this.fetchFlags();
4162
+ };
4163
+
4144
4164
  FeatureFlagManager.prototype.markFetchComplete = function() {
4145
4165
  if (!this._fetchInProgressStartTime) {
4146
4166
  logger$4.error('Fetch in progress started time not set, cannot mark fetch complete');
@@ -4420,6 +4440,13 @@
4420
4440
  this.track('$experiment_started', trackingProperties);
4421
4441
  };
4422
4442
 
4443
+ FeatureFlagManager.prototype.whenReady = function() {
4444
+ if (this.fetchPromise) {
4445
+ return this.fetchPromise;
4446
+ }
4447
+ return Promise.resolve();
4448
+ };
4449
+
4423
4450
  FeatureFlagManager.prototype.minApisSupported = function() {
4424
4451
  return !!this.fetch &&
4425
4452
  typeof Promise !== 'undefined' &&
@@ -4436,7 +4463,9 @@
4436
4463
  FeatureFlagManager.prototype['get_variant_value_sync'] = FeatureFlagManager.prototype.getVariantValueSync;
4437
4464
  FeatureFlagManager.prototype['is_enabled'] = FeatureFlagManager.prototype.isEnabled;
4438
4465
  FeatureFlagManager.prototype['is_enabled_sync'] = FeatureFlagManager.prototype.isEnabledSync;
4466
+ FeatureFlagManager.prototype['load_flags'] = FeatureFlagManager.prototype.loadFlags;
4439
4467
  FeatureFlagManager.prototype['update_context'] = FeatureFlagManager.prototype.updateContext;
4468
+ FeatureFlagManager.prototype['when_ready'] = FeatureFlagManager.prototype.whenReady;
4440
4469
 
4441
4470
  // Deprecated method
4442
4471
  FeatureFlagManager.prototype['get_feature_data'] = FeatureFlagManager.prototype.getFeatureData;
@@ -9143,7 +9172,9 @@
9143
9172
 
9144
9173
  // check feature flags again if distinct id has changed
9145
9174
  if (new_distinct_id !== previous_distinct_id) {
9146
- this.flags.fetchFlags();
9175
+ this.flags.fetchFlags().catch(function() {
9176
+ console.error('[flags] Error fetching flags during identify');
9177
+ });
9147
9178
  }
9148
9179
  };
9149
9180