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
@@ -1,6 +1,6 @@
1
1
  /* eslint camelcase: "off" */
2
2
  import {Config, TARGETING_FILENAME} from './config';
3
- import { MAX_RECORDING_MS, _, console, userAgent, document, navigator, slice, NOOP_FUNC, JSONStringify } from './utils';
3
+ import { MAX_RECORDING_MS, _, console, userAgent, document, navigator, slice, NOOP_FUNC, JSONStringify, safewrap } from './utils';
4
4
  import { window } from './window';
5
5
  import { Autocapture } from './autocapture';
6
6
  import { FeatureFlagManager } from './flags';
@@ -341,6 +341,7 @@ MixpanelLib.prototype._init = function(token, config, name) {
341
341
  'disable_all_events': false,
342
342
  'identify_called': false
343
343
  };
344
+ this._remote_settings_strict_disabled = false;
344
345
 
345
346
  // set up request queueing/batching
346
347
  this.request_batchers = {};
@@ -415,9 +416,6 @@ MixpanelLib.prototype._init = function(token, config, name) {
415
416
  this.flags.init();
416
417
  this['flags'] = this.flags;
417
418
 
418
- this.autocapture = new Autocapture(this);
419
- this.autocapture.init();
420
-
421
419
  this._init_tab_id();
422
420
 
423
421
  // Based on remote_settings_mode, fetch remote settings and then start session recording if applicable
@@ -429,6 +427,9 @@ MixpanelLib.prototype._init = function(token, config, name) {
429
427
  } else {
430
428
  this.__session_recording_init_promise = this._check_and_start_session_recording();
431
429
  }
430
+
431
+ this.autocapture = new Autocapture(this);
432
+ this.autocapture.init();
432
433
  };
433
434
 
434
435
  /**
@@ -475,9 +476,19 @@ MixpanelLib.prototype._check_and_start_session_recording = addOptOutCheckMixpane
475
476
  return this.recorderManager.checkAndStartSessionRecording(force_start);
476
477
  });
477
478
 
478
- MixpanelLib.prototype._start_recording_on_event = function(event_name, properties) {
479
- return this.recorderManager.startRecordingOnEvent(event_name, properties);
480
- };
479
+ MixpanelLib.prototype._start_recording_on_event = safewrap(function(event_name, properties) {
480
+ // Wait for recording init to complete before evaluating event triggers.
481
+ // This ensures recording_event_triggers config is fully loaded when remote settings are used.
482
+ if (this.__session_recording_init_promise) {
483
+ this.__session_recording_init_promise.then(_.bind(function() {
484
+ // In strict mode, skip recording if remote settings failed
485
+ if (this._remote_settings_strict_disabled) {
486
+ return;
487
+ }
488
+ return this.recorderManager.startRecordingOnEvent(event_name, properties);
489
+ }, this));
490
+ }
491
+ });
481
492
 
482
493
  MixpanelLib.prototype.start_session_recording = function () {
483
494
  return this._check_and_start_session_recording(true);
@@ -776,6 +787,7 @@ MixpanelLib.prototype._fetch_remote_settings = function(mode) {
776
787
  var disableRecordingIfStrict = function() {
777
788
  if (mode === 'strict') {
778
789
  self.set_config({'record_sessions_percent': 0});
790
+ self._remote_settings_strict_disabled = true;
779
791
  }
780
792
  };
781
793
 
@@ -1401,6 +1413,10 @@ MixpanelLib.prototype.track_pageview = addOptOutCheckMixpanelLib(function(proper
1401
1413
  properties
1402
1414
  );
1403
1415
 
1416
+ if (this.is_recording_heatmap_data()) {
1417
+ event_properties['$captured_for_heatmap'] = true;
1418
+ }
1419
+
1404
1420
  return this.track(event_name, event_properties);
1405
1421
  });
1406
1422
 
@@ -1724,7 +1740,9 @@ MixpanelLib.prototype.identify = function(
1724
1740
 
1725
1741
  // check feature flags again if distinct id has changed
1726
1742
  if (new_distinct_id !== previous_distinct_id) {
1727
- this.flags.fetchFlags();
1743
+ this.flags.fetchFlags().catch(function() {
1744
+ console.error('[flags] Error fetching flags during identify');
1745
+ });
1728
1746
  }
1729
1747
  };
1730
1748
 
@@ -1742,6 +1760,7 @@ MixpanelLib.prototype.reset = function() {
1742
1760
  '$device_id': uuid
1743
1761
  }, '');
1744
1762
  this._check_and_start_session_recording();
1763
+ this.flags.reset();
1745
1764
  };
1746
1765
 
1747
1766
  /**
@@ -0,0 +1,16 @@
1
+ var MIXPANEL_BROWSER_DB_NAME = 'mixpanelBrowserDb';
2
+ var RECORDING_EVENTS_STORE_NAME = 'mixpanelRecordingEvents';
3
+ var RECORDING_REGISTRY_STORE_NAME = 'mixpanelRecordingRegistry';
4
+
5
+ // Keeping these two properties closeby, as adding additional stores to a DB in IndexedDB requires a version increment
6
+ var RECORDER_VERSION_DATA = {
7
+ version: 1,
8
+ storeNames: [RECORDING_EVENTS_STORE_NAME, RECORDING_REGISTRY_STORE_NAME]
9
+ };
10
+
11
+ export {
12
+ MIXPANEL_BROWSER_DB_NAME,
13
+ RECORDING_EVENTS_STORE_NAME,
14
+ RECORDING_REGISTRY_STORE_NAME,
15
+ RECORDER_VERSION_DATA
16
+ };
@@ -1,5 +1,10 @@
1
1
  import { Promise } from '../promise-polyfill';
2
- import { IDBStorageWrapper, RECORDING_REGISTRY_STORE_NAME } from '../storage/indexed-db';
2
+ import { IDBStorageWrapper } from '../storage/indexed-db';
3
+ import {
4
+ MIXPANEL_BROWSER_DB_NAME,
5
+ RECORDING_REGISTRY_STORE_NAME,
6
+ RECORDER_VERSION_DATA
7
+ } from './idb-config';
3
8
  import { SessionRecording } from './session-recording';
4
9
  import { isRecordingExpired } from './utils';
5
10
 
@@ -9,7 +14,7 @@ import { isRecordingExpired } from './utils';
9
14
  */
10
15
  var RecordingRegistry = function (options) {
11
16
  /** @type {IDBStorageWrapper} */
12
- this.idb = new IDBStorageWrapper(RECORDING_REGISTRY_STORE_NAME);
17
+ this.idb = new IDBStorageWrapper(MIXPANEL_BROWSER_DB_NAME, RECORDING_REGISTRY_STORE_NAME, RECORDER_VERSION_DATA);
13
18
  this.errorReporter = options.errorReporter;
14
19
  this.mixpanelInstance = options.mixpanelInstance;
15
20
  this.sharedLockStorage = options.sharedLockStorage;
@@ -4,8 +4,13 @@
4
4
 
5
5
  import { window } from '../window';
6
6
  import { EventType, getRecordConsolePlugin, IncrementalSource } from './rrweb-entrypoint';
7
- import { MAX_RECORDING_MS, MAX_VALUE_FOR_MIN_RECORDING_MS, console_with_prefix, NOOP_FUNC, _, localStorageSupported, canUseCompressionStream, navigator, userAgent, windowOpera} from '../utils'; // eslint-disable-line camelcase
8
- import { IDBStorageWrapper, RECORDING_EVENTS_STORE_NAME } from '../storage/indexed-db';
7
+ import { MAX_RECORDING_MS, MAX_VALUE_FOR_MIN_RECORDING_MS, console_with_prefix, NOOP_FUNC, _, localStorageSupported, getLocalStorage, canUseCompressionStream, navigator, userAgent, windowOpera} from '../utils'; // eslint-disable-line camelcase
8
+ import { IDBStorageWrapper } from '../storage/indexed-db';
9
+ import {
10
+ MIXPANEL_BROWSER_DB_NAME,
11
+ RECORDING_EVENTS_STORE_NAME,
12
+ RECORDER_VERSION_DATA
13
+ } from './idb-config';
9
14
  import { addOptOutCheckMixpanelLib } from '../gdpr-utils';
10
15
  import { RequestBatcher } from '../request-batcher';
11
16
 
@@ -111,11 +116,11 @@ var SessionRecording = function(options) {
111
116
 
112
117
  // disable persistence if localStorage is not supported
113
118
  // request-queue will automatically disable persistence if indexedDB fails to initialize
114
- var usePersistence = localStorageSupported(options.sharedLockStorage, true) && !this.getConfig('disable_persistence');
119
+ var usePersistence = localStorageSupported(options.sharedLockStorage || getLocalStorage(), true) && !this.getConfig('disable_persistence');
115
120
 
116
121
  // each replay has its own batcher key to avoid conflicts between rrweb events of different recordings
117
122
  this.batcherKey = '__mprec_' + this.getConfig('name') + '_' + this.getConfig('token') + '_' + this.replayId;
118
- this.queueStorage = new IDBStorageWrapper(RECORDING_EVENTS_STORE_NAME);
123
+ this.queueStorage = new IDBStorageWrapper(MIXPANEL_BROWSER_DB_NAME, RECORDING_EVENTS_STORE_NAME, RECORDER_VERSION_DATA);
119
124
  this.batcher = new RequestBatcher(this.batcherKey, {
120
125
  errorReporter: this.reportError.bind(this),
121
126
  flushOnlyOnInterval: true,
@@ -4,7 +4,12 @@ import {RECORDER_FILENAME, TARGETING_FILENAME, RECORDER_GLOBAL_NAME} from './con
4
4
  import { _, console, console_with_prefix, safewrap, safewrapClass } from './utils';
5
5
  import { window } from './window';
6
6
  import { Promise } from './promise-polyfill';
7
- import { IDBStorageWrapper, RECORDING_REGISTRY_STORE_NAME } from './storage/indexed-db';
7
+ import { IDBStorageWrapper } from './storage/indexed-db';
8
+ import {
9
+ MIXPANEL_BROWSER_DB_NAME,
10
+ RECORDING_REGISTRY_STORE_NAME,
11
+ RECORDER_VERSION_DATA
12
+ } from './recorder/idb-config';
8
13
  import { isRecordingExpired, validateAllowedOrigins } from './recorder/utils';
9
14
  import { getTargetingPromise } from './targeting/loader';
10
15
 
@@ -43,7 +48,7 @@ RecorderManager.prototype.shouldLoadRecorder = function() {
43
48
  return Promise.resolve(false);
44
49
  }
45
50
 
46
- var recording_registry_idb = new IDBStorageWrapper(RECORDING_REGISTRY_STORE_NAME);
51
+ var recording_registry_idb = new IDBStorageWrapper(MIXPANEL_BROWSER_DB_NAME, RECORDING_REGISTRY_STORE_NAME, RECORDER_VERSION_DATA);
47
52
  var tab_id = this.getTabId();
48
53
  return recording_registry_idb.init()
49
54
  .then(function () {
@@ -1,6 +1,5 @@
1
1
  import { SharedLock } from './shared-lock';
2
2
  import { batchedThrottle, cheap_guid, console_with_prefix, localStorageSupported, _ } from './utils'; // eslint-disable-line camelcase
3
- import { window } from './window';
4
3
  import { LocalStorageWrapper } from './storage/local-storage';
5
4
  import { Promise } from './promise-polyfill';
6
5
 
@@ -29,7 +28,7 @@ var RequestQueue = function (storageKey, options) {
29
28
  if (this.usePersistence) {
30
29
  this.queueStorage = options.queueStorage || new LocalStorageWrapper();
31
30
  this.lock = new SharedLock(storageKey, {
32
- storage: options.sharedLockStorage || window.localStorage,
31
+ storage: options.sharedLockStorage,
33
32
  timeoutMS: options.sharedLockTimeoutMS,
34
33
  });
35
34
  }
@@ -1,6 +1,5 @@
1
1
  import { Promise } from './promise-polyfill';
2
- import { console_with_prefix, localStorageSupported, _ } from './utils'; // eslint-disable-line camelcase
3
- import { window } from './window';
2
+ import { console_with_prefix, localStorageSupported, getLocalStorage, _ } from './utils'; // eslint-disable-line camelcase
4
3
 
5
4
  var logger = console_with_prefix('lock');
6
5
 
@@ -28,7 +27,7 @@ var SharedLock = function(key, options) {
28
27
  options = options || {};
29
28
 
30
29
  this.storageKey = key;
31
- this.storage = options.storage || window.localStorage;
30
+ this.storage = options.storage || getLocalStorage();
32
31
  this.pollIntervalMS = options.pollIntervalMS || 100;
33
32
  this.timeoutMS = options.timeoutMS || 2000;
34
33
 
@@ -1,29 +1,26 @@
1
1
  import { Promise } from '../promise-polyfill';
2
2
  import { window } from '../window';
3
3
 
4
- var MIXPANEL_DB_NAME = 'mixpanelBrowserDb';
5
-
6
- var RECORDING_EVENTS_STORE_NAME = 'mixpanelRecordingEvents';
7
- var RECORDING_REGISTRY_STORE_NAME = 'mixpanelRecordingRegistry';
8
-
9
- // note: increment the version number when adding new object stores
10
- var DB_VERSION = 1;
11
- var OBJECT_STORES = [RECORDING_EVENTS_STORE_NAME, RECORDING_REGISTRY_STORE_NAME];
12
-
13
4
  /**
14
5
  * @type {import('./wrapper').StorageWrapper}
15
6
  */
16
- var IDBStorageWrapper = function (storeName) {
7
+ var IDBStorageWrapper = function (dbName, storeName, versionData) {
8
+ this.dbName = dbName;
9
+ this.storeName = storeName;
10
+ this.version = versionData.version;
11
+ this.storeNamesInDb = versionData.storeNames;
17
12
  /**
18
13
  * @type {Promise<IDBDatabase>|null}
19
14
  */
20
15
  this.dbPromise = null;
21
- this.storeName = storeName;
22
16
  };
23
17
 
24
18
  IDBStorageWrapper.prototype._openDb = function () {
19
+ var dbName = this.dbName;
20
+ var version = this.version;
21
+ var storeNamesInDb = this.storeNamesInDb;
25
22
  return new Promise(function (resolve, reject) {
26
- var openRequest = window.indexedDB.open(MIXPANEL_DB_NAME, DB_VERSION);
23
+ var openRequest = window.indexedDB.open(dbName, version);
27
24
  openRequest['onerror'] = function () {
28
25
  reject(openRequest.error);
29
26
  };
@@ -35,8 +32,10 @@ IDBStorageWrapper.prototype._openDb = function () {
35
32
  openRequest['onupgradeneeded'] = function (ev) {
36
33
  var db = ev.target.result;
37
34
 
38
- OBJECT_STORES.forEach(function (storeName) {
39
- db.createObjectStore(storeName);
35
+ storeNamesInDb.forEach(function (storeName) {
36
+ if (!db.objectStoreNames.contains(storeName)) {
37
+ db.createObjectStore(storeName);
38
+ }
40
39
  });
41
40
  };
42
41
  });
@@ -128,4 +127,6 @@ IDBStorageWrapper.prototype.getAll = function () {
128
127
  });
129
128
  };
130
129
 
131
- export { IDBStorageWrapper, RECORDING_EVENTS_STORE_NAME, RECORDING_REGISTRY_STORE_NAME };
130
+ export {
131
+ IDBStorageWrapper
132
+ };
@@ -1,15 +1,17 @@
1
1
  import { Promise } from '../promise-polyfill';
2
- import { _, JSONParse, JSONStringify } from '../utils'; // eslint-disable-line camelcase
3
- import { window } from '../window';
2
+ import { _, JSONParse, JSONStringify, getLocalStorage } from '../utils'; // eslint-disable-line camelcase
4
3
 
5
4
  /**
6
5
  * @type {import('./wrapper').StorageWrapper}
7
6
  */
8
7
  var LocalStorageWrapper = function (storageOverride) {
9
- this.storage = storageOverride || window.localStorage;
8
+ this.storage = storageOverride || getLocalStorage();
10
9
  };
11
10
 
12
11
  LocalStorageWrapper.prototype.init = function () {
12
+ if (!this.storage) {
13
+ return Promise.reject(new Error('localStorage is not available'));
14
+ }
13
15
  return Promise.resolve();
14
16
  };
15
17
 
package/src/utils.js CHANGED
@@ -104,6 +104,7 @@ var log_func_with_prefix = function(func, prefix) {
104
104
  var console_with_prefix = function(prefix) {
105
105
  return {
106
106
  log: log_func_with_prefix(console.log, prefix),
107
+ warn: log_func_with_prefix(console.warn, prefix),
107
108
  error: log_func_with_prefix(console.error, prefix),
108
109
  critical: log_func_with_prefix(console.critical, prefix)
109
110
  };
@@ -1050,7 +1051,8 @@ var localStorageSupported = function(storage, forceCheck) {
1050
1051
  if (_localStorageSupported !== null && !forceCheck) {
1051
1052
  return _localStorageSupported;
1052
1053
  }
1053
- return _localStorageSupported = _testStorageSupported(storage || window.localStorage);
1054
+
1055
+ return _localStorageSupported = _testStorageSupported(storage);
1054
1056
  };
1055
1057
 
1056
1058
  var _sessionStorageSupported = null;
@@ -1058,7 +1060,8 @@ var sessionStorageSupported = function(storage, forceCheck) {
1058
1060
  if (_sessionStorageSupported !== null && !forceCheck) {
1059
1061
  return _sessionStorageSupported;
1060
1062
  }
1061
- return _sessionStorageSupported = _testStorageSupported(storage || window.sessionStorage);
1063
+
1064
+ return _sessionStorageSupported = _testStorageSupported(storage);
1062
1065
  };
1063
1066
 
1064
1067
  function _storageWrapper(storage, name, is_supported_fn) {
@@ -1108,17 +1111,26 @@ function _storageWrapper(storage, name, is_supported_fn) {
1108
1111
  };
1109
1112
  }
1110
1113
 
1111
- // Safari errors out accessing localStorage/sessionStorage when cookies are disabled,
1112
- // so create dummy storage wrappers that silently fail as a fallback.
1113
- var windowLocalStorage = null, windowSessionStorage = null;
1114
- try {
1115
- windowLocalStorage = window.localStorage;
1116
- windowSessionStorage = window.sessionStorage;
1117
- // eslint-disable-next-line no-empty
1118
- } catch (_err) {}
1114
+ // Safari and other browsers may error out accessing localStorage/sessionStorage
1115
+ // when cookies are disabled, so wrap access in a try-catch.
1116
+ var getLocalStorage = function() {
1117
+ try {
1118
+ return window.localStorage; // eslint-disable-line no-restricted-properties
1119
+ } catch (_err) {
1120
+ return null;
1121
+ }
1122
+ };
1123
+
1124
+ var getSessionStorage = function() {
1125
+ try {
1126
+ return window.sessionStorage; // eslint-disable-line no-restricted-properties
1127
+ } catch (_err) {
1128
+ return null;
1129
+ }
1130
+ };
1119
1131
 
1120
- _.localStorage = _storageWrapper(windowLocalStorage, 'localStorage', localStorageSupported);
1121
- _.sessionStorage = _storageWrapper(windowSessionStorage, 'sessionStorage', sessionStorageSupported);
1132
+ _.localStorage = _storageWrapper(getLocalStorage(), 'localStorage', localStorageSupported);
1133
+ _.sessionStorage = _storageWrapper(getSessionStorage(), 'sessionStorage', sessionStorageSupported);
1122
1134
 
1123
1135
  _.register_event = (function() {
1124
1136
  // written by Dean Edwards, 2005
@@ -1810,5 +1822,6 @@ export {
1810
1822
  slice,
1811
1823
  urlMatchesRegexList,
1812
1824
  userAgent,
1825
+ getLocalStorage,
1813
1826
  windowOpera,
1814
1827
  };
package/testServer.js CHANGED
@@ -124,6 +124,8 @@ for (const [suiteId, suite] of Object.entries(TEST_SUITES)) {
124
124
  // Cross-origin child iframe page for session recording tests
125
125
  app.get('/tests/new/' + suiteId + '-cross-origin-page', function(req, res) {
126
126
  res.render('cross-origin-page.pug', {
127
+ customLibUrl: suite.customLibUrl || './static/build/mixpanel.js',
128
+ snippetUrl: suite.snippetUrl || './static/src/loaders/mixpanel-jslib-snippet.js',
127
129
  testUrl: './static/build/test/browser/cross-origin-page.js'
128
130
  });
129
131
  });
@@ -0,0 +1,9 @@
1
+ {
2
+ "compilerOptions": {
3
+ "strict": true,
4
+ "esModuleInterop": true,
5
+ "skipLibCheck": true,
6
+ "forceConsistentCasingInFileNames": true,
7
+ "moduleResolution": "node"
8
+ }
9
+ }