mixpanel-react-native 3.1.0 → 3.1.2

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 (63) hide show
  1. package/.claude/settings.local.json +6 -0
  2. package/.vscode/settings.json +2 -4
  3. package/CHANGELOG.md +26 -0
  4. package/CLAUDE.md +26 -2
  5. package/Samples/MixpanelExample/.bundle/config +2 -0
  6. package/Samples/MixpanelExample/.eslintrc.js +4 -0
  7. package/Samples/MixpanelExample/.prettierrc.js +7 -0
  8. package/Samples/MixpanelExample/.watchmanconfig +1 -0
  9. package/Samples/MixpanelExample/App.tsx +143 -0
  10. package/Samples/MixpanelExample/Gemfile +16 -0
  11. package/Samples/MixpanelExample/README.md +97 -0
  12. package/Samples/MixpanelExample/__tests__/App.test.tsx +13 -0
  13. package/Samples/MixpanelExample/android/app/build.gradle +119 -0
  14. package/Samples/MixpanelExample/android/app/debug.keystore +0 -0
  15. package/Samples/MixpanelExample/android/app/proguard-rules.pro +10 -0
  16. package/Samples/MixpanelExample/android/app/src/debug/AndroidManifest.xml +9 -0
  17. package/Samples/MixpanelExample/android/app/src/main/AndroidManifest.xml +26 -0
  18. package/Samples/MixpanelExample/android/app/src/main/java/com/mixpanelexample/MainActivity.kt +22 -0
  19. package/Samples/MixpanelExample/android/app/src/main/java/com/mixpanelexample/MainApplication.kt +44 -0
  20. package/Samples/MixpanelExample/android/app/src/main/res/drawable/rn_edit_text_material.xml +37 -0
  21. package/Samples/MixpanelExample/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
  22. package/Samples/MixpanelExample/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png +0 -0
  23. package/Samples/MixpanelExample/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
  24. package/Samples/MixpanelExample/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png +0 -0
  25. package/Samples/MixpanelExample/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
  26. package/Samples/MixpanelExample/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png +0 -0
  27. package/Samples/MixpanelExample/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
  28. package/Samples/MixpanelExample/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png +0 -0
  29. package/Samples/MixpanelExample/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
  30. package/Samples/MixpanelExample/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png +0 -0
  31. package/Samples/MixpanelExample/android/app/src/main/res/values/strings.xml +3 -0
  32. package/Samples/MixpanelExample/android/app/src/main/res/values/styles.xml +9 -0
  33. package/Samples/MixpanelExample/android/build.gradle +21 -0
  34. package/Samples/MixpanelExample/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  35. package/Samples/MixpanelExample/android/gradle/wrapper/gradle-wrapper.properties +7 -0
  36. package/Samples/MixpanelExample/android/gradle.properties +39 -0
  37. package/Samples/MixpanelExample/android/gradlew +251 -0
  38. package/Samples/MixpanelExample/android/gradlew.bat +94 -0
  39. package/Samples/MixpanelExample/android/settings.gradle +6 -0
  40. package/Samples/MixpanelExample/app.json +4 -0
  41. package/Samples/MixpanelExample/babel.config.js +3 -0
  42. package/Samples/MixpanelExample/index.js +9 -0
  43. package/Samples/MixpanelExample/ios/.xcode.env +11 -0
  44. package/Samples/MixpanelExample/ios/MixpanelExample/AppDelegate.swift +48 -0
  45. package/Samples/MixpanelExample/ios/MixpanelExample/Images.xcassets/AppIcon.appiconset/Contents.json +53 -0
  46. package/Samples/MixpanelExample/ios/MixpanelExample/Images.xcassets/Contents.json +6 -0
  47. package/Samples/MixpanelExample/ios/MixpanelExample/Info.plist +52 -0
  48. package/Samples/MixpanelExample/ios/MixpanelExample/LaunchScreen.storyboard +47 -0
  49. package/Samples/MixpanelExample/ios/MixpanelExample/PrivacyInfo.xcprivacy +37 -0
  50. package/Samples/MixpanelExample/ios/MixpanelExample.xcodeproj/project.pbxproj +505 -0
  51. package/Samples/MixpanelExample/ios/MixpanelExample.xcodeproj/xcshareddata/xcschemes/MixpanelExample.xcscheme +88 -0
  52. package/Samples/MixpanelExample/ios/Podfile +35 -0
  53. package/Samples/MixpanelExample/jest.config.js +3 -0
  54. package/Samples/MixpanelExample/metro.config.js +22 -0
  55. package/Samples/MixpanelExample/package-lock.json +12456 -0
  56. package/Samples/MixpanelExample/package.json +42 -0
  57. package/Samples/MixpanelExample/tsconfig.json +3 -0
  58. package/__tests__/jest_setup.js +5 -5
  59. package/__tests__/persistent.test.js +6 -55
  60. package/index.d.ts +2 -1
  61. package/ios/MixpanelReactNative.m +1 -1
  62. package/javascript/mixpanel-persistent.js +3 -6
  63. package/package.json +3 -3
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "MixpanelExample",
3
+ "version": "0.0.1",
4
+ "private": true,
5
+ "scripts": {
6
+ "android": "react-native run-android",
7
+ "ios": "react-native run-ios",
8
+ "lint": "eslint .",
9
+ "start": "react-native start",
10
+ "test": "jest"
11
+ },
12
+ "dependencies": {
13
+ "@react-native-async-storage/async-storage": "^1.24.0",
14
+ "mixpanel-react-native": "file:../..",
15
+ "react": "19.0.0",
16
+ "react-native": "0.79.3",
17
+ "uuid": "^3.3.2"
18
+ },
19
+ "devDependencies": {
20
+ "@babel/core": "^7.25.2",
21
+ "@babel/preset-env": "^7.25.3",
22
+ "@babel/runtime": "^7.25.0",
23
+ "@react-native-community/cli": "18.0.0",
24
+ "@react-native-community/cli-platform-android": "18.0.0",
25
+ "@react-native-community/cli-platform-ios": "18.0.0",
26
+ "@react-native/babel-preset": "0.79.3",
27
+ "@react-native/eslint-config": "0.79.3",
28
+ "@react-native/metro-config": "0.79.3",
29
+ "@react-native/typescript-config": "0.79.3",
30
+ "@types/jest": "^29.5.13",
31
+ "@types/react": "^19.0.0",
32
+ "@types/react-test-renderer": "^19.0.0",
33
+ "eslint": "^8.19.0",
34
+ "jest": "^29.6.3",
35
+ "prettier": "2.8.8",
36
+ "react-test-renderer": "19.0.0",
37
+ "typescript": "5.0.4"
38
+ },
39
+ "engines": {
40
+ "node": ">=18"
41
+ }
42
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "extends": "@react-native/typescript-config/tsconfig.json"
3
+ }
@@ -1,11 +1,11 @@
1
1
  import * as ReactNative from "react-native";
2
2
  import { jest } from "@jest/globals";
3
3
 
4
- jest.mock("expo-crypto", () => ({
5
- randomUUID: jest.fn(
6
- () => "mocked-uuid-string-" + Math.random().toString(36).substring(2, 15)
7
- ), // Provides a somewhat unique mock UUID
8
- }));
4
+ // Mock react-native-get-random-values polyfill
5
+ jest.mock("react-native-get-random-values", () => {
6
+ // Polyfill is imported for side effects, no need to mock specific functions
7
+ return {};
8
+ });
9
9
 
10
10
  jest.mock("mixpanel-react-native/javascript/mixpanel-storage", () => {
11
11
  return {
@@ -1,5 +1,4 @@
1
- // We need to test the actual module behavior, not mocked behavior
2
- // So we'll use jest.isolateModules to get a fresh instance
1
+ // Test UUID generation with polyfilled crypto.getRandomValues
3
2
  describe("MixpanelPersistent - UUID Generation", () => {
4
3
  const token = "test-token";
5
4
 
@@ -7,25 +6,17 @@ describe("MixpanelPersistent - UUID Generation", () => {
7
6
  jest.clearAllMocks();
8
7
  });
9
8
 
10
- it("should fallback to uuid.v4() when expo-crypto throws", async () => {
9
+ it("should generate device ID using uuid.v4() with polyfill", async () => {
11
10
  let mixpanelPersistent;
12
11
 
13
12
  await jest.isolateModules(async () => {
14
- // Mock expo-crypto to throw an error
15
- jest.doMock("expo-crypto", () => ({
16
- randomUUID: jest.fn(() => {
17
- throw new Error("Expo crypto not available");
18
- }),
19
- }));
20
-
21
13
  // Mock uuid to return a specific value
22
14
  jest.doMock("uuid", () => ({
23
- v4: jest.fn(() => "fallback-uuid-1234"),
15
+ v4: jest.fn(() => "polyfilled-uuid-1234"),
24
16
  }));
25
17
 
26
18
  // Now require the modules
27
19
  const { MixpanelPersistent } = require("mixpanel-react-native/javascript/mixpanel-persistent");
28
- const { randomUUID } = require("expo-crypto");
29
20
  const uuid = require("uuid");
30
21
 
31
22
  // Create instance
@@ -35,51 +26,11 @@ describe("MixpanelPersistent - UUID Generation", () => {
35
26
  // Load device ID (which triggers UUID generation)
36
27
  await mixpanelPersistent.loadDeviceId(token);
37
28
 
38
- // Verify randomUUID was called
39
- expect(randomUUID).toHaveBeenCalled();
40
-
41
- // Verify uuid.v4 was called as fallback
29
+ // Verify uuid.v4 was called
42
30
  expect(uuid.v4).toHaveBeenCalled();
43
31
 
44
- // Verify the device ID was set to the fallback value
45
- expect(mixpanelPersistent.getDeviceId(token)).toBe("fallback-uuid-1234");
46
- });
47
- });
48
-
49
- it("should use expo-crypto randomUUID when available", async () => {
50
- let mixpanelPersistent;
51
-
52
- await jest.isolateModules(async () => {
53
- // Mock expo-crypto to return a specific value
54
- jest.doMock("expo-crypto", () => ({
55
- randomUUID: jest.fn(() => "expo-uuid-5678"),
56
- }));
57
-
58
- // Mock uuid
59
- jest.doMock("uuid", () => ({
60
- v4: jest.fn(() => "should-not-be-called"),
61
- }));
62
-
63
- // Now require the modules
64
- const { MixpanelPersistent } = require("mixpanel-react-native/javascript/mixpanel-persistent");
65
- const { randomUUID } = require("expo-crypto");
66
- const uuid = require("uuid");
67
-
68
- // Create instance
69
- MixpanelPersistent.instance = null;
70
- mixpanelPersistent = MixpanelPersistent.getInstance(null, token);
71
-
72
- // Load device ID
73
- await mixpanelPersistent.loadDeviceId(token);
74
-
75
- // Verify randomUUID was called
76
- expect(randomUUID).toHaveBeenCalled();
77
-
78
- // Verify uuid.v4 was NOT called
79
- expect(uuid.v4).not.toHaveBeenCalled();
80
-
81
- // Verify the device ID was set to the expo value
82
- expect(mixpanelPersistent.getDeviceId(token)).toBe("expo-uuid-5678");
32
+ // Verify the device ID was set
33
+ expect(mixpanelPersistent.getDeviceId(token)).toBe("polyfilled-uuid-1234");
83
34
  });
84
35
  });
85
36
 
package/index.d.ts CHANGED
@@ -24,7 +24,8 @@ export class Mixpanel {
24
24
  init(
25
25
  optOutTrackingDefault?: boolean,
26
26
  superProperties?: MixpanelProperties,
27
- serverURL?: String
27
+ serverURL?: string,
28
+ useGzipCompression?: boolean
28
29
  ): Promise<void>;
29
30
  setServerURL(serverURL: string): void;
30
31
  setLoggingEnabled(loggingEnabled: boolean): void;
@@ -5,7 +5,7 @@
5
5
 
6
6
  // MARK: - Mixpanel Instance
7
7
 
8
- RCT_EXTERN_METHOD(initialize:(NSString *)token trackAutomaticEvents:(BOOL)trackAutomaticEvents optOutTrackingByDefault:(BOOL)optOutTrackingByDefault properties:(NSDictionary *)properties serverURL:(NSString *)serverURL resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
8
+ RCT_EXTERN_METHOD(initialize:(NSString *)token trackAutomaticEvents:(BOOL)trackAutomaticEvents optOutTrackingByDefault:(BOOL)optOutTrackingByDefault properties:(NSDictionary *)properties serverURL:(NSString *)serverURL useGzipCompression:(BOOL)useGzipCompression resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
9
9
 
10
10
  // Mark: - Settings
11
11
  RCT_EXTERN_METHOD(setServerURL:(NSString *)token serverURL:(NSString *)serverURL resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
@@ -9,10 +9,10 @@ import {
9
9
  getAppHasOpenedBeforeKey,
10
10
  } from "./mixpanel-constants";
11
11
 
12
+ import "react-native-get-random-values"; // Polyfill for crypto.getRandomValues
12
13
  import { AsyncStorageAdapter } from "./mixpanel-storage";
13
14
  import uuid from "uuid";
14
15
  import { MixpanelLogger } from "mixpanel-react-native/javascript/mixpanel-logger";
15
- import { randomUUID } from "expo-crypto";
16
16
 
17
17
  export class MixpanelPersistent {
18
18
  static instance;
@@ -67,11 +67,8 @@ export class MixpanelPersistent {
67
67
  this._identity[token].deviceId = storageToken;
68
68
 
69
69
  if (!this._identity[token].deviceId) {
70
- try {
71
- this._identity[token].deviceId = randomUUID();
72
- } catch (e) {
73
- this._identity[token].deviceId = uuid.v4();
74
- }
70
+ // Generate device ID using uuid.v4() with polyfilled crypto.getRandomValues
71
+ this._identity[token].deviceId = uuid.v4();
75
72
  await this.storageAdapter.setItem(
76
73
  getDeviceIdKey(token),
77
74
  this._identity[token].deviceId
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mixpanel-react-native",
3
- "version": "3.1.0",
3
+ "version": "3.1.2",
4
4
  "description": "Official React Native Tracking Library for Mixpanel Analytics",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -60,7 +60,7 @@
60
60
  },
61
61
  "dependencies": {
62
62
  "@react-native-async-storage/async-storage": "^1.21.0",
63
- "uuid": "3.3.2",
64
- "expo-crypto": "~14.1.4"
63
+ "react-native-get-random-values": "^1.9.0",
64
+ "uuid": "3.3.2"
65
65
  }
66
66
  }