mixpanel-react-native 3.2.0-beta.2 → 3.2.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.
@@ -18,39 +18,16 @@ open class MixpanelReactNative: NSObject {
18
18
  properties: [String: Any],
19
19
  serverURL: String,
20
20
  useGzipCompression: Bool = false,
21
- featureFlagsOptions: [String: Any]?,
22
21
  resolver resolve: RCTPromiseResolveBlock,
23
22
  rejecter reject: RCTPromiseRejectBlock) -> Void {
24
23
  let autoProps = properties // copy
25
24
  AutomaticProperties.setAutomaticProperties(autoProps)
26
25
  let propsProcessed = MixpanelTypeHandler.processProperties(properties: autoProps)
27
-
28
- // Handle feature flags options
29
- var featureFlagsEnabled = false
30
- var featureFlagsContext: [String: Any]? = nil
31
-
32
- if let flagsOptions = featureFlagsOptions {
33
- featureFlagsEnabled = flagsOptions["enabled"] as? Bool ?? false
34
- featureFlagsContext = flagsOptions["context"] as? [String: Any]
35
- }
36
-
37
- // Create MixpanelOptions with all configuration including feature flags
38
- let options = MixpanelOptions(
39
- token: token,
40
- flushInterval: Constants.DEFAULT_FLUSH_INTERVAL,
41
- instanceName: token,
42
- trackAutomaticEvents: trackAutomaticEvents,
43
- optOutTrackingByDefault: optOutTrackingByDefault,
44
- useUniqueDistinctId: false,
45
- superProperties: propsProcessed,
46
- serverURL: serverURL,
47
- proxyServerConfig: nil,
48
- useGzipCompression: useGzipCompression,
49
- featureFlagsEnabled: featureFlagsEnabled,
50
- featureFlagsContext: featureFlagsContext ?? [:]
51
- )
52
-
53
- Mixpanel.initialize(options: options)
26
+ Mixpanel.initialize(token: token, trackAutomaticEvents: trackAutomaticEvents, flushInterval: Constants.DEFAULT_FLUSH_INTERVAL,
27
+ instanceName: token, optOutTrackingByDefault: optOutTrackingByDefault,
28
+ superProperties: propsProcessed,
29
+ serverURL: serverURL,
30
+ useGzipCompression: useGzipCompression)
54
31
  resolve(true)
55
32
  }
56
33
 
@@ -483,159 +460,4 @@ open class MixpanelReactNative: NSObject {
483
460
  return Mixpanel.getInstance(name: token)
484
461
  }
485
462
 
486
- // MARK: - Feature Flags
487
-
488
- @objc
489
- func loadFlags(_ token: String,
490
- resolver resolve: RCTPromiseResolveBlock,
491
- rejecter reject: RCTPromiseRejectBlock) -> Void {
492
- guard let instance = MixpanelReactNative.getMixpanelInstance(token),
493
- let flags = instance.flags else {
494
- resolve(nil)
495
- return
496
- }
497
- flags.loadFlags()
498
- resolve(nil)
499
- }
500
-
501
- @objc
502
- func areFlagsReadySync(_ token: String) -> NSNumber {
503
- guard let instance = MixpanelReactNative.getMixpanelInstance(token) else {
504
- NSLog("[Mixpanel - areFlagsReadySync: instance is nil for token: \(token)]")
505
- return NSNumber(value: false)
506
- }
507
-
508
- guard let flags = instance.flags else {
509
- NSLog("[Mixpanel - areFlagsReadySync: flags is nil")
510
- return NSNumber(value: false)
511
- }
512
-
513
- let ready = flags.areFlagsReady()
514
- NSLog("[Mixpanel - areFlagsReadySync: flags ready = \(ready)")
515
- return NSNumber(value: ready)
516
- }
517
-
518
- @objc
519
- func getVariantSync(_ token: String,
520
- featureName: String,
521
- fallback: [String: Any]) -> [String: Any] {
522
- guard let instance = MixpanelReactNative.getMixpanelInstance(token),
523
- let flags = instance.flags else {
524
- return fallback
525
- }
526
-
527
- let fallbackVariant = convertDictToVariant(fallback)
528
- let variant = flags.getVariantSync(featureName, fallback: fallbackVariant)
529
- return convertVariantToDict(variant)
530
- }
531
-
532
- @objc
533
- func getVariantValueSync(_ token: String,
534
- featureName: String,
535
- fallbackValue: Any) -> Any {
536
- guard let instance = MixpanelReactNative.getMixpanelInstance(token),
537
- let flags = instance.flags else {
538
- return fallbackValue
539
- }
540
-
541
- return flags.getVariantValueSync(featureName, fallbackValue: fallbackValue) ?? fallbackValue
542
- }
543
-
544
- @objc
545
- func isEnabledSync(_ token: String,
546
- featureName: String,
547
- fallbackValue: Bool) -> NSNumber {
548
- guard let instance = MixpanelReactNative.getMixpanelInstance(token),
549
- let flags = instance.flags else {
550
- return NSNumber(value: fallbackValue)
551
- }
552
-
553
- let enabled = flags.isEnabledSync(featureName, fallbackValue: fallbackValue)
554
- return NSNumber(value: enabled)
555
- }
556
-
557
- @objc
558
- func getVariant(_ token: String,
559
- featureName: String,
560
- fallback: [String: Any],
561
- resolver resolve: @escaping RCTPromiseResolveBlock,
562
- rejecter reject: @escaping RCTPromiseRejectBlock) -> Void {
563
- guard let instance = MixpanelReactNative.getMixpanelInstance(token),
564
- let flags = instance.flags else {
565
- resolve(fallback)
566
- return
567
- }
568
-
569
- let fallbackVariant = convertDictToVariant(fallback)
570
- flags.getVariant(featureName, fallback: fallbackVariant) { variant in
571
- resolve(self.convertVariantToDict(variant))
572
- }
573
- }
574
-
575
- @objc
576
- func getVariantValue(_ token: String,
577
- featureName: String,
578
- fallbackValue: Any,
579
- resolver resolve: @escaping RCTPromiseResolveBlock,
580
- rejecter reject: @escaping RCTPromiseRejectBlock) -> Void {
581
- guard let instance = MixpanelReactNative.getMixpanelInstance(token),
582
- let flags = instance.flags else {
583
- resolve(fallbackValue)
584
- return
585
- }
586
-
587
- flags.getVariantValue(featureName, fallbackValue: fallbackValue) { value in
588
- resolve(value)
589
- }
590
- }
591
-
592
- @objc
593
- func isEnabled(_ token: String,
594
- featureName: String,
595
- fallbackValue: Bool,
596
- resolver resolve: @escaping RCTPromiseResolveBlock,
597
- rejecter reject: @escaping RCTPromiseRejectBlock) -> Void {
598
- guard let instance = MixpanelReactNative.getMixpanelInstance(token),
599
- let flags = instance.flags else {
600
- resolve(fallbackValue)
601
- return
602
- }
603
-
604
- flags.isEnabled(featureName, fallbackValue: fallbackValue) { isEnabled in
605
- resolve(isEnabled)
606
- }
607
- }
608
-
609
- // Helper methods for variant conversion
610
- private func convertDictToVariant(_ dict: [String: Any]) -> MixpanelFlagVariant {
611
- let key = dict["key"] as? String ?? ""
612
- let value = dict["value"] ?? NSNull()
613
- let experimentID = dict["experimentID"] as? String
614
- let isExperimentActive = dict["isExperimentActive"] as? Bool
615
- let isQATester = dict["isQATester"] as? Bool
616
-
617
- return MixpanelFlagVariant(
618
- key: key,
619
- value: value,
620
- isExperimentActive: isExperimentActive,
621
- isQATester: isQATester,
622
- experimentID: experimentID
623
- )
624
- }
625
-
626
- private func convertVariantToDict(_ variant: MixpanelFlagVariant) -> [String: Any] {
627
- var dict: [String: Any] = [
628
- "key": variant.key,
629
- "value": variant.value ?? NSNull()
630
- ]
631
-
632
- if let experimentID = variant.experimentID {
633
- dict["experimentID"] = experimentID
634
- }
635
- dict["isExperimentActive"] = variant.isExperimentActive
636
- dict["isQATester"] = variant.isQATester
637
-
638
- return dict
639
- }
640
-
641
463
  }
@@ -4,7 +4,7 @@ import {
4
4
  defaultServerURL,
5
5
  } from "./mixpanel-constants";
6
6
 
7
- import {MixpanelLogger} from "./mixpanel-logger";
7
+ import { MixpanelLogger } from "./mixpanel-logger";
8
8
 
9
9
  export class MixpanelConfig {
10
10
  static instance;
@@ -65,10 +65,14 @@ export class MixpanelConfig {
65
65
  }
66
66
 
67
67
  getUseIpAddressForGeolocation(token) {
68
- return (
69
- (this._config[token] && this._config[token].useIpAddressForGeolocation) ||
70
- true
71
- );
68
+ if (
69
+ this._config[token] &&
70
+ "useIpAddressForGeolocation" in this._config[token]
71
+ ) {
72
+ return this._config[token].useIpAddressForGeolocation;
73
+ }
74
+
75
+ return true;
72
76
  }
73
77
 
74
78
  setFlushBatchSize(token, batchSize) {
@@ -21,17 +21,10 @@ export default class MixpanelMain {
21
21
  trackAutomaticEvents = false,
22
22
  optOutTrackingDefault = false,
23
23
  superProperties = null,
24
- serverURL = "https://api.mixpanel.com",
25
- useGzipCompression = false,
26
- featureFlagsOptions = {}
24
+ serverURL = "https://api.mixpanel.com"
27
25
  ) {
28
26
  MixpanelLogger.log(token, `Initializing Mixpanel`);
29
27
 
30
- // Store feature flags options for later use
31
- this.featureFlagsOptions = featureFlagsOptions;
32
- this.featureFlagsEnabled = featureFlagsOptions.enabled || false;
33
- this.featureFlagsContext = featureFlagsOptions.context || {};
34
-
35
28
  await this.mixpanelPersistent.initializationCompletePromise(token);
36
29
  if (optOutTrackingDefault) {
37
30
  await this.optOutTracking(token);
@@ -44,11 +37,6 @@ export default class MixpanelMain {
44
37
  await this.registerSuperProperties(token, {
45
38
  ...superProperties,
46
39
  });
47
-
48
- // Initialize feature flags if enabled
49
- if (this.featureFlagsEnabled) {
50
- MixpanelLogger.log(token, "Feature flags enabled during initialization");
51
- }
52
40
  }
53
41
 
54
42
  getMetaData() {
@@ -11,7 +11,7 @@ import {
11
11
 
12
12
  import "react-native-get-random-values"; // Polyfill for crypto.getRandomValues
13
13
  import { AsyncStorageAdapter } from "./mixpanel-storage";
14
- import uuid from "uuid";
14
+ import { v4 as uuidv4 } from "uuid";
15
15
  import { MixpanelLogger } from "mixpanel-react-native/javascript/mixpanel-logger";
16
16
 
17
17
  export class MixpanelPersistent {
@@ -42,7 +42,7 @@ export class MixpanelPersistent {
42
42
  }
43
43
 
44
44
  async initializationCompletePromise(token) {
45
- Promise.all([
45
+ await Promise.all([
46
46
  this.loadIdentity(token),
47
47
  this.loadSuperProperties(token),
48
48
  this.loadTimeEvents(token),
@@ -67,8 +67,8 @@ export class MixpanelPersistent {
67
67
  this._identity[token].deviceId = storageToken;
68
68
 
69
69
  if (!this._identity[token].deviceId) {
70
- // Generate device ID using uuid.v4() with polyfilled crypto.getRandomValues
71
- this._identity[token].deviceId = uuid.v4();
70
+ // Generate device ID using uuidv4() with polyfilled crypto.getRandomValues
71
+ this._identity[token].deviceId = uuidv4();
72
72
  await this.storageAdapter.setItem(
73
73
  getDeviceIdKey(token),
74
74
  this._identity[token].deviceId
@@ -12,9 +12,9 @@ export class AsyncStorageAdapter {
12
12
  }
13
13
  } catch {
14
14
  console.error(
15
- "[@RNC/AsyncStorage]: NativeModule: AsyncStorage is null. Please run 'npm install @react-native-async-storage/async-storage' or follow the Mixpanel guide to set up your own Storage class."
15
+ "[Mixpanel] AsyncStorage not available. Install @react-native-async-storage/async-storage (^1.15.0 or ^2.0.0), or provide a custom storage implementation. See: https://github.com/mixpanel/mixpanel-react-native#readme"
16
16
  );
17
- console.error("[Mixpanel] Falling back to in-memory storage");
17
+ console.error("[Mixpanel] Falling back to in-memory storage. Data will not persist across app restarts.");
18
18
  this.storage = new InMemoryStorage();
19
19
  }
20
20
  } else {
package/package.json CHANGED
@@ -1,8 +1,21 @@
1
1
  {
2
2
  "name": "mixpanel-react-native",
3
- "version": "3.2.0-beta.2",
3
+ "version": "3.2.0",
4
4
  "description": "Official React Native Tracking Library for Mixpanel Analytics",
5
5
  "main": "index.js",
6
+ "files": [
7
+ "index.js",
8
+ "index.d.ts",
9
+ "javascript/",
10
+ "ios/",
11
+ "android/src/",
12
+ "android/build.gradle",
13
+ "MixpanelReactNative.podspec",
14
+ "react-native.config.js",
15
+ "README.md",
16
+ "LICENSE.md",
17
+ "CHANGELOG.md"
18
+ ],
6
19
  "scripts": {
7
20
  "test": "jest"
8
21
  },
@@ -31,17 +44,17 @@
31
44
  "mp_lib": "react-native"
32
45
  },
33
46
  "devDependencies": {
34
- "@babel/core": "^7.12.3",
35
- "@babel/runtime": "^7.12.1",
36
- "@react-native-community/eslint-config": "^2.0.0",
37
- "babel-jest": "^26.6.0",
38
- "eslint": "^7.11.0",
39
- "jest": "^26.6.3",
47
+ "@react-native-async-storage/async-storage": "^1.24.0",
48
+ "@babel/core": "^7.26.0",
49
+ "@babel/runtime": "^7.26.0",
50
+ "@react-native-community/eslint-config": "^3.2.0",
51
+ "babel-jest": "^29.7.0",
52
+ "eslint": "^8.57.0",
53
+ "jest": "^29.7.0",
40
54
  "jest-fetch-mock": "^3.0.3",
41
- "jsdoc": "^4.0.5",
42
- "metro-react-native-babel-preset": "^0.63.0",
43
- "react-native": "^0.63.3",
44
- "react-test-renderer": "16.13.1"
55
+ "metro-react-native-babel-preset": "^0.77.0",
56
+ "react-native": "^0.76.0",
57
+ "react-test-renderer": "^18.3.1"
45
58
  },
46
59
  "jest": {
47
60
  "modulePathIgnorePatterns": [
@@ -55,13 +68,21 @@
55
68
  ],
56
69
  "verbose": true,
57
70
  "preset": "react-native",
58
- "transform": {
59
- "^.+\\.js$": "<rootDir>/node_modules/react-native/jest/preprocessor.js"
60
- }
71
+ "transformIgnorePatterns": [
72
+ "node_modules/(?!(@react-native|react-native|react-native-get-random-values|uuid)/)"
73
+ ],
74
+ "testEnvironment": "node"
61
75
  },
62
76
  "dependencies": {
63
- "@react-native-async-storage/async-storage": "^1.21.0",
64
77
  "react-native-get-random-values": "^1.9.0",
65
- "uuid": "3.3.2"
78
+ "uuid": "^9.0.1"
79
+ },
80
+ "peerDependencies": {
81
+ "@react-native-async-storage/async-storage": "^1.15.0 || ^2.0.0"
82
+ },
83
+ "peerDependenciesMeta": {
84
+ "@react-native-async-storage/async-storage": {
85
+ "optional": true
86
+ }
66
87
  }
67
- }
88
+ }
@@ -1,7 +0,0 @@
1
- # .github/dependabot.yml
2
- version: 2
3
- updates:
4
- - package-ecosystem: "npm" # Or "yarn"
5
- directory: "/" # Tells Dependabot to scan root directory only
6
- schedule:
7
- interval: "daily"