mixpanel-browser 2.77.0 → 2.79.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 (68) hide show
  1. package/.claude/settings.local.json +6 -9
  2. package/.eslintrc.json +12 -0
  3. package/.github/workflows/openfeature-provider-tests.yml +31 -0
  4. package/CHANGELOG.md +11 -0
  5. package/build.sh +2 -2
  6. package/dist/async-modules/{mixpanel-recorder-wIWnMDLA.min.js → mixpanel-recorder-D5HJyV2E.min.js} +2 -2
  7. package/dist/async-modules/mixpanel-recorder-D5HJyV2E.min.js.map +1 -0
  8. package/dist/async-modules/{mixpanel-recorder-DLKbUIEE.js → mixpanel-recorder-P6SEnnPV.js} +57 -33
  9. package/dist/async-modules/mixpanel-targeting-1L9FyetZ.min.js +2 -0
  10. package/dist/async-modules/mixpanel-targeting-1L9FyetZ.min.js.map +1 -0
  11. package/dist/async-modules/{mixpanel-targeting-CmVvUyFM.js → mixpanel-targeting-BBMVbgJF.js} +24 -13
  12. package/dist/mixpanel-core.cjs.d.ts +46 -1
  13. package/dist/mixpanel-core.cjs.js +671 -272
  14. package/dist/mixpanel-recorder.js +57 -33
  15. package/dist/mixpanel-recorder.min.js +1 -1
  16. package/dist/mixpanel-recorder.min.js.map +1 -1
  17. package/dist/mixpanel-targeting.js +24 -13
  18. package/dist/mixpanel-targeting.min.js +1 -1
  19. package/dist/mixpanel-targeting.min.js.map +1 -1
  20. package/dist/mixpanel-with-async-modules.cjs.d.ts +46 -1
  21. package/dist/mixpanel-with-async-modules.cjs.js +673 -274
  22. package/dist/mixpanel-with-async-recorder.cjs.d.ts +46 -1
  23. package/dist/mixpanel-with-async-recorder.cjs.js +673 -274
  24. package/dist/mixpanel-with-recorder.d.ts +46 -1
  25. package/dist/mixpanel-with-recorder.js +596 -197
  26. package/dist/mixpanel-with-recorder.min.d.ts +46 -1
  27. package/dist/mixpanel-with-recorder.min.js +1 -1
  28. package/dist/mixpanel.amd.d.ts +46 -1
  29. package/dist/mixpanel.amd.js +596 -197
  30. package/dist/mixpanel.cjs.d.ts +46 -1
  31. package/dist/mixpanel.cjs.js +596 -197
  32. package/dist/mixpanel.globals.js +673 -274
  33. package/dist/mixpanel.min.js +200 -189
  34. package/dist/mixpanel.module.d.ts +46 -1
  35. package/dist/mixpanel.module.js +596 -197
  36. package/dist/mixpanel.umd.d.ts +46 -1
  37. package/dist/mixpanel.umd.js +596 -197
  38. package/package.json +1 -1
  39. package/packages/openfeature-web-provider/README.md +357 -0
  40. package/packages/openfeature-web-provider/package-lock.json +1636 -0
  41. package/packages/openfeature-web-provider/package.json +51 -0
  42. package/packages/openfeature-web-provider/rollup.config.browser.mjs +26 -0
  43. package/packages/openfeature-web-provider/src/MixpanelProvider.ts +302 -0
  44. package/packages/openfeature-web-provider/src/index.ts +1 -0
  45. package/packages/openfeature-web-provider/src/types.ts +72 -0
  46. package/packages/openfeature-web-provider/test/MixpanelProvider.spec.ts +484 -0
  47. package/packages/openfeature-web-provider/tsconfig.json +15 -0
  48. package/src/autocapture/index.js +7 -2
  49. package/src/config.js +1 -1
  50. package/src/flags/CLAUDE.md +24 -0
  51. package/src/flags/flags-persistence.js +176 -0
  52. package/src/flags/index.js +278 -98
  53. package/src/index.d.ts +46 -1
  54. package/src/mixpanel-core.js +27 -8
  55. package/src/recorder/idb-config.js +16 -0
  56. package/src/recorder/recording-registry.js +7 -2
  57. package/src/recorder/session-recording.js +9 -4
  58. package/src/recorder-manager.js +7 -2
  59. package/src/request-queue.js +1 -2
  60. package/src/shared-lock.js +2 -3
  61. package/src/storage/indexed-db.js +16 -15
  62. package/src/storage/local-storage.js +5 -3
  63. package/src/utils.js +25 -12
  64. package/testServer.js +2 -0
  65. package/tsconfig.base.json +9 -0
  66. package/dist/async-modules/mixpanel-recorder-wIWnMDLA.min.js.map +0 -1
  67. package/dist/async-modules/mixpanel-targeting-CTcftSJC.min.js +0 -2
  68. package/dist/async-modules/mixpanel-targeting-CTcftSJC.min.js.map +0 -1
@@ -0,0 +1,176 @@
1
+ import { _, console_with_prefix } from '../utils'; // eslint-disable-line camelcase
2
+ import { IDBStorageWrapper } from '../storage/indexed-db';
3
+
4
+ var logger = console_with_prefix('flags');
5
+
6
+ var MIXPANEL_FLAGS_DB_NAME = 'mixpanelFlagsDb';
7
+ var FLAGS_STORE_NAME = 'mixpanelFlags';
8
+
9
+ // Keeping these two properties closeby, as adding additional stores to a DB in IndexedDB requires a version increment
10
+ var FLAGS_VERSION_DATA = { version: 1, storeNames: [FLAGS_STORE_NAME] };
11
+
12
+ var PERSISTED_VARIANTS_KEY_PREFIX = 'persisted_variants_for_';
13
+ var DEFAULT_TTL_MS = 24 * 60 * 60 * 1000;
14
+
15
+ var VariantLookupPolicy = Object.freeze({
16
+ NETWORK_ONLY: 'networkOnly',
17
+ NETWORK_FIRST: 'networkFirst',
18
+ PERSISTENCE_UNTIL_NETWORK_SUCCESS: 'persistenceUntilNetworkSuccess'
19
+ });
20
+
21
+ var VALID_POLICIES = [
22
+ VariantLookupPolicy.NETWORK_ONLY,
23
+ VariantLookupPolicy.NETWORK_FIRST,
24
+ VariantLookupPolicy.PERSISTENCE_UNTIL_NETWORK_SUCCESS
25
+ ];
26
+
27
+ /**
28
+ * Module for handling the storage and retrieval of persisted feature flag variants.
29
+ */
30
+ var FeatureFlagPersistence = function(persistenceConfig, token, isGloballyDisabled) {
31
+ this.idb = new IDBStorageWrapper(MIXPANEL_FLAGS_DB_NAME, FLAGS_STORE_NAME, FLAGS_VERSION_DATA);
32
+ this.persistenceConfig = persistenceConfig;
33
+ this.persistedVariantsKey = PERSISTED_VARIANTS_KEY_PREFIX + token;
34
+ this.isGloballyDisabled = isGloballyDisabled || function() { return false; };
35
+ };
36
+
37
+ FeatureFlagPersistence.prototype.getPolicy = function() {
38
+ if (this.isGloballyDisabled() || !this._isConfigValid()) {
39
+ return VariantLookupPolicy.NETWORK_ONLY;
40
+ }
41
+ return this.persistenceConfig['variantLookupPolicy'];
42
+ };
43
+
44
+ FeatureFlagPersistence.prototype.getTtlMs = function() {
45
+ if (!this._isConfigValid()) {
46
+ return DEFAULT_TTL_MS;
47
+ }
48
+ var configuredTtl = this.persistenceConfig['persistenceTtlMs'];
49
+ return (configuredTtl === undefined || configuredTtl === null) ? DEFAULT_TTL_MS : configuredTtl;
50
+ };
51
+
52
+ FeatureFlagPersistence.prototype._isConfigValid = function() {
53
+ var config = this.persistenceConfig;
54
+ if (!config) {
55
+ return false;
56
+ }
57
+
58
+ if (VALID_POLICIES.indexOf(config['variantLookupPolicy']) === -1) {
59
+ logger.error('Invalid variantLookupPolicy:', config['variantLookupPolicy']);
60
+ return false;
61
+ }
62
+
63
+ if (config['persistenceTtlMs'] !== undefined &&
64
+ config['persistenceTtlMs'] !== null &&
65
+ config['persistenceTtlMs'] <= 0) {
66
+ logger.error('If provided, persistenceTtlMs must be a positive number. Provided value:', config['persistenceTtlMs']);
67
+ return false;
68
+ }
69
+
70
+ return true;
71
+ };
72
+
73
+ FeatureFlagPersistence.prototype.loadFlagsFromStorage = function(context) {
74
+ var clearAndReturnNull = _.bind(function() {
75
+ return this.clear().then(function() { return null; }).catch(function() { return null; });
76
+ }, this);
77
+
78
+ if (this.getPolicy() === VariantLookupPolicy.NETWORK_ONLY) {
79
+ return clearAndReturnNull();
80
+ }
81
+
82
+ var ttlMs = this.getTtlMs();
83
+
84
+ return this.idb.init().then(_.bind(function() {
85
+ return this.idb.getItem(this.persistedVariantsKey);
86
+ }, this)).then(_.bind(function(data) {
87
+ if (!data) {
88
+ logger.log('No persisted variants found in IndexedDB');
89
+ return null;
90
+ }
91
+
92
+ if (ttlMs && Date.now() - data['persistedAt'] >= ttlMs) {
93
+ logger.log('Persisted variants are expiring');
94
+ return null;
95
+ }
96
+
97
+ if (!context || data['distinctId'] !== context['distinct_id']) {
98
+ logger.log('Persisted variants found, but for a different distinct_id so clearing.');
99
+ return clearAndReturnNull();
100
+ }
101
+
102
+ var persistedFlags = new Map();
103
+ _.each(data['flagVariants'], function(variantData, key) {
104
+ persistedFlags.set(key, {
105
+ 'key': variantData['variant_key'],
106
+ 'value': variantData['variant_value'],
107
+ 'experiment_id': variantData['experiment_id'],
108
+ 'is_experiment_active': variantData['is_experiment_active'],
109
+ 'is_qa_tester': variantData['is_qa_tester'],
110
+ 'variant_source': 'persistence',
111
+ 'persisted_at_in_ms': data['persistedAt'],
112
+ 'ttl_in_ms': ttlMs
113
+ });
114
+ });
115
+
116
+ logger.log('Loaded', persistedFlags.size, 'variants from IndexedDB for distinct_id', data['distinctId']);
117
+
118
+ return {
119
+ flags: persistedFlags,
120
+ pendingFirstTimeEvents: data['pendingFirstTimeEvents'] || {},
121
+ persistedAtMs: data['persistedAt'],
122
+ ttlMs: ttlMs
123
+ };
124
+ }, this)).catch(_.bind(function(error) {
125
+ logger.error('Failed to load persisted variants from IndexedDB, so clearing', error);
126
+ return clearAndReturnNull();
127
+ }, this));
128
+ };
129
+
130
+ FeatureFlagPersistence.prototype.save = function(context, flagsMap, pendingFirstTimeEvents) {
131
+ if (this.getPolicy() === VariantLookupPolicy.NETWORK_ONLY) {
132
+ return Promise.resolve();
133
+ }
134
+
135
+ var flagVariants = {};
136
+ flagsMap.forEach(function(variant, key) {
137
+ flagVariants[key] = {
138
+ 'variant_key': variant['key'],
139
+ 'variant_value': variant['value'],
140
+ 'experiment_id': variant['experiment_id'],
141
+ 'is_experiment_active': variant['is_experiment_active'],
142
+ 'is_qa_tester': variant['is_qa_tester']
143
+ };
144
+ });
145
+
146
+ var data = {
147
+ 'persistedAt': Date.now(),
148
+ 'distinctId': context && context['distinct_id'],
149
+ 'context': context,
150
+ 'flagVariants': flagVariants,
151
+ 'pendingFirstTimeEvents': pendingFirstTimeEvents || {}
152
+ };
153
+
154
+ return this.idb.init().then(_.bind(function() {
155
+ return this.idb.setItem(this.persistedVariantsKey, data);
156
+ }, this)).then(function() {
157
+ logger.log('Saved', flagsMap.size, 'variants to IndexedDB for distinct_id', data['distinctId']);
158
+ }).catch(function(error) {
159
+ logger.error('Failed to persist variants to IndexedDB:', error);
160
+ });
161
+ };
162
+
163
+ FeatureFlagPersistence.prototype.clear = function() {
164
+ if (this.isGloballyDisabled()) {
165
+ return Promise.resolve();
166
+ }
167
+ return this.idb.init().then(_.bind(function() {
168
+ return this.idb.removeItem(this.persistedVariantsKey);
169
+ }, this)).then(function() {
170
+ logger.log('Cleared persisted variants from IndexedDB');
171
+ }).catch(function(error) {
172
+ logger.error('Failed to clear persisted variants from IndexedDB:', error);
173
+ });
174
+ };
175
+
176
+ export { FeatureFlagPersistence, VariantLookupPolicy, FLAGS_STORE_NAME, PERSISTED_VARIANTS_KEY_PREFIX };