customerio-expo-plugin 3.3.0 → 3.5.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/package.json +8 -1
- package/plugin/lib/commonjs/android/withAndroidManifestUpdates.js +64 -59
- package/plugin/lib/commonjs/android/withAndroidManifestUpdates.js.map +1 -1
- package/plugin/lib/commonjs/android/withAppGoogleServices.js +10 -7
- package/plugin/lib/commonjs/android/withAppGoogleServices.js.map +1 -1
- package/plugin/lib/commonjs/android/withGoogleServicesJSON.js +18 -21
- package/plugin/lib/commonjs/android/withGoogleServicesJSON.js.map +1 -1
- package/plugin/lib/commonjs/android/withLocationGradleProperties.js +16 -12
- package/plugin/lib/commonjs/android/withLocationGradleProperties.js.map +1 -1
- package/plugin/lib/commonjs/android/withMainApplicationModifications.js +19 -12
- package/plugin/lib/commonjs/android/withMainApplicationModifications.js.map +1 -1
- package/plugin/lib/commonjs/android/withNotificationChannelMetadata.js +2 -1
- package/plugin/lib/commonjs/android/withNotificationChannelMetadata.js.map +1 -1
- package/plugin/lib/commonjs/android/withProjectBuildGradle.js +29 -25
- package/plugin/lib/commonjs/android/withProjectBuildGradle.js.map +1 -1
- package/plugin/lib/commonjs/android/withProjectGoogleServices.js +9 -5
- package/plugin/lib/commonjs/android/withProjectGoogleServices.js.map +1 -1
- package/plugin/lib/commonjs/helpers/constants/ios.js +76 -8
- package/plugin/lib/commonjs/helpers/constants/ios.js.map +1 -1
- package/plugin/lib/commonjs/helpers/utils/injectCIOPodfileCode.js +76 -31
- package/plugin/lib/commonjs/helpers/utils/injectCIOPodfileCode.js.map +1 -1
- package/plugin/lib/commonjs/index.js +7 -0
- package/plugin/lib/commonjs/index.js.map +1 -1
- package/plugin/lib/commonjs/ios/withAppDelegateModifications.js +47 -33
- package/plugin/lib/commonjs/ios/withAppDelegateModifications.js.map +1 -1
- package/plugin/lib/commonjs/ios/withCIOIosSwift.js +44 -54
- package/plugin/lib/commonjs/ios/withCIOIosSwift.js.map +1 -1
- package/plugin/lib/commonjs/ios/withGoogleServicesJsonFile.js +46 -30
- package/plugin/lib/commonjs/ios/withGoogleServicesJsonFile.js.map +1 -1
- package/plugin/lib/commonjs/ios/withNotificationsXcodeProject.js +192 -122
- package/plugin/lib/commonjs/ios/withNotificationsXcodeProject.js.map +1 -1
- package/plugin/lib/commonjs/postInstallHelper.js +58 -11
- package/plugin/lib/commonjs/postInstallHelper.js.map +1 -1
- package/plugin/lib/commonjs/utils/resolveRNSDK.js +97 -0
- package/plugin/lib/commonjs/utils/resolveRNSDK.js.map +1 -0
- package/plugin/lib/commonjs/utils/writeExpoVersion.js +56 -0
- package/plugin/lib/commonjs/utils/writeExpoVersion.js.map +1 -0
- package/plugin/lib/module/android/withAndroidManifestUpdates.js +61 -58
- package/plugin/lib/module/android/withAndroidManifestUpdates.js.map +1 -1
- package/plugin/lib/module/android/withAppGoogleServices.js +9 -7
- package/plugin/lib/module/android/withAppGoogleServices.js.map +1 -1
- package/plugin/lib/module/android/withGoogleServicesJSON.js +17 -21
- package/plugin/lib/module/android/withGoogleServicesJSON.js.map +1 -1
- package/plugin/lib/module/android/withLocationGradleProperties.js +15 -12
- package/plugin/lib/module/android/withLocationGradleProperties.js.map +1 -1
- package/plugin/lib/module/android/withMainApplicationModifications.js +18 -12
- package/plugin/lib/module/android/withMainApplicationModifications.js.map +1 -1
- package/plugin/lib/module/android/withNotificationChannelMetadata.js +1 -1
- package/plugin/lib/module/android/withNotificationChannelMetadata.js.map +1 -1
- package/plugin/lib/module/android/withProjectBuildGradle.js +28 -25
- package/plugin/lib/module/android/withProjectBuildGradle.js.map +1 -1
- package/plugin/lib/module/android/withProjectGoogleServices.js +8 -5
- package/plugin/lib/module/android/withProjectGoogleServices.js.map +1 -1
- package/plugin/lib/module/helpers/constants/ios.js +75 -8
- package/plugin/lib/module/helpers/constants/ios.js.map +1 -1
- package/plugin/lib/module/helpers/utils/injectCIOPodfileCode.js +74 -31
- package/plugin/lib/module/helpers/utils/injectCIOPodfileCode.js.map +1 -1
- package/plugin/lib/module/index.js +7 -0
- package/plugin/lib/module/index.js.map +1 -1
- package/plugin/lib/module/ios/withAppDelegateModifications.js +45 -33
- package/plugin/lib/module/ios/withAppDelegateModifications.js.map +1 -1
- package/plugin/lib/module/ios/withCIOIosSwift.js +42 -54
- package/plugin/lib/module/ios/withCIOIosSwift.js.map +1 -1
- package/plugin/lib/module/ios/withGoogleServicesJsonFile.js +45 -30
- package/plugin/lib/module/ios/withGoogleServicesJsonFile.js.map +1 -1
- package/plugin/lib/module/ios/withNotificationsXcodeProject.js +187 -122
- package/plugin/lib/module/ios/withNotificationsXcodeProject.js.map +1 -1
- package/plugin/lib/module/postInstallHelper.js +58 -11
- package/plugin/lib/module/postInstallHelper.js.map +1 -1
- package/plugin/lib/module/utils/resolveRNSDK.js +88 -0
- package/plugin/lib/module/utils/resolveRNSDK.js.map +1 -0
- package/plugin/lib/module/utils/writeExpoVersion.js +48 -0
- package/plugin/lib/module/utils/writeExpoVersion.js.map +1 -0
- package/plugin/lib/typescript/android/withAndroidManifestUpdates.d.ts +2 -0
- package/plugin/lib/typescript/android/withAppGoogleServices.d.ts +1 -0
- package/plugin/lib/typescript/android/withGoogleServicesJSON.d.ts +1 -0
- package/plugin/lib/typescript/android/withLocationGradleProperties.d.ts +2 -0
- package/plugin/lib/typescript/android/withMainApplicationModifications.d.ts +6 -0
- package/plugin/lib/typescript/android/withNotificationChannelMetadata.d.ts +5 -0
- package/plugin/lib/typescript/android/withProjectBuildGradle.d.ts +9 -0
- package/plugin/lib/typescript/android/withProjectGoogleServices.d.ts +1 -0
- package/plugin/lib/typescript/helpers/constants/ios.d.ts +18 -0
- package/plugin/lib/typescript/helpers/utils/injectCIOPodfileCode.d.ts +25 -1
- package/plugin/lib/typescript/ios/withAppDelegateModifications.d.ts +13 -0
- package/plugin/lib/typescript/ios/withCIOIosSwift.d.ts +11 -0
- package/plugin/lib/typescript/ios/withGoogleServicesJsonFile.d.ts +14 -1
- package/plugin/lib/typescript/ios/withNotificationsXcodeProject.d.ts +53 -2
- package/plugin/lib/typescript/utils/resolveRNSDK.d.ts +7 -0
- package/plugin/lib/typescript/utils/writeExpoVersion.d.ts +3 -0
- package/plugin/src/android/withAndroidManifestUpdates.ts +83 -73
- package/plugin/src/android/withAppGoogleServices.ts +13 -11
- package/plugin/src/android/withGoogleServicesJSON.ts +30 -28
- package/plugin/src/android/withLocationGradleProperties.ts +23 -17
- package/plugin/src/android/withMainApplicationModifications.ts +25 -15
- package/plugin/src/android/withNotificationChannelMetadata.ts +1 -1
- package/plugin/src/android/withProjectBuildGradle.ts +37 -27
- package/plugin/src/android/withProjectGoogleServices.ts +14 -9
- package/plugin/src/helpers/constants/ios.ts +87 -8
- package/plugin/src/helpers/utils/injectCIOPodfileCode.ts +97 -50
- package/plugin/src/index.ts +7 -0
- package/plugin/src/ios/withAppDelegateModifications.ts +61 -48
- package/plugin/src/ios/withCIOIosSwift.ts +58 -62
- package/plugin/src/ios/withGoogleServicesJsonFile.ts +66 -48
- package/plugin/src/ios/withNotificationsXcodeProject.ts +257 -207
- package/plugin/src/postInstallHelper.js +75 -17
- package/plugin/src/utils/resolveRNSDK.ts +118 -0
- package/plugin/src/utils/writeExpoVersion.ts +62 -0
|
@@ -18,6 +18,21 @@ import { isExpoVersion53OrHigher, isFcmPushProvider } from './utils';
|
|
|
18
18
|
const PLIST_FILENAME = `${CIO_NOTIFICATION_TARGET_NAME}-Info.plist`;
|
|
19
19
|
const ENV_FILENAME = 'Env.swift';
|
|
20
20
|
|
|
21
|
+
// NSE source files registered in the Xcode group AND copied to the target
|
|
22
|
+
// directory. Single source of truth — both `addNotificationServiceExtensionToXcodeProject`
|
|
23
|
+
// (registers them in the PBXGroup) and `addRichPushXcodeProj` (copies them
|
|
24
|
+
// from the plugin's native-files dir) read the same arrays. Keeping these
|
|
25
|
+
// in sync is load-bearing: the Xcode group must reference the same files
|
|
26
|
+
// that exist on disk, or the build fails with "no such file" / unresolved
|
|
27
|
+
// references.
|
|
28
|
+
const NSE_PLATFORM_SPECIFIC_FILES = ['NotificationService.swift'];
|
|
29
|
+
const NSE_COMMON_FILES = [
|
|
30
|
+
PLIST_FILENAME,
|
|
31
|
+
'NotificationService.h',
|
|
32
|
+
'NotificationService.m',
|
|
33
|
+
ENV_FILENAME,
|
|
34
|
+
];
|
|
35
|
+
|
|
21
36
|
const TARGETED_DEVICE_FAMILY = `"1,2"`;
|
|
22
37
|
|
|
23
38
|
const addNotificationServiceExtension = async (
|
|
@@ -101,109 +116,54 @@ export const withCioNotificationsXcodeProject: ConfigPlugin<
|
|
|
101
116
|
});
|
|
102
117
|
};
|
|
103
118
|
|
|
104
|
-
const
|
|
105
|
-
options: CustomerIOPluginOptionsIOS,
|
|
106
|
-
xcodeProject: XcodeProject,
|
|
107
|
-
) => {
|
|
108
|
-
const {
|
|
109
|
-
appleTeamId,
|
|
110
|
-
bundleIdentifier,
|
|
111
|
-
bundleShortVersion,
|
|
112
|
-
bundleVersion,
|
|
113
|
-
iosPath,
|
|
114
|
-
iosDeploymentTarget,
|
|
115
|
-
useFrameworks,
|
|
116
|
-
} = options;
|
|
119
|
+
const NSE_ENTITLEMENTS_FILENAME = 'NotificationService.entitlements';
|
|
117
120
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
+
export type AddNseTargetToXcodeProjectOptions = {
|
|
122
|
+
appleTeamId?: string;
|
|
123
|
+
bundleIdentifier?: string;
|
|
124
|
+
iosDeploymentTarget?: string;
|
|
125
|
+
appGroupId?: string;
|
|
126
|
+
};
|
|
121
127
|
|
|
122
|
-
|
|
123
|
-
|
|
128
|
+
/**
|
|
129
|
+
* Mutates the parsed XcodeProject to register the rich-push NotificationService
|
|
130
|
+
* extension target: creates a PBXGroup for its files, registers the group under
|
|
131
|
+
* the project's top-level group, adds the app_extension target, wires three
|
|
132
|
+
* build phases (Sources, Resources, Frameworks), configures the target's build
|
|
133
|
+
* settings (DEVELOPMENT_TEAM, IPHONEOS_DEPLOYMENT_TARGET, code-sign style,
|
|
134
|
+
* Swift version, and CODE_SIGN_ENTITLEMENTS when `appGroupId` is set), and
|
|
135
|
+
* stamps the development team attribute on both the new target and the
|
|
136
|
+
* project's main target attributes.
|
|
137
|
+
*
|
|
138
|
+
* Idempotent — returns the project unchanged if a target named
|
|
139
|
+
* `CIO_NOTIFICATION_TARGET_NAME` is already present.
|
|
140
|
+
*/
|
|
141
|
+
export function addNotificationServiceExtensionToXcodeProject(
|
|
142
|
+
xcodeProject: XcodeProject,
|
|
143
|
+
options: AddNseTargetToXcodeProjectOptions,
|
|
144
|
+
): XcodeProject {
|
|
124
145
|
if (xcodeProject.pbxTargetByName(CIO_NOTIFICATION_TARGET_NAME)) {
|
|
125
146
|
logger.warn(
|
|
126
|
-
`${CIO_NOTIFICATION_TARGET_NAME} already exists in project. Skipping
|
|
147
|
+
`${CIO_NOTIFICATION_TARGET_NAME} already exists in project. Skipping...`,
|
|
127
148
|
);
|
|
128
|
-
return;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
const nsePath = `${iosPath}/${CIO_NOTIFICATION_TARGET_NAME}`;
|
|
132
|
-
FileManagement.mkdir(nsePath, {
|
|
133
|
-
recursive: true,
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
const platformSpecificFiles = ['NotificationService.swift'];
|
|
137
|
-
|
|
138
|
-
const nseEntitlementsFilename = 'NotificationService.entitlements';
|
|
139
|
-
const appGroupId = options.pushNotification?.appGroupId;
|
|
140
|
-
|
|
141
|
-
// Write NSE entitlements file only when appGroupId is explicitly configured
|
|
142
|
-
if (appGroupId) {
|
|
143
|
-
const nseEntitlementsContent = `<?xml version="1.0" encoding="UTF-8"?>
|
|
144
|
-
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
145
|
-
<plist version="1.0">
|
|
146
|
-
<dict>
|
|
147
|
-
<key>com.apple.security.application-groups</key>
|
|
148
|
-
<array>
|
|
149
|
-
<string>${appGroupId}</string>
|
|
150
|
-
</array>
|
|
151
|
-
</dict>
|
|
152
|
-
</plist>
|
|
153
|
-
`;
|
|
154
|
-
FileManagement.writeFile(`${nsePath}/${nseEntitlementsFilename}`, nseEntitlementsContent);
|
|
149
|
+
return xcodeProject;
|
|
155
150
|
}
|
|
156
151
|
|
|
157
|
-
const
|
|
158
|
-
PLIST_FILENAME,
|
|
159
|
-
'NotificationService.h',
|
|
160
|
-
'NotificationService.m',
|
|
161
|
-
ENV_FILENAME,
|
|
162
|
-
];
|
|
163
|
-
|
|
164
|
-
const getTargetFile = (filename: string) => `${nsePath}/${filename}`;
|
|
165
|
-
// Copy platform-specific files
|
|
166
|
-
platformSpecificFiles.forEach((filename) => {
|
|
167
|
-
const targetFile = getTargetFile(filename);
|
|
168
|
-
FileManagement.copyFile(
|
|
169
|
-
`${getIosNativeFilesPath()}/${isFcmProvider ? 'fcm' : 'apn'
|
|
170
|
-
}/${filename}`,
|
|
171
|
-
targetFile
|
|
172
|
-
);
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
// Copy common files
|
|
176
|
-
commonFiles.forEach((filename) => {
|
|
177
|
-
const targetFile = getTargetFile(filename);
|
|
178
|
-
FileManagement.copyFile(
|
|
179
|
-
`${getIosNativeFilesPath()}/common/${filename}`,
|
|
180
|
-
targetFile
|
|
181
|
-
);
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
/* MODIFY COPIED EXTENSION FILES */
|
|
185
|
-
const infoPlistTargetFile = getTargetFile(PLIST_FILENAME);
|
|
186
|
-
updateNseInfoPlist({
|
|
187
|
-
bundleVersion,
|
|
188
|
-
bundleShortVersion,
|
|
189
|
-
infoPlistTargetFile,
|
|
190
|
-
});
|
|
191
|
-
updateNseEnv(getTargetFile(ENV_FILENAME), options.pushNotification?.env);
|
|
192
|
-
updateNseNotificationService(getTargetFile('NotificationService.swift'), options.pushNotification?.appGroupId);
|
|
152
|
+
const { appleTeamId, bundleIdentifier, iosDeploymentTarget, appGroupId } = options;
|
|
193
153
|
|
|
194
154
|
// The entitlements file is generated (not copied from source), so it's listed separately
|
|
195
|
-
// for the Xcode group so it appears in the file navigator
|
|
155
|
+
// for the Xcode group so it appears in the file navigator.
|
|
196
156
|
const allGroupFiles = [
|
|
197
|
-
...
|
|
198
|
-
...
|
|
199
|
-
...(appGroupId ? [
|
|
157
|
+
...NSE_PLATFORM_SPECIFIC_FILES,
|
|
158
|
+
...NSE_COMMON_FILES,
|
|
159
|
+
...(appGroupId ? [NSE_ENTITLEMENTS_FILENAME] : []),
|
|
200
160
|
];
|
|
201
161
|
|
|
202
162
|
// Create new PBXGroup for the extension
|
|
203
163
|
const extGroup = xcodeProject.addPbxGroup(
|
|
204
164
|
allGroupFiles,
|
|
205
165
|
CIO_NOTIFICATION_TARGET_NAME,
|
|
206
|
-
CIO_NOTIFICATION_TARGET_NAME
|
|
166
|
+
CIO_NOTIFICATION_TARGET_NAME,
|
|
207
167
|
);
|
|
208
168
|
|
|
209
169
|
// Add the new PBXGroup to the top level group. This makes the
|
|
@@ -223,20 +183,12 @@ const addRichPushXcodeProj = async (
|
|
|
223
183
|
projObjects.PBXTargetDependency = projObjects.PBXTargetDependency || {};
|
|
224
184
|
projObjects.PBXContainerItemProxy = projObjects.PBXTargetDependency || {};
|
|
225
185
|
|
|
226
|
-
|
|
227
|
-
logger.warn(
|
|
228
|
-
`${CIO_NOTIFICATION_TARGET_NAME} already exists in project. Skipping...`
|
|
229
|
-
);
|
|
230
|
-
return;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
// Add the NSE target
|
|
234
|
-
// This also adds PBXTargetDependency and PBXContainerItemProxy
|
|
186
|
+
// Add the NSE target. This also adds PBXTargetDependency and PBXContainerItemProxy.
|
|
235
187
|
const nseTarget = xcodeProject.addTarget(
|
|
236
188
|
CIO_NOTIFICATION_TARGET_NAME,
|
|
237
189
|
'app_extension',
|
|
238
190
|
CIO_NOTIFICATION_TARGET_NAME,
|
|
239
|
-
`${bundleIdentifier}.richpush
|
|
191
|
+
`${bundleIdentifier}.richpush`,
|
|
240
192
|
);
|
|
241
193
|
|
|
242
194
|
// Add build phases to the new target
|
|
@@ -244,21 +196,10 @@ const addRichPushXcodeProj = async (
|
|
|
244
196
|
['NotificationService.m', 'NotificationService.swift', 'Env.swift'],
|
|
245
197
|
'PBXSourcesBuildPhase',
|
|
246
198
|
'Sources',
|
|
247
|
-
nseTarget.uuid
|
|
248
|
-
);
|
|
249
|
-
xcodeProject.addBuildPhase(
|
|
250
|
-
[],
|
|
251
|
-
'PBXResourcesBuildPhase',
|
|
252
|
-
'Resources',
|
|
253
|
-
nseTarget.uuid
|
|
254
|
-
);
|
|
255
|
-
|
|
256
|
-
xcodeProject.addBuildPhase(
|
|
257
|
-
[],
|
|
258
|
-
'PBXFrameworksBuildPhase',
|
|
259
|
-
'Frameworks',
|
|
260
|
-
nseTarget.uuid
|
|
199
|
+
nseTarget.uuid,
|
|
261
200
|
);
|
|
201
|
+
xcodeProject.addBuildPhase([], 'PBXResourcesBuildPhase', 'Resources', nseTarget.uuid);
|
|
202
|
+
xcodeProject.addBuildPhase([], 'PBXFrameworksBuildPhase', 'Frameworks', nseTarget.uuid);
|
|
262
203
|
|
|
263
204
|
// Edit the Deployment info of the target
|
|
264
205
|
const configurations = xcodeProject.pbxXCBuildConfigurationSection();
|
|
@@ -266,17 +207,16 @@ const addRichPushXcodeProj = async (
|
|
|
266
207
|
if (
|
|
267
208
|
typeof configurations[key].buildSettings !== 'undefined' &&
|
|
268
209
|
configurations[key].buildSettings.PRODUCT_NAME ===
|
|
269
|
-
|
|
210
|
+
`"${CIO_NOTIFICATION_TARGET_NAME}"`
|
|
270
211
|
) {
|
|
271
212
|
const buildSettingsObj = configurations[key].buildSettings;
|
|
272
213
|
buildSettingsObj.DEVELOPMENT_TEAM = appleTeamId;
|
|
273
|
-
buildSettingsObj.IPHONEOS_DEPLOYMENT_TARGET =
|
|
274
|
-
iosDeploymentTarget || '15.1';
|
|
214
|
+
buildSettingsObj.IPHONEOS_DEPLOYMENT_TARGET = iosDeploymentTarget || '15.1';
|
|
275
215
|
buildSettingsObj.TARGETED_DEVICE_FAMILY = TARGETED_DEVICE_FAMILY;
|
|
276
216
|
buildSettingsObj.CODE_SIGN_STYLE = 'Automatic';
|
|
277
217
|
buildSettingsObj.SWIFT_VERSION = 4.2;
|
|
278
218
|
if (appGroupId) {
|
|
279
|
-
buildSettingsObj.CODE_SIGN_ENTITLEMENTS = `${CIO_NOTIFICATION_TARGET_NAME}/${
|
|
219
|
+
buildSettingsObj.CODE_SIGN_ENTITLEMENTS = `${CIO_NOTIFICATION_TARGET_NAME}/${NSE_ENTITLEMENTS_FILENAME}`;
|
|
280
220
|
}
|
|
281
221
|
}
|
|
282
222
|
}
|
|
@@ -284,91 +224,196 @@ const addRichPushXcodeProj = async (
|
|
|
284
224
|
// Add development team to the target & the main
|
|
285
225
|
xcodeProject.addTargetAttribute('DevelopmentTeam', appleTeamId, nseTarget);
|
|
286
226
|
xcodeProject.addTargetAttribute('DevelopmentTeam', appleTeamId);
|
|
287
|
-
};
|
|
288
227
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
228
|
+
return xcodeProject;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const addRichPushXcodeProj = async (
|
|
232
|
+
options: CustomerIOPluginOptionsIOS,
|
|
233
|
+
xcodeProject: XcodeProject,
|
|
234
|
+
) => {
|
|
235
|
+
const {
|
|
236
|
+
appleTeamId,
|
|
237
|
+
bundleIdentifier,
|
|
238
|
+
bundleShortVersion,
|
|
239
|
+
bundleVersion,
|
|
240
|
+
iosPath,
|
|
241
|
+
iosDeploymentTarget,
|
|
242
|
+
useFrameworks,
|
|
243
|
+
} = options;
|
|
296
244
|
|
|
297
|
-
|
|
245
|
+
const isFcmProvider = isFcmPushProvider(options);
|
|
246
|
+
const appGroupId = options.pushNotification?.appGroupId;
|
|
298
247
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
248
|
+
await injectCIONotificationPodfileCode(iosPath, useFrameworks, isFcmProvider);
|
|
249
|
+
|
|
250
|
+
// Skip the rest of the work if the NSE target is already in place. The pbxproj-mutating
|
|
251
|
+
// helper has its own idempotency check, but bailing out here also avoids redundant file
|
|
252
|
+
// copies and entitlements writes when prebuild re-runs against an already-prepared project.
|
|
253
|
+
if (xcodeProject.pbxTargetByName(CIO_NOTIFICATION_TARGET_NAME)) {
|
|
254
|
+
logger.warn(
|
|
255
|
+
`${CIO_NOTIFICATION_TARGET_NAME} already exists in project. Skipping...`,
|
|
304
256
|
);
|
|
257
|
+
return;
|
|
305
258
|
}
|
|
306
259
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
260
|
+
const nsePath = `${iosPath}/${CIO_NOTIFICATION_TARGET_NAME}`;
|
|
261
|
+
FileManagement.mkdir(nsePath, { recursive: true });
|
|
262
|
+
|
|
263
|
+
// Write NSE entitlements file only when appGroupId is explicitly configured
|
|
264
|
+
if (appGroupId) {
|
|
265
|
+
const nseEntitlementsContent = `<?xml version="1.0" encoding="UTF-8"?>
|
|
266
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
267
|
+
<plist version="1.0">
|
|
268
|
+
<dict>
|
|
269
|
+
<key>com.apple.security.application-groups</key>
|
|
270
|
+
<array>
|
|
271
|
+
<string>${appGroupId}</string>
|
|
272
|
+
</array>
|
|
273
|
+
</dict>
|
|
274
|
+
</plist>
|
|
275
|
+
`;
|
|
276
|
+
FileManagement.writeFile(`${nsePath}/${NSE_ENTITLEMENTS_FILENAME}`, nseEntitlementsContent);
|
|
313
277
|
}
|
|
314
278
|
|
|
315
|
-
|
|
279
|
+
const getTargetFile = (filename: string) => `${nsePath}/${filename}`;
|
|
280
|
+
|
|
281
|
+
// Copy platform-specific files
|
|
282
|
+
NSE_PLATFORM_SPECIFIC_FILES.forEach((filename) => {
|
|
283
|
+
FileManagement.copyFile(
|
|
284
|
+
`${getIosNativeFilesPath()}/${isFcmProvider ? 'fcm' : 'apn'}/${filename}`,
|
|
285
|
+
getTargetFile(filename),
|
|
286
|
+
);
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
// Copy common files
|
|
290
|
+
NSE_COMMON_FILES.forEach((filename) => {
|
|
291
|
+
FileManagement.copyFile(
|
|
292
|
+
`${getIosNativeFilesPath()}/common/${filename}`,
|
|
293
|
+
getTargetFile(filename),
|
|
294
|
+
);
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
/* MODIFY COPIED EXTENSION FILES */
|
|
298
|
+
updateNseInfoPlist({
|
|
299
|
+
bundleVersion,
|
|
300
|
+
bundleShortVersion,
|
|
301
|
+
infoPlistTargetFile: getTargetFile(PLIST_FILENAME),
|
|
302
|
+
});
|
|
303
|
+
updateNseEnv(getTargetFile(ENV_FILENAME), options.pushNotification?.env);
|
|
304
|
+
updateNseNotificationService(getTargetFile('NotificationService.swift'), appGroupId);
|
|
305
|
+
|
|
306
|
+
// Register the NSE target in the parsed Xcode project
|
|
307
|
+
addNotificationServiceExtensionToXcodeProject(xcodeProject, {
|
|
308
|
+
appleTeamId,
|
|
309
|
+
bundleIdentifier,
|
|
310
|
+
iosDeploymentTarget,
|
|
311
|
+
appGroupId,
|
|
312
|
+
});
|
|
316
313
|
};
|
|
317
314
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
315
|
+
/**
|
|
316
|
+
* Pure string transform: substitutes the `{{BUNDLE_VERSION}}` and
|
|
317
|
+
* `{{BUNDLE_SHORT_VERSION}}` placeholders in the NSE Info.plist template.
|
|
318
|
+
* Either or both may be provided; missing values leave the corresponding
|
|
319
|
+
* placeholder untouched.
|
|
320
|
+
*/
|
|
321
|
+
export function applyBundleVersionToNsePlist(
|
|
322
|
+
content: string,
|
|
323
|
+
payload: { bundleVersion?: string; bundleShortVersion?: string }
|
|
324
|
+
): string {
|
|
325
|
+
let next = content;
|
|
326
|
+
if (payload.bundleVersion) {
|
|
327
|
+
next = replaceCodeByRegex(next, /\{\{BUNDLE_VERSION\}\}/, payload.bundleVersion);
|
|
328
|
+
}
|
|
329
|
+
if (payload.bundleShortVersion) {
|
|
330
|
+
next = replaceCodeByRegex(next, /\{\{BUNDLE_SHORT_VERSION\}\}/, payload.bundleShortVersion);
|
|
331
|
+
}
|
|
332
|
+
return next;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
const updateNseInfoPlist = (payload: {
|
|
336
|
+
bundleVersion?: string;
|
|
337
|
+
bundleShortVersion?: string;
|
|
338
|
+
infoPlistTargetFile: string;
|
|
339
|
+
}) => {
|
|
340
|
+
const next = applyBundleVersionToNsePlist(
|
|
341
|
+
FileManagement.readFile(payload.infoPlistTargetFile),
|
|
342
|
+
payload,
|
|
343
|
+
);
|
|
344
|
+
FileManagement.writeFile(payload.infoPlistTargetFile, next);
|
|
345
|
+
};
|
|
323
346
|
|
|
324
|
-
|
|
347
|
+
/**
|
|
348
|
+
* Pure string transform: substitutes the `{{APP_GROUP_ID_BUILDER_LINE}}`
|
|
349
|
+
* placeholder in NotificationService.swift with either the configured
|
|
350
|
+
* appGroupId builder line or an empty string.
|
|
351
|
+
*/
|
|
352
|
+
export function applyAppGroupIdToNotificationService(
|
|
353
|
+
content: string,
|
|
354
|
+
appGroupId?: string
|
|
355
|
+
): string {
|
|
325
356
|
const builderLine = appGroupId
|
|
326
357
|
? ` .appGroupId(${JSON.stringify(appGroupId)})\n`
|
|
327
358
|
: '';
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
};
|
|
359
|
+
return replaceCodeByRegex(content, /\{\{APP_GROUP_ID_BUILDER_LINE\}\}/, builderLine);
|
|
360
|
+
}
|
|
331
361
|
|
|
332
|
-
const
|
|
333
|
-
|
|
334
|
-
|
|
362
|
+
const updateNseNotificationService = (
|
|
363
|
+
notificationServiceFile: string,
|
|
364
|
+
appGroupId?: string,
|
|
335
365
|
) => {
|
|
336
|
-
const
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
366
|
+
const next = applyAppGroupIdToNotificationService(
|
|
367
|
+
FileManagement.readFile(notificationServiceFile),
|
|
368
|
+
appGroupId,
|
|
369
|
+
);
|
|
370
|
+
FileManagement.writeFile(notificationServiceFile, next);
|
|
371
|
+
};
|
|
340
372
|
|
|
341
|
-
|
|
373
|
+
/**
|
|
374
|
+
* Pure string transform: substitutes the `{{CDP_API_KEY}}` and `{{REGION}}`
|
|
375
|
+
* placeholders in the NSE Env.swift template. Missing or invalid region
|
|
376
|
+
* falls back to `Region.US` and logs a warning.
|
|
377
|
+
*/
|
|
378
|
+
export function applyRichPushConfigToEnv(
|
|
379
|
+
content: string,
|
|
380
|
+
richPushConfig?: RichPushConfig,
|
|
381
|
+
): string {
|
|
342
382
|
const cdpApiKey = richPushConfig?.cdpApiKey;
|
|
343
383
|
const region = richPushConfig?.region;
|
|
344
384
|
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
envFileContent = replaceCodeByRegex(
|
|
349
|
-
envFileContent,
|
|
350
|
-
CDP_API_KEY_RE,
|
|
385
|
+
let next = replaceCodeByRegex(
|
|
386
|
+
content,
|
|
387
|
+
/\{\{CDP_API_KEY\}\}/,
|
|
351
388
|
cdpApiKey || 'MISSING_API_KEY',
|
|
352
389
|
);
|
|
353
390
|
|
|
354
|
-
// Simplify region mapping with case insensitive keys and fallback for invalid regions
|
|
355
391
|
const regionKey = region?.toLowerCase() ?? '';
|
|
356
|
-
const regionMap = {
|
|
357
|
-
us: 'Region.US',
|
|
358
|
-
eu: 'Region.EU',
|
|
359
|
-
} as const;
|
|
392
|
+
const regionMap = { us: 'Region.US', eu: 'Region.EU' } as const;
|
|
360
393
|
const mappedRegion = regionMap[regionKey as keyof typeof regionMap];
|
|
361
394
|
if (!mappedRegion) {
|
|
362
395
|
logger.warn(
|
|
363
396
|
`${regionKey} is an invalid region. Please use the values from the docs: https://docs.customer.io/integrations/sdk/expo/getting-started/packages-options/#configuring-the-expo-plugin`
|
|
364
397
|
);
|
|
365
|
-
|
|
366
|
-
envFileContent = replaceCodeByRegex(envFileContent, REGION_RE, regionMap.us);
|
|
398
|
+
next = replaceCodeByRegex(next, /\{\{REGION\}\}/, regionMap.us);
|
|
367
399
|
} else {
|
|
368
|
-
|
|
400
|
+
next = replaceCodeByRegex(next, /\{\{REGION\}\}/, mappedRegion);
|
|
369
401
|
}
|
|
402
|
+
return next;
|
|
403
|
+
}
|
|
370
404
|
|
|
371
|
-
|
|
405
|
+
const updateNseEnv = (
|
|
406
|
+
envFileName: string,
|
|
407
|
+
richPushConfig?: RichPushConfig
|
|
408
|
+
) => {
|
|
409
|
+
if (!validateRichPushConfig(richPushConfig)) {
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
const next = applyRichPushConfigToEnv(
|
|
413
|
+
FileManagement.readFile(envFileName),
|
|
414
|
+
richPushConfig,
|
|
415
|
+
);
|
|
416
|
+
FileManagement.writeFile(envFileName, next);
|
|
372
417
|
};
|
|
373
418
|
|
|
374
419
|
async function addPushNotificationFile(
|
|
@@ -410,79 +455,84 @@ async function addPushNotificationFile(
|
|
|
410
455
|
xcodeProject.addSourceFile(`${appName}/${targetFileName}`, null, group);
|
|
411
456
|
}
|
|
412
457
|
|
|
413
|
-
|
|
458
|
+
/**
|
|
459
|
+
* Pure string transform: substitutes every PushService.swift placeholder
|
|
460
|
+
* (`{{REGISTER_SNIPPET}}`, `{{CDP_API_KEY}}`, `{{REGION}}`,
|
|
461
|
+
* `{{AUTO_TRACK_PUSH_EVENTS}}`, `{{AUTO_FETCH_DEVICE_TOKEN}}`,
|
|
462
|
+
* `{{SHOW_PUSH_APP_IN_FOREGROUND}}`, `{{APP_GROUP_ID_BUILDER_LINE}}`) using
|
|
463
|
+
* the configured push-notification options. Validation of the rich-push
|
|
464
|
+
* config (cdpApiKey/region required) is the wrapper's responsibility.
|
|
465
|
+
*/
|
|
466
|
+
export function applyConfigToPushFile(
|
|
467
|
+
content: string,
|
|
414
468
|
options: CustomerIOPluginOptionsIOS,
|
|
415
|
-
|
|
416
|
-
) => {
|
|
417
|
-
const REGISTER_RE = /\{\{REGISTER_SNIPPET\}\}/;
|
|
418
|
-
|
|
419
|
-
let envFileContent = FileManagement.readFile(envFileName);
|
|
420
|
-
const disableNotificationRegistration =
|
|
421
|
-
options.pushNotification?.disableNotificationRegistration;
|
|
469
|
+
): string {
|
|
422
470
|
const richPushConfig = options.pushNotification?.env;
|
|
423
471
|
const { cdpApiKey, region } = richPushConfig || {
|
|
424
472
|
cdpApiKey: 'MISSING_API_KEY',
|
|
425
473
|
region: undefined,
|
|
426
474
|
};
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
}
|
|
475
|
+
const disableNotificationRegistration =
|
|
476
|
+
options.pushNotification?.disableNotificationRegistration;
|
|
430
477
|
|
|
431
|
-
let snippet = '';
|
|
432
478
|
// unless this property is explicitly set to true, push notification
|
|
433
479
|
// registration will be added to the AppDelegate
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
envFileContent = replaceCodeByRegex(envFileContent, REGISTER_RE, snippet);
|
|
480
|
+
const registerSnippet = disableNotificationRegistration !== true
|
|
481
|
+
? CIO_REGISTER_PUSHNOTIFICATION_SNIPPET
|
|
482
|
+
: '';
|
|
438
483
|
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
/\{\{CDP_API_KEY\}\}/,
|
|
442
|
-
cdpApiKey,
|
|
443
|
-
);
|
|
484
|
+
let next = replaceCodeByRegex(content, /\{\{REGISTER_SNIPPET\}\}/, registerSnippet);
|
|
485
|
+
next = replaceCodeByRegex(next, /\{\{CDP_API_KEY\}\}/, cdpApiKey);
|
|
444
486
|
|
|
445
487
|
if (region) {
|
|
446
|
-
|
|
447
|
-
envFileContent,
|
|
448
|
-
/\{\{REGION\}\}/,
|
|
449
|
-
region.toUpperCase()
|
|
450
|
-
);
|
|
488
|
+
next = replaceCodeByRegex(next, /\{\{REGION\}\}/, region.toUpperCase());
|
|
451
489
|
}
|
|
452
490
|
|
|
453
491
|
const autoTrackPushEvents =
|
|
454
492
|
options.pushNotification?.autoTrackPushEvents !== false;
|
|
455
|
-
|
|
456
|
-
|
|
493
|
+
next = replaceCodeByRegex(
|
|
494
|
+
next,
|
|
457
495
|
/\{\{AUTO_TRACK_PUSH_EVENTS\}\}/,
|
|
458
|
-
autoTrackPushEvents.toString()
|
|
496
|
+
autoTrackPushEvents.toString(),
|
|
459
497
|
);
|
|
460
498
|
|
|
461
499
|
const autoFetchDeviceToken =
|
|
462
500
|
options.pushNotification?.autoFetchDeviceToken !== false;
|
|
463
|
-
|
|
464
|
-
|
|
501
|
+
next = replaceCodeByRegex(
|
|
502
|
+
next,
|
|
465
503
|
/\{\{AUTO_FETCH_DEVICE_TOKEN\}\}/,
|
|
466
|
-
autoFetchDeviceToken.toString()
|
|
504
|
+
autoFetchDeviceToken.toString(),
|
|
467
505
|
);
|
|
468
506
|
|
|
469
507
|
const showPushAppInForeground =
|
|
470
508
|
options.pushNotification?.showPushAppInForeground !== false;
|
|
471
|
-
|
|
472
|
-
|
|
509
|
+
next = replaceCodeByRegex(
|
|
510
|
+
next,
|
|
473
511
|
/\{\{SHOW_PUSH_APP_IN_FOREGROUND\}\}/,
|
|
474
|
-
showPushAppInForeground.toString()
|
|
512
|
+
showPushAppInForeground.toString(),
|
|
475
513
|
);
|
|
476
514
|
|
|
477
515
|
const appGroupId = options.pushNotification?.appGroupId;
|
|
478
516
|
const appGroupIdBuilderLine = appGroupId
|
|
479
517
|
? ` .appGroupId(${JSON.stringify(appGroupId)})\n`
|
|
480
518
|
: '';
|
|
481
|
-
|
|
482
|
-
|
|
519
|
+
next = replaceCodeByRegex(
|
|
520
|
+
next,
|
|
483
521
|
/\{\{APP_GROUP_ID_BUILDER_LINE\}\}/,
|
|
484
|
-
appGroupIdBuilderLine
|
|
522
|
+
appGroupIdBuilderLine,
|
|
485
523
|
);
|
|
486
524
|
|
|
487
|
-
|
|
525
|
+
return next;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
const updatePushFile = (
|
|
529
|
+
options: CustomerIOPluginOptionsIOS,
|
|
530
|
+
envFileName: string
|
|
531
|
+
) => {
|
|
532
|
+
const richPushConfig = options.pushNotification?.env;
|
|
533
|
+
if (!validateRichPushConfig(richPushConfig)) {
|
|
534
|
+
return;
|
|
535
|
+
}
|
|
536
|
+
const next = applyConfigToPushFile(FileManagement.readFile(envFileName), options);
|
|
537
|
+
FileManagement.writeFile(envFileName, next);
|
|
488
538
|
};
|