customerio-expo-plugin 1.0.0-alpha.4 → 1.0.0-alpha.6

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 (80) hide show
  1. package/README.md +10 -8
  2. package/lib/commonjs/android/withGoogleServicesJSON.js +7 -5
  3. package/lib/commonjs/android/withGoogleServicesJSON.js.map +1 -1
  4. package/lib/commonjs/helpers/constants/ios.js +5 -52
  5. package/lib/commonjs/helpers/constants/ios.js.map +1 -1
  6. package/lib/commonjs/helpers/native-files/ios/Env.swift +8 -0
  7. package/lib/commonjs/helpers/native-files/ios/NotificationService.swift +4 -1
  8. package/lib/commonjs/helpers/native-files/ios/{PushNotification.swift → PushService.swift} +0 -0
  9. package/lib/commonjs/helpers/utils/codeInjection.js +4 -0
  10. package/lib/commonjs/helpers/utils/codeInjection.js.map +1 -1
  11. package/lib/commonjs/helpers/utils/injectCIOPodfileCode.js +1 -3
  12. package/lib/commonjs/helpers/utils/injectCIOPodfileCode.js.map +1 -1
  13. package/lib/commonjs/index.js +0 -2
  14. package/lib/commonjs/index.js.map +1 -1
  15. package/lib/commonjs/ios/withCIOIos.js +2 -7
  16. package/lib/commonjs/ios/withCIOIos.js.map +1 -1
  17. package/lib/commonjs/ios/withNotificationsXcodeProject.js +147 -76
  18. package/lib/commonjs/ios/withNotificationsXcodeProject.js.map +1 -1
  19. package/lib/commonjs/postInstall.js +7 -0
  20. package/lib/commonjs/postInstall.js.map +1 -0
  21. package/lib/commonjs/postInstallHelper.js +20 -0
  22. package/lib/commonjs/postInstallHelper.js.map +1 -0
  23. package/lib/commonjs/types/cio-types.js.map +1 -1
  24. package/lib/module/android/withGoogleServicesJSON.js +7 -5
  25. package/lib/module/android/withGoogleServicesJSON.js.map +1 -1
  26. package/lib/module/helpers/constants/ios.js +3 -47
  27. package/lib/module/helpers/constants/ios.js.map +1 -1
  28. package/lib/module/helpers/native-files/ios/Env.swift +8 -0
  29. package/lib/module/helpers/native-files/ios/NotificationService.swift +4 -1
  30. package/lib/module/helpers/native-files/ios/{PushNotification.swift → PushService.swift} +0 -0
  31. package/lib/module/helpers/utils/codeInjection.js +3 -0
  32. package/lib/module/helpers/utils/codeInjection.js.map +1 -1
  33. package/lib/module/helpers/utils/injectCIOPodfileCode.js +2 -4
  34. package/lib/module/helpers/utils/injectCIOPodfileCode.js.map +1 -1
  35. package/lib/module/index.js +0 -2
  36. package/lib/module/index.js.map +1 -1
  37. package/lib/module/ios/withCIOIos.js +2 -7
  38. package/lib/module/ios/withCIOIos.js.map +1 -1
  39. package/lib/module/ios/withNotificationsXcodeProject.js +148 -77
  40. package/lib/module/ios/withNotificationsXcodeProject.js.map +1 -1
  41. package/lib/module/postInstall.js +5 -0
  42. package/lib/module/postInstall.js.map +1 -0
  43. package/lib/module/postInstallHelper.js +18 -0
  44. package/lib/module/postInstallHelper.js.map +1 -0
  45. package/lib/module/types/cio-types.js.map +1 -1
  46. package/lib/typescript/helpers/constants/ios.d.ts +2 -5
  47. package/lib/typescript/helpers/utils/codeInjection.d.ts +1 -0
  48. package/lib/typescript/types/cio-types.d.ts +6 -1
  49. package/package.json +9 -5
  50. package/src/android/withGoogleServicesJSON.ts +9 -5
  51. package/src/helpers/constants/ios.ts +3 -46
  52. package/src/helpers/native-files/ios/Env.swift +8 -0
  53. package/src/helpers/native-files/ios/NotificationService.swift +4 -1
  54. package/src/helpers/native-files/ios/{PushNotification.swift → PushService.swift} +0 -0
  55. package/src/helpers/utils/codeInjection.ts +8 -0
  56. package/src/helpers/utils/injectCIOPodfileCode.ts +2 -10
  57. package/src/index.ts +0 -3
  58. package/src/ios/withCIOIos.ts +2 -8
  59. package/src/ios/withNotificationsXcodeProject.ts +221 -127
  60. package/src/postInstall.js +5 -0
  61. package/src/postInstallHelper.js +22 -0
  62. package/src/types/cio-types.ts +6 -1
  63. package/lib/commonjs/analytics/injectAnalytics.js +0 -31
  64. package/lib/commonjs/analytics/injectAnalytics.js.map +0 -1
  65. package/lib/commonjs/ios/withAppDelegateXcodeProject.js +0 -79
  66. package/lib/commonjs/ios/withAppDelegateXcodeProject.js.map +0 -1
  67. package/lib/commonjs/version.js +0 -9
  68. package/lib/commonjs/version.js.map +0 -1
  69. package/lib/module/analytics/injectAnalytics.js +0 -24
  70. package/lib/module/analytics/injectAnalytics.js.map +0 -1
  71. package/lib/module/ios/withAppDelegateXcodeProject.js +0 -71
  72. package/lib/module/ios/withAppDelegateXcodeProject.js.map +0 -1
  73. package/lib/module/version.js +0 -2
  74. package/lib/module/version.js.map +0 -1
  75. package/lib/typescript/analytics/injectAnalytics.d.ts +0 -3
  76. package/lib/typescript/ios/withAppDelegateXcodeProject.d.ts +0 -3
  77. package/lib/typescript/version.d.ts +0 -1
  78. package/src/analytics/injectAnalytics.ts +0 -36
  79. package/src/ios/withAppDelegateXcodeProject.ts +0 -89
  80. package/src/version.ts +0 -1
@@ -9,21 +9,25 @@ export const withGoogleServicesJSON: ConfigPlugin<
9
9
  return withProjectBuildGradle(configOuter, (props) => {
10
10
  const options: CustomerIOPluginOptionsAndroid = {
11
11
  androidPath: props.modRequest.platformProjectRoot,
12
- googleServicesFilePath: cioProps?.googleServicesFilePath,
12
+ googleServicesFile: cioProps?.googleServicesFile,
13
13
  };
14
- const { androidPath, googleServicesFilePath } = options;
14
+ const { androidPath, googleServicesFile } = options;
15
15
  if (!FileManagement.exists(`${androidPath}/app/google-services.json`)) {
16
- if (googleServicesFilePath) {
16
+ if (googleServicesFile && FileManagement.exists(googleServicesFile)) {
17
17
  try {
18
18
  FileManagement.copyFile(
19
- `${googleServicesFilePath}google-services.json`,
19
+ googleServicesFile,
20
20
  `${androidPath}/app/google-services.json`
21
21
  );
22
22
  } catch (e) {
23
23
  console.log(
24
- `There was an error copying your google-services.json file. You can copy it manually into ${androidPath}/app/`
24
+ `There was an error copying your google-services.json file. You can copy it manually into ${androidPath}/app/google-services.json`
25
25
  );
26
26
  }
27
+ } else {
28
+ console.log(
29
+ `The Google Services file provided in ${googleServicesFile} doesn't seem to exist. You can copy it manually into ${androidPath}/app/google-services.json`
30
+ );
27
31
  }
28
32
  } else {
29
33
  console.log(
@@ -1,13 +1,13 @@
1
1
  export const LOCAL_PATH_TO_CIO_NSE_FILES = `node_modules/customerio-expo-plugin/src/helpers/native-files/ios`;
2
2
  export const IOS_DEPLOYMENT_TARGET = '13.0';
3
- export const CIO_SDK_VERSION = '1.2.6';
3
+ export const CIO_SDK_VERSION = '~> 2.0.0';
4
4
  export const CIO_PODFILE_REGEX = /pod 'CustomerIO\/MessagingPushAPN'/;
5
5
  export const CIO_CIO_TARGET_REGEX = /cio_target_names/;
6
6
  export const CIO_PODFILE_NOTIFICATION_REGEX = /target 'NotificationService' do/;
7
+ export const CIO_PODFILE_POST_INSTALL_REGEX = /post_install do \|installer\|/;
7
8
  export const GROUP_IDENTIFIER_TEMPLATE_REGEX = /{{GROUP_IDENTIFIER}}/gm;
8
9
  export const BUNDLE_SHORT_VERSION_TEMPLATE_REGEX = /{{BUNDLE_SHORT_VERSION}}/gm;
9
10
  export const BUNDLE_VERSION_TEMPLATE_REGEX = /{{BUNDLE_VERSION}}/gm;
10
- export const CIO_PODFILE_POST_INSTALL_REGEX = /post_install do \|installer\|/;
11
11
  export const CIO_DIDFINISHLAUNCHINGMETHOD_REGEX =
12
12
  /(- \(BOOL\)application:\(UIApplication \*\)application didFinishLaunchingWithOptions:\(NSDictionary \*\)launchOptions(\s|\n)*?\{)((.|\n)*)\[super(\s)application:application(\s)didFinishLaunchingWithOptions:launchOptions\];/;
13
13
 
@@ -47,8 +47,6 @@ export const CIO_DIDREGISTERFORREMOTENOTIFICATIONSWITHDEVICETOKEN_SNIPPET = `
47
47
  return [pnHandlerObj application:application deviceToken:deviceToken];
48
48
  `;
49
49
 
50
- // Configure Customerio push notifications SDK by adding to application:didFinishLaunchingWithOptions: delegate method
51
- // From Braze docs: https://www.customer.io/docs/sdk/react-native/push/#obj-c-push
52
50
  export const CIO_CONFIGURECIOSDKPUSHNOTIFICATION_SNIPPET = `
53
51
  // Register for push notifications
54
52
  [pnHandlerObj registerPushNotification:self];
@@ -66,7 +64,7 @@ export const CIO_WILLPRESENTNOTIFICATIONHANDLER_SNIPPET = `
66
64
  - (void)userNotificationCenter:(UNUserNotificationCenter* )center willPresentNotification:(UNNotification* )notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler {
67
65
  completionHandler( UNNotificationPresentationOptionAlert + UNNotificationPresentationOptionSound);
68
66
  }`;
69
- export const CIO_PODFILE_SNIPPET = ` pod 'CustomerIO/MessagingPushAPN', '~> ${CIO_SDK_VERSION}'`;
67
+ export const CIO_PODFILE_SNIPPET = ` pod 'CustomerIO/MessagingPushAPN', '${CIO_SDK_VERSION}'`;
70
68
  export const CIO_PODFILE_NOTIFICATION_SNIPPET = `
71
69
  target '${CIO_NOTIFICATION_TARGET_NAME}' do
72
70
  ${CIO_PODFILE_SNIPPET}
@@ -76,44 +74,3 @@ target '${CIO_NOTIFICATION_TARGET_NAME}' do
76
74
  use_frameworks! :linkage => :static
77
75
  ${CIO_PODFILE_SNIPPET}
78
76
  end`;
79
- export const CIO_PODFILE_TARGET_NAMES_SNIPPET = `
80
- cio_target_names = [
81
- 'CustomerIOTracking',
82
- 'CustomerIOCommon',
83
- 'CustomerIOMessagingPushAPN',
84
- 'CustomerIOMessagingPush'
85
- ]`;
86
- export const CIO_PODFILE_POST_INSTALL_SNIPPET = `
87
- installer.pods_project.targets.each do |target|
88
- if cio_target_names.include? target.name
89
- puts "Modifying target #{target.name}"
90
-
91
- target.build_configurations.each do |config|
92
- puts "Setting build config settings for #{target.name}"
93
- config.build_settings['APPLICATION_EXTENSION_API_ONLY'] ||= 'NO'
94
- end
95
- end
96
- end`;
97
- export const CIO_PODFILE_POST_INSTALL_FALLBACK_SNIPPET = `
98
- cio_target_names = [
99
- 'CustomerIOTracking',
100
- 'CustomerIOCommon',
101
- 'CustomerIOMessagingPushAPN',
102
- 'CustomerIOMessagingPush'
103
- ]
104
-
105
- post_install do |installer|
106
-
107
- installer.pods_project.targets.each do |target|
108
- if cio_target_names.include? target.name
109
- puts "Modifying target #{target.name}"
110
-
111
- target.build_configurations.each do |config|
112
- puts "Setting build config settings for #{target.name}"
113
- config.build_settings['APPLICATION_EXTENSION_API_ONLY'] ||= 'NO'
114
- end
115
- end
116
- end
117
- react_native_post_install(installer)
118
- __apply_Xcode_12_5_M1_post_install_workaround(installer)
119
- end`;
@@ -0,0 +1,8 @@
1
+ import Foundation
2
+ import CioTracking
3
+
4
+ class Env {
5
+ static var customerIOSiteId: String = "{{SITE_ID}}"
6
+ static var customerIOApiKey: String = "{{API_KEY}}"
7
+ static var customerIORegion: Region = {{REGION}} // "us" or "eu"
8
+ }
@@ -1,6 +1,7 @@
1
1
  import Foundation
2
2
  import UserNotifications
3
- import CioMessagingPush
3
+ import CioTracking
4
+ import CioMessagingPushAPN
4
5
 
5
6
  @objc
6
7
  public class NotificationServiceCioManager : NSObject {
@@ -9,6 +10,8 @@ public class NotificationServiceCioManager : NSObject {
9
10
 
10
11
  @objc(didReceive:withContentHandler:)
11
12
  public func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
13
+ CustomerIO
14
+ .initialize(siteId: Env.customerIOSiteId, apiKey: Env.customerIOApiKey, region: Env.customerIORegion) { config in }
12
15
  MessagingPush.shared.didReceive(request, withContentHandler: contentHandler)
13
16
  }
14
17
 
@@ -22,6 +22,14 @@ export function injectCodeByMultiLineRegex(
22
22
  return fileContent.replace(lineRegex, `$&\n${snippet}`);
23
23
  }
24
24
 
25
+ export function replaceCodeByRegex(
26
+ fileContent: string,
27
+ lineRegex: RegExp,
28
+ snippet: string
29
+ ) {
30
+ return fileContent.replace(lineRegex, snippet);
31
+ }
32
+
25
33
  export function injectCodeByMultiLineRegexAndReplaceLine(
26
34
  fileContent: string,
27
35
  lineRegex: RegExp,
@@ -2,14 +2,11 @@ import type { CustomerIOPluginOptionsIOS } from '../../types/cio-types';
2
2
  import {
3
3
  CIO_PODFILE_REGEX,
4
4
  CIO_PODFILE_SNIPPET,
5
- CIO_PODFILE_POST_INSTALL_REGEX,
6
- CIO_PODFILE_TARGET_NAMES_SNIPPET,
7
- CIO_PODFILE_POST_INSTALL_SNIPPET,
8
- CIO_PODFILE_POST_INSTALL_FALLBACK_SNIPPET,
9
5
  CIO_PODFILE_NOTIFICATION_SNIPPET,
10
6
  CIO_PODFILE_NOTIFICATION_STATIC_FRAMEWORK_SNIPPET,
11
7
  CIO_PODFILE_NOTIFICATION_REGEX,
12
8
  CIO_CIO_TARGET_REGEX,
9
+ CIO_PODFILE_POST_INSTALL_REGEX,
13
10
  } from '../constants/ios';
14
11
  import { FileManagement } from './fileManagement';
15
12
 
@@ -29,13 +26,8 @@ export async function injectCIOPodfileCode(iosPath: string) {
29
26
  content = [
30
27
  ...lines.slice(0, index - 1),
31
28
  !matches ? CIO_PODFILE_SNIPPET : '',
32
- CIO_PODFILE_TARGET_NAMES_SNIPPET,
33
- ...lines.slice(index - 1, index + 1),
34
- CIO_PODFILE_POST_INSTALL_SNIPPET,
35
- ...lines.slice(index + 1),
29
+ ...lines.slice(index - 1),
36
30
  ];
37
- } else {
38
- content.push(CIO_PODFILE_POST_INSTALL_FALLBACK_SNIPPET);
39
31
  }
40
32
 
41
33
  FileManagement.write(filename, content.join('\n'));
package/src/index.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  import type { ExpoConfig } from '@expo/config-types';
2
2
 
3
- import { withAnalytics } from './analytics/injectAnalytics';
4
3
  import { withCIOAndroid } from './android/withCIOAndroid';
5
4
  import { withCIOIos } from './ios/withCIOIos';
6
5
  import type { CustomerIOPluginOptions } from './types/cio-types';
@@ -18,8 +17,6 @@ function withCustomerIOPlugin(
18
17
  config = withCIOAndroid(config, props.android);
19
18
  }
20
19
 
21
- config = withAnalytics(config, props);
22
-
23
20
  return config;
24
21
  }
25
22
 
@@ -2,7 +2,6 @@ import type { ExpoConfig } from '@expo/config-types';
2
2
 
3
3
  import type { CustomerIOPluginOptionsIOS } from '../types/cio-types';
4
4
  import { withAppDelegateModifications } from './withAppDelegateModifications';
5
- import { withCioAppdelegateXcodeProject } from './withAppDelegateXcodeProject';
6
5
  import { withCioNotificationsXcodeProject } from './withNotificationsXcodeProject';
7
6
  import { withCioXcodeProject } from './withXcodeProject';
8
7
 
@@ -10,16 +9,11 @@ export function withCIOIos(
10
9
  config: ExpoConfig,
11
10
  props: CustomerIOPluginOptionsIOS
12
11
  ) {
13
- if (props.pushNotification?.useRichPush) {
14
- config = withCioNotificationsXcodeProject(config, props);
15
- }
16
-
17
12
  if (props.pushNotification) {
18
13
  config = withAppDelegateModifications(config, props);
19
- config = withCioAppdelegateXcodeProject(config, props);
14
+ config = withCioNotificationsXcodeProject(config, props);
15
+ config = withCioXcodeProject(config, props);
20
16
  }
21
17
 
22
- config = withCioXcodeProject(config, props);
23
-
24
18
  return config;
25
19
  }
@@ -6,28 +6,22 @@ import {
6
6
  DEFAULT_BUNDLE_VERSION,
7
7
  LOCAL_PATH_TO_CIO_NSE_FILES,
8
8
  } from '../helpers/constants/ios';
9
- import { injectCodeByMultiLineRegex } from '../helpers/utils/codeInjection';
9
+ import { replaceCodeByRegex } from '../helpers/utils/codeInjection';
10
10
  import { injectCIONotificationPodfileCode } from '../helpers/utils/injectCIOPodfileCode';
11
11
  import type { CustomerIOPluginOptionsIOS } from '../types/cio-types';
12
12
  import { FileManagement } from './../helpers/utils/fileManagement';
13
13
 
14
14
  const PLIST_FILENAME = `${CIO_NOTIFICATION_TARGET_NAME}-Info.plist`;
15
+ const ENV_FILENAME = 'Env.swift';
15
16
 
16
17
  const TARGETED_DEVICE_FAMILY = `"1,2"`;
17
18
 
18
19
  const addNotificationServiceExtension = async (
19
20
  options: CustomerIOPluginOptionsIOS
20
21
  ) => {
21
- const {
22
- appleTeamId,
23
- bundleIdentifier,
24
- bundleShortVersion,
25
- bundleVersion,
26
- iosPath,
27
- useFrameworks,
28
- appName,
29
- iosDeploymentTarget,
30
- } = options;
22
+ // iosPath and appName are predefined from Expo config.
23
+ // See function withCioNotificationsXcodeProject to get where the variabes are pulled from.
24
+ const { iosPath, appName } = options;
31
25
 
32
26
  const projPath = `${iosPath}/${appName}.xcodeproj/project.pbxproj`;
33
27
 
@@ -38,123 +32,14 @@ const addNotificationServiceExtension = async (
38
32
  throw new Error(`Error parsing iOS project: ${JSON.stringify(err)}`);
39
33
  }
40
34
 
41
- await injectCIONotificationPodfileCode(iosPath, useFrameworks);
42
-
43
- FileManagement.mkdir(`${iosPath}/${CIO_NOTIFICATION_TARGET_NAME}`, {
44
- recursive: true,
45
- });
46
-
47
- const files = [
48
- PLIST_FILENAME,
49
- 'NotificationService.h',
50
- 'NotificationService.swift',
51
- 'NotificationService.m',
52
- ];
53
-
54
- const getTargetFile = (filename: string) =>
55
- `${iosPath}/${CIO_NOTIFICATION_TARGET_NAME}/${filename}`;
56
-
57
- files.forEach((filename) => {
58
- const targetFile = getTargetFile(filename);
59
- FileManagement.copyFile(
60
- `${LOCAL_PATH_TO_CIO_NSE_FILES}/${filename}`,
61
- targetFile
62
- );
63
- });
64
-
65
- /* MODIFY COPIED EXTENSION FILES */
66
- const infoPlistTargetFile = getTargetFile(PLIST_FILENAME);
67
- updateNseInfoPlist({
68
- bundleVersion,
69
- bundleShortVersion,
70
- infoPlistTargetFile,
71
- });
72
-
73
- // Create new PBXGroup for the extension
74
- const extGroup = xcodeProject.addPbxGroup(
75
- files,
76
- CIO_NOTIFICATION_TARGET_NAME,
77
- CIO_NOTIFICATION_TARGET_NAME
78
- );
79
-
80
- // Add the new PBXGroup to the top level group. This makes the
81
- // files / folder appear in the file explorer in Xcode.
82
- const groups = xcodeProject.hash.project.objects['PBXGroup'];
83
- Object.keys(groups).forEach((key) => {
84
- if (groups[key].name === undefined) {
85
- xcodeProject.addToPbxGroup(extGroup.uuid, key);
86
- }
87
- });
88
-
89
- // WORK AROUND for codeProject.addTarget BUG
90
- // Xcode projects don't contain these if there is only one target
91
- // An upstream fix should be made to the code referenced in this link:
92
- // - https://github.com/apache/cordova-node-xcode/blob/8b98cabc5978359db88dc9ff2d4c015cba40f150/lib/pbxProject.js#L860
93
- const projObjects = xcodeProject.hash.project.objects;
94
- projObjects['PBXTargetDependency'] =
95
- projObjects['PBXTargetDependency'] || {};
96
- projObjects['PBXContainerItemProxy'] =
97
- projObjects['PBXTargetDependency'] || {};
98
-
99
- if (xcodeProject.pbxTargetByName(CIO_NOTIFICATION_TARGET_NAME)) {
100
- console.warn(
101
- `${CIO_NOTIFICATION_TARGET_NAME} already exists in project. Skipping...`
102
- );
103
- return;
35
+ if (options.pushNotification) {
36
+ await addPushNotificationFile(options, xcodeProject);
104
37
  }
105
38
 
106
- // Add the NSE target
107
- // This also adds PBXTargetDependency and PBXContainerItemProxy
108
- const nseTarget = xcodeProject.addTarget(
109
- CIO_NOTIFICATION_TARGET_NAME,
110
- 'app_extension',
111
- CIO_NOTIFICATION_TARGET_NAME,
112
- `${bundleIdentifier}.richpush`
113
- );
114
-
115
- // Add build phases to the new target
116
- xcodeProject.addBuildPhase(
117
- ['NotificationService.m', 'NotificationService.swift'],
118
- 'PBXSourcesBuildPhase',
119
- 'Sources',
120
- nseTarget.uuid
121
- );
122
- xcodeProject.addBuildPhase(
123
- [],
124
- 'PBXResourcesBuildPhase',
125
- 'Resources',
126
- nseTarget.uuid
127
- );
128
-
129
- xcodeProject.addBuildPhase(
130
- [],
131
- 'PBXFrameworksBuildPhase',
132
- 'Frameworks',
133
- nseTarget.uuid
134
- );
135
-
136
- // Edit the Deployment info of the target
137
- const configurations = xcodeProject.pbxXCBuildConfigurationSection();
138
- for (const key in configurations) {
139
- if (
140
- typeof configurations[key].buildSettings !== 'undefined' &&
141
- configurations[key].buildSettings.PRODUCT_NAME ===
142
- `"${CIO_NOTIFICATION_TARGET_NAME}"`
143
- ) {
144
- const buildSettingsObj = configurations[key].buildSettings;
145
- buildSettingsObj.DEVELOPMENT_TEAM = appleTeamId;
146
- buildSettingsObj.IPHONEOS_DEPLOYMENT_TARGET =
147
- iosDeploymentTarget || '13.0';
148
- buildSettingsObj.TARGETED_DEVICE_FAMILY = TARGETED_DEVICE_FAMILY;
149
- buildSettingsObj.CODE_SIGN_STYLE = 'Automatic';
150
- buildSettingsObj.SWIFT_VERSION = 4.2;
151
- }
39
+ if (options.pushNotification?.useRichPush) {
40
+ await addRichPushXcodeProj(options, xcodeProject);
152
41
  }
153
42
 
154
- // Add development team to the target & the main
155
- xcodeProject.addTargetAttribute('DevelopmentTeam', appleTeamId, nseTarget);
156
- xcodeProject.addTargetAttribute('DevelopmentTeam', appleTeamId);
157
-
158
43
  FileManagement.writeFile(projPath, xcodeProject.writeSync());
159
44
  });
160
45
  };
@@ -164,13 +49,19 @@ export const withCioNotificationsXcodeProject: ConfigPlugin<
164
49
  > = (configOuter, props) => {
165
50
  return withXcodeProject(configOuter, async (config) => {
166
51
  const { modRequest, ios, version: bundleShortVersion } = config;
167
- const { appleTeamId, iosDeploymentTarget, useFrameworks } = props;
52
+ const {
53
+ appleTeamId,
54
+ iosDeploymentTarget,
55
+ pushNotification,
56
+ useFrameworks,
57
+ } = props;
168
58
 
169
59
  if (ios === undefined)
170
60
  throw new Error(
171
61
  'Adding NotificationServiceExtension failed: ios config missing from app.config.js or app.json.'
172
62
  );
173
63
 
64
+ // projectName and platformProjectRoot translates to appName and iosPath in addNotificationServiceExtension()
174
65
  const { projectName, platformProjectRoot } = modRequest;
175
66
  const { bundleIdentifier, buildNumber } = ios;
176
67
 
@@ -201,6 +92,7 @@ export const withCioNotificationsXcodeProject: ConfigPlugin<
201
92
  appName: projectName,
202
93
  useFrameworks,
203
94
  iosDeploymentTarget,
95
+ pushNotification,
204
96
  };
205
97
 
206
98
  await addNotificationServiceExtension(options);
@@ -209,6 +101,139 @@ export const withCioNotificationsXcodeProject: ConfigPlugin<
209
101
  });
210
102
  };
211
103
 
104
+ const addRichPushXcodeProj = async (
105
+ options: CustomerIOPluginOptionsIOS,
106
+ xcodeProject: any
107
+ ) => {
108
+ const {
109
+ appleTeamId,
110
+ bundleIdentifier,
111
+ bundleShortVersion,
112
+ bundleVersion,
113
+ iosPath,
114
+ iosDeploymentTarget,
115
+ useFrameworks,
116
+ } = options;
117
+
118
+ await injectCIONotificationPodfileCode(iosPath, useFrameworks);
119
+
120
+ const nsePath = `${iosPath}/${CIO_NOTIFICATION_TARGET_NAME}`;
121
+ FileManagement.mkdir(nsePath, {
122
+ recursive: true,
123
+ });
124
+
125
+ const files = [
126
+ PLIST_FILENAME,
127
+ 'NotificationService.h',
128
+ 'NotificationService.swift',
129
+ 'NotificationService.m',
130
+ ENV_FILENAME,
131
+ ];
132
+
133
+ const getTargetFile = (filename: string) => `${nsePath}/${filename}`;
134
+
135
+ files.forEach((filename) => {
136
+ const targetFile = getTargetFile(filename);
137
+ FileManagement.copyFile(
138
+ `${LOCAL_PATH_TO_CIO_NSE_FILES}/${filename}`,
139
+ targetFile
140
+ );
141
+ });
142
+
143
+ /* MODIFY COPIED EXTENSION FILES */
144
+ const infoPlistTargetFile = getTargetFile(PLIST_FILENAME);
145
+ updateNseInfoPlist({
146
+ bundleVersion,
147
+ bundleShortVersion,
148
+ infoPlistTargetFile,
149
+ });
150
+ updateNseEnv(options, getTargetFile(ENV_FILENAME));
151
+
152
+ // Create new PBXGroup for the extension
153
+ const extGroup = xcodeProject.addPbxGroup(
154
+ files,
155
+ CIO_NOTIFICATION_TARGET_NAME,
156
+ CIO_NOTIFICATION_TARGET_NAME
157
+ );
158
+
159
+ // Add the new PBXGroup to the top level group. This makes the
160
+ // files / folder appear in the file explorer in Xcode.
161
+ const groups = xcodeProject.hash.project.objects['PBXGroup'];
162
+ Object.keys(groups).forEach((key) => {
163
+ if (groups[key].name === undefined) {
164
+ xcodeProject.addToPbxGroup(extGroup.uuid, key);
165
+ }
166
+ });
167
+
168
+ // WORK AROUND for codeProject.addTarget BUG
169
+ // Xcode projects don't contain these if there is only one target
170
+ // An upstream fix should be made to the code referenced in this link:
171
+ // - https://github.com/apache/cordova-node-xcode/blob/8b98cabc5978359db88dc9ff2d4c015cba40f150/lib/pbxProject.js#L860
172
+ const projObjects = xcodeProject.hash.project.objects;
173
+ projObjects['PBXTargetDependency'] = projObjects['PBXTargetDependency'] || {};
174
+ projObjects['PBXContainerItemProxy'] =
175
+ projObjects['PBXTargetDependency'] || {};
176
+
177
+ if (xcodeProject.pbxTargetByName(CIO_NOTIFICATION_TARGET_NAME)) {
178
+ console.warn(
179
+ `${CIO_NOTIFICATION_TARGET_NAME} already exists in project. Skipping...`
180
+ );
181
+ return;
182
+ }
183
+
184
+ // Add the NSE target
185
+ // This also adds PBXTargetDependency and PBXContainerItemProxy
186
+ const nseTarget = xcodeProject.addTarget(
187
+ CIO_NOTIFICATION_TARGET_NAME,
188
+ 'app_extension',
189
+ CIO_NOTIFICATION_TARGET_NAME,
190
+ `${bundleIdentifier}.richpush`
191
+ );
192
+
193
+ // Add build phases to the new target
194
+ xcodeProject.addBuildPhase(
195
+ ['NotificationService.m', 'NotificationService.swift', 'Env.swift'],
196
+ 'PBXSourcesBuildPhase',
197
+ 'Sources',
198
+ nseTarget.uuid
199
+ );
200
+ xcodeProject.addBuildPhase(
201
+ [],
202
+ 'PBXResourcesBuildPhase',
203
+ 'Resources',
204
+ nseTarget.uuid
205
+ );
206
+
207
+ xcodeProject.addBuildPhase(
208
+ [],
209
+ 'PBXFrameworksBuildPhase',
210
+ 'Frameworks',
211
+ nseTarget.uuid
212
+ );
213
+
214
+ // Edit the Deployment info of the target
215
+ const configurations = xcodeProject.pbxXCBuildConfigurationSection();
216
+ for (const key in configurations) {
217
+ if (
218
+ typeof configurations[key].buildSettings !== 'undefined' &&
219
+ configurations[key].buildSettings.PRODUCT_NAME ===
220
+ `"${CIO_NOTIFICATION_TARGET_NAME}"`
221
+ ) {
222
+ const buildSettingsObj = configurations[key].buildSettings;
223
+ buildSettingsObj.DEVELOPMENT_TEAM = appleTeamId;
224
+ buildSettingsObj.IPHONEOS_DEPLOYMENT_TARGET =
225
+ iosDeploymentTarget || '13.0';
226
+ buildSettingsObj.TARGETED_DEVICE_FAMILY = TARGETED_DEVICE_FAMILY;
227
+ buildSettingsObj.CODE_SIGN_STYLE = 'Automatic';
228
+ buildSettingsObj.SWIFT_VERSION = 4.2;
229
+ }
230
+ }
231
+
232
+ // Add development team to the target & the main
233
+ xcodeProject.addTargetAttribute('DevelopmentTeam', appleTeamId, nseTarget);
234
+ xcodeProject.addTargetAttribute('DevelopmentTeam', appleTeamId);
235
+ };
236
+
212
237
  const updateNseInfoPlist = (payload: {
213
238
  bundleVersion?: string;
214
239
  bundleShortVersion?: string;
@@ -220,7 +245,7 @@ const updateNseInfoPlist = (payload: {
220
245
  let plistFileString = FileManagement.readFile(payload.infoPlistTargetFile);
221
246
 
222
247
  if (payload.bundleVersion) {
223
- plistFileString = injectCodeByMultiLineRegex(
248
+ plistFileString = replaceCodeByRegex(
224
249
  plistFileString,
225
250
  BUNDLE_VERSION_RE,
226
251
  payload.bundleVersion
@@ -228,7 +253,7 @@ const updateNseInfoPlist = (payload: {
228
253
  }
229
254
 
230
255
  if (payload.bundleShortVersion) {
231
- plistFileString = injectCodeByMultiLineRegex(
256
+ plistFileString = replaceCodeByRegex(
232
257
  plistFileString,
233
258
  BUNDLE_SHORT_VERSION_RE,
234
259
  payload.bundleShortVersion
@@ -237,3 +262,72 @@ const updateNseInfoPlist = (payload: {
237
262
 
238
263
  FileManagement.writeFile(payload.infoPlistTargetFile, plistFileString);
239
264
  };
265
+
266
+ const updateNseEnv = (
267
+ options: CustomerIOPluginOptionsIOS,
268
+ envFileName: string
269
+ ) => {
270
+ const SITE_ID_RE = /\{\{SITE_ID\}\}/;
271
+ const API_KEY_RE = /\{\{API_KEY\}\}/;
272
+ const REGION_RE = /\{\{REGION\}\}/;
273
+
274
+ let envFileContent = FileManagement.readFile(envFileName);
275
+
276
+ if (options.pushNotification?.env?.siteId) {
277
+ envFileContent = replaceCodeByRegex(
278
+ envFileContent,
279
+ SITE_ID_RE,
280
+ options.pushNotification?.env?.siteId
281
+ );
282
+ }
283
+
284
+ if (options.pushNotification?.env?.apiKey) {
285
+ envFileContent = replaceCodeByRegex(
286
+ envFileContent,
287
+ API_KEY_RE,
288
+ options.pushNotification?.env?.apiKey
289
+ );
290
+ }
291
+
292
+ if (options.pushNotification?.env?.region) {
293
+ let region = '';
294
+ if (options.pushNotification?.env?.region === 'us') {
295
+ region = 'Region.US';
296
+ } else if (options.pushNotification?.env?.region === 'eu') {
297
+ region = 'Region.EU';
298
+ }
299
+ envFileContent = replaceCodeByRegex(envFileContent, REGION_RE, region);
300
+ }
301
+
302
+ FileManagement.writeFile(envFileName, envFileContent);
303
+ };
304
+
305
+ async function addPushNotificationFile(
306
+ options: CustomerIOPluginOptionsIOS,
307
+ xcodeProject: any
308
+ ) {
309
+ const { iosPath, appName } = options;
310
+ const file = 'PushService.swift';
311
+ const appPath = `${iosPath}/${appName}`;
312
+ const getTargetFile = (filename: string) => `${appPath}/${filename}`;
313
+
314
+ if (!FileManagement.exists(getTargetFile(file))) {
315
+ FileManagement.mkdir(appPath, {
316
+ recursive: true,
317
+ });
318
+
319
+ const targetFile = getTargetFile(file);
320
+ FileManagement.copyFile(
321
+ `${LOCAL_PATH_TO_CIO_NSE_FILES}/${file}`,
322
+ targetFile
323
+ );
324
+ } else {
325
+ console.log(`${getTargetFile(file)} already exists. Skipping...`);
326
+ }
327
+
328
+ const group = xcodeProject.pbxCreateGroup('CustomerIONotifications');
329
+ const classesKey = xcodeProject.findPBXGroupKey({ name: `${appName}` });
330
+ xcodeProject.addToPbxGroup(group, classesKey);
331
+
332
+ xcodeProject.addSourceFile(`${appName}/${file}`, null, group);
333
+ }
@@ -0,0 +1,5 @@
1
+ try {
2
+ const ph = require('./postInstallHelper');
3
+
4
+ ph.runPostInstall();
5
+ } catch (error) {}
@@ -0,0 +1,22 @@
1
+ const fs = require('fs');
2
+
3
+ function runPostInstall() {
4
+ // react native SDK package.json path
5
+ const rnPjsonFile = `${__dirname}/../../customerio-reactnative/package.json`;
6
+ const expoPjsonFile = `${__dirname}/../package.json`;
7
+ try {
8
+ // if react native SDK is installed
9
+ if (fs.existsSync(rnPjsonFile)) {
10
+ const rnPJson = fs.readFileSync(rnPjsonFile, 'utf8');
11
+ expoPjson = require(expoPjsonFile);
12
+
13
+ const rnPackage = JSON.parse(rnPJson);
14
+ rnPackage.expoVersion = expoPjson.version;
15
+
16
+
17
+ fs.writeFileSync(rnPjsonFile, JSON.stringify(rnPackage, null, 2));
18
+ }
19
+ } catch (error) {}
20
+ }
21
+
22
+ exports.runPostInstall = runPostInstall;