mixpanel-browser 2.78.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.
- package/.claude/settings.local.json +6 -11
- package/.eslintrc.json +12 -0
- package/.github/workflows/openfeature-provider-tests.yml +31 -0
- package/CHANGELOG.md +8 -1
- package/build.sh +2 -2
- package/dist/async-modules/{mixpanel-recorder-BjSlYaNJ.min.js → mixpanel-recorder-D5HJyV2E.min.js} +2 -2
- package/dist/async-modules/mixpanel-recorder-D5HJyV2E.min.js.map +1 -0
- package/dist/async-modules/{mixpanel-recorder-zMBXIyeG.js → mixpanel-recorder-P6SEnnPV.js} +57 -33
- package/dist/async-modules/mixpanel-targeting-1L9FyetZ.min.js +2 -0
- package/dist/async-modules/mixpanel-targeting-1L9FyetZ.min.js.map +1 -0
- package/dist/async-modules/{mixpanel-targeting-UHf4eBfC.js → mixpanel-targeting-BBMVbgJF.js} +24 -13
- package/dist/mixpanel-core.cjs.d.ts +45 -1
- package/dist/mixpanel-core.cjs.js +565 -197
- package/dist/mixpanel-recorder.js +57 -33
- package/dist/mixpanel-recorder.min.js +1 -1
- package/dist/mixpanel-recorder.min.js.map +1 -1
- package/dist/mixpanel-targeting.js +24 -13
- package/dist/mixpanel-targeting.min.js +1 -1
- package/dist/mixpanel-targeting.min.js.map +1 -1
- package/dist/mixpanel-with-async-modules.cjs.d.ts +45 -1
- package/dist/mixpanel-with-async-modules.cjs.js +567 -199
- package/dist/mixpanel-with-async-recorder.cjs.d.ts +45 -1
- package/dist/mixpanel-with-async-recorder.cjs.js +567 -199
- package/dist/mixpanel-with-recorder.d.ts +45 -1
- package/dist/mixpanel-with-recorder.js +490 -122
- package/dist/mixpanel-with-recorder.min.d.ts +45 -1
- package/dist/mixpanel-with-recorder.min.js +1 -1
- package/dist/mixpanel.amd.d.ts +45 -1
- package/dist/mixpanel.amd.js +490 -122
- package/dist/mixpanel.cjs.d.ts +45 -1
- package/dist/mixpanel.cjs.js +490 -122
- package/dist/mixpanel.globals.js +567 -199
- package/dist/mixpanel.min.js +199 -189
- package/dist/mixpanel.module.d.ts +45 -1
- package/dist/mixpanel.module.js +490 -122
- package/dist/mixpanel.umd.d.ts +45 -1
- package/dist/mixpanel.umd.js +490 -122
- package/package.json +1 -1
- package/packages/openfeature-web-provider/README.md +357 -0
- package/packages/openfeature-web-provider/package-lock.json +1636 -0
- package/packages/openfeature-web-provider/package.json +51 -0
- package/packages/openfeature-web-provider/rollup.config.browser.mjs +26 -0
- package/packages/openfeature-web-provider/src/MixpanelProvider.ts +302 -0
- package/packages/openfeature-web-provider/src/index.ts +1 -0
- package/packages/openfeature-web-provider/src/types.ts +72 -0
- package/packages/openfeature-web-provider/test/MixpanelProvider.spec.ts +484 -0
- package/packages/openfeature-web-provider/tsconfig.json +15 -0
- package/src/autocapture/index.js +7 -2
- package/src/config.js +1 -1
- package/src/flags/flags-persistence.js +176 -0
- package/src/flags/index.js +174 -23
- package/src/index.d.ts +45 -1
- package/src/mixpanel-core.js +24 -7
- package/src/recorder/idb-config.js +16 -0
- package/src/recorder/recording-registry.js +7 -2
- package/src/recorder/session-recording.js +9 -4
- package/src/recorder-manager.js +7 -2
- package/src/request-queue.js +1 -2
- package/src/shared-lock.js +2 -3
- package/src/storage/indexed-db.js +16 -15
- package/src/storage/local-storage.js +5 -3
- package/src/utils.js +25 -12
- package/tsconfig.base.json +9 -0
- package/dist/async-modules/mixpanel-recorder-BjSlYaNJ.min.js.map +0 -1
- package/dist/async-modules/mixpanel-targeting-BSHal4N9.min.js +0 -2
- package/dist/async-modules/mixpanel-targeting-BSHal4N9.min.js.map +0 -1
package/dist/mixpanel.umd.js
CHANGED
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
|
|
32
32
|
var Config = {
|
|
33
33
|
DEBUG: false,
|
|
34
|
-
LIB_VERSION: '2.
|
|
34
|
+
LIB_VERSION: '2.79.0'
|
|
35
35
|
};
|
|
36
36
|
|
|
37
37
|
// Window global names for async modules
|
|
@@ -19129,6 +19129,7 @@
|
|
|
19129
19129
|
var console_with_prefix = function(prefix) {
|
|
19130
19130
|
return {
|
|
19131
19131
|
log: log_func_with_prefix(console$1.log, prefix),
|
|
19132
|
+
warn: log_func_with_prefix(console$1.warn, prefix),
|
|
19132
19133
|
error: log_func_with_prefix(console$1.error, prefix),
|
|
19133
19134
|
critical: log_func_with_prefix(console$1.critical, prefix)
|
|
19134
19135
|
};
|
|
@@ -20075,7 +20076,8 @@
|
|
|
20075
20076
|
if (_localStorageSupported !== null && !forceCheck) {
|
|
20076
20077
|
return _localStorageSupported;
|
|
20077
20078
|
}
|
|
20078
|
-
|
|
20079
|
+
|
|
20080
|
+
return _localStorageSupported = _testStorageSupported(storage);
|
|
20079
20081
|
};
|
|
20080
20082
|
|
|
20081
20083
|
var _sessionStorageSupported = null;
|
|
@@ -20083,7 +20085,8 @@
|
|
|
20083
20085
|
if (_sessionStorageSupported !== null && !forceCheck) {
|
|
20084
20086
|
return _sessionStorageSupported;
|
|
20085
20087
|
}
|
|
20086
|
-
|
|
20088
|
+
|
|
20089
|
+
return _sessionStorageSupported = _testStorageSupported(storage);
|
|
20087
20090
|
};
|
|
20088
20091
|
|
|
20089
20092
|
function _storageWrapper(storage, name, is_supported_fn) {
|
|
@@ -20133,17 +20136,26 @@
|
|
|
20133
20136
|
};
|
|
20134
20137
|
}
|
|
20135
20138
|
|
|
20136
|
-
// Safari
|
|
20137
|
-
//
|
|
20138
|
-
var
|
|
20139
|
-
|
|
20140
|
-
|
|
20141
|
-
|
|
20142
|
-
|
|
20143
|
-
|
|
20139
|
+
// Safari and other browsers may error out accessing localStorage/sessionStorage
|
|
20140
|
+
// when cookies are disabled, so wrap access in a try-catch.
|
|
20141
|
+
var getLocalStorage = function() {
|
|
20142
|
+
try {
|
|
20143
|
+
return win.localStorage; // eslint-disable-line no-restricted-properties
|
|
20144
|
+
} catch (_err) {
|
|
20145
|
+
return null;
|
|
20146
|
+
}
|
|
20147
|
+
};
|
|
20148
|
+
|
|
20149
|
+
var getSessionStorage = function() {
|
|
20150
|
+
try {
|
|
20151
|
+
return win.sessionStorage; // eslint-disable-line no-restricted-properties
|
|
20152
|
+
} catch (_err) {
|
|
20153
|
+
return null;
|
|
20154
|
+
}
|
|
20155
|
+
};
|
|
20144
20156
|
|
|
20145
|
-
_.localStorage = _storageWrapper(
|
|
20146
|
-
_.sessionStorage = _storageWrapper(
|
|
20157
|
+
_.localStorage = _storageWrapper(getLocalStorage(), 'localStorage', localStorageSupported);
|
|
20158
|
+
_.sessionStorage = _storageWrapper(getSessionStorage(), 'sessionStorage', sessionStorageSupported);
|
|
20147
20159
|
|
|
20148
20160
|
_.register_event = (function() {
|
|
20149
20161
|
// written by Dean Edwards, 2005
|
|
@@ -20812,29 +20824,26 @@
|
|
|
20812
20824
|
_['toArray'] = _.toArray;
|
|
20813
20825
|
_['NPO'] = NpoPromise;
|
|
20814
20826
|
|
|
20815
|
-
var MIXPANEL_DB_NAME = 'mixpanelBrowserDb';
|
|
20816
|
-
|
|
20817
|
-
var RECORDING_EVENTS_STORE_NAME = 'mixpanelRecordingEvents';
|
|
20818
|
-
var RECORDING_REGISTRY_STORE_NAME = 'mixpanelRecordingRegistry';
|
|
20819
|
-
|
|
20820
|
-
// note: increment the version number when adding new object stores
|
|
20821
|
-
var DB_VERSION = 1;
|
|
20822
|
-
var OBJECT_STORES = [RECORDING_EVENTS_STORE_NAME, RECORDING_REGISTRY_STORE_NAME];
|
|
20823
|
-
|
|
20824
20827
|
/**
|
|
20825
20828
|
* @type {import('./wrapper').StorageWrapper}
|
|
20826
20829
|
*/
|
|
20827
|
-
var IDBStorageWrapper = function (storeName) {
|
|
20830
|
+
var IDBStorageWrapper = function (dbName, storeName, versionData) {
|
|
20831
|
+
this.dbName = dbName;
|
|
20832
|
+
this.storeName = storeName;
|
|
20833
|
+
this.version = versionData.version;
|
|
20834
|
+
this.storeNamesInDb = versionData.storeNames;
|
|
20828
20835
|
/**
|
|
20829
20836
|
* @type {Promise<IDBDatabase>|null}
|
|
20830
20837
|
*/
|
|
20831
20838
|
this.dbPromise = null;
|
|
20832
|
-
this.storeName = storeName;
|
|
20833
20839
|
};
|
|
20834
20840
|
|
|
20835
20841
|
IDBStorageWrapper.prototype._openDb = function () {
|
|
20842
|
+
var dbName = this.dbName;
|
|
20843
|
+
var version = this.version;
|
|
20844
|
+
var storeNamesInDb = this.storeNamesInDb;
|
|
20836
20845
|
return new PromisePolyfill(function (resolve, reject) {
|
|
20837
|
-
var openRequest = win.indexedDB.open(
|
|
20846
|
+
var openRequest = win.indexedDB.open(dbName, version);
|
|
20838
20847
|
openRequest['onerror'] = function () {
|
|
20839
20848
|
reject(openRequest.error);
|
|
20840
20849
|
};
|
|
@@ -20846,8 +20855,10 @@
|
|
|
20846
20855
|
openRequest['onupgradeneeded'] = function (ev) {
|
|
20847
20856
|
var db = ev.target.result;
|
|
20848
20857
|
|
|
20849
|
-
|
|
20850
|
-
db.
|
|
20858
|
+
storeNamesInDb.forEach(function (storeName) {
|
|
20859
|
+
if (!db.objectStoreNames.contains(storeName)) {
|
|
20860
|
+
db.createObjectStore(storeName);
|
|
20861
|
+
}
|
|
20851
20862
|
});
|
|
20852
20863
|
};
|
|
20853
20864
|
});
|
|
@@ -20939,6 +20950,16 @@
|
|
|
20939
20950
|
});
|
|
20940
20951
|
};
|
|
20941
20952
|
|
|
20953
|
+
var MIXPANEL_BROWSER_DB_NAME = 'mixpanelBrowserDb';
|
|
20954
|
+
var RECORDING_EVENTS_STORE_NAME = 'mixpanelRecordingEvents';
|
|
20955
|
+
var RECORDING_REGISTRY_STORE_NAME = 'mixpanelRecordingRegistry';
|
|
20956
|
+
|
|
20957
|
+
// Keeping these two properties closeby, as adding additional stores to a DB in IndexedDB requires a version increment
|
|
20958
|
+
var RECORDER_VERSION_DATA = {
|
|
20959
|
+
version: 1,
|
|
20960
|
+
storeNames: [RECORDING_EVENTS_STORE_NAME, RECORDING_REGISTRY_STORE_NAME]
|
|
20961
|
+
};
|
|
20962
|
+
|
|
20942
20963
|
/**
|
|
20943
20964
|
* GDPR utils
|
|
20944
20965
|
*
|
|
@@ -21239,7 +21260,7 @@
|
|
|
21239
21260
|
};
|
|
21240
21261
|
}
|
|
21241
21262
|
|
|
21242
|
-
var logger$
|
|
21263
|
+
var logger$9 = console_with_prefix('lock');
|
|
21243
21264
|
|
|
21244
21265
|
/**
|
|
21245
21266
|
* SharedLock: a mutex built on HTML5 localStorage, to ensure that only one browser
|
|
@@ -21265,7 +21286,7 @@
|
|
|
21265
21286
|
options = options || {};
|
|
21266
21287
|
|
|
21267
21288
|
this.storageKey = key;
|
|
21268
|
-
this.storage = options.storage ||
|
|
21289
|
+
this.storage = options.storage || getLocalStorage();
|
|
21269
21290
|
this.pollIntervalMS = options.pollIntervalMS || 100;
|
|
21270
21291
|
this.timeoutMS = options.timeoutMS || 2000;
|
|
21271
21292
|
|
|
@@ -21291,7 +21312,7 @@
|
|
|
21291
21312
|
|
|
21292
21313
|
var delay = function(cb) {
|
|
21293
21314
|
if (new Date().getTime() - startTime > timeoutMS) {
|
|
21294
|
-
logger$
|
|
21315
|
+
logger$9.error('Timeout waiting for mutex on ' + key + '; clearing lock. [' + i + ']');
|
|
21295
21316
|
storage.removeItem(keyZ);
|
|
21296
21317
|
storage.removeItem(keyY);
|
|
21297
21318
|
loop();
|
|
@@ -21393,10 +21414,13 @@
|
|
|
21393
21414
|
* @type {import('./wrapper').StorageWrapper}
|
|
21394
21415
|
*/
|
|
21395
21416
|
var LocalStorageWrapper = function (storageOverride) {
|
|
21396
|
-
this.storage = storageOverride ||
|
|
21417
|
+
this.storage = storageOverride || getLocalStorage();
|
|
21397
21418
|
};
|
|
21398
21419
|
|
|
21399
21420
|
LocalStorageWrapper.prototype.init = function () {
|
|
21421
|
+
if (!this.storage) {
|
|
21422
|
+
return PromisePolyfill.reject(new Error('localStorage is not available'));
|
|
21423
|
+
}
|
|
21400
21424
|
return PromisePolyfill.resolve();
|
|
21401
21425
|
};
|
|
21402
21426
|
|
|
@@ -21438,7 +21462,7 @@
|
|
|
21438
21462
|
}, this));
|
|
21439
21463
|
};
|
|
21440
21464
|
|
|
21441
|
-
var logger$
|
|
21465
|
+
var logger$8 = console_with_prefix('batch');
|
|
21442
21466
|
|
|
21443
21467
|
/**
|
|
21444
21468
|
* RequestQueue: queue for batching API requests with localStorage backup for retries.
|
|
@@ -21463,11 +21487,11 @@
|
|
|
21463
21487
|
if (this.usePersistence) {
|
|
21464
21488
|
this.queueStorage = options.queueStorage || new LocalStorageWrapper();
|
|
21465
21489
|
this.lock = new SharedLock(storageKey, {
|
|
21466
|
-
storage: options.sharedLockStorage
|
|
21490
|
+
storage: options.sharedLockStorage,
|
|
21467
21491
|
timeoutMS: options.sharedLockTimeoutMS,
|
|
21468
21492
|
});
|
|
21469
21493
|
}
|
|
21470
|
-
this.reportError = options.errorReporter || _.bind(logger$
|
|
21494
|
+
this.reportError = options.errorReporter || _.bind(logger$8.error, logger$8);
|
|
21471
21495
|
|
|
21472
21496
|
this.pid = options.pid || null; // pass pid to test out storage lock contention scenarios
|
|
21473
21497
|
|
|
@@ -21800,7 +21824,7 @@
|
|
|
21800
21824
|
// maximum interval between request retries after exponential backoff
|
|
21801
21825
|
var MAX_RETRY_INTERVAL_MS = 10 * 60 * 1000; // 10 minutes
|
|
21802
21826
|
|
|
21803
|
-
var logger$
|
|
21827
|
+
var logger$7 = console_with_prefix('batch');
|
|
21804
21828
|
|
|
21805
21829
|
/**
|
|
21806
21830
|
* RequestBatcher: manages the queueing, flushing, retry etc of requests of one
|
|
@@ -21928,7 +21952,7 @@
|
|
|
21928
21952
|
*/
|
|
21929
21953
|
RequestBatcher.prototype.flush = function(options) {
|
|
21930
21954
|
if (this.requestInProgress) {
|
|
21931
|
-
logger$
|
|
21955
|
+
logger$7.log('Flush: Request already in progress');
|
|
21932
21956
|
return PromisePolyfill.resolve();
|
|
21933
21957
|
}
|
|
21934
21958
|
|
|
@@ -22105,7 +22129,7 @@
|
|
|
22105
22129
|
if (options.unloading) {
|
|
22106
22130
|
requestOptions.transport = 'sendBeacon';
|
|
22107
22131
|
}
|
|
22108
|
-
logger$
|
|
22132
|
+
logger$7.log('MIXPANEL REQUEST:', dataForRequest);
|
|
22109
22133
|
return this.sendRequestPromise(dataForRequest, requestOptions).then(batchSendCallback);
|
|
22110
22134
|
}, this))
|
|
22111
22135
|
.catch(_.bind(function(err) {
|
|
@@ -22118,7 +22142,7 @@
|
|
|
22118
22142
|
* Log error to global logger and optional user-defined logger.
|
|
22119
22143
|
*/
|
|
22120
22144
|
RequestBatcher.prototype.reportError = function(msg, err) {
|
|
22121
|
-
logger$
|
|
22145
|
+
logger$7.error.apply(logger$7.error, arguments);
|
|
22122
22146
|
if (this.errorReporter) {
|
|
22123
22147
|
try {
|
|
22124
22148
|
if (!(err instanceof Error)) {
|
|
@@ -22126,7 +22150,7 @@
|
|
|
22126
22150
|
}
|
|
22127
22151
|
this.errorReporter(msg, err);
|
|
22128
22152
|
} catch(err) {
|
|
22129
|
-
logger$
|
|
22153
|
+
logger$7.error(err);
|
|
22130
22154
|
}
|
|
22131
22155
|
}
|
|
22132
22156
|
};
|
|
@@ -22271,7 +22295,7 @@
|
|
|
22271
22295
|
|
|
22272
22296
|
var MAX_DEPTH = 5;
|
|
22273
22297
|
|
|
22274
|
-
var logger$
|
|
22298
|
+
var logger$6 = console_with_prefix('autocapture');
|
|
22275
22299
|
|
|
22276
22300
|
|
|
22277
22301
|
function getClasses(el) {
|
|
@@ -22535,7 +22559,7 @@
|
|
|
22535
22559
|
return false;
|
|
22536
22560
|
}
|
|
22537
22561
|
} catch (err) {
|
|
22538
|
-
logger$
|
|
22562
|
+
logger$6.critical('Error while checking element in allowElementCallback', err);
|
|
22539
22563
|
return false;
|
|
22540
22564
|
}
|
|
22541
22565
|
}
|
|
@@ -22552,7 +22576,7 @@
|
|
|
22552
22576
|
return true;
|
|
22553
22577
|
}
|
|
22554
22578
|
} catch (err) {
|
|
22555
|
-
logger$
|
|
22579
|
+
logger$6.critical('Error while checking selector: ' + sel, err);
|
|
22556
22580
|
}
|
|
22557
22581
|
}
|
|
22558
22582
|
return false;
|
|
@@ -22567,7 +22591,7 @@
|
|
|
22567
22591
|
return true;
|
|
22568
22592
|
}
|
|
22569
22593
|
} catch (err) {
|
|
22570
|
-
logger$
|
|
22594
|
+
logger$6.critical('Error while checking element in blockElementCallback', err);
|
|
22571
22595
|
return true;
|
|
22572
22596
|
}
|
|
22573
22597
|
}
|
|
@@ -22581,7 +22605,7 @@
|
|
|
22581
22605
|
return true;
|
|
22582
22606
|
}
|
|
22583
22607
|
} catch (err) {
|
|
22584
|
-
logger$
|
|
22608
|
+
logger$6.critical('Error while checking selector: ' + sel, err);
|
|
22585
22609
|
}
|
|
22586
22610
|
}
|
|
22587
22611
|
}
|
|
@@ -23137,7 +23161,7 @@
|
|
|
23137
23161
|
*
|
|
23138
23162
|
*/
|
|
23139
23163
|
|
|
23140
|
-
var logger$
|
|
23164
|
+
var logger$5 = console_with_prefix('network-plugin');
|
|
23141
23165
|
|
|
23142
23166
|
/**
|
|
23143
23167
|
* Get the time origin for converting performance timestamps to absolute timestamps.
|
|
@@ -23289,7 +23313,7 @@
|
|
|
23289
23313
|
return str;
|
|
23290
23314
|
}
|
|
23291
23315
|
if (str.length > MAX_BODY_SIZE) {
|
|
23292
|
-
logger$
|
|
23316
|
+
logger$5.error('Body truncated from ' + str.length + ' to ' + MAX_BODY_SIZE + ' characters');
|
|
23293
23317
|
return str.substring(0, MAX_BODY_SIZE) + '... [truncated]';
|
|
23294
23318
|
}
|
|
23295
23319
|
return str;
|
|
@@ -23303,7 +23327,7 @@
|
|
|
23303
23327
|
*/
|
|
23304
23328
|
function initPerformanceObserver(cb, win, options) {
|
|
23305
23329
|
if (!win.PerformanceObserver) {
|
|
23306
|
-
logger$
|
|
23330
|
+
logger$5.error('PerformanceObserver not supported');
|
|
23307
23331
|
return function() {
|
|
23308
23332
|
//
|
|
23309
23333
|
};
|
|
@@ -23456,7 +23480,7 @@
|
|
|
23456
23480
|
attempt = 0;
|
|
23457
23481
|
}
|
|
23458
23482
|
if (attempt > 10) {
|
|
23459
|
-
logger$
|
|
23483
|
+
logger$5.error('Cannot find performance entry');
|
|
23460
23484
|
return Promise.resolve(null);
|
|
23461
23485
|
}
|
|
23462
23486
|
var urlPerformanceEntries = /** @type {PerformanceResourceTiming[]} */ (
|
|
@@ -23577,7 +23601,7 @@
|
|
|
23577
23601
|
)
|
|
23578
23602
|
.then(function(entry) {
|
|
23579
23603
|
if (!entry) {
|
|
23580
|
-
logger$
|
|
23604
|
+
logger$5.error('Failed to get performance entry for XHR request to ' + req.url);
|
|
23581
23605
|
return;
|
|
23582
23606
|
}
|
|
23583
23607
|
/** @type {NetworkRequest} */
|
|
@@ -23597,7 +23621,7 @@
|
|
|
23597
23621
|
cb({ requests: [request] });
|
|
23598
23622
|
})
|
|
23599
23623
|
.catch(function(e) {
|
|
23600
|
-
logger$
|
|
23624
|
+
logger$5.error('Error recording XHR request to ' + req.url + ': ' + String(e));
|
|
23601
23625
|
});
|
|
23602
23626
|
});
|
|
23603
23627
|
|
|
@@ -23689,7 +23713,7 @@
|
|
|
23689
23713
|
})
|
|
23690
23714
|
.then(function(entry) {
|
|
23691
23715
|
if (!entry) {
|
|
23692
|
-
logger$
|
|
23716
|
+
logger$5.error('Failed to get performance entry for fetch request to ' + req.url);
|
|
23693
23717
|
return;
|
|
23694
23718
|
}
|
|
23695
23719
|
/** @type {NetworkRequest} */
|
|
@@ -23709,7 +23733,7 @@
|
|
|
23709
23733
|
cb({ requests: [request] });
|
|
23710
23734
|
})
|
|
23711
23735
|
.catch(function (e) {
|
|
23712
|
-
logger$
|
|
23736
|
+
logger$5.error('Error recording fetch request to ' + req.url + ': ' + String(e));
|
|
23713
23737
|
});
|
|
23714
23738
|
|
|
23715
23739
|
return originalFetchPromise;
|
|
@@ -23782,7 +23806,7 @@
|
|
|
23782
23806
|
*/
|
|
23783
23807
|
|
|
23784
23808
|
|
|
23785
|
-
var logger$
|
|
23809
|
+
var logger$4 = console_with_prefix('recorder');
|
|
23786
23810
|
var CompressionStream = win['CompressionStream'];
|
|
23787
23811
|
|
|
23788
23812
|
var RECORDER_BATCHER_LIB_CONFIG = {
|
|
@@ -23879,11 +23903,11 @@
|
|
|
23879
23903
|
|
|
23880
23904
|
// disable persistence if localStorage is not supported
|
|
23881
23905
|
// request-queue will automatically disable persistence if indexedDB fails to initialize
|
|
23882
|
-
var usePersistence = localStorageSupported(options.sharedLockStorage, true) && !this.getConfig('disable_persistence');
|
|
23906
|
+
var usePersistence = localStorageSupported(options.sharedLockStorage || getLocalStorage(), true) && !this.getConfig('disable_persistence');
|
|
23883
23907
|
|
|
23884
23908
|
// each replay has its own batcher key to avoid conflicts between rrweb events of different recordings
|
|
23885
23909
|
this.batcherKey = '__mprec_' + this.getConfig('name') + '_' + this.getConfig('token') + '_' + this.replayId;
|
|
23886
|
-
this.queueStorage = new IDBStorageWrapper(RECORDING_EVENTS_STORE_NAME);
|
|
23910
|
+
this.queueStorage = new IDBStorageWrapper(MIXPANEL_BROWSER_DB_NAME, RECORDING_EVENTS_STORE_NAME, RECORDER_VERSION_DATA);
|
|
23887
23911
|
this.batcher = new RequestBatcher(this.batcherKey, {
|
|
23888
23912
|
errorReporter: this.reportError.bind(this),
|
|
23889
23913
|
flushOnlyOnInterval: true,
|
|
@@ -23962,14 +23986,14 @@
|
|
|
23962
23986
|
}
|
|
23963
23987
|
|
|
23964
23988
|
if (this._stopRecording !== null) {
|
|
23965
|
-
logger$
|
|
23989
|
+
logger$4.log('Recording already in progress, skipping startRecording.');
|
|
23966
23990
|
return;
|
|
23967
23991
|
}
|
|
23968
23992
|
|
|
23969
23993
|
this.recordMaxMs = this.getConfig('record_max_ms');
|
|
23970
23994
|
if (this.recordMaxMs > MAX_RECORDING_MS) {
|
|
23971
23995
|
this.recordMaxMs = MAX_RECORDING_MS;
|
|
23972
|
-
logger$
|
|
23996
|
+
logger$4.critical('record_max_ms cannot be greater than ' + MAX_RECORDING_MS + 'ms. Capping value.');
|
|
23973
23997
|
}
|
|
23974
23998
|
|
|
23975
23999
|
if (!this.maxExpires) {
|
|
@@ -24033,7 +24057,7 @@
|
|
|
24033
24057
|
);
|
|
24034
24058
|
}
|
|
24035
24059
|
|
|
24036
|
-
var validatedOrigins = validateAllowedOrigins(this.getConfig('record_allowed_iframe_origins'), logger$
|
|
24060
|
+
var validatedOrigins = validateAllowedOrigins(this.getConfig('record_allowed_iframe_origins'), logger$4);
|
|
24037
24061
|
|
|
24038
24062
|
try {
|
|
24039
24063
|
this._stopRecording = this._rrwebRecord({
|
|
@@ -24295,14 +24319,14 @@
|
|
|
24295
24319
|
|
|
24296
24320
|
|
|
24297
24321
|
SessionRecording.prototype.reportError = function(msg, err) {
|
|
24298
|
-
logger$
|
|
24322
|
+
logger$4.error.apply(logger$4.error, arguments);
|
|
24299
24323
|
try {
|
|
24300
24324
|
if (!err && !(msg instanceof Error)) {
|
|
24301
24325
|
msg = new Error(msg);
|
|
24302
24326
|
}
|
|
24303
24327
|
this.getConfig('error_reporter')(msg, err);
|
|
24304
24328
|
} catch(err) {
|
|
24305
|
-
logger$
|
|
24329
|
+
logger$4.error(err);
|
|
24306
24330
|
}
|
|
24307
24331
|
};
|
|
24308
24332
|
|
|
@@ -24331,7 +24355,7 @@
|
|
|
24331
24355
|
var configValue = this.getConfig('record_min_ms');
|
|
24332
24356
|
|
|
24333
24357
|
if (configValue > MAX_VALUE_FOR_MIN_RECORDING_MS) {
|
|
24334
|
-
logger$
|
|
24358
|
+
logger$4.critical('record_min_ms cannot be greater than ' + MAX_VALUE_FOR_MIN_RECORDING_MS + 'ms. Capping value.');
|
|
24335
24359
|
return MAX_VALUE_FOR_MIN_RECORDING_MS;
|
|
24336
24360
|
}
|
|
24337
24361
|
|
|
@@ -24373,7 +24397,7 @@
|
|
|
24373
24397
|
*/
|
|
24374
24398
|
var RecordingRegistry = function (options) {
|
|
24375
24399
|
/** @type {IDBStorageWrapper} */
|
|
24376
|
-
this.idb = new IDBStorageWrapper(RECORDING_REGISTRY_STORE_NAME);
|
|
24400
|
+
this.idb = new IDBStorageWrapper(MIXPANEL_BROWSER_DB_NAME, RECORDING_REGISTRY_STORE_NAME, RECORDER_VERSION_DATA);
|
|
24377
24401
|
this.errorReporter = options.errorReporter;
|
|
24378
24402
|
this.mixpanelInstance = options.mixpanelInstance;
|
|
24379
24403
|
this.sharedLockStorage = options.sharedLockStorage;
|
|
@@ -24494,7 +24518,7 @@
|
|
|
24494
24518
|
.catch(this.handleError.bind(this));
|
|
24495
24519
|
};
|
|
24496
24520
|
|
|
24497
|
-
var logger$
|
|
24521
|
+
var logger$3 = console_with_prefix('recorder');
|
|
24498
24522
|
|
|
24499
24523
|
/**
|
|
24500
24524
|
* Recorder API: bundles rrweb and and exposes methods to start and stop recordings.
|
|
@@ -24510,7 +24534,7 @@
|
|
|
24510
24534
|
*/
|
|
24511
24535
|
this.recordingRegistry = new RecordingRegistry({
|
|
24512
24536
|
mixpanelInstance: this.mixpanelInstance,
|
|
24513
|
-
errorReporter: logger$
|
|
24537
|
+
errorReporter: logger$3.error,
|
|
24514
24538
|
sharedLockStorage: sharedLockStorage
|
|
24515
24539
|
});
|
|
24516
24540
|
this._flushInactivePromise = this.recordingRegistry.flushInactiveRecordings();
|
|
@@ -24522,17 +24546,17 @@
|
|
|
24522
24546
|
MixpanelRecorder.prototype.startRecording = function(options) {
|
|
24523
24547
|
options = options || {};
|
|
24524
24548
|
if (this.activeRecording && !this.activeRecording.isRrwebStopped()) {
|
|
24525
|
-
logger$
|
|
24549
|
+
logger$3.log('Recording already in progress, skipping startRecording.');
|
|
24526
24550
|
return;
|
|
24527
24551
|
}
|
|
24528
24552
|
|
|
24529
24553
|
var onIdleTimeout = function () {
|
|
24530
|
-
logger$
|
|
24554
|
+
logger$3.log('Idle timeout reached, restarting recording.');
|
|
24531
24555
|
this.resetRecording();
|
|
24532
24556
|
}.bind(this);
|
|
24533
24557
|
|
|
24534
24558
|
var onMaxLengthReached = function () {
|
|
24535
|
-
logger$
|
|
24559
|
+
logger$3.log('Max recording length reached, stopping recording.');
|
|
24536
24560
|
this.resetRecording();
|
|
24537
24561
|
}.bind(this);
|
|
24538
24562
|
|
|
@@ -24602,7 +24626,7 @@
|
|
|
24602
24626
|
} else if (startNewIfInactive) {
|
|
24603
24627
|
return this.startRecording({shouldStopBatcher: false});
|
|
24604
24628
|
} else {
|
|
24605
|
-
logger$
|
|
24629
|
+
logger$3.log('No resumable recording found.');
|
|
24606
24630
|
return null;
|
|
24607
24631
|
}
|
|
24608
24632
|
}.bind(this));
|
|
@@ -25267,7 +25291,7 @@
|
|
|
25267
25291
|
observer.observe(shadowRoot, this.observerConfig);
|
|
25268
25292
|
this.shadowObservers.push(observer);
|
|
25269
25293
|
} catch (e) {
|
|
25270
|
-
logger$
|
|
25294
|
+
logger$6.critical('Error while observing shadow root', e);
|
|
25271
25295
|
}
|
|
25272
25296
|
};
|
|
25273
25297
|
|
|
@@ -25278,7 +25302,7 @@
|
|
|
25278
25302
|
}
|
|
25279
25303
|
|
|
25280
25304
|
if (!weakSetSupported()) {
|
|
25281
|
-
logger$
|
|
25305
|
+
logger$6.critical('Shadow DOM observation unavailable: WeakSet not supported');
|
|
25282
25306
|
return;
|
|
25283
25307
|
}
|
|
25284
25308
|
|
|
@@ -25294,7 +25318,7 @@
|
|
|
25294
25318
|
try {
|
|
25295
25319
|
this.shadowObservers[i].disconnect();
|
|
25296
25320
|
} catch (e) {
|
|
25297
|
-
logger$
|
|
25321
|
+
logger$6.critical('Error while disconnecting shadow DOM observer', e);
|
|
25298
25322
|
}
|
|
25299
25323
|
}
|
|
25300
25324
|
this.shadowObservers = [];
|
|
@@ -25482,7 +25506,7 @@
|
|
|
25482
25506
|
|
|
25483
25507
|
this.mutationObserver.observe(document.body || document.documentElement, MUTATION_OBSERVER_CONFIG);
|
|
25484
25508
|
} catch (e) {
|
|
25485
|
-
logger$
|
|
25509
|
+
logger$6.critical('Error while setting up mutation observer', e);
|
|
25486
25510
|
}
|
|
25487
25511
|
}
|
|
25488
25512
|
|
|
@@ -25497,7 +25521,7 @@
|
|
|
25497
25521
|
);
|
|
25498
25522
|
this.shadowDOMObserver.start();
|
|
25499
25523
|
} catch (e) {
|
|
25500
|
-
logger$
|
|
25524
|
+
logger$6.critical('Error while setting up shadow DOM observer', e);
|
|
25501
25525
|
this.shadowDOMObserver = null;
|
|
25502
25526
|
}
|
|
25503
25527
|
}
|
|
@@ -25524,7 +25548,7 @@
|
|
|
25524
25548
|
try {
|
|
25525
25549
|
listener.target.removeEventListener(listener.event, listener.handler, listener.options);
|
|
25526
25550
|
} catch (e) {
|
|
25527
|
-
logger$
|
|
25551
|
+
logger$6.critical('Error while removing event listener', e);
|
|
25528
25552
|
}
|
|
25529
25553
|
}
|
|
25530
25554
|
this.eventListeners = [];
|
|
@@ -25533,7 +25557,7 @@
|
|
|
25533
25557
|
try {
|
|
25534
25558
|
this.mutationObserver.disconnect();
|
|
25535
25559
|
} catch (e) {
|
|
25536
|
-
logger$
|
|
25560
|
+
logger$6.critical('Error while disconnecting mutation observer', e);
|
|
25537
25561
|
}
|
|
25538
25562
|
this.mutationObserver = null;
|
|
25539
25563
|
}
|
|
@@ -25542,7 +25566,7 @@
|
|
|
25542
25566
|
try {
|
|
25543
25567
|
this.shadowDOMObserver.stop();
|
|
25544
25568
|
} catch (e) {
|
|
25545
|
-
logger$
|
|
25569
|
+
logger$6.critical('Error while stopping shadow DOM observer', e);
|
|
25546
25570
|
}
|
|
25547
25571
|
this.shadowDOMObserver = null;
|
|
25548
25572
|
}
|
|
@@ -25620,7 +25644,7 @@
|
|
|
25620
25644
|
|
|
25621
25645
|
Autocapture.prototype.init = function() {
|
|
25622
25646
|
if (!minDOMApisSupported()) {
|
|
25623
|
-
logger$
|
|
25647
|
+
logger$6.critical('Autocapture unavailable: missing required DOM APIs');
|
|
25624
25648
|
return;
|
|
25625
25649
|
}
|
|
25626
25650
|
this.initPageListeners();
|
|
@@ -25660,7 +25684,7 @@
|
|
|
25660
25684
|
try {
|
|
25661
25685
|
return !urlMatchesRegexList(currentUrl, allowUrlRegexes);
|
|
25662
25686
|
} catch (err) {
|
|
25663
|
-
logger$
|
|
25687
|
+
logger$6.critical('Error while checking block URL regexes: ', err);
|
|
25664
25688
|
return true;
|
|
25665
25689
|
}
|
|
25666
25690
|
}
|
|
@@ -25673,7 +25697,7 @@
|
|
|
25673
25697
|
try {
|
|
25674
25698
|
return urlMatchesRegexList(currentUrl, blockUrlRegexes);
|
|
25675
25699
|
} catch (err) {
|
|
25676
|
-
logger$
|
|
25700
|
+
logger$6.critical('Error while checking block URL regexes: ', err);
|
|
25677
25701
|
return true;
|
|
25678
25702
|
}
|
|
25679
25703
|
};
|
|
@@ -25811,7 +25835,7 @@
|
|
|
25811
25835
|
return;
|
|
25812
25836
|
}
|
|
25813
25837
|
|
|
25814
|
-
logger$
|
|
25838
|
+
logger$6.log('Initializing scroll depth tracking');
|
|
25815
25839
|
|
|
25816
25840
|
this.maxScrollViewDepth = Math.max(document$1.documentElement.clientHeight, win.innerHeight || 0);
|
|
25817
25841
|
|
|
@@ -25837,7 +25861,7 @@
|
|
|
25837
25861
|
if (!this.getConfig(CONFIG_TRACK_CLICK) && !this.mp.get_config('record_heatmap_data')) {
|
|
25838
25862
|
return;
|
|
25839
25863
|
}
|
|
25840
|
-
logger$
|
|
25864
|
+
logger$6.log('Initializing click tracking');
|
|
25841
25865
|
|
|
25842
25866
|
this.listenerClick = function(ev) {
|
|
25843
25867
|
if (!this.getConfig(CONFIG_TRACK_CLICK) && !this.mp.is_recording_heatmap_data()) {
|
|
@@ -25856,7 +25880,7 @@
|
|
|
25856
25880
|
return;
|
|
25857
25881
|
}
|
|
25858
25882
|
|
|
25859
|
-
logger$
|
|
25883
|
+
logger$6.log('Initializing dead click tracking');
|
|
25860
25884
|
if (!this._deadClickTracker) {
|
|
25861
25885
|
this._deadClickTracker = new DeadClickTracker(function(deadClickEvent) {
|
|
25862
25886
|
this.trackDomEvent(deadClickEvent, MP_EV_DEAD_CLICK);
|
|
@@ -25890,7 +25914,7 @@
|
|
|
25890
25914
|
if (!this.getConfig(CONFIG_TRACK_INPUT)) {
|
|
25891
25915
|
return;
|
|
25892
25916
|
}
|
|
25893
|
-
logger$
|
|
25917
|
+
logger$6.log('Initializing input tracking');
|
|
25894
25918
|
|
|
25895
25919
|
this.listenerChange = function(ev) {
|
|
25896
25920
|
if (!this.getConfig(CONFIG_TRACK_INPUT)) {
|
|
@@ -25904,14 +25928,15 @@
|
|
|
25904
25928
|
Autocapture.prototype.initPageviewTracking = function() {
|
|
25905
25929
|
win.removeEventListener(EV_MP_LOCATION_CHANGE, this.listenerLocationchange);
|
|
25906
25930
|
|
|
25907
|
-
if (!this.pageviewTrackingConfig()) {
|
|
25931
|
+
if (!this.pageviewTrackingConfig() && !this.mp.get_config('record_heatmap_data')) {
|
|
25908
25932
|
return;
|
|
25909
25933
|
}
|
|
25910
|
-
logger$
|
|
25934
|
+
logger$6.log('Initializing pageview tracking');
|
|
25911
25935
|
|
|
25912
25936
|
var previousTrackedUrl = '';
|
|
25913
25937
|
var tracked = false;
|
|
25914
|
-
if
|
|
25938
|
+
// Track initial pageview if pageview tracking enabled OR heatmap recording is active
|
|
25939
|
+
if ((this.pageviewTrackingConfig() || this.mp.is_recording_heatmap_data()) && !this.currentUrlBlocked()) {
|
|
25915
25940
|
tracked = this.mp.track_pageview(DEFAULT_PROPS);
|
|
25916
25941
|
}
|
|
25917
25942
|
if (tracked) {
|
|
@@ -25927,6 +25952,10 @@
|
|
|
25927
25952
|
var shouldTrack = false;
|
|
25928
25953
|
var didPathChange = currentUrl.split('#')[0].split('?')[0] !== previousTrackedUrl.split('#')[0].split('?')[0];
|
|
25929
25954
|
var trackPageviewOption = this.pageviewTrackingConfig();
|
|
25955
|
+
if (!trackPageviewOption && this.mp.is_recording_heatmap_data()) {
|
|
25956
|
+
trackPageviewOption = PAGEVIEW_OPTION_FULL_URL;
|
|
25957
|
+
}
|
|
25958
|
+
|
|
25930
25959
|
if (trackPageviewOption === PAGEVIEW_OPTION_FULL_URL) {
|
|
25931
25960
|
shouldTrack = currentUrl !== previousTrackedUrl;
|
|
25932
25961
|
} else if (trackPageviewOption === PAGEVIEW_OPTION_URL_WITH_PATH_AND_QUERY_STRING) {
|
|
@@ -25942,7 +25971,7 @@
|
|
|
25942
25971
|
}
|
|
25943
25972
|
if (didPathChange) {
|
|
25944
25973
|
this.lastScrollCheckpoint = 0;
|
|
25945
|
-
logger$
|
|
25974
|
+
logger$6.log('Path change: re-initializing scroll depth checkpoints');
|
|
25946
25975
|
}
|
|
25947
25976
|
}
|
|
25948
25977
|
}.bind(this));
|
|
@@ -25957,7 +25986,7 @@
|
|
|
25957
25986
|
return;
|
|
25958
25987
|
}
|
|
25959
25988
|
|
|
25960
|
-
logger$
|
|
25989
|
+
logger$6.log('Initializing rage click tracking');
|
|
25961
25990
|
if (!this._rageClickTracker) {
|
|
25962
25991
|
this._rageClickTracker = new RageClickTracker();
|
|
25963
25992
|
}
|
|
@@ -25987,7 +26016,7 @@
|
|
|
25987
26016
|
if (!this.getConfig(CONFIG_TRACK_SCROLL)) {
|
|
25988
26017
|
return;
|
|
25989
26018
|
}
|
|
25990
|
-
logger$
|
|
26019
|
+
logger$6.log('Initializing scroll tracking');
|
|
25991
26020
|
this.lastScrollCheckpoint = 0;
|
|
25992
26021
|
|
|
25993
26022
|
var scrollTrackFunction = function() {
|
|
@@ -26024,7 +26053,7 @@
|
|
|
26024
26053
|
}
|
|
26025
26054
|
}
|
|
26026
26055
|
} catch (err) {
|
|
26027
|
-
logger$
|
|
26056
|
+
logger$6.critical('Error while calculating scroll percentage', err);
|
|
26028
26057
|
}
|
|
26029
26058
|
if (shouldTrack) {
|
|
26030
26059
|
this.mp.track(MP_EV_SCROLL, props);
|
|
@@ -26042,7 +26071,7 @@
|
|
|
26042
26071
|
if (!this.getConfig(CONFIG_TRACK_SUBMIT)) {
|
|
26043
26072
|
return;
|
|
26044
26073
|
}
|
|
26045
|
-
logger$
|
|
26074
|
+
logger$6.log('Initializing submit tracking');
|
|
26046
26075
|
|
|
26047
26076
|
this.listenerSubmit = function(ev) {
|
|
26048
26077
|
if (!this.getConfig(CONFIG_TRACK_SUBMIT)) {
|
|
@@ -26064,7 +26093,7 @@
|
|
|
26064
26093
|
return;
|
|
26065
26094
|
}
|
|
26066
26095
|
|
|
26067
|
-
logger$
|
|
26096
|
+
logger$6.log('Initializing page visibility tracking.');
|
|
26068
26097
|
this._initScrollDepthTracking();
|
|
26069
26098
|
var previousTrackedUrl = _.info.currentUrl();
|
|
26070
26099
|
|
|
@@ -26149,10 +26178,183 @@
|
|
|
26149
26178
|
return win[TARGETING_GLOBAL_NAME];
|
|
26150
26179
|
};
|
|
26151
26180
|
|
|
26181
|
+
var logger$2 = console_with_prefix('flags');
|
|
26182
|
+
|
|
26183
|
+
var MIXPANEL_FLAGS_DB_NAME = 'mixpanelFlagsDb';
|
|
26184
|
+
var FLAGS_STORE_NAME = 'mixpanelFlags';
|
|
26185
|
+
|
|
26186
|
+
// Keeping these two properties closeby, as adding additional stores to a DB in IndexedDB requires a version increment
|
|
26187
|
+
var FLAGS_VERSION_DATA = { version: 1, storeNames: [FLAGS_STORE_NAME] };
|
|
26188
|
+
|
|
26189
|
+
var PERSISTED_VARIANTS_KEY_PREFIX = 'persisted_variants_for_';
|
|
26190
|
+
var DEFAULT_TTL_MS = 24 * 60 * 60 * 1000;
|
|
26191
|
+
|
|
26192
|
+
var VariantLookupPolicy = Object.freeze({
|
|
26193
|
+
NETWORK_ONLY: 'networkOnly',
|
|
26194
|
+
NETWORK_FIRST: 'networkFirst',
|
|
26195
|
+
PERSISTENCE_UNTIL_NETWORK_SUCCESS: 'persistenceUntilNetworkSuccess'
|
|
26196
|
+
});
|
|
26197
|
+
|
|
26198
|
+
var VALID_POLICIES = [
|
|
26199
|
+
VariantLookupPolicy.NETWORK_ONLY,
|
|
26200
|
+
VariantLookupPolicy.NETWORK_FIRST,
|
|
26201
|
+
VariantLookupPolicy.PERSISTENCE_UNTIL_NETWORK_SUCCESS
|
|
26202
|
+
];
|
|
26203
|
+
|
|
26204
|
+
/**
|
|
26205
|
+
* Module for handling the storage and retrieval of persisted feature flag variants.
|
|
26206
|
+
*/
|
|
26207
|
+
var FeatureFlagPersistence = function(persistenceConfig, token, isGloballyDisabled) {
|
|
26208
|
+
this.idb = new IDBStorageWrapper(MIXPANEL_FLAGS_DB_NAME, FLAGS_STORE_NAME, FLAGS_VERSION_DATA);
|
|
26209
|
+
this.persistenceConfig = persistenceConfig;
|
|
26210
|
+
this.persistedVariantsKey = PERSISTED_VARIANTS_KEY_PREFIX + token;
|
|
26211
|
+
this.isGloballyDisabled = isGloballyDisabled || function() { return false; };
|
|
26212
|
+
};
|
|
26213
|
+
|
|
26214
|
+
FeatureFlagPersistence.prototype.getPolicy = function() {
|
|
26215
|
+
if (this.isGloballyDisabled() || !this._isConfigValid()) {
|
|
26216
|
+
return VariantLookupPolicy.NETWORK_ONLY;
|
|
26217
|
+
}
|
|
26218
|
+
return this.persistenceConfig['variantLookupPolicy'];
|
|
26219
|
+
};
|
|
26220
|
+
|
|
26221
|
+
FeatureFlagPersistence.prototype.getTtlMs = function() {
|
|
26222
|
+
if (!this._isConfigValid()) {
|
|
26223
|
+
return DEFAULT_TTL_MS;
|
|
26224
|
+
}
|
|
26225
|
+
var configuredTtl = this.persistenceConfig['persistenceTtlMs'];
|
|
26226
|
+
return (configuredTtl === undefined || configuredTtl === null) ? DEFAULT_TTL_MS : configuredTtl;
|
|
26227
|
+
};
|
|
26228
|
+
|
|
26229
|
+
FeatureFlagPersistence.prototype._isConfigValid = function() {
|
|
26230
|
+
var config = this.persistenceConfig;
|
|
26231
|
+
if (!config) {
|
|
26232
|
+
return false;
|
|
26233
|
+
}
|
|
26234
|
+
|
|
26235
|
+
if (VALID_POLICIES.indexOf(config['variantLookupPolicy']) === -1) {
|
|
26236
|
+
logger$2.error('Invalid variantLookupPolicy:', config['variantLookupPolicy']);
|
|
26237
|
+
return false;
|
|
26238
|
+
}
|
|
26239
|
+
|
|
26240
|
+
if (config['persistenceTtlMs'] !== undefined &&
|
|
26241
|
+
config['persistenceTtlMs'] !== null &&
|
|
26242
|
+
config['persistenceTtlMs'] <= 0) {
|
|
26243
|
+
logger$2.error('If provided, persistenceTtlMs must be a positive number. Provided value:', config['persistenceTtlMs']);
|
|
26244
|
+
return false;
|
|
26245
|
+
}
|
|
26246
|
+
|
|
26247
|
+
return true;
|
|
26248
|
+
};
|
|
26249
|
+
|
|
26250
|
+
FeatureFlagPersistence.prototype.loadFlagsFromStorage = function(context) {
|
|
26251
|
+
var clearAndReturnNull = _.bind(function() {
|
|
26252
|
+
return this.clear().then(function() { return null; }).catch(function() { return null; });
|
|
26253
|
+
}, this);
|
|
26254
|
+
|
|
26255
|
+
if (this.getPolicy() === VariantLookupPolicy.NETWORK_ONLY) {
|
|
26256
|
+
return clearAndReturnNull();
|
|
26257
|
+
}
|
|
26258
|
+
|
|
26259
|
+
var ttlMs = this.getTtlMs();
|
|
26260
|
+
|
|
26261
|
+
return this.idb.init().then(_.bind(function() {
|
|
26262
|
+
return this.idb.getItem(this.persistedVariantsKey);
|
|
26263
|
+
}, this)).then(_.bind(function(data) {
|
|
26264
|
+
if (!data) {
|
|
26265
|
+
logger$2.log('No persisted variants found in IndexedDB');
|
|
26266
|
+
return null;
|
|
26267
|
+
}
|
|
26268
|
+
|
|
26269
|
+
if (ttlMs && Date.now() - data['persistedAt'] >= ttlMs) {
|
|
26270
|
+
logger$2.log('Persisted variants are expiring');
|
|
26271
|
+
return null;
|
|
26272
|
+
}
|
|
26273
|
+
|
|
26274
|
+
if (!context || data['distinctId'] !== context['distinct_id']) {
|
|
26275
|
+
logger$2.log('Persisted variants found, but for a different distinct_id so clearing.');
|
|
26276
|
+
return clearAndReturnNull();
|
|
26277
|
+
}
|
|
26278
|
+
|
|
26279
|
+
var persistedFlags = new Map();
|
|
26280
|
+
_.each(data['flagVariants'], function(variantData, key) {
|
|
26281
|
+
persistedFlags.set(key, {
|
|
26282
|
+
'key': variantData['variant_key'],
|
|
26283
|
+
'value': variantData['variant_value'],
|
|
26284
|
+
'experiment_id': variantData['experiment_id'],
|
|
26285
|
+
'is_experiment_active': variantData['is_experiment_active'],
|
|
26286
|
+
'is_qa_tester': variantData['is_qa_tester'],
|
|
26287
|
+
'variant_source': 'persistence',
|
|
26288
|
+
'persisted_at_in_ms': data['persistedAt'],
|
|
26289
|
+
'ttl_in_ms': ttlMs
|
|
26290
|
+
});
|
|
26291
|
+
});
|
|
26292
|
+
|
|
26293
|
+
logger$2.log('Loaded', persistedFlags.size, 'variants from IndexedDB for distinct_id', data['distinctId']);
|
|
26294
|
+
|
|
26295
|
+
return {
|
|
26296
|
+
flags: persistedFlags,
|
|
26297
|
+
pendingFirstTimeEvents: data['pendingFirstTimeEvents'] || {},
|
|
26298
|
+
persistedAtMs: data['persistedAt'],
|
|
26299
|
+
ttlMs: ttlMs
|
|
26300
|
+
};
|
|
26301
|
+
}, this)).catch(_.bind(function(error) {
|
|
26302
|
+
logger$2.error('Failed to load persisted variants from IndexedDB, so clearing', error);
|
|
26303
|
+
return clearAndReturnNull();
|
|
26304
|
+
}, this));
|
|
26305
|
+
};
|
|
26306
|
+
|
|
26307
|
+
FeatureFlagPersistence.prototype.save = function(context, flagsMap, pendingFirstTimeEvents) {
|
|
26308
|
+
if (this.getPolicy() === VariantLookupPolicy.NETWORK_ONLY) {
|
|
26309
|
+
return Promise.resolve();
|
|
26310
|
+
}
|
|
26311
|
+
|
|
26312
|
+
var flagVariants = {};
|
|
26313
|
+
flagsMap.forEach(function(variant, key) {
|
|
26314
|
+
flagVariants[key] = {
|
|
26315
|
+
'variant_key': variant['key'],
|
|
26316
|
+
'variant_value': variant['value'],
|
|
26317
|
+
'experiment_id': variant['experiment_id'],
|
|
26318
|
+
'is_experiment_active': variant['is_experiment_active'],
|
|
26319
|
+
'is_qa_tester': variant['is_qa_tester']
|
|
26320
|
+
};
|
|
26321
|
+
});
|
|
26322
|
+
|
|
26323
|
+
var data = {
|
|
26324
|
+
'persistedAt': Date.now(),
|
|
26325
|
+
'distinctId': context && context['distinct_id'],
|
|
26326
|
+
'context': context,
|
|
26327
|
+
'flagVariants': flagVariants,
|
|
26328
|
+
'pendingFirstTimeEvents': pendingFirstTimeEvents || {}
|
|
26329
|
+
};
|
|
26330
|
+
|
|
26331
|
+
return this.idb.init().then(_.bind(function() {
|
|
26332
|
+
return this.idb.setItem(this.persistedVariantsKey, data);
|
|
26333
|
+
}, this)).then(function() {
|
|
26334
|
+
logger$2.log('Saved', flagsMap.size, 'variants to IndexedDB for distinct_id', data['distinctId']);
|
|
26335
|
+
}).catch(function(error) {
|
|
26336
|
+
logger$2.error('Failed to persist variants to IndexedDB:', error);
|
|
26337
|
+
});
|
|
26338
|
+
};
|
|
26339
|
+
|
|
26340
|
+
FeatureFlagPersistence.prototype.clear = function() {
|
|
26341
|
+
if (this.isGloballyDisabled()) {
|
|
26342
|
+
return Promise.resolve();
|
|
26343
|
+
}
|
|
26344
|
+
return this.idb.init().then(_.bind(function() {
|
|
26345
|
+
return this.idb.removeItem(this.persistedVariantsKey);
|
|
26346
|
+
}, this)).then(function() {
|
|
26347
|
+
logger$2.log('Cleared persisted variants from IndexedDB');
|
|
26348
|
+
}).catch(function(error) {
|
|
26349
|
+
logger$2.error('Failed to clear persisted variants from IndexedDB:', error);
|
|
26350
|
+
});
|
|
26351
|
+
};
|
|
26352
|
+
|
|
26152
26353
|
var logger$1 = console_with_prefix('flags');
|
|
26153
26354
|
var FLAGS_CONFIG_KEY = 'flags';
|
|
26154
26355
|
|
|
26155
26356
|
var CONFIG_CONTEXT = 'context';
|
|
26357
|
+
var CONFIG_PERSISTENCE = 'persistence';
|
|
26156
26358
|
var CONFIG_DEFAULTS = {};
|
|
26157
26359
|
CONFIG_DEFAULTS[CONFIG_CONTEXT] = {};
|
|
26158
26360
|
|
|
@@ -26175,6 +26377,13 @@
|
|
|
26175
26377
|
return eventKey.split(':')[0];
|
|
26176
26378
|
};
|
|
26177
26379
|
|
|
26380
|
+
var withFallbackSource = function(fallback) {
|
|
26381
|
+
if (_.isObject(fallback)) {
|
|
26382
|
+
return _.extend({}, fallback, {'variant_source': 'fallback'});
|
|
26383
|
+
}
|
|
26384
|
+
return {'value': fallback, 'variant_source': 'fallback'};
|
|
26385
|
+
};
|
|
26386
|
+
|
|
26178
26387
|
/**
|
|
26179
26388
|
* FeatureFlagManager: support for Mixpanel's feature flagging product
|
|
26180
26389
|
* @constructor
|
|
@@ -26197,13 +26406,63 @@
|
|
|
26197
26406
|
}
|
|
26198
26407
|
|
|
26199
26408
|
this.flags = null;
|
|
26200
|
-
this.fetchFlags().catch(function() {
|
|
26201
|
-
logger$1.error('Error fetching flags during init');
|
|
26202
|
-
});
|
|
26203
|
-
|
|
26204
26409
|
this.trackedFeatures = new Set();
|
|
26205
26410
|
this.pendingFirstTimeEvents = {};
|
|
26206
26411
|
this.activatedFirstTimeEvents = {};
|
|
26412
|
+
this._loadedPersistedAtMs = null;
|
|
26413
|
+
this._loadedTtlMs = null;
|
|
26414
|
+
|
|
26415
|
+
this.persistence = new FeatureFlagPersistence(
|
|
26416
|
+
this.getConfig(CONFIG_PERSISTENCE),
|
|
26417
|
+
this.getMpConfig('token'),
|
|
26418
|
+
_.bind(function() { return this.getMpConfig('disable_persistence'); }, this)
|
|
26419
|
+
);
|
|
26420
|
+
|
|
26421
|
+
this.persistenceLoadedPromise = this.persistence.loadFlagsFromStorage(this._buildContext())
|
|
26422
|
+
.then(_.bind(function(loaded) {
|
|
26423
|
+
if (loaded) {
|
|
26424
|
+
this.flags = loaded.flags;
|
|
26425
|
+
this.pendingFirstTimeEvents = loaded.pendingFirstTimeEvents;
|
|
26426
|
+
this._loadedPersistedAtMs = loaded.persistedAtMs;
|
|
26427
|
+
this._loadedTtlMs = loaded.ttlMs;
|
|
26428
|
+
}
|
|
26429
|
+
}, this));
|
|
26430
|
+
|
|
26431
|
+
return this.persistenceLoadedPromise
|
|
26432
|
+
.then(_.bind(function() {
|
|
26433
|
+
return this.fetchFlags();
|
|
26434
|
+
}, this))
|
|
26435
|
+
.catch(function() {
|
|
26436
|
+
logger$1.error('Error initializing feature flags');
|
|
26437
|
+
});
|
|
26438
|
+
};
|
|
26439
|
+
|
|
26440
|
+
FeatureFlagManager.prototype._buildContext = function() {
|
|
26441
|
+
return _.extend(
|
|
26442
|
+
{'distinct_id': this.getMpProperty('distinct_id'), 'device_id': this.getMpProperty('$device_id')},
|
|
26443
|
+
this.getConfig(CONFIG_CONTEXT)
|
|
26444
|
+
);
|
|
26445
|
+
};
|
|
26446
|
+
|
|
26447
|
+
FeatureFlagManager.prototype.reset = function() {
|
|
26448
|
+
if (!this.persistence) {
|
|
26449
|
+
return Promise.resolve();
|
|
26450
|
+
}
|
|
26451
|
+
|
|
26452
|
+
this.flags = null;
|
|
26453
|
+
this.pendingFirstTimeEvents = {};
|
|
26454
|
+
this.activatedFirstTimeEvents = {};
|
|
26455
|
+
this.trackedFeatures = new Set();
|
|
26456
|
+
this.fetchPromise = null;
|
|
26457
|
+
this._fetchInProgressStartTime = null;
|
|
26458
|
+
this._loadedPersistedAtMs = null;
|
|
26459
|
+
this._loadedTtlMs = null;
|
|
26460
|
+
|
|
26461
|
+
return this.persistence.clear().then(_.bind(function() {
|
|
26462
|
+
return this.fetchFlags();
|
|
26463
|
+
}, this)).catch(function() {
|
|
26464
|
+
logger$1.error('Error during flags reset');
|
|
26465
|
+
});
|
|
26207
26466
|
};
|
|
26208
26467
|
|
|
26209
26468
|
FeatureFlagManager.prototype.getFullConfig = function() {
|
|
@@ -26260,12 +26519,11 @@
|
|
|
26260
26519
|
return Promise.resolve();
|
|
26261
26520
|
}
|
|
26262
26521
|
|
|
26263
|
-
var
|
|
26264
|
-
var
|
|
26522
|
+
var context = this._buildContext();
|
|
26523
|
+
var distinctId = context['distinct_id'];
|
|
26265
26524
|
var traceparent = generateTraceparent();
|
|
26266
26525
|
logger$1.log('Fetching flags for distinct ID: ' + distinctId);
|
|
26267
26526
|
|
|
26268
|
-
var context = _.extend({'distinct_id': distinctId, 'device_id': deviceId}, this.getConfig(CONFIG_CONTEXT));
|
|
26269
26527
|
var searchParams = new URLSearchParams();
|
|
26270
26528
|
searchParams.set('context', JSON.stringify(context));
|
|
26271
26529
|
searchParams.set('token', this.getMpConfig('token'));
|
|
@@ -26315,7 +26573,8 @@
|
|
|
26315
26573
|
'value': data['variant_value'],
|
|
26316
26574
|
'experiment_id': data['experiment_id'],
|
|
26317
26575
|
'is_experiment_active': data['is_experiment_active'],
|
|
26318
|
-
'is_qa_tester': data['is_qa_tester']
|
|
26576
|
+
'is_qa_tester': data['is_qa_tester'],
|
|
26577
|
+
'variant_source': 'network'
|
|
26319
26578
|
});
|
|
26320
26579
|
}
|
|
26321
26580
|
}, this);
|
|
@@ -26357,10 +26616,15 @@
|
|
|
26357
26616
|
}
|
|
26358
26617
|
|
|
26359
26618
|
this.flags = flags;
|
|
26619
|
+
this.trackedFeatures = new Set();
|
|
26360
26620
|
this.pendingFirstTimeEvents = pendingFirstTimeEvents;
|
|
26621
|
+
this._loadedPersistedAtMs = null;
|
|
26622
|
+
this._loadedTtlMs = null;
|
|
26361
26623
|
this._traceparent = traceparent;
|
|
26362
26624
|
|
|
26363
26625
|
this._loadTargetingIfNeeded();
|
|
26626
|
+
|
|
26627
|
+
this.persistence.save(context, this.flags, this.pendingFirstTimeEvents);
|
|
26364
26628
|
}.bind(this)).catch(function(error) {
|
|
26365
26629
|
if (this._fetchInProgressStartTime) {
|
|
26366
26630
|
this.markFetchComplete();
|
|
@@ -26520,6 +26784,7 @@
|
|
|
26520
26784
|
};
|
|
26521
26785
|
|
|
26522
26786
|
this.flags.set(flagKey, newVariant);
|
|
26787
|
+
this.trackedFeatures.delete(flagKey);
|
|
26523
26788
|
this.activatedFirstTimeEvents[eventKey] = true;
|
|
26524
26789
|
|
|
26525
26790
|
this.recordFirstTimeEvent(
|
|
@@ -26569,35 +26834,106 @@
|
|
|
26569
26834
|
};
|
|
26570
26835
|
|
|
26571
26836
|
FeatureFlagManager.prototype.getVariant = function(featureName, fallback) {
|
|
26572
|
-
if (!this.
|
|
26837
|
+
if (!this.persistenceLoadedPromise) {
|
|
26573
26838
|
return new Promise(function(resolve) {
|
|
26574
26839
|
logger$1.critical('Feature Flags not initialized');
|
|
26575
|
-
resolve(fallback);
|
|
26840
|
+
resolve(withFallbackSource(fallback));
|
|
26576
26841
|
});
|
|
26577
26842
|
}
|
|
26578
26843
|
|
|
26579
|
-
|
|
26580
|
-
|
|
26581
|
-
|
|
26582
|
-
|
|
26583
|
-
|
|
26584
|
-
|
|
26844
|
+
var policy = this.persistence.getPolicy();
|
|
26845
|
+
|
|
26846
|
+
return this.persistenceLoadedPromise.then(_.bind(function() {
|
|
26847
|
+
// Serve from persistence until the network completes a successful fetch. If a non-expired cached value is available, return it without waiting on the in-flight fetch.
|
|
26848
|
+
if (policy === VariantLookupPolicy.PERSISTENCE_UNTIL_NETWORK_SUCCESS) {
|
|
26849
|
+
if (this.areFlagsReady() && !this._loadedPersistenceIsStale()) {
|
|
26850
|
+
return this.getVariantSync(featureName, fallback);
|
|
26851
|
+
}
|
|
26852
|
+
if (!this.fetchPromise) {
|
|
26853
|
+
return withFallbackSource(fallback);
|
|
26854
|
+
}
|
|
26855
|
+
return this.fetchPromise.then(_.bind(function() {
|
|
26856
|
+
return this.getVariantSync(featureName, fallback);
|
|
26857
|
+
}, this)).catch(function(error) {
|
|
26858
|
+
logger$1.error(error);
|
|
26859
|
+
return withFallbackSource(fallback);
|
|
26860
|
+
});
|
|
26861
|
+
}
|
|
26862
|
+
|
|
26863
|
+
var serve = _.bind(function() { return this.getVariantSync(featureName, fallback); }, this);
|
|
26864
|
+
if (!this.fetchPromise) {
|
|
26865
|
+
return withFallbackSource(fallback);
|
|
26866
|
+
}
|
|
26867
|
+
return this.fetchPromise.then(serve).catch(serve);
|
|
26868
|
+
}, this));
|
|
26869
|
+
};
|
|
26870
|
+
|
|
26871
|
+
FeatureFlagManager.prototype._loadedPersistenceIsStale = function() {
|
|
26872
|
+
if (!this._loadedPersistedAtMs || !this._loadedTtlMs) {
|
|
26873
|
+
return false;
|
|
26874
|
+
}
|
|
26875
|
+
return Date.now() - this._loadedPersistedAtMs >= this._loadedTtlMs;
|
|
26585
26876
|
};
|
|
26586
26877
|
|
|
26587
26878
|
FeatureFlagManager.prototype.getVariantSync = function(featureName, fallback) {
|
|
26879
|
+
if (this._loadedPersistenceIsStale()) {
|
|
26880
|
+
logger$1.log('Loaded persisted variants are past TTL so returning fallback for "' + featureName + '"');
|
|
26881
|
+
return withFallbackSource(fallback);
|
|
26882
|
+
}
|
|
26588
26883
|
if (!this.areFlagsReady()) {
|
|
26589
26884
|
logger$1.log('Flags not loaded yet');
|
|
26590
|
-
return fallback;
|
|
26885
|
+
return withFallbackSource(fallback);
|
|
26591
26886
|
}
|
|
26592
26887
|
var feature = this.flags.get(featureName);
|
|
26593
26888
|
if (!feature) {
|
|
26594
26889
|
logger$1.log('No flag found: "' + featureName + '"');
|
|
26595
|
-
return fallback;
|
|
26890
|
+
return withFallbackSource(fallback);
|
|
26596
26891
|
}
|
|
26597
26892
|
this.trackFeatureCheck(featureName, feature);
|
|
26598
26893
|
return feature;
|
|
26599
26894
|
};
|
|
26600
26895
|
|
|
26896
|
+
FeatureFlagManager.prototype.getAllVariants = function() {
|
|
26897
|
+
if (!this.persistenceLoadedPromise) {
|
|
26898
|
+
logger$1.critical('Feature Flags not initialized');
|
|
26899
|
+
return Promise.resolve(new Map());
|
|
26900
|
+
}
|
|
26901
|
+
|
|
26902
|
+
var policy = this.persistence.getPolicy();
|
|
26903
|
+
|
|
26904
|
+
return this.persistenceLoadedPromise.then(_.bind(function() {
|
|
26905
|
+
// Serve from persistence until the network completes a successful fetch. If a non-expired cached value is available, return it without waiting on the in-flight fetch.
|
|
26906
|
+
if (policy === VariantLookupPolicy.PERSISTENCE_UNTIL_NETWORK_SUCCESS) {
|
|
26907
|
+
if (this.areFlagsReady() && !this._loadedPersistenceIsStale()) {
|
|
26908
|
+
return this.getAllVariantsSync();
|
|
26909
|
+
}
|
|
26910
|
+
if (!this.fetchPromise) {
|
|
26911
|
+
return new Map();
|
|
26912
|
+
}
|
|
26913
|
+
return this.fetchPromise.then(_.bind(function() {
|
|
26914
|
+
return this.getAllVariantsSync();
|
|
26915
|
+
}, this)).catch(function(error) {
|
|
26916
|
+
logger$1.error(error);
|
|
26917
|
+
return new Map();
|
|
26918
|
+
});
|
|
26919
|
+
}
|
|
26920
|
+
|
|
26921
|
+
var serve = _.bind(this.getAllVariantsSync, this);
|
|
26922
|
+
if (!this.fetchPromise) {
|
|
26923
|
+
return new Map();
|
|
26924
|
+
}
|
|
26925
|
+
return this.fetchPromise.then(serve).catch(serve);
|
|
26926
|
+
}, this));
|
|
26927
|
+
};
|
|
26928
|
+
|
|
26929
|
+
FeatureFlagManager.prototype.getAllVariantsSync = function() {
|
|
26930
|
+
if (this._loadedPersistenceIsStale()) {
|
|
26931
|
+
logger$1.log('Loaded persisted variants are past TTL so returning empty Map');
|
|
26932
|
+
return new Map();
|
|
26933
|
+
}
|
|
26934
|
+
return this.flags || new Map();
|
|
26935
|
+
};
|
|
26936
|
+
|
|
26601
26937
|
FeatureFlagManager.prototype.getVariantValue = function(featureName, fallbackValue) {
|
|
26602
26938
|
return this.getVariant(featureName, {'value': fallbackValue}).then(function(feature) {
|
|
26603
26939
|
return feature['value'];
|
|
@@ -26636,6 +26972,10 @@
|
|
|
26636
26972
|
return val;
|
|
26637
26973
|
};
|
|
26638
26974
|
|
|
26975
|
+
function isPresent(v) {
|
|
26976
|
+
return v !== undefined && v !== null;
|
|
26977
|
+
}
|
|
26978
|
+
|
|
26639
26979
|
FeatureFlagManager.prototype.trackFeatureCheck = function(featureName, feature) {
|
|
26640
26980
|
if (this.trackedFeatures.has(featureName)) {
|
|
26641
26981
|
return;
|
|
@@ -26646,21 +26986,30 @@
|
|
|
26646
26986
|
'Experiment name': featureName,
|
|
26647
26987
|
'Variant name': feature['key'],
|
|
26648
26988
|
'$experiment_type': 'feature_flag',
|
|
26649
|
-
'Variant fetch start time': new Date(this._fetchStartTime).toISOString(),
|
|
26650
|
-
'Variant fetch complete time': new Date(this._fetchCompleteTime).toISOString(),
|
|
26989
|
+
'Variant fetch start time': isPresent(this._fetchStartTime) ? new Date(this._fetchStartTime).toISOString() : null,
|
|
26990
|
+
'Variant fetch complete time': isPresent(this._fetchCompleteTime) ? new Date(this._fetchCompleteTime).toISOString() : null,
|
|
26651
26991
|
'Variant fetch latency (ms)': this._fetchLatency,
|
|
26652
26992
|
'Variant fetch traceparent': this._traceparent,
|
|
26653
26993
|
};
|
|
26654
26994
|
|
|
26655
|
-
if (feature['experiment_id']
|
|
26995
|
+
if (isPresent(feature['experiment_id'])) {
|
|
26656
26996
|
trackingProperties['$experiment_id'] = feature['experiment_id'];
|
|
26657
26997
|
}
|
|
26658
|
-
if (feature['is_experiment_active']
|
|
26998
|
+
if (isPresent(feature['is_experiment_active'])) {
|
|
26659
26999
|
trackingProperties['$is_experiment_active'] = feature['is_experiment_active'];
|
|
26660
27000
|
}
|
|
26661
|
-
if (feature['is_qa_tester']
|
|
27001
|
+
if (isPresent(feature['is_qa_tester'])) {
|
|
26662
27002
|
trackingProperties['$is_qa_tester'] = feature['is_qa_tester'];
|
|
26663
27003
|
}
|
|
27004
|
+
if (isPresent(feature['variant_source'])) {
|
|
27005
|
+
trackingProperties['$variant_source'] = feature['variant_source'];
|
|
27006
|
+
}
|
|
27007
|
+
if (isPresent(feature['persisted_at_in_ms'])) {
|
|
27008
|
+
trackingProperties['$persisted_at_in_ms'] = feature['persisted_at_in_ms'];
|
|
27009
|
+
}
|
|
27010
|
+
if (isPresent(feature['ttl_in_ms'])) {
|
|
27011
|
+
trackingProperties['$ttl_in_ms'] = feature['ttl_in_ms'];
|
|
27012
|
+
}
|
|
26664
27013
|
|
|
26665
27014
|
this.track('$experiment_started', trackingProperties);
|
|
26666
27015
|
};
|
|
@@ -26684,6 +27033,8 @@
|
|
|
26684
27033
|
FeatureFlagManager.prototype['are_flags_ready'] = FeatureFlagManager.prototype.areFlagsReady;
|
|
26685
27034
|
FeatureFlagManager.prototype['get_variant'] = FeatureFlagManager.prototype.getVariant;
|
|
26686
27035
|
FeatureFlagManager.prototype['get_variant_sync'] = FeatureFlagManager.prototype.getVariantSync;
|
|
27036
|
+
FeatureFlagManager.prototype['get_all_variants'] = FeatureFlagManager.prototype.getAllVariants;
|
|
27037
|
+
FeatureFlagManager.prototype['get_all_variants_sync'] = FeatureFlagManager.prototype.getAllVariantsSync;
|
|
26687
27038
|
FeatureFlagManager.prototype['get_variant_value'] = FeatureFlagManager.prototype.getVariantValue;
|
|
26688
27039
|
FeatureFlagManager.prototype['get_variant_value_sync'] = FeatureFlagManager.prototype.getVariantValueSync;
|
|
26689
27040
|
FeatureFlagManager.prototype['is_enabled'] = FeatureFlagManager.prototype.isEnabled;
|
|
@@ -26736,7 +27087,7 @@
|
|
|
26736
27087
|
return PromisePolyfill.resolve(false);
|
|
26737
27088
|
}
|
|
26738
27089
|
|
|
26739
|
-
var recording_registry_idb = new IDBStorageWrapper(RECORDING_REGISTRY_STORE_NAME);
|
|
27090
|
+
var recording_registry_idb = new IDBStorageWrapper(MIXPANEL_BROWSER_DB_NAME, RECORDING_REGISTRY_STORE_NAME, RECORDER_VERSION_DATA);
|
|
26740
27091
|
var tab_id = this.getTabId();
|
|
26741
27092
|
return recording_registry_idb.init()
|
|
26742
27093
|
.then(function () {
|
|
@@ -28663,6 +29014,7 @@
|
|
|
28663
29014
|
'disable_all_events': false,
|
|
28664
29015
|
'identify_called': false
|
|
28665
29016
|
};
|
|
29017
|
+
this._remote_settings_strict_disabled = false;
|
|
28666
29018
|
|
|
28667
29019
|
// set up request queueing/batching
|
|
28668
29020
|
this.request_batchers = {};
|
|
@@ -28737,9 +29089,6 @@
|
|
|
28737
29089
|
this.flags.init();
|
|
28738
29090
|
this['flags'] = this.flags;
|
|
28739
29091
|
|
|
28740
|
-
this.autocapture = new Autocapture(this);
|
|
28741
|
-
this.autocapture.init();
|
|
28742
|
-
|
|
28743
29092
|
this._init_tab_id();
|
|
28744
29093
|
|
|
28745
29094
|
// Based on remote_settings_mode, fetch remote settings and then start session recording if applicable
|
|
@@ -28751,6 +29100,9 @@
|
|
|
28751
29100
|
} else {
|
|
28752
29101
|
this.__session_recording_init_promise = this._check_and_start_session_recording();
|
|
28753
29102
|
}
|
|
29103
|
+
|
|
29104
|
+
this.autocapture = new Autocapture(this);
|
|
29105
|
+
this.autocapture.init();
|
|
28754
29106
|
};
|
|
28755
29107
|
|
|
28756
29108
|
/**
|
|
@@ -28797,9 +29149,19 @@
|
|
|
28797
29149
|
return this.recorderManager.checkAndStartSessionRecording(force_start);
|
|
28798
29150
|
});
|
|
28799
29151
|
|
|
28800
|
-
MixpanelLib.prototype._start_recording_on_event = function(event_name, properties) {
|
|
28801
|
-
|
|
28802
|
-
|
|
29152
|
+
MixpanelLib.prototype._start_recording_on_event = safewrap(function(event_name, properties) {
|
|
29153
|
+
// Wait for recording init to complete before evaluating event triggers.
|
|
29154
|
+
// This ensures recording_event_triggers config is fully loaded when remote settings are used.
|
|
29155
|
+
if (this.__session_recording_init_promise) {
|
|
29156
|
+
this.__session_recording_init_promise.then(_.bind(function() {
|
|
29157
|
+
// In strict mode, skip recording if remote settings failed
|
|
29158
|
+
if (this._remote_settings_strict_disabled) {
|
|
29159
|
+
return;
|
|
29160
|
+
}
|
|
29161
|
+
return this.recorderManager.startRecordingOnEvent(event_name, properties);
|
|
29162
|
+
}, this));
|
|
29163
|
+
}
|
|
29164
|
+
});
|
|
28803
29165
|
|
|
28804
29166
|
MixpanelLib.prototype.start_session_recording = function () {
|
|
28805
29167
|
return this._check_and_start_session_recording(true);
|
|
@@ -29098,6 +29460,7 @@
|
|
|
29098
29460
|
var disableRecordingIfStrict = function() {
|
|
29099
29461
|
if (mode === 'strict') {
|
|
29100
29462
|
self.set_config({'record_sessions_percent': 0});
|
|
29463
|
+
self._remote_settings_strict_disabled = true;
|
|
29101
29464
|
}
|
|
29102
29465
|
};
|
|
29103
29466
|
|
|
@@ -29723,6 +30086,10 @@
|
|
|
29723
30086
|
properties
|
|
29724
30087
|
);
|
|
29725
30088
|
|
|
30089
|
+
if (this.is_recording_heatmap_data()) {
|
|
30090
|
+
event_properties['$captured_for_heatmap'] = true;
|
|
30091
|
+
}
|
|
30092
|
+
|
|
29726
30093
|
return this.track(event_name, event_properties);
|
|
29727
30094
|
});
|
|
29728
30095
|
|
|
@@ -30066,6 +30433,7 @@
|
|
|
30066
30433
|
'$device_id': uuid
|
|
30067
30434
|
}, '');
|
|
30068
30435
|
this._check_and_start_session_recording();
|
|
30436
|
+
this.flags.reset();
|
|
30069
30437
|
};
|
|
30070
30438
|
|
|
30071
30439
|
/**
|