react-native-mparticle 2.8.1 → 2.9.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/README.md +252 -94
- package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/android/gradle/wrapper/gradle-wrapper.properties +6 -0
- package/android/gradle.properties +26 -0
- package/android/gradlew +160 -0
- package/android/gradlew.bat +90 -0
- package/android/libs/java-json.jar +0 -0
- package/android/src/main/java/com/mparticle/react/MParticleModule.kt +1 -1
- package/android/src/test/java/com/mparticle/react/IdentityApiTest.java +230 -0
- package/android/src/test/java/com/mparticle/react/MParticleUserTest.java +173 -0
- package/android/src/test/java/com/mparticle/react/testutils/MockMParticleUser.java +109 -0
- package/android/src/test/java/com/mparticle/react/testutils/MockMap.java +203 -0
- package/android/src/test/java/com/mparticle/react/testutils/MockReadableArray.java +68 -0
- package/android/src/test/java/com/mparticle/react/testutils/MockWritableMap.java +4 -0
- package/android/src/test/java/com/mparticle/react/testutils/Mutable.java +13 -0
- package/app.plugin.js +1 -0
- package/ios/RNMParticle/RNMPRokt.mm +25 -11
- package/ios/RNMParticle/RNMParticle.mm +2 -1
- package/js/codegenSpecs/NativeMParticle.ts +3 -4
- package/js/rokt/rokt-layout-view.android.tsx +2 -1
- package/lib/codegenSpecs/NativeMParticle.d.ts +3 -4
- package/lib/codegenSpecs/NativeMParticle.js.map +1 -1
- package/lib/rokt/rokt-layout-view.android.js +1 -0
- package/lib/rokt/rokt-layout-view.android.js.map +1 -1
- package/package.json +28 -4
- package/plugin/build/withMParticle.d.ts +60 -0
- package/plugin/build/withMParticle.js +30 -0
- package/plugin/build/withMParticleAndroid.d.ts +6 -0
- package/plugin/build/withMParticleAndroid.js +266 -0
- package/plugin/build/withMParticleIOS.d.ts +6 -0
- package/plugin/build/withMParticleIOS.js +362 -0
- package/plugin/src/withMParticle.ts +106 -0
- package/plugin/src/withMParticleAndroid.ts +359 -0
- package/plugin/src/withMParticleIOS.ts +459 -0
- package/plugin/tsconfig.json +8 -0
- package/react-native-mparticle.podspec +11 -0
- package/SECURITY.md +0 -9
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const config_plugins_1 = require("@expo/config-plugins");
|
|
4
|
+
const withMParticleIOS_1 = require("./withMParticleIOS");
|
|
5
|
+
const withMParticleAndroid_1 = require("./withMParticleAndroid");
|
|
6
|
+
const pkg = require('../../package.json');
|
|
7
|
+
/**
|
|
8
|
+
* Expo Config Plugin for mParticle React Native SDK
|
|
9
|
+
*
|
|
10
|
+
* This plugin configures your Expo project to use the mParticle SDK by:
|
|
11
|
+
* - Adding mParticle SDK initialization to iOS AppDelegate
|
|
12
|
+
* - Adding mParticle SDK initialization to Android MainApplication
|
|
13
|
+
* - Adding kit dependencies to iOS Podfile
|
|
14
|
+
* - Adding kit dependencies to Android build.gradle
|
|
15
|
+
*/
|
|
16
|
+
const withMParticle = (config, props) => {
|
|
17
|
+
// Validate required props
|
|
18
|
+
if (!props.iosApiKey || !props.iosApiSecret) {
|
|
19
|
+
throw new Error('react-native-mparticle plugin requires iosApiKey and iosApiSecret');
|
|
20
|
+
}
|
|
21
|
+
if (!props.androidApiKey || !props.androidApiSecret) {
|
|
22
|
+
throw new Error('react-native-mparticle plugin requires androidApiKey and androidApiSecret');
|
|
23
|
+
}
|
|
24
|
+
// Apply iOS modifications
|
|
25
|
+
config = (0, withMParticleIOS_1.withMParticleIOS)(config, props);
|
|
26
|
+
// Apply Android modifications
|
|
27
|
+
config = (0, withMParticleAndroid_1.withMParticleAndroid)(config, props);
|
|
28
|
+
return config;
|
|
29
|
+
};
|
|
30
|
+
exports.default = (0, config_plugins_1.createRunOncePlugin)(withMParticle, pkg.name, pkg.version);
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.withMParticleAndroid = void 0;
|
|
4
|
+
const config_plugins_1 = require("@expo/config-plugins");
|
|
5
|
+
const generateCode_1 = require("@expo/config-plugins/build/utils/generateCode");
|
|
6
|
+
// Tag used for mergeContents to identify code blocks added by this plugin
|
|
7
|
+
const MPARTICLE_TAG = 'react-native-mparticle';
|
|
8
|
+
/**
|
|
9
|
+
* Get the mParticle log level string for Android
|
|
10
|
+
*/
|
|
11
|
+
function getAndroidLogLevel(logLevel) {
|
|
12
|
+
switch (logLevel) {
|
|
13
|
+
case 'none':
|
|
14
|
+
return 'MParticle.LogLevel.NONE';
|
|
15
|
+
case 'error':
|
|
16
|
+
return 'MParticle.LogLevel.ERROR';
|
|
17
|
+
case 'warning':
|
|
18
|
+
return 'MParticle.LogLevel.WARNING';
|
|
19
|
+
case 'debug':
|
|
20
|
+
return 'MParticle.LogLevel.DEBUG';
|
|
21
|
+
case 'verbose':
|
|
22
|
+
return 'MParticle.LogLevel.VERBOSE';
|
|
23
|
+
default:
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Get the mParticle environment string for Android
|
|
29
|
+
*/
|
|
30
|
+
function getAndroidEnvironment(environment) {
|
|
31
|
+
switch (environment) {
|
|
32
|
+
case 'development':
|
|
33
|
+
return 'MParticle.Environment.Development';
|
|
34
|
+
case 'production':
|
|
35
|
+
return 'MParticle.Environment.Production';
|
|
36
|
+
case 'autoDetect':
|
|
37
|
+
return 'MParticle.Environment.AutoDetect';
|
|
38
|
+
default:
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Generate mParticle initialization code for Kotlin MainApplication
|
|
44
|
+
*/
|
|
45
|
+
function generateKotlinInitCode(props) {
|
|
46
|
+
const { androidApiKey, androidApiSecret, logLevel, environment, useEmptyIdentifyRequest = true, dataPlanId, dataPlanVersion, } = props;
|
|
47
|
+
const lines = [
|
|
48
|
+
'// mParticle SDK initialization',
|
|
49
|
+
'val mParticleOptions = MParticleOptions.builder(this)',
|
|
50
|
+
` .credentials("${androidApiKey}", "${androidApiSecret}")`,
|
|
51
|
+
];
|
|
52
|
+
const androidLogLevel = getAndroidLogLevel(logLevel);
|
|
53
|
+
if (androidLogLevel) {
|
|
54
|
+
lines.push(` .logLevel(${androidLogLevel})`);
|
|
55
|
+
}
|
|
56
|
+
const androidEnvironment = getAndroidEnvironment(environment);
|
|
57
|
+
if (androidEnvironment) {
|
|
58
|
+
lines.push(` .environment(${androidEnvironment})`);
|
|
59
|
+
}
|
|
60
|
+
if (dataPlanId) {
|
|
61
|
+
const versionParam = dataPlanVersion ? `, ${dataPlanVersion}` : '';
|
|
62
|
+
lines.push(` .dataplan("${dataPlanId}"${versionParam})`);
|
|
63
|
+
}
|
|
64
|
+
if (useEmptyIdentifyRequest) {
|
|
65
|
+
lines.push(' .identify(IdentityApiRequest.withEmptyUser().build())');
|
|
66
|
+
}
|
|
67
|
+
lines.push(' .build()');
|
|
68
|
+
lines.push('MParticle.start(mParticleOptions)');
|
|
69
|
+
return lines.join('\n ');
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Generate mParticle initialization code for Java MainApplication
|
|
73
|
+
*/
|
|
74
|
+
function generateJavaInitCode(props) {
|
|
75
|
+
const { androidApiKey, androidApiSecret, logLevel, environment, useEmptyIdentifyRequest = true, dataPlanId, dataPlanVersion, } = props;
|
|
76
|
+
const lines = [
|
|
77
|
+
'// mParticle SDK initialization',
|
|
78
|
+
'MParticleOptions.Builder optionsBuilder = MParticleOptions.builder(this)',
|
|
79
|
+
` .credentials("${androidApiKey}", "${androidApiSecret}")`,
|
|
80
|
+
];
|
|
81
|
+
const androidLogLevel = getAndroidLogLevel(logLevel);
|
|
82
|
+
if (androidLogLevel) {
|
|
83
|
+
lines.push(` .logLevel(${androidLogLevel})`);
|
|
84
|
+
}
|
|
85
|
+
const androidEnvironment = getAndroidEnvironment(environment);
|
|
86
|
+
if (androidEnvironment) {
|
|
87
|
+
lines.push(` .environment(${androidEnvironment})`);
|
|
88
|
+
}
|
|
89
|
+
if (dataPlanId) {
|
|
90
|
+
const versionParam = dataPlanVersion ? `, ${dataPlanVersion}` : '';
|
|
91
|
+
lines.push(` .dataplan("${dataPlanId}"${versionParam})`);
|
|
92
|
+
}
|
|
93
|
+
if (useEmptyIdentifyRequest) {
|
|
94
|
+
lines.push(' .identify(IdentityApiRequest.withEmptyUser().build())');
|
|
95
|
+
}
|
|
96
|
+
// Java needs semicolons
|
|
97
|
+
lines.push(';');
|
|
98
|
+
lines.push('MParticle.start(optionsBuilder.build());');
|
|
99
|
+
return lines.join('\n ');
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Generate mParticle import statements for Kotlin
|
|
103
|
+
*/
|
|
104
|
+
function getKotlinImports() {
|
|
105
|
+
return `import com.mparticle.MParticle
|
|
106
|
+
import com.mparticle.MParticleOptions
|
|
107
|
+
import com.mparticle.identity.IdentityApiRequest`;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Generate mParticle import statements for Java
|
|
111
|
+
*/
|
|
112
|
+
function getJavaImports() {
|
|
113
|
+
return `import com.mparticle.MParticle;
|
|
114
|
+
import com.mparticle.MParticleOptions;
|
|
115
|
+
import com.mparticle.identity.IdentityApiRequest;`;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Add mParticle configuration to MainApplication
|
|
119
|
+
* Handles both Kotlin and Java
|
|
120
|
+
*/
|
|
121
|
+
const withMParticleMainApplication = (config, props) => {
|
|
122
|
+
return (0, config_plugins_1.withMainApplication)(config, config => {
|
|
123
|
+
const { contents, language } = config.modResults;
|
|
124
|
+
// Check if mParticle is already initialized
|
|
125
|
+
if (contents.includes('MParticleOptions') ||
|
|
126
|
+
contents.includes('mParticleOptions')) {
|
|
127
|
+
return config;
|
|
128
|
+
}
|
|
129
|
+
const isKotlin = language === 'kt';
|
|
130
|
+
if (isKotlin) {
|
|
131
|
+
config.modResults.contents = addMParticleToKotlinMainApplication(contents, props);
|
|
132
|
+
}
|
|
133
|
+
else if (language === 'java') {
|
|
134
|
+
config.modResults.contents = addMParticleToJavaMainApplication(contents, props);
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
console.warn(`[react-native-mparticle] Unsupported MainApplication language: ${language}. ` +
|
|
138
|
+
'mParticle initialization must be added manually.');
|
|
139
|
+
}
|
|
140
|
+
return config;
|
|
141
|
+
});
|
|
142
|
+
};
|
|
143
|
+
/**
|
|
144
|
+
* Add mParticle import and initialization to Kotlin MainApplication
|
|
145
|
+
*/
|
|
146
|
+
function addMParticleToKotlinMainApplication(contents, props) {
|
|
147
|
+
// Add import statements using mergeContents
|
|
148
|
+
const withImports = (0, generateCode_1.mergeContents)({
|
|
149
|
+
src: contents,
|
|
150
|
+
newSrc: getKotlinImports(),
|
|
151
|
+
anchor: /^package .+$/m,
|
|
152
|
+
offset: 1,
|
|
153
|
+
tag: `${MPARTICLE_TAG}-import`,
|
|
154
|
+
comment: '//',
|
|
155
|
+
});
|
|
156
|
+
// Generate initialization code
|
|
157
|
+
const initCode = generateKotlinInitCode(props);
|
|
158
|
+
// Find the right place to add initialization code
|
|
159
|
+
// Try ApplicationLifecycleDispatcher first (Expo pattern), then super.onCreate()
|
|
160
|
+
let result = withImports.contents;
|
|
161
|
+
if (result.includes('ApplicationLifecycleDispatcher.onApplicationCreate(this)')) {
|
|
162
|
+
const withInit = (0, generateCode_1.mergeContents)({
|
|
163
|
+
src: result,
|
|
164
|
+
newSrc: `\n ${initCode}\n`,
|
|
165
|
+
anchor: /ApplicationLifecycleDispatcher\.onApplicationCreate\(this\)/,
|
|
166
|
+
offset: 1,
|
|
167
|
+
tag: `${MPARTICLE_TAG}-init`,
|
|
168
|
+
comment: '//',
|
|
169
|
+
});
|
|
170
|
+
result = withInit.contents;
|
|
171
|
+
}
|
|
172
|
+
else if (result.includes('super.onCreate()')) {
|
|
173
|
+
const withInit = (0, generateCode_1.mergeContents)({
|
|
174
|
+
src: result,
|
|
175
|
+
newSrc: `\n ${initCode}\n`,
|
|
176
|
+
anchor: /super\.onCreate\(\)/,
|
|
177
|
+
offset: 1,
|
|
178
|
+
tag: `${MPARTICLE_TAG}-init`,
|
|
179
|
+
comment: '//',
|
|
180
|
+
});
|
|
181
|
+
result = withInit.contents;
|
|
182
|
+
}
|
|
183
|
+
return result;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Add mParticle import and initialization to Java MainApplication
|
|
187
|
+
*/
|
|
188
|
+
function addMParticleToJavaMainApplication(contents, props) {
|
|
189
|
+
// Add import statements using mergeContents
|
|
190
|
+
const withImports = (0, generateCode_1.mergeContents)({
|
|
191
|
+
src: contents,
|
|
192
|
+
newSrc: getJavaImports(),
|
|
193
|
+
anchor: /^package .+;$/m,
|
|
194
|
+
offset: 1,
|
|
195
|
+
tag: `${MPARTICLE_TAG}-import`,
|
|
196
|
+
comment: '//',
|
|
197
|
+
});
|
|
198
|
+
// Generate initialization code
|
|
199
|
+
const initCode = generateJavaInitCode(props);
|
|
200
|
+
// Find the right place to add initialization code
|
|
201
|
+
let result = withImports.contents;
|
|
202
|
+
if (result.includes('ApplicationLifecycleDispatcher.onApplicationCreate(this);')) {
|
|
203
|
+
const withInit = (0, generateCode_1.mergeContents)({
|
|
204
|
+
src: result,
|
|
205
|
+
newSrc: `\n ${initCode}\n`,
|
|
206
|
+
anchor: /ApplicationLifecycleDispatcher\.onApplicationCreate\(this\);/,
|
|
207
|
+
offset: 1,
|
|
208
|
+
tag: `${MPARTICLE_TAG}-init`,
|
|
209
|
+
comment: '//',
|
|
210
|
+
});
|
|
211
|
+
result = withInit.contents;
|
|
212
|
+
}
|
|
213
|
+
else if (result.includes('super.onCreate();')) {
|
|
214
|
+
const withInit = (0, generateCode_1.mergeContents)({
|
|
215
|
+
src: result,
|
|
216
|
+
newSrc: `\n ${initCode}\n`,
|
|
217
|
+
anchor: /super\.onCreate\(\);/,
|
|
218
|
+
offset: 1,
|
|
219
|
+
tag: `${MPARTICLE_TAG}-init`,
|
|
220
|
+
comment: '//',
|
|
221
|
+
});
|
|
222
|
+
result = withInit.contents;
|
|
223
|
+
}
|
|
224
|
+
return result;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Add kit dependencies to app/build.gradle
|
|
228
|
+
*/
|
|
229
|
+
const withMParticleAppBuildGradle = (config, props) => {
|
|
230
|
+
return (0, config_plugins_1.withAppBuildGradle)(config, config => {
|
|
231
|
+
const { contents } = config.modResults;
|
|
232
|
+
if (!props.androidKits || props.androidKits.length === 0) {
|
|
233
|
+
return config;
|
|
234
|
+
}
|
|
235
|
+
// Check if kits are already added
|
|
236
|
+
const kitsAlreadyAdded = props.androidKits.every(kit => contents.includes(`com.mparticle:${kit}`));
|
|
237
|
+
if (kitsAlreadyAdded) {
|
|
238
|
+
return config;
|
|
239
|
+
}
|
|
240
|
+
// Generate kit dependency lines
|
|
241
|
+
// Use + for version to auto-match core SDK version
|
|
242
|
+
const kitDependencies = props.androidKits
|
|
243
|
+
.map(kit => ` implementation "com.mparticle:${kit}:+"`)
|
|
244
|
+
.join('\n');
|
|
245
|
+
// Use mergeContents for idempotent injection
|
|
246
|
+
const withKits = (0, generateCode_1.mergeContents)({
|
|
247
|
+
src: contents,
|
|
248
|
+
newSrc: `\n // mParticle kits\n${kitDependencies}`,
|
|
249
|
+
anchor: /dependencies\s*\{/,
|
|
250
|
+
offset: 1,
|
|
251
|
+
tag: `${MPARTICLE_TAG}-kits`,
|
|
252
|
+
comment: '//',
|
|
253
|
+
});
|
|
254
|
+
config.modResults.contents = withKits.contents;
|
|
255
|
+
return config;
|
|
256
|
+
});
|
|
257
|
+
};
|
|
258
|
+
/**
|
|
259
|
+
* Apply all Android-specific mParticle configurations
|
|
260
|
+
*/
|
|
261
|
+
const withMParticleAndroid = (config, props) => {
|
|
262
|
+
config = withMParticleMainApplication(config, props);
|
|
263
|
+
config = withMParticleAppBuildGradle(config, props);
|
|
264
|
+
return config;
|
|
265
|
+
};
|
|
266
|
+
exports.withMParticleAndroid = withMParticleAndroid;
|
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.withMParticleIOS = void 0;
|
|
27
|
+
const config_plugins_1 = require("@expo/config-plugins");
|
|
28
|
+
const generateCode_1 = require("@expo/config-plugins/build/utils/generateCode");
|
|
29
|
+
const fs = __importStar(require("fs"));
|
|
30
|
+
const path = __importStar(require("path"));
|
|
31
|
+
// Tag used for mergeContents to identify code blocks added by this plugin
|
|
32
|
+
const MPARTICLE_TAG = 'react-native-mparticle';
|
|
33
|
+
/**
|
|
34
|
+
* Get the mParticle log level for iOS (Swift syntax)
|
|
35
|
+
*/
|
|
36
|
+
function getSwiftLogLevel(logLevel) {
|
|
37
|
+
switch (logLevel) {
|
|
38
|
+
case 'none':
|
|
39
|
+
return '.none';
|
|
40
|
+
case 'error':
|
|
41
|
+
return '.error';
|
|
42
|
+
case 'warning':
|
|
43
|
+
return '.warning';
|
|
44
|
+
case 'debug':
|
|
45
|
+
return '.debug';
|
|
46
|
+
case 'verbose':
|
|
47
|
+
return '.verbose';
|
|
48
|
+
default:
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Get the mParticle environment for iOS (Swift syntax)
|
|
54
|
+
*/
|
|
55
|
+
function getSwiftEnvironment(environment) {
|
|
56
|
+
switch (environment) {
|
|
57
|
+
case 'development':
|
|
58
|
+
return '.development';
|
|
59
|
+
case 'production':
|
|
60
|
+
return '.production';
|
|
61
|
+
case 'autoDetect':
|
|
62
|
+
return '.autoDetect';
|
|
63
|
+
default:
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Get the mParticle log level for iOS (Objective-C syntax)
|
|
69
|
+
*/
|
|
70
|
+
function getObjcLogLevel(logLevel) {
|
|
71
|
+
switch (logLevel) {
|
|
72
|
+
case 'none':
|
|
73
|
+
return 'MPILogLevelNone';
|
|
74
|
+
case 'error':
|
|
75
|
+
return 'MPILogLevelError';
|
|
76
|
+
case 'warning':
|
|
77
|
+
return 'MPILogLevelWarning';
|
|
78
|
+
case 'debug':
|
|
79
|
+
return 'MPILogLevelDebug';
|
|
80
|
+
case 'verbose':
|
|
81
|
+
return 'MPILogLevelVerbose';
|
|
82
|
+
default:
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Get the mParticle environment for iOS (Objective-C syntax)
|
|
88
|
+
*/
|
|
89
|
+
function getObjcEnvironment(environment) {
|
|
90
|
+
switch (environment) {
|
|
91
|
+
case 'development':
|
|
92
|
+
return 'MPEnvironmentDevelopment';
|
|
93
|
+
case 'production':
|
|
94
|
+
return 'MPEnvironmentProduction';
|
|
95
|
+
case 'autoDetect':
|
|
96
|
+
return 'MPEnvironmentAutoDetect';
|
|
97
|
+
default:
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Generate mParticle initialization code for Swift AppDelegate
|
|
103
|
+
*/
|
|
104
|
+
function generateSwiftInitCode(props) {
|
|
105
|
+
const { iosApiKey, iosApiSecret, logLevel, environment, useEmptyIdentifyRequest = true, dataPlanId, dataPlanVersion, } = props;
|
|
106
|
+
const lines = [
|
|
107
|
+
'// mParticle SDK initialization',
|
|
108
|
+
`let mParticleOptions = MParticleOptions(key: "${iosApiKey}", secret: "${iosApiSecret}")`,
|
|
109
|
+
];
|
|
110
|
+
const swiftLogLevel = getSwiftLogLevel(logLevel);
|
|
111
|
+
if (swiftLogLevel) {
|
|
112
|
+
lines.push(`mParticleOptions.logLevel = ${swiftLogLevel}`);
|
|
113
|
+
}
|
|
114
|
+
const swiftEnvironment = getSwiftEnvironment(environment);
|
|
115
|
+
if (swiftEnvironment) {
|
|
116
|
+
lines.push(`mParticleOptions.environment = ${swiftEnvironment}`);
|
|
117
|
+
}
|
|
118
|
+
if (dataPlanId) {
|
|
119
|
+
lines.push(`mParticleOptions.dataPlanId = "${dataPlanId}"`);
|
|
120
|
+
if (dataPlanVersion) {
|
|
121
|
+
lines.push(`mParticleOptions.dataPlanVersion = ${dataPlanVersion} as NSNumber`);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
if (useEmptyIdentifyRequest) {
|
|
125
|
+
lines.push('let identifyRequest = MPIdentityApiRequest.withEmptyUser()');
|
|
126
|
+
lines.push('mParticleOptions.identifyRequest = identifyRequest');
|
|
127
|
+
}
|
|
128
|
+
lines.push('MParticle.sharedInstance().start(with: mParticleOptions)');
|
|
129
|
+
return lines.join('\n ');
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Generate mParticle initialization code for Objective-C AppDelegate
|
|
133
|
+
*/
|
|
134
|
+
function generateObjcInitCode(props) {
|
|
135
|
+
const { iosApiKey, iosApiSecret, logLevel, environment, useEmptyIdentifyRequest = true, dataPlanId, dataPlanVersion, } = props;
|
|
136
|
+
const lines = [
|
|
137
|
+
'// mParticle SDK initialization',
|
|
138
|
+
`MParticleOptions *mParticleOptions = [MParticleOptions optionsWithKey:@"${iosApiKey}"`,
|
|
139
|
+
` secret:@"${iosApiSecret}"];`,
|
|
140
|
+
];
|
|
141
|
+
const objcLogLevel = getObjcLogLevel(logLevel);
|
|
142
|
+
if (objcLogLevel) {
|
|
143
|
+
lines.push(`mParticleOptions.logLevel = ${objcLogLevel};`);
|
|
144
|
+
}
|
|
145
|
+
const objcEnvironment = getObjcEnvironment(environment);
|
|
146
|
+
if (objcEnvironment) {
|
|
147
|
+
lines.push(`mParticleOptions.environment = ${objcEnvironment};`);
|
|
148
|
+
}
|
|
149
|
+
if (dataPlanId) {
|
|
150
|
+
lines.push(`mParticleOptions.dataPlanId = @"${dataPlanId}";`);
|
|
151
|
+
if (dataPlanVersion) {
|
|
152
|
+
lines.push(`mParticleOptions.dataPlanVersion = @(${dataPlanVersion});`);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
if (useEmptyIdentifyRequest) {
|
|
156
|
+
lines.push('MPIdentityApiRequest *identifyRequest = [MPIdentityApiRequest requestWithEmptyUser];');
|
|
157
|
+
lines.push('mParticleOptions.identifyRequest = identifyRequest;');
|
|
158
|
+
}
|
|
159
|
+
lines.push('[[MParticle sharedInstance] startWithOptions:mParticleOptions];');
|
|
160
|
+
return lines.join('\n ');
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Add mParticle configuration to AppDelegate
|
|
164
|
+
* Handles both Swift and Objective-C/Objective-C++
|
|
165
|
+
*/
|
|
166
|
+
const withMParticleAppDelegate = (config, props) => {
|
|
167
|
+
return (0, config_plugins_1.withAppDelegate)(config, config => {
|
|
168
|
+
const { contents, language } = config.modResults;
|
|
169
|
+
// Check if mParticle is already initialized
|
|
170
|
+
if (contents.includes('MParticleOptions') ||
|
|
171
|
+
contents.includes('mParticleOptions')) {
|
|
172
|
+
return config;
|
|
173
|
+
}
|
|
174
|
+
if (language === 'swift') {
|
|
175
|
+
config.modResults.contents = addMParticleToSwiftAppDelegate(contents, props);
|
|
176
|
+
}
|
|
177
|
+
else if (language === 'objc' || language === 'objcpp') {
|
|
178
|
+
config.modResults.contents = addMParticleToObjcAppDelegate(contents, props);
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
console.warn(`[react-native-mparticle] Unsupported AppDelegate language: ${language}. ` +
|
|
182
|
+
'mParticle initialization must be added manually.');
|
|
183
|
+
}
|
|
184
|
+
return config;
|
|
185
|
+
});
|
|
186
|
+
};
|
|
187
|
+
/**
|
|
188
|
+
* Add mParticle import and initialization to Swift AppDelegate
|
|
189
|
+
*/
|
|
190
|
+
function addMParticleToSwiftAppDelegate(contents, props) {
|
|
191
|
+
// Add import statement
|
|
192
|
+
// Use mergeContents for safe, idempotent code injection
|
|
193
|
+
const withImport = (0, generateCode_1.mergeContents)({
|
|
194
|
+
src: contents,
|
|
195
|
+
newSrc: 'import mParticle_Apple_SDK',
|
|
196
|
+
anchor: /import Expo/,
|
|
197
|
+
offset: 1,
|
|
198
|
+
tag: `${MPARTICLE_TAG}-import`,
|
|
199
|
+
comment: '//',
|
|
200
|
+
});
|
|
201
|
+
// Generate initialization code
|
|
202
|
+
const initCode = generateSwiftInitCode(props);
|
|
203
|
+
// Find the right place to add initialization code
|
|
204
|
+
// For Expo SDK 53+, it should be in didFinishLaunchingWithOptions before the return
|
|
205
|
+
// Look for the return super.application pattern
|
|
206
|
+
const withInit = (0, generateCode_1.mergeContents)({
|
|
207
|
+
src: withImport.contents,
|
|
208
|
+
newSrc: `\n ${initCode}\n`,
|
|
209
|
+
anchor: /return super\.application\(application, didFinishLaunchingWithOptions: launchOptions\)/,
|
|
210
|
+
offset: 0,
|
|
211
|
+
tag: `${MPARTICLE_TAG}-init`,
|
|
212
|
+
comment: '//',
|
|
213
|
+
});
|
|
214
|
+
return withInit.contents;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Add mParticle import and initialization to Objective-C AppDelegate
|
|
218
|
+
*/
|
|
219
|
+
function addMParticleToObjcAppDelegate(contents, props) {
|
|
220
|
+
// Add import statement after React import or first import
|
|
221
|
+
const withImport = (0, generateCode_1.mergeContents)({
|
|
222
|
+
src: contents,
|
|
223
|
+
newSrc: '#import "mParticle.h"',
|
|
224
|
+
anchor: /#import <React\/RCTBundleURLProvider\.h>|#import "AppDelegate\.h"/,
|
|
225
|
+
offset: 1,
|
|
226
|
+
tag: `${MPARTICLE_TAG}-import`,
|
|
227
|
+
comment: '//',
|
|
228
|
+
});
|
|
229
|
+
// Generate initialization code
|
|
230
|
+
const initCode = generateObjcInitCode(props);
|
|
231
|
+
// Try different patterns for where to insert the init code
|
|
232
|
+
let result = withImport.contents;
|
|
233
|
+
// Pattern 1: Expo's return [super application...
|
|
234
|
+
if (result.includes('return [super application:application didFinishLaunchingWithOptions:launchOptions];')) {
|
|
235
|
+
const withInit = (0, generateCode_1.mergeContents)({
|
|
236
|
+
src: result,
|
|
237
|
+
newSrc: `\n ${initCode}\n`,
|
|
238
|
+
anchor: /return \[super application:application didFinishLaunchingWithOptions:launchOptions\];/,
|
|
239
|
+
offset: 0,
|
|
240
|
+
tag: `${MPARTICLE_TAG}-init`,
|
|
241
|
+
comment: '//',
|
|
242
|
+
});
|
|
243
|
+
result = withInit.contents;
|
|
244
|
+
}
|
|
245
|
+
// Pattern 2: self.initialProps = @{};
|
|
246
|
+
else if (result.includes('self.initialProps = @{};')) {
|
|
247
|
+
const withInit = (0, generateCode_1.mergeContents)({
|
|
248
|
+
src: result,
|
|
249
|
+
newSrc: `\n ${initCode}\n`,
|
|
250
|
+
anchor: /self\.initialProps = @\{\};/,
|
|
251
|
+
offset: 1,
|
|
252
|
+
tag: `${MPARTICLE_TAG}-init`,
|
|
253
|
+
comment: '//',
|
|
254
|
+
});
|
|
255
|
+
result = withInit.contents;
|
|
256
|
+
}
|
|
257
|
+
// Pattern 3: return YES;
|
|
258
|
+
else if (result.includes('return YES;')) {
|
|
259
|
+
const withInit = (0, generateCode_1.mergeContents)({
|
|
260
|
+
src: result,
|
|
261
|
+
newSrc: `\n ${initCode}\n`,
|
|
262
|
+
anchor: /return YES;/,
|
|
263
|
+
offset: 0,
|
|
264
|
+
tag: `${MPARTICLE_TAG}-init`,
|
|
265
|
+
comment: '//',
|
|
266
|
+
});
|
|
267
|
+
result = withInit.contents;
|
|
268
|
+
}
|
|
269
|
+
return result;
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Known transitive dependencies that need dynamic linking for each kit
|
|
273
|
+
* These are dependencies of mParticle kits that must also be dynamic frameworks
|
|
274
|
+
*/
|
|
275
|
+
const KIT_TRANSITIVE_DEPENDENCIES = {
|
|
276
|
+
'mParticle-Rokt': ['Rokt-Widget'],
|
|
277
|
+
// Add other kit dependencies here as needed
|
|
278
|
+
// "mParticle-Amplitude": [],
|
|
279
|
+
// "mParticle-Braze": [],
|
|
280
|
+
};
|
|
281
|
+
/**
|
|
282
|
+
* Get all pods that need dynamic framework linking
|
|
283
|
+
*/
|
|
284
|
+
function getDynamicFrameworkPods(iosKits) {
|
|
285
|
+
const pods = ['mParticle-Apple-SDK'];
|
|
286
|
+
if (iosKits) {
|
|
287
|
+
for (const kit of iosKits) {
|
|
288
|
+
pods.push(kit);
|
|
289
|
+
// Add transitive dependencies for this kit
|
|
290
|
+
const transitiveDeps = KIT_TRANSITIVE_DEPENDENCIES[kit];
|
|
291
|
+
if (transitiveDeps) {
|
|
292
|
+
pods.push(...transitiveDeps);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
return [...new Set(pods)]; // Remove duplicates
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Add kit pods and pre_install hook to Podfile
|
|
300
|
+
*/
|
|
301
|
+
const withMParticlePodfile = (config, props) => {
|
|
302
|
+
return (0, config_plugins_1.withDangerousMod)(config, [
|
|
303
|
+
'ios',
|
|
304
|
+
async (config) => {
|
|
305
|
+
const podfilePath = path.join(config.modRequest.platformProjectRoot, 'Podfile');
|
|
306
|
+
if (!fs.existsSync(podfilePath)) {
|
|
307
|
+
return config;
|
|
308
|
+
}
|
|
309
|
+
let podfileContent = fs.readFileSync(podfilePath, 'utf-8');
|
|
310
|
+
// Add pre_install hook for dynamic framework linking if not already present
|
|
311
|
+
if (!podfileContent.includes('mParticle-Apple-SDK')) {
|
|
312
|
+
// Get all pods that need dynamic linking (including transitive dependencies)
|
|
313
|
+
const dynamicPods = getDynamicFrameworkPods(props.iosKits);
|
|
314
|
+
const podConditions = dynamicPods
|
|
315
|
+
.map(pod => `pod.name == '${pod}'`)
|
|
316
|
+
.join(' || ');
|
|
317
|
+
const preInstallHook = `
|
|
318
|
+
# mParticle dynamic framework linking (added by react-native-mparticle expo plugin)
|
|
319
|
+
pre_install do |installer|
|
|
320
|
+
installer.pod_targets.each do |pod|
|
|
321
|
+
if ${podConditions}
|
|
322
|
+
def pod.build_type;
|
|
323
|
+
Pod::BuildType.new(:linkage => :dynamic, :packaging => :framework)
|
|
324
|
+
end
|
|
325
|
+
end
|
|
326
|
+
end
|
|
327
|
+
end
|
|
328
|
+
`;
|
|
329
|
+
// Add pre_install hook after platform declaration
|
|
330
|
+
const platformRegex = /platform :ios.*\n/;
|
|
331
|
+
if (platformRegex.test(podfileContent)) {
|
|
332
|
+
podfileContent = podfileContent.replace(platformRegex, `$&${preInstallHook}`);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
// Add kit pods if specified
|
|
336
|
+
if (props.iosKits && props.iosKits.length > 0) {
|
|
337
|
+
const kitPods = props.iosKits.map(kit => ` pod '${kit}'`).join('\n');
|
|
338
|
+
// Check if kits are already added
|
|
339
|
+
const kitsAlreadyAdded = props.iosKits.every(kit => podfileContent.includes(`pod '${kit}'`));
|
|
340
|
+
if (!kitsAlreadyAdded) {
|
|
341
|
+
// Add kit pods inside the main target block
|
|
342
|
+
// Look for use_react_native! and add after it
|
|
343
|
+
const useReactNativeRegex = /(use_react_native!\([^)]*\))/s;
|
|
344
|
+
if (useReactNativeRegex.test(podfileContent)) {
|
|
345
|
+
podfileContent = podfileContent.replace(useReactNativeRegex, `$1\n\n # mParticle kits (added by react-native-mparticle expo plugin)\n${kitPods}`);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
fs.writeFileSync(podfilePath, podfileContent);
|
|
350
|
+
return config;
|
|
351
|
+
},
|
|
352
|
+
]);
|
|
353
|
+
};
|
|
354
|
+
/**
|
|
355
|
+
* Apply all iOS-specific mParticle configurations
|
|
356
|
+
*/
|
|
357
|
+
const withMParticleIOS = (config, props) => {
|
|
358
|
+
config = withMParticleAppDelegate(config, props);
|
|
359
|
+
config = withMParticlePodfile(config, props);
|
|
360
|
+
return config;
|
|
361
|
+
};
|
|
362
|
+
exports.withMParticleIOS = withMParticleIOS;
|