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.
Files changed (37) hide show
  1. package/README.md +252 -94
  2. package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  3. package/android/gradle/wrapper/gradle-wrapper.properties +6 -0
  4. package/android/gradle.properties +26 -0
  5. package/android/gradlew +160 -0
  6. package/android/gradlew.bat +90 -0
  7. package/android/libs/java-json.jar +0 -0
  8. package/android/src/main/java/com/mparticle/react/MParticleModule.kt +1 -1
  9. package/android/src/test/java/com/mparticle/react/IdentityApiTest.java +230 -0
  10. package/android/src/test/java/com/mparticle/react/MParticleUserTest.java +173 -0
  11. package/android/src/test/java/com/mparticle/react/testutils/MockMParticleUser.java +109 -0
  12. package/android/src/test/java/com/mparticle/react/testutils/MockMap.java +203 -0
  13. package/android/src/test/java/com/mparticle/react/testutils/MockReadableArray.java +68 -0
  14. package/android/src/test/java/com/mparticle/react/testutils/MockWritableMap.java +4 -0
  15. package/android/src/test/java/com/mparticle/react/testutils/Mutable.java +13 -0
  16. package/app.plugin.js +1 -0
  17. package/ios/RNMParticle/RNMPRokt.mm +25 -11
  18. package/ios/RNMParticle/RNMParticle.mm +2 -1
  19. package/js/codegenSpecs/NativeMParticle.ts +3 -4
  20. package/js/rokt/rokt-layout-view.android.tsx +2 -1
  21. package/lib/codegenSpecs/NativeMParticle.d.ts +3 -4
  22. package/lib/codegenSpecs/NativeMParticle.js.map +1 -1
  23. package/lib/rokt/rokt-layout-view.android.js +1 -0
  24. package/lib/rokt/rokt-layout-view.android.js.map +1 -1
  25. package/package.json +28 -4
  26. package/plugin/build/withMParticle.d.ts +60 -0
  27. package/plugin/build/withMParticle.js +30 -0
  28. package/plugin/build/withMParticleAndroid.d.ts +6 -0
  29. package/plugin/build/withMParticleAndroid.js +266 -0
  30. package/plugin/build/withMParticleIOS.d.ts +6 -0
  31. package/plugin/build/withMParticleIOS.js +362 -0
  32. package/plugin/src/withMParticle.ts +106 -0
  33. package/plugin/src/withMParticleAndroid.ts +359 -0
  34. package/plugin/src/withMParticleIOS.ts +459 -0
  35. package/plugin/tsconfig.json +8 -0
  36. package/react-native-mparticle.podspec +11 -0
  37. 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,6 @@
1
+ import { ConfigPlugin } from '@expo/config-plugins';
2
+ import { MParticlePluginProps } from './withMParticle';
3
+ /**
4
+ * Apply all Android-specific mParticle configurations
5
+ */
6
+ export declare const withMParticleAndroid: ConfigPlugin<MParticlePluginProps>;
@@ -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,6 @@
1
+ import { ConfigPlugin } from '@expo/config-plugins';
2
+ import { MParticlePluginProps } from './withMParticle';
3
+ /**
4
+ * Apply all iOS-specific mParticle configurations
5
+ */
6
+ export declare const withMParticleIOS: ConfigPlugin<MParticlePluginProps>;
@@ -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;