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.
- package/.claude/settings.local.json +6 -0
- package/.vscode/settings.json +2 -4
- package/CHANGELOG.md +26 -0
- package/CLAUDE.md +26 -2
- package/Samples/MixpanelExample/.bundle/config +2 -0
- package/Samples/MixpanelExample/.eslintrc.js +4 -0
- package/Samples/MixpanelExample/.prettierrc.js +7 -0
- package/Samples/MixpanelExample/.watchmanconfig +1 -0
- package/Samples/MixpanelExample/App.tsx +143 -0
- package/Samples/MixpanelExample/Gemfile +16 -0
- package/Samples/MixpanelExample/README.md +97 -0
- package/Samples/MixpanelExample/__tests__/App.test.tsx +13 -0
- package/Samples/MixpanelExample/android/app/build.gradle +119 -0
- package/Samples/MixpanelExample/android/app/debug.keystore +0 -0
- package/Samples/MixpanelExample/android/app/proguard-rules.pro +10 -0
- package/Samples/MixpanelExample/android/app/src/debug/AndroidManifest.xml +9 -0
- package/Samples/MixpanelExample/android/app/src/main/AndroidManifest.xml +26 -0
- package/Samples/MixpanelExample/android/app/src/main/java/com/mixpanelexample/MainActivity.kt +22 -0
- package/Samples/MixpanelExample/android/app/src/main/java/com/mixpanelexample/MainApplication.kt +44 -0
- package/Samples/MixpanelExample/android/app/src/main/res/drawable/rn_edit_text_material.xml +37 -0
- package/Samples/MixpanelExample/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
- package/Samples/MixpanelExample/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png +0 -0
- package/Samples/MixpanelExample/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
- package/Samples/MixpanelExample/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png +0 -0
- package/Samples/MixpanelExample/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
- package/Samples/MixpanelExample/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png +0 -0
- package/Samples/MixpanelExample/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
- package/Samples/MixpanelExample/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png +0 -0
- package/Samples/MixpanelExample/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
- package/Samples/MixpanelExample/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png +0 -0
- package/Samples/MixpanelExample/android/app/src/main/res/values/strings.xml +3 -0
- package/Samples/MixpanelExample/android/app/src/main/res/values/styles.xml +9 -0
- package/Samples/MixpanelExample/android/build.gradle +21 -0
- package/Samples/MixpanelExample/android/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/Samples/MixpanelExample/android/gradle/wrapper/gradle-wrapper.properties +7 -0
- package/Samples/MixpanelExample/android/gradle.properties +39 -0
- package/Samples/MixpanelExample/android/gradlew +251 -0
- package/Samples/MixpanelExample/android/gradlew.bat +94 -0
- package/Samples/MixpanelExample/android/settings.gradle +6 -0
- package/Samples/MixpanelExample/app.json +4 -0
- package/Samples/MixpanelExample/babel.config.js +3 -0
- package/Samples/MixpanelExample/index.js +9 -0
- package/Samples/MixpanelExample/ios/.xcode.env +11 -0
- package/Samples/MixpanelExample/ios/MixpanelExample/AppDelegate.swift +48 -0
- package/Samples/MixpanelExample/ios/MixpanelExample/Images.xcassets/AppIcon.appiconset/Contents.json +53 -0
- package/Samples/MixpanelExample/ios/MixpanelExample/Images.xcassets/Contents.json +6 -0
- package/Samples/MixpanelExample/ios/MixpanelExample/Info.plist +52 -0
- package/Samples/MixpanelExample/ios/MixpanelExample/LaunchScreen.storyboard +47 -0
- package/Samples/MixpanelExample/ios/MixpanelExample/PrivacyInfo.xcprivacy +37 -0
- package/Samples/MixpanelExample/ios/MixpanelExample.xcodeproj/project.pbxproj +505 -0
- package/Samples/MixpanelExample/ios/MixpanelExample.xcodeproj/xcshareddata/xcschemes/MixpanelExample.xcscheme +88 -0
- package/Samples/MixpanelExample/ios/Podfile +35 -0
- package/Samples/MixpanelExample/jest.config.js +3 -0
- package/Samples/MixpanelExample/metro.config.js +22 -0
- package/Samples/MixpanelExample/package-lock.json +12456 -0
- package/Samples/MixpanelExample/package.json +42 -0
- package/Samples/MixpanelExample/tsconfig.json +3 -0
- package/__tests__/jest_setup.js +5 -5
- package/__tests__/persistent.test.js +6 -55
- package/index.d.ts +2 -1
- package/ios/MixpanelReactNative.m +1 -1
- package/javascript/mixpanel-persistent.js +3 -6
- 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
|
+
}
|
package/__tests__/jest_setup.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import * as ReactNative from "react-native";
|
|
2
2
|
import { jest } from "@jest/globals";
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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
|
-
//
|
|
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
|
|
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(() => "
|
|
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
|
|
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
|
|
45
|
-
expect(mixpanelPersistent.getDeviceId(token)).toBe("
|
|
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?:
|
|
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
|
-
|
|
71
|
-
|
|
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.
|
|
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
|
-
"
|
|
64
|
-
"
|
|
63
|
+
"react-native-get-random-values": "^1.9.0",
|
|
64
|
+
"uuid": "3.3.2"
|
|
65
65
|
}
|
|
66
66
|
}
|