mixpanel-browser 2.62.0 → 2.64.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mixpanel-browser",
3
- "version": "2.62.0",
3
+ "version": "2.64.0",
4
4
  "description": "The official Mixpanel JavaScript browser client library",
5
5
  "main": "dist/mixpanel.cjs.js",
6
6
  "module": "dist/mixpanel.module.js",
@@ -33,7 +33,11 @@
33
33
  },
34
34
  "homepage": "https://github.com/mixpanel/mixpanel-js",
35
35
  "devDependencies": {
36
+ "@ampproject/rollup-plugin-closure-compiler": "0.27.0",
37
+ "@rollup/plugin-alias": "5.1.1",
36
38
  "@rollup/plugin-node-resolve": "15.2.3",
39
+ "@rollup/plugin-swc": "0.4.0",
40
+ "@swc/core": "1.11.7",
37
41
  "babel": "6.5.2",
38
42
  "babel-core": "6.7.2",
39
43
  "babel-preset-es2015": "6.6.0",
@@ -54,13 +58,13 @@
54
58
  "morgan": "1.9.1",
55
59
  "rdme": "7.5.0",
56
60
  "request": "2.88.0",
57
- "rollup": "2.79.1",
58
- "rollup-plugin-esbuild": "4.10.3",
61
+ "rollup": "4.34.9",
62
+ "rollup-plugin-esbuild": "6.2.1",
59
63
  "sinon": "8.1.1",
60
64
  "sinon-chai": "3.5.0",
61
65
  "webpack": "1.12.2"
62
66
  },
63
67
  "dependencies": {
64
- "rrweb": "2.0.0-alpha.13"
68
+ "rrweb": "2.0.0-alpha.18"
65
69
  }
66
70
  }
@@ -0,0 +1,223 @@
1
+ import nodeResolve from '@rollup/plugin-node-resolve';
2
+ import swc from '@rollup/plugin-swc';
3
+ import esbuild from 'rollup-plugin-esbuild';
4
+ import alias from '@rollup/plugin-alias';
5
+ import closureCompiler from '@ampproject/rollup-plugin-closure-compiler';
6
+
7
+ const COMPILED_RRWEB_PATH = 'build/rrweb-compiled.js';
8
+
9
+ const aliasRrweb = () => alias({
10
+ entries: [
11
+ { find: 'rrweb', replacement: COMPILED_RRWEB_PATH },
12
+ ]
13
+ });
14
+
15
+ const COMMON_CLOSURE_FLAGS = {
16
+ compilation_level: 'ADVANCED_OPTIMIZATIONS',
17
+ language_in: 'ECMASCRIPT5',
18
+ externs: ['src/externs.js'],
19
+ };
20
+
21
+ const MINIFY = process.env.MINIFY || process.env.FULL;
22
+
23
+ // Main builds used to develop / iterate quickly
24
+ const MAIN_BUILDS = [
25
+ // compile rrweb first to es5 with swc, we'll replace the import later on
26
+ {
27
+ 'input': 'rrweb',
28
+ 'output': [
29
+ {
30
+ file: COMPILED_RRWEB_PATH,
31
+ }
32
+ ],
33
+ plugins: [nodeResolve({browser: true}), swc({swc: {jsc: {target: 'es5'}}})]
34
+ },
35
+
36
+ // IIFE recorder bundle that is loaded asynchronously
37
+ // rrweb uses esbuild to minify, so do that here as well
38
+ {
39
+ input: 'src/recorder/index.js',
40
+ output: [
41
+ {
42
+ file: 'build/mixpanel-recorder.js',
43
+ name: 'mixpanel_recorder',
44
+ format: 'iife',
45
+ },
46
+ ...(MINIFY
47
+ ? [
48
+ {
49
+ file: 'build/mixpanel-recorder.min.js',
50
+ name: 'mixpanel_recorder',
51
+ format: 'iife',
52
+ plugins: [esbuild({target: 'es5', minify: true, sourceMap: true})],
53
+ sourcemap: true,
54
+ },
55
+ ]
56
+ : []),
57
+ ],
58
+ plugins: [aliasRrweb()],
59
+ },
60
+
61
+ // IIFE main mixpanel build
62
+ {
63
+ input: 'src/loaders/loader-globals.js',
64
+ output: [
65
+ {
66
+ file: 'build/mixpanel.globals.js',
67
+ name: 'mixpanel',
68
+ format: 'iife',
69
+ },
70
+ ...(MINIFY
71
+ ? [
72
+ {
73
+ file: 'build/mixpanel.min.js',
74
+ format: 'iife',
75
+ plugins: [closureCompiler(COMMON_CLOSURE_FLAGS)],
76
+ },
77
+ ]
78
+ : []),
79
+ ],
80
+ plugins: [
81
+ nodeResolve({
82
+ browser: true,
83
+ main: true,
84
+ jsnext: true,
85
+ })
86
+ ]
87
+ },
88
+ ]
89
+
90
+ const ALL_BUILDS = [
91
+ ...MAIN_BUILDS,
92
+ // Minified snippets for loading mixpanel
93
+ {
94
+ input: 'src/loaders/mixpanel-jslib-snippet.js',
95
+ output: [
96
+ {
97
+ file: 'build/mixpanel-jslib-snippet.min.js',
98
+ plugins: [closureCompiler(COMMON_CLOSURE_FLAGS)]
99
+ },
100
+ {
101
+ file: 'build/mixpanel-jslib-snippet.min.test.js',
102
+ plugins: [closureCompiler({...COMMON_CLOSURE_FLAGS, define: 'MIXPANEL_LIB_URL="../build/mixpanel.min.js"'})],
103
+ }
104
+ ],
105
+ },
106
+
107
+ // IIFE mixpanel snippet loader
108
+ {
109
+ input: 'src/loaders/mixpanel-js-wrapper.js',
110
+ output: [
111
+ {
112
+ file: 'build/mixpanel-js-wrapper.js',
113
+ },
114
+ {
115
+ file: 'build/mixpanel-js-wrapper.min.js',
116
+ plugins: [closureCompiler(COMMON_CLOSURE_FLAGS)],
117
+ }
118
+ ],
119
+ },
120
+
121
+ // IIFE mixpanel core with bundled recorder
122
+ {
123
+ input: 'src/loaders/loader-globals-with-recorder.js',
124
+ output: [
125
+ {
126
+ file: 'build/mixpanel-with-recorder.js',
127
+ name: 'mixpanel',
128
+ format: 'iife',
129
+ },
130
+ {
131
+ file: 'build/mixpanel-with-recorder.min.js',
132
+ name: 'mixpanel',
133
+ format: 'iife',
134
+ plugins: [esbuild({target: 'es5', minify: true, sourceMap: true})],
135
+ },
136
+ ],
137
+ plugins: [
138
+ aliasRrweb(),
139
+ nodeResolve({
140
+ browser: true,
141
+ main: true,
142
+ jsnext: true,
143
+ })
144
+ ],
145
+ },
146
+
147
+
148
+ // Modules builds that are bundled with the recorder
149
+ {
150
+ input: 'src/loaders/loader-module.js',
151
+ output: [
152
+ {
153
+ file: 'build/mixpanel.cjs.js',
154
+ name: 'mixpanel',
155
+ format: 'cjs',
156
+ },
157
+ {
158
+ file: 'build/mixpanel.amd.js',
159
+ name: 'mixpanel',
160
+ format: 'amd',
161
+ },
162
+ {
163
+ file: 'build/mixpanel.umd.js',
164
+ name: 'mixpanel',
165
+ format: 'umd',
166
+ },
167
+ {
168
+ file: 'build/mixpanel.module.js',
169
+ name: 'mixpanel',
170
+ format: 'es',
171
+ },
172
+ ],
173
+ plugins: [
174
+ aliasRrweb(),
175
+ nodeResolve({
176
+ browser: true,
177
+ main: true,
178
+ jsnext: true,
179
+ })
180
+ ],
181
+ },
182
+
183
+
184
+ // Alternative CJS builds without recorder
185
+ {
186
+ input: 'src/loaders/loader-module-core.js',
187
+ output: [
188
+ {
189
+ file: 'build/mixpanel-core.cjs.js',
190
+ name: 'mixpanel',
191
+ format: 'cjs',
192
+ },
193
+ ],
194
+ plugins: [
195
+ aliasRrweb(),
196
+ nodeResolve({
197
+ browser: true,
198
+ main: true,
199
+ jsnext: true,
200
+ })
201
+ ],
202
+ },
203
+ {
204
+ input: 'src/loaders/loader-module-with-async-recorder.js',
205
+ output: [
206
+ {
207
+ file: 'build/mixpanel-with-async-recorder.cjs.js',
208
+ name: 'mixpanel',
209
+ format: 'cjs',
210
+ },
211
+ ],
212
+ plugins: [
213
+ aliasRrweb(),
214
+ nodeResolve({
215
+ browser: true,
216
+ main: true,
217
+ jsnext: true,
218
+ })
219
+ ],
220
+ }
221
+ ];
222
+
223
+ export default process.env.FULL ? ALL_BUILDS : MAIN_BUILDS;
@@ -160,7 +160,8 @@ Autocapture.prototype.trackDomEvent = function(ev, mpEventName) {
160
160
  blockElementCallback: this.getConfig(CONFIG_BLOCK_ELEMENT_CALLBACK),
161
161
  blockSelectors: this.getConfig(CONFIG_BLOCK_SELECTORS),
162
162
  captureExtraAttrs: this.getConfig(CONFIG_CAPTURE_EXTRA_ATTRS),
163
- captureTextContent: this.getConfig(CONFIG_CAPTURE_TEXT_CONTENT)
163
+ captureTextContent: this.getConfig(CONFIG_CAPTURE_TEXT_CONTENT),
164
+ capturedForHeatMap: mpEventName === MP_EV_CLICK && !this.getConfig(CONFIG_TRACK_CLICK) && this.mp.is_recording_heatmap_data(),
164
165
  });
165
166
  if (props) {
166
167
  _.extend(props, DEFAULT_PROPS);
@@ -171,13 +172,13 @@ Autocapture.prototype.trackDomEvent = function(ev, mpEventName) {
171
172
  Autocapture.prototype.initClickTracking = function() {
172
173
  window.removeEventListener(EV_CLICK, this.listenerClick);
173
174
 
174
- if (!this.getConfig(CONFIG_TRACK_CLICK)) {
175
+ if (!this.getConfig(CONFIG_TRACK_CLICK) && !this.mp.get_config('record_heatmap_data')) {
175
176
  return;
176
177
  }
177
178
  logger.log('Initializing click tracking');
178
179
 
179
180
  this.listenerClick = window.addEventListener(EV_CLICK, function(ev) {
180
- if (!this.getConfig(CONFIG_TRACK_CLICK)) {
181
+ if (!this.getConfig(CONFIG_TRACK_CLICK) && !this.mp.is_recording_heatmap_data()) {
181
182
  return;
182
183
  }
183
184
  this.trackDomEvent(ev, MP_EV_CLICK);
@@ -114,6 +114,7 @@ function getPropsForDOMEvent(ev, config) {
114
114
  var blockSelectors = config.blockSelectors || [];
115
115
  var captureTextContent = config.captureTextContent || false;
116
116
  var captureExtraAttrs = config.captureExtraAttrs || [];
117
+ var capturedForHeatMap = config.capturedForHeatMap || false;
117
118
 
118
119
  // convert array to set every time, as the config may have changed
119
120
  var blockAttrsSet = {};
@@ -192,6 +193,9 @@ function getPropsForDOMEvent(ev, config) {
192
193
  props['$' + prop] = ev[prop];
193
194
  }
194
195
  });
196
+ if (capturedForHeatMap) {
197
+ props['$captured_for_heatmap'] = true;
198
+ }
195
199
  target = guessRealClickTarget(ev);
196
200
  }
197
201
  // prioritize text content from "real" click target if different from original target
package/src/config.js CHANGED
@@ -1,6 +1,6 @@
1
1
  var Config = {
2
2
  DEBUG: false,
3
- LIB_VERSION: '2.62.0'
3
+ LIB_VERSION: '2.64.0'
4
4
  };
5
5
 
6
6
  export default Config;
@@ -0,0 +1,191 @@
1
+ import { _, console_with_prefix, safewrapClass } from '../utils'; // eslint-disable-line camelcase
2
+ import { window } from '../window';
3
+
4
+ var fetch = window['fetch'];
5
+ var logger = console_with_prefix('flags');
6
+
7
+ var FLAGS_CONFIG_KEY = 'flags';
8
+
9
+ var CONFIG_CONTEXT = 'context';
10
+ var CONFIG_DEFAULTS = {};
11
+ CONFIG_DEFAULTS[CONFIG_CONTEXT] = {};
12
+
13
+ /**
14
+ * FeatureFlagManager: support for Mixpanel's feature flagging product
15
+ * @constructor
16
+ */
17
+ var FeatureFlagManager = function(initOptions) {
18
+ this.getMpConfig = initOptions.getConfigFunc;
19
+ this.getDistinctId = initOptions.getDistinctIdFunc;
20
+ this.track = initOptions.trackingFunc;
21
+ };
22
+
23
+ FeatureFlagManager.prototype.init = function() {
24
+ if (!minApisSupported()) {
25
+ logger.critical('Feature Flags unavailable: missing minimum required APIs');
26
+ return;
27
+ }
28
+
29
+ this.flags = null;
30
+ this.fetchFlags();
31
+
32
+ this.trackedFeatures = new Set();
33
+ };
34
+
35
+ FeatureFlagManager.prototype.getFullConfig = function() {
36
+ var ffConfig = this.getMpConfig(FLAGS_CONFIG_KEY);
37
+ if (!ffConfig) {
38
+ // flags are completely off
39
+ return {};
40
+ } else if (_.isObject(ffConfig)) {
41
+ return _.extend({}, CONFIG_DEFAULTS, ffConfig);
42
+ } else {
43
+ // config is non-object truthy value, return default
44
+ return CONFIG_DEFAULTS;
45
+ }
46
+ };
47
+
48
+ FeatureFlagManager.prototype.getConfig = function(key) {
49
+ return this.getFullConfig()[key];
50
+ };
51
+
52
+ FeatureFlagManager.prototype.isEnabled = function() {
53
+ return !!this.getMpConfig(FLAGS_CONFIG_KEY);
54
+ };
55
+
56
+ FeatureFlagManager.prototype.areFeaturesReady = function() {
57
+ if (!this.isEnabled()) {
58
+ logger.error('Feature Flags not enabled');
59
+ }
60
+ return !!this.flags;
61
+ };
62
+
63
+ FeatureFlagManager.prototype.fetchFlags = function() {
64
+ if (!this.isEnabled()) {
65
+ return;
66
+ }
67
+
68
+ var distinctId = this.getDistinctId();
69
+ logger.log('Fetching flags for distinct ID: ' + distinctId);
70
+ var reqParams = {
71
+ 'context': _.extend({'distinct_id': distinctId}, this.getConfig(CONFIG_CONTEXT))
72
+ };
73
+ this.fetchPromise = window['fetch'](this.getMpConfig('api_host') + '/' + this.getMpConfig('api_routes')['flags'], {
74
+ 'method': 'POST',
75
+ 'headers': {
76
+ 'Authorization': 'Basic ' + btoa(this.getMpConfig('token') + ':'),
77
+ 'Content-Type': 'application/octet-stream'
78
+ },
79
+ 'body': JSON.stringify(reqParams)
80
+ }).then(function(response) {
81
+ return response.json().then(function(responseBody) {
82
+ var responseFlags = responseBody['flags'];
83
+ if (!responseFlags) {
84
+ throw new Error('No flags in API response');
85
+ }
86
+ var flags = new Map();
87
+ _.each(responseFlags, function(data, key) {
88
+ flags.set(key, {
89
+ 'key': data['variant_key'],
90
+ 'data': data['variant_value']
91
+ });
92
+ });
93
+ this.flags = flags;
94
+ }.bind(this)).catch(function(error) {
95
+ logger.error(error);
96
+ });
97
+ }.bind(this)).catch(function() {});
98
+ };
99
+
100
+ FeatureFlagManager.prototype.getFeature = function(featureName, fallback) {
101
+ if (!this.fetchPromise) {
102
+ return new Promise(function(resolve) {
103
+ logger.critical('Feature Flags not initialized');
104
+ resolve(fallback);
105
+ });
106
+ }
107
+
108
+ return this.fetchPromise.then(function() {
109
+ return this.getFeatureSync(featureName, fallback);
110
+ }.bind(this)).catch(function(error) {
111
+ logger.error(error);
112
+ return fallback;
113
+ });
114
+ };
115
+
116
+ FeatureFlagManager.prototype.getFeatureSync = function(featureName, fallback) {
117
+ if (!this.areFeaturesReady()) {
118
+ logger.log('Flags not loaded yet');
119
+ return fallback;
120
+ }
121
+ var feature = this.flags.get(featureName);
122
+ if (!feature) {
123
+ logger.log('No flag found: "' + featureName + '"');
124
+ return fallback;
125
+ }
126
+ this.trackFeatureCheck(featureName, feature);
127
+ return feature;
128
+ };
129
+
130
+ FeatureFlagManager.prototype.getFeatureData = function(featureName, fallbackValue) {
131
+ return this.getFeature(featureName, {'data': fallbackValue}).then(function(feature) {
132
+ return feature['data'];
133
+ }).catch(function(error) {
134
+ logger.error(error);
135
+ return fallbackValue;
136
+ });
137
+ };
138
+
139
+ FeatureFlagManager.prototype.getFeatureDataSync = function(featureName, fallbackValue) {
140
+ return this.getFeatureSync(featureName, {'data': fallbackValue})['data'];
141
+ };
142
+
143
+ FeatureFlagManager.prototype.isFeatureEnabled = function(featureName, fallbackValue) {
144
+ return this.getFeatureData(featureName).then(function() {
145
+ return this.isFeatureEnabledSync(featureName, fallbackValue);
146
+ }.bind(this)).catch(function(error) {
147
+ logger.error(error);
148
+ return fallbackValue;
149
+ });
150
+ };
151
+
152
+ FeatureFlagManager.prototype.isFeatureEnabledSync = function(featureName, fallbackValue) {
153
+ fallbackValue = fallbackValue || false;
154
+ var val = this.getFeatureDataSync(featureName, fallbackValue);
155
+ if (val !== true && val !== false) {
156
+ logger.error('Feature flag "' + featureName + '" value: ' + val + ' is not a boolean; returning fallback value: ' + fallbackValue);
157
+ val = fallbackValue;
158
+ }
159
+ return val;
160
+ };
161
+
162
+ FeatureFlagManager.prototype.trackFeatureCheck = function(featureName, feature) {
163
+ if (this.trackedFeatures.has(featureName)) {
164
+ return;
165
+ }
166
+ this.trackedFeatures.add(featureName);
167
+ this.track('$experiment_started', {
168
+ 'Experiment name': featureName,
169
+ 'Variant name': feature['key'],
170
+ '$experiment_type': 'feature_flag'
171
+ });
172
+ };
173
+
174
+ function minApisSupported() {
175
+ return !!fetch &&
176
+ typeof Promise !== 'undefined' &&
177
+ typeof Map !== 'undefined' &&
178
+ typeof Set !== 'undefined';
179
+ }
180
+
181
+ safewrapClass(FeatureFlagManager);
182
+
183
+ FeatureFlagManager.prototype['are_features_ready'] = FeatureFlagManager.prototype.areFeaturesReady;
184
+ FeatureFlagManager.prototype['get_feature'] = FeatureFlagManager.prototype.getFeature;
185
+ FeatureFlagManager.prototype['get_feature_data'] = FeatureFlagManager.prototype.getFeatureData;
186
+ FeatureFlagManager.prototype['get_feature_data_sync'] = FeatureFlagManager.prototype.getFeatureDataSync;
187
+ FeatureFlagManager.prototype['get_feature_sync'] = FeatureFlagManager.prototype.getFeatureSync;
188
+ FeatureFlagManager.prototype['is_feature_enabled'] = FeatureFlagManager.prototype.isFeatureEnabled;
189
+ FeatureFlagManager.prototype['is_feature_enabled_sync'] = FeatureFlagManager.prototype.isFeatureEnabledSync;
190
+
191
+ export { FeatureFlagManager };
@@ -0,0 +1,7 @@
1
+ /* eslint camelcase: "off" */
2
+ import '../recorder';
3
+
4
+ import { init_from_snippet } from '../mixpanel-core';
5
+ import { loadNoop } from './bundle-loaders';
6
+
7
+ init_from_snippet(loadNoop);
@@ -4,6 +4,7 @@ import { MAX_RECORDING_MS, _, console, userAgent, document, navigator, slice, NO
4
4
  import { isRecordingExpired } from './recorder/utils';
5
5
  import { window } from './window';
6
6
  import { Autocapture } from './autocapture';
7
+ import { FeatureFlagManager } from './flags';
7
8
  import { FormTracker, LinkTracker } from './dom-trackers';
8
9
  import { RequestBatcher } from './request-batcher';
9
10
  import { MixpanelGroup } from './mixpanel-group';
@@ -86,10 +87,11 @@ if (navigator['sendBeacon']) {
86
87
  }
87
88
 
88
89
  var DEFAULT_API_ROUTES = {
89
- 'track': 'track/',
90
+ 'track': 'track/',
90
91
  'engage': 'engage/',
91
92
  'groups': 'groups/',
92
- 'record': 'record/'
93
+ 'record': 'record/',
94
+ 'flags': 'flags/'
93
95
  };
94
96
 
95
97
  /*
@@ -107,6 +109,7 @@ var DEFAULT_CONFIG = {
107
109
  'cross_site_cookie': false,
108
110
  'cross_subdomain_cookie': true,
109
111
  'error_reporter': NOOP_FUNC,
112
+ 'flags': false,
110
113
  'persistence': 'cookie',
111
114
  'persistence_name': '',
112
115
  'cookie_domain': '',
@@ -147,6 +150,7 @@ var DEFAULT_CONFIG = {
147
150
  'record_block_selector': 'img, video',
148
151
  'record_canvas': false,
149
152
  'record_collect_fonts': false,
153
+ 'record_heatmap_data': false,
150
154
  'record_idle_timeout_ms': 30 * 60 * 1000, // 30 minutes
151
155
  'record_mask_text_class': new RegExp('^(mp-mask|fs-mask|amp-mask|rr-mask|ph-mask)$'),
152
156
  'record_mask_text_selector': '*',
@@ -362,6 +366,14 @@ MixpanelLib.prototype._init = function(token, config, name) {
362
366
  }, '');
363
367
  }
364
368
 
369
+ this.flags = new FeatureFlagManager({
370
+ getConfigFunc: _.bind(this.get_config, this),
371
+ getDistinctIdFunc: _.bind(this.get_distinct_id, this),
372
+ trackingFunc: _.bind(this.track, this)
373
+ });
374
+ this.flags.init();
375
+ this['flags'] = this.flags;
376
+
365
377
  this.autocapture = new Autocapture(this);
366
378
  this.autocapture.init();
367
379
 
@@ -487,6 +499,10 @@ MixpanelLib.prototype.resume_session_recording = function () {
487
499
  }
488
500
  };
489
501
 
502
+ MixpanelLib.prototype.is_recording_heatmap_data = function () {
503
+ return this._get_session_replay_id() && this.get_config('record_heatmap_data');
504
+ };
505
+
490
506
  MixpanelLib.prototype.get_session_recording_properties = function () {
491
507
  var props = {};
492
508
  var replay_id = this._get_session_replay_id();
@@ -1568,6 +1584,11 @@ MixpanelLib.prototype.identify = function(
1568
1584
  '$anon_distinct_id': previous_distinct_id
1569
1585
  }, {skip_hooks: true});
1570
1586
  }
1587
+
1588
+ // check feature flags again if distinct id has changed
1589
+ if (new_distinct_id !== previous_distinct_id) {
1590
+ this.flags.fetchFlags();
1591
+ }
1571
1592
  };
1572
1593
 
1573
1594
  /**
@@ -1842,7 +1863,7 @@ MixpanelLib.prototype.set_config = function(config) {
1842
1863
  }
1843
1864
  Config.DEBUG = Config.DEBUG || this.get_config('debug');
1844
1865
 
1845
- if ('autocapture' in config && this.autocapture) {
1866
+ if (('autocapture' in config || 'record_heatmap_data' in config) && this.autocapture) {
1846
1867
  this.autocapture.init();
1847
1868
  }
1848
1869
  }
@@ -1,5 +1,5 @@
1
1
  import { window } from '../window';
2
- import { IncrementalSource, EventType } from '@rrweb/types';
2
+ import { IncrementalSource, EventType } from 'rrweb';
3
3
  import { MAX_RECORDING_MS, MAX_VALUE_FOR_MIN_RECORDING_MS, console_with_prefix, NOOP_FUNC, _, localStorageSupported} from '../utils'; // eslint-disable-line camelcase
4
4
  import { IDBStorageWrapper, RECORDING_EVENTS_STORE_NAME } from '../storage/indexed-db';
5
5
  import { addOptOutCheckMixpanelLib } from '../gdpr-utils';
@@ -1,11 +1,12 @@
1
1
  import { Promise } from '../promise-polyfill';
2
2
  import { _, JSONParse, JSONStringify } from '../utils'; // eslint-disable-line camelcase
3
+ import { window } from '../window';
3
4
 
4
5
  /**
5
6
  * @type {import('./wrapper').StorageWrapper}
6
7
  */
7
8
  var LocalStorageWrapper = function (storageOverride) {
8
- this.storage = storageOverride || localStorage;
9
+ this.storage = storageOverride || window.localStorage;
9
10
  };
10
11
 
11
12
  LocalStorageWrapper.prototype.init = function () {
package/rollup.config.js DELETED
@@ -1,11 +0,0 @@
1
- import nodeResolve from '@rollup/plugin-node-resolve';
2
-
3
- export default {
4
- plugins: [
5
- nodeResolve({
6
- browser: true,
7
- main: true,
8
- jsnext: true,
9
- })
10
- ]
11
- };
@@ -1,20 +0,0 @@
1
- import esbuild from 'rollup-plugin-esbuild';
2
- import { nodeResolve } from '@rollup/plugin-node-resolve';
3
-
4
- export default {
5
- input: 'index.js',
6
- output: [
7
- {
8
- file: 'build/mixpanel-recorder.js',
9
- format: 'esm'
10
- },
11
- {
12
- file: 'build/mixpanel-recorder.min.js',
13
- format: 'esm',
14
- name: 'version',
15
- plugins: [esbuild({minify: true, sourceMap: true})],
16
- sourcemap: true,
17
- }
18
- ],
19
- plugins: [nodeResolve({browser: true})],
20
- };