customerio-expo-plugin 2.7.1 → 2.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. package/package.json +3 -2
  2. package/plugin/lib/commonjs/android/withAndroidManifestUpdates.js +5 -4
  3. package/plugin/lib/commonjs/android/withAndroidManifestUpdates.js.map +1 -1
  4. package/plugin/lib/commonjs/android/withAppGoogleServices.js +2 -1
  5. package/plugin/lib/commonjs/android/withAppGoogleServices.js.map +1 -1
  6. package/plugin/lib/commonjs/android/withCIOAndroid.js +17 -11
  7. package/plugin/lib/commonjs/android/withCIOAndroid.js.map +1 -1
  8. package/plugin/lib/commonjs/android/withGistMavenRepository.js +2 -1
  9. package/plugin/lib/commonjs/android/withGistMavenRepository.js.map +1 -1
  10. package/plugin/lib/commonjs/android/withGoogleServicesJSON.js +4 -3
  11. package/plugin/lib/commonjs/android/withGoogleServicesJSON.js.map +1 -1
  12. package/plugin/lib/commonjs/android/withMainApplicationModifications.js +2 -1
  13. package/plugin/lib/commonjs/android/withMainApplicationModifications.js.map +1 -1
  14. package/plugin/lib/commonjs/helpers/utils/fileManagement.js +5 -4
  15. package/plugin/lib/commonjs/helpers/utils/fileManagement.js.map +1 -1
  16. package/plugin/lib/commonjs/helpers/utils/injectCIOPodfileCode.js +2 -1
  17. package/plugin/lib/commonjs/helpers/utils/injectCIOPodfileCode.js.map +1 -1
  18. package/plugin/lib/commonjs/helpers/utils/patchPluginNativeCode.js +5 -1
  19. package/plugin/lib/commonjs/helpers/utils/patchPluginNativeCode.js.map +1 -1
  20. package/plugin/lib/commonjs/index.js +3 -11
  21. package/plugin/lib/commonjs/index.js.map +1 -1
  22. package/plugin/lib/commonjs/ios/withAppDelegateModifications.js +2 -1
  23. package/plugin/lib/commonjs/ios/withAppDelegateModifications.js.map +1 -1
  24. package/plugin/lib/commonjs/ios/withCIOIos.js +7 -3
  25. package/plugin/lib/commonjs/ios/withCIOIos.js.map +1 -1
  26. package/plugin/lib/commonjs/ios/withCIOIosSwift.js +11 -10
  27. package/plugin/lib/commonjs/ios/withCIOIosSwift.js.map +1 -1
  28. package/plugin/lib/commonjs/ios/withGoogleServicesJsonFile.js +8 -7
  29. package/plugin/lib/commonjs/ios/withGoogleServicesJsonFile.js.map +1 -1
  30. package/plugin/lib/commonjs/ios/withNotificationsXcodeProject.js +29 -23
  31. package/plugin/lib/commonjs/ios/withNotificationsXcodeProject.js.map +1 -1
  32. package/plugin/lib/commonjs/utils/android.js +2 -1
  33. package/plugin/lib/commonjs/utils/android.js.map +1 -1
  34. package/plugin/lib/commonjs/utils/config.js +3 -2
  35. package/plugin/lib/commonjs/utils/config.js.map +1 -1
  36. package/plugin/lib/commonjs/utils/logger.js +35 -0
  37. package/plugin/lib/commonjs/utils/logger.js.map +1 -0
  38. package/plugin/lib/commonjs/utils/validation.js +68 -25
  39. package/plugin/lib/commonjs/utils/validation.js.map +1 -1
  40. package/plugin/lib/commonjs/utils/xcode.js +2 -1
  41. package/plugin/lib/commonjs/utils/xcode.js.map +1 -1
  42. package/plugin/lib/module/android/withAndroidManifestUpdates.js +6 -4
  43. package/plugin/lib/module/android/withAndroidManifestUpdates.js.map +1 -1
  44. package/plugin/lib/module/android/withAppGoogleServices.js +2 -1
  45. package/plugin/lib/module/android/withAppGoogleServices.js.map +1 -1
  46. package/plugin/lib/module/android/withCIOAndroid.js +17 -11
  47. package/plugin/lib/module/android/withCIOAndroid.js.map +1 -1
  48. package/plugin/lib/module/android/withGistMavenRepository.js +2 -1
  49. package/plugin/lib/module/android/withGistMavenRepository.js.map +1 -1
  50. package/plugin/lib/module/android/withGoogleServicesJSON.js +4 -3
  51. package/plugin/lib/module/android/withGoogleServicesJSON.js.map +1 -1
  52. package/plugin/lib/module/android/withMainApplicationModifications.js +2 -1
  53. package/plugin/lib/module/android/withMainApplicationModifications.js.map +1 -1
  54. package/plugin/lib/module/helpers/utils/fileManagement.js +6 -5
  55. package/plugin/lib/module/helpers/utils/fileManagement.js.map +1 -1
  56. package/plugin/lib/module/helpers/utils/injectCIOPodfileCode.js +2 -1
  57. package/plugin/lib/module/helpers/utils/injectCIOPodfileCode.js.map +1 -1
  58. package/plugin/lib/module/helpers/utils/patchPluginNativeCode.js +5 -1
  59. package/plugin/lib/module/helpers/utils/patchPluginNativeCode.js.map +1 -1
  60. package/plugin/lib/module/index.js +3 -12
  61. package/plugin/lib/module/index.js.map +1 -1
  62. package/plugin/lib/module/ios/withAppDelegateModifications.js +2 -1
  63. package/plugin/lib/module/ios/withAppDelegateModifications.js.map +1 -1
  64. package/plugin/lib/module/ios/withCIOIos.js +7 -3
  65. package/plugin/lib/module/ios/withCIOIos.js.map +1 -1
  66. package/plugin/lib/module/ios/withCIOIosSwift.js +11 -10
  67. package/plugin/lib/module/ios/withCIOIosSwift.js.map +1 -1
  68. package/plugin/lib/module/ios/withGoogleServicesJsonFile.js +8 -7
  69. package/plugin/lib/module/ios/withGoogleServicesJsonFile.js.map +1 -1
  70. package/plugin/lib/module/ios/withNotificationsXcodeProject.js +29 -23
  71. package/plugin/lib/module/ios/withNotificationsXcodeProject.js.map +1 -1
  72. package/plugin/lib/module/utils/android.js +2 -1
  73. package/plugin/lib/module/utils/android.js.map +1 -1
  74. package/plugin/lib/module/utils/config.js +4 -2
  75. package/plugin/lib/module/utils/config.js.map +1 -1
  76. package/plugin/lib/module/utils/logger.js +29 -0
  77. package/plugin/lib/module/utils/logger.js.map +1 -0
  78. package/plugin/lib/module/utils/validation.js +68 -27
  79. package/plugin/lib/module/utils/validation.js.map +1 -1
  80. package/plugin/lib/module/utils/xcode.js +2 -1
  81. package/plugin/lib/module/utils/xcode.js.map +1 -1
  82. package/plugin/lib/typescript/android/withCIOAndroid.d.ts +1 -1
  83. package/plugin/lib/typescript/ios/withCIOIos.d.ts +1 -1
  84. package/plugin/lib/typescript/ios/withCIOIosSwift.d.ts +1 -1
  85. package/plugin/lib/typescript/utils/logger.d.ts +8 -0
  86. package/plugin/lib/typescript/utils/validation.d.ts +6 -3
  87. package/plugin/src/android/withAndroidManifestUpdates.ts +5 -4
  88. package/plugin/src/android/withAppGoogleServices.ts +2 -1
  89. package/plugin/src/android/withCIOAndroid.ts +18 -12
  90. package/plugin/src/android/withGistMavenRepository.ts +3 -2
  91. package/plugin/src/android/withGoogleServicesJSON.ts +4 -3
  92. package/plugin/src/android/withMainApplicationModifications.ts +2 -1
  93. package/plugin/src/helpers/utils/fileManagement.ts +10 -9
  94. package/plugin/src/helpers/utils/injectCIOPodfileCode.ts +2 -1
  95. package/plugin/src/helpers/utils/patchPluginNativeCode.ts +6 -1
  96. package/plugin/src/index.ts +3 -13
  97. package/plugin/src/ios/withAppDelegateModifications.ts +2 -1
  98. package/plugin/src/ios/withCIOIos.ts +12 -8
  99. package/plugin/src/ios/withCIOIosSwift.ts +15 -14
  100. package/plugin/src/ios/withGoogleServicesJsonFile.ts +8 -7
  101. package/plugin/src/ios/withNotificationsXcodeProject.ts +31 -35
  102. package/plugin/src/utils/android.ts +2 -1
  103. package/plugin/src/utils/config.ts +3 -2
  104. package/plugin/src/utils/logger.ts +37 -0
  105. package/plugin/src/utils/validation.ts +96 -32
  106. package/plugin/src/utils/xcode.ts +2 -1
@@ -12,24 +12,30 @@ import { withProjectStrings } from './withProjectStrings';
12
12
 
13
13
  export function withCIOAndroid(
14
14
  config: ExpoConfig,
15
- sdkConfig: NativeSDKConfig | undefined,
16
- props: CustomerIOPluginOptionsAndroid
15
+ sdkConfig?: NativeSDKConfig,
16
+ props?: CustomerIOPluginOptionsAndroid,
17
17
  ): ExpoConfig {
18
- config = withGistMavenRepository(config, props);
19
- config = withProjectGoogleServices(config, props);
20
- config = withAppGoogleServices(config, props);
21
- config = withGoogleServicesJSON(config, props);
22
- config = withProjectStrings(config);
23
- if (props.setHighPriorityPushHandler !== undefined) {
24
- config = withAndroidManifestUpdates(config, props);
25
- }
26
- if (props.pushNotification?.channel) {
27
- config = withNotificationChannelMetadata(config, props);
18
+ // Only run notification setup if props are provided
19
+ if (props) {
20
+ config = withGistMavenRepository(config, props);
21
+ config = withProjectGoogleServices(config, props);
22
+ config = withAppGoogleServices(config, props);
23
+ config = withGoogleServicesJSON(config, props);
24
+ if (props.setHighPriorityPushHandler !== undefined) {
25
+ config = withAndroidManifestUpdates(config, props);
26
+ }
27
+ if (props.pushNotification?.channel) {
28
+ config = withNotificationChannelMetadata(config, props);
29
+ }
28
30
  }
31
+
29
32
  // Add auto initialization if sdkConfig is provided
30
33
  if (sdkConfig) {
31
34
  config = withMainApplicationModifications(config, sdkConfig);
32
35
  }
33
36
 
37
+ // Update project strings for user agent metadata
38
+ config = withProjectStrings(config);
39
+
34
40
  return config;
35
41
  }
@@ -1,11 +1,12 @@
1
- import { withProjectBuildGradle } from '@expo/config-plugins';
2
1
  import type { ConfigPlugin } from '@expo/config-plugins';
2
+ import { withProjectBuildGradle } from '@expo/config-plugins';
3
3
 
4
4
  import {
5
5
  CIO_GIST_MAVEN_REGEX,
6
6
  CIO_PROJECT_ALLPROJECTS_REGEX,
7
7
  CIO_PROJECT_GIST_MAVEN_SNIPPET,
8
8
  } from '../helpers/constants/android';
9
+ import { logger } from '../utils/logger';
9
10
  import type { CustomerIOPluginOptionsAndroid } from './../types/cio-types';
10
11
 
11
12
  export const withGistMavenRepository: ConfigPlugin<
@@ -19,7 +20,7 @@ export const withGistMavenRepository: ConfigPlugin<
19
20
  `$1\n${CIO_PROJECT_GIST_MAVEN_SNIPPET}`
20
21
  );
21
22
  } else {
22
- console.log('build.gradle snippet alreade exists. Skipping...');
23
+ logger.info('build.gradle snippet already exists. Skipping...');
23
24
  }
24
25
 
25
26
  return props;
@@ -1,6 +1,7 @@
1
1
  import type { ConfigPlugin } from '@expo/config-plugins';
2
2
  import { withProjectBuildGradle } from '@expo/config-plugins';
3
3
 
4
+ import { logger } from '../utils/logger';
4
5
  import { FileManagement } from './../helpers/utils/fileManagement';
5
6
  import type { CustomerIOPluginOptionsAndroid } from './../types/cio-types';
6
7
 
@@ -21,17 +22,17 @@ export const withGoogleServicesJSON: ConfigPlugin<
21
22
  `${androidPath}/app/google-services.json`
22
23
  );
23
24
  } catch {
24
- console.log(
25
+ logger.info(
25
26
  `There was an error copying your google-services.json file. You can copy it manually into ${androidPath}/app/google-services.json`
26
27
  );
27
28
  }
28
29
  } else {
29
- console.log(
30
+ logger.info(
30
31
  `The Google Services file provided in ${googleServicesFile} doesn't seem to exist. You can copy it manually into ${androidPath}/app/google-services.json`
31
32
  );
32
33
  }
33
34
  } else {
34
- console.log(
35
+ logger.info(
35
36
  `File already exists: ${androidPath}/app/google-services.json. Skipping...`
36
37
  );
37
38
  }
@@ -6,6 +6,7 @@ import { PLATFORM } from '../helpers/constants/common';
6
6
  import { patchNativeSDKInitializer } from '../helpers/utils/patchPluginNativeCode';
7
7
  import type { NativeSDKConfig } from '../types/cio-types';
8
8
  import { addCodeToMethod, addImportToFile, copyTemplateFile } from '../utils/android';
9
+ import { logger } from '../utils/logger';
9
10
 
10
11
  export const withMainApplicationModifications: ConfigPlugin<NativeSDKConfig> = (configOuter, sdkConfig) => {
11
12
  return withMainApplication(configOuter, async (config) => {
@@ -42,7 +43,7 @@ const setupCustomerIOSDKInitializer = (
42
43
  content = addCodeToMethod(content, CIO_MAINAPPLICATION_ONCREATE_REGEX, CIO_NATIVE_SDK_INITIALIZE_SNIPPET);
43
44
  }
44
45
  } catch (error) {
45
- console.warn(`Could not setup ${SDK_INITIALIZER_CLASS}:`, error);
46
+ logger.warn(`Could not setup ${SDK_INITIALIZER_CLASS}:`, error);
46
47
  return config.modResults.contents;
47
48
  }
48
49
 
@@ -1,14 +1,15 @@
1
+ import type { MakeDirectoryOptions } from 'fs';
1
2
  import {
2
- readFile,
3
- writeFile,
4
3
  appendFile,
5
- existsSync,
6
4
  copyFileSync,
5
+ existsSync,
7
6
  mkdirSync,
8
- writeFileSync,
7
+ readFile,
9
8
  readFileSync,
9
+ writeFile,
10
+ writeFileSync,
10
11
  } from 'fs';
11
- import type { MakeDirectoryOptions } from 'fs';
12
+ import { logger } from '../../utils/logger';
12
13
 
13
14
  export class FileManagement {
14
15
  static async read(path: string): Promise<string> {
@@ -55,7 +56,7 @@ export class FileManagement {
55
56
  try {
56
57
  copyFileSync(src, dest);
57
58
  } catch (err) {
58
- console.log(`Error copying file from ${src} to ${dest}: `, err);
59
+ logger.error(`Error copying file from ${src} to ${dest}: `, err);
59
60
  }
60
61
  }
61
62
 
@@ -63,7 +64,7 @@ export class FileManagement {
63
64
  try {
64
65
  mkdirSync(path, options);
65
66
  } catch (err) {
66
- console.log(`Error creating directory ${path}: `, err);
67
+ logger.error(`Error creating directory ${path}: `, err);
67
68
  }
68
69
  }
69
70
 
@@ -71,7 +72,7 @@ export class FileManagement {
71
72
  try {
72
73
  writeFileSync(path, data);
73
74
  } catch (err) {
74
- console.log(`Error writing to file ${path}: `, err);
75
+ logger.error(`Error writing to file ${path}: `, err);
75
76
  }
76
77
  }
77
78
 
@@ -79,7 +80,7 @@ export class FileManagement {
79
80
  try {
80
81
  return readFileSync(path, 'utf-8');
81
82
  } catch (err) {
82
- console.log(`Error reading file ${path}: `, err);
83
+ logger.error(`Error reading file ${path}: `, err);
83
84
  }
84
85
 
85
86
  return '';
@@ -1,4 +1,5 @@
1
1
  import type { CustomerIOPluginOptionsIOS } from '../../types/cio-types';
2
+ import { logger } from '../../utils/logger';
2
3
  import { getRelativePathToRNSDK } from '../constants/ios';
3
4
  import { injectCodeByRegex } from './codeInjection';
4
5
  import { FileManagement } from './fileManagement';
@@ -36,7 +37,7 @@ ${blockEnd}
36
37
  ).join('\n')
37
38
  );
38
39
  } else {
39
- console.log('CustomerIO Podfile snippets already exists. Skipping...');
40
+ logger.info('CustomerIO Podfile snippets already exists. Skipping...');
40
41
  }
41
42
  }
42
43
 
@@ -1,6 +1,7 @@
1
1
  import type { NativeSDKConfig } from '../../types/cio-types';
2
- import { PLATFORM, type Platform } from '../constants/common';
3
2
  import { getPluginVersion } from '../../utils/plugin';
3
+ import { validateNativeSDKConfig } from '../../utils/validation';
4
+ import { PLATFORM, type Platform } from '../constants/common';
4
5
 
5
6
  /**
6
7
  * Shared utility function to perform common SDK config replacements
@@ -11,6 +12,10 @@ export function patchNativeSDKInitializer(
11
12
  platform: Platform,
12
13
  sdkConfig: NativeSDKConfig
13
14
  ): string {
15
+ // Validate SDK configuration to ensure all fields are present and
16
+ // correct at the time of patching in prebuild
17
+ validateNativeSDKConfig(sdkConfig);
18
+
14
19
  let content = rawContent;
15
20
 
16
21
  // Helper function to replace placeholders with platform-specific fallback values
@@ -4,7 +4,6 @@ import { withCIOAndroid } from './android/withCIOAndroid';
4
4
  import { isExpoVersion53OrHigher } from './ios/utils';
5
5
  import { withCIOIos } from './ios/withCIOIos';
6
6
  import type { CustomerIOPluginOptions } from './types/cio-types';
7
- import { validateNativeSDKConfig } from './utils/validation';
8
7
 
9
8
  // Entry point for config plugin
10
9
  function withCustomerIOPlugin(
@@ -20,18 +19,9 @@ function withCustomerIOPlugin(
20
19
  );
21
20
  }
22
21
 
23
- // Validate SDK config if provided
24
- if (props.config) {
25
- validateNativeSDKConfig(props.config);
26
- }
27
-
28
- if (props.ios) {
29
- config = withCIOIos(config, props.config, props.ios);
30
- }
31
-
32
- if (props.android) {
33
- config = withCIOAndroid(config, props.config, props.android);
34
- }
22
+ // Apply platform specific modifications
23
+ config = withCIOIos(config, props.config, props.ios);
24
+ config = withCIOAndroid(config, props.config, props.android);
35
25
 
36
26
  return config;
37
27
  }
@@ -32,6 +32,7 @@ import {
32
32
  } from '../helpers/utils/codeInjection';
33
33
  import { FileManagement } from '../helpers/utils/fileManagement';
34
34
  import type { CustomerIOPluginOptionsIOS } from '../types/cio-types';
35
+ import { logger } from '../utils/logger';
35
36
  import { isFcmPushProvider } from './utils';
36
37
 
37
38
  const addImport = (stringContents: string, appName: string) => {
@@ -268,7 +269,7 @@ export const withAppDelegateModifications: ConfigPlugin<
268
269
 
269
270
  config.modResults.contents = stringContents;
270
271
  } else {
271
- console.log('Customerio AppDelegate changes already exist. Skipping...');
272
+ logger.info('Customerio AppDelegate changes already exist. Skipping...');
272
273
  }
273
274
 
274
275
  return config;
@@ -1,11 +1,11 @@
1
1
  import type { ExpoConfig } from '@expo/config-types';
2
-
3
2
  import type {
4
3
  CustomerIOPluginOptionsIOS,
5
4
  CustomerIOPluginPushNotificationOptions,
6
5
  NativeSDKConfig,
7
6
  } from '../types/cio-types';
8
7
  import { mergeConfigWithEnvValues } from '../utils/config';
8
+ import { logger } from '../utils/logger';
9
9
  import { isExpoVersion53OrHigher } from './utils';
10
10
  import { withAppDelegateModifications } from './withAppDelegateModifications';
11
11
  import { withCIOIosSwift } from './withCIOIosSwift';
@@ -15,13 +15,13 @@ import { withCioXcodeProject } from './withXcodeProject';
15
15
 
16
16
  export function withCIOIos(
17
17
  config: ExpoConfig,
18
- sdkConfig: NativeSDKConfig | undefined,
19
- props: CustomerIOPluginOptionsIOS
18
+ sdkConfig?: NativeSDKConfig,
19
+ props?: CustomerIOPluginOptionsIOS,
20
20
  ) {
21
21
  const isSwiftProject = isExpoVersion53OrHigher(config);
22
22
  const platformConfig = mergeDeprecatedPropertiesAndLogWarnings(props);
23
23
 
24
- if (platformConfig.pushNotification) {
24
+ if (platformConfig?.pushNotification) {
25
25
  if (isSwiftProject) {
26
26
  config = withCIOIosSwift(config, sdkConfig, platformConfig);
27
27
  } else {
@@ -49,14 +49,18 @@ export function withCIOIos(
49
49
  while the rest of the plugin code remains unchanged.
50
50
  */
51
51
  const mergeDeprecatedPropertiesAndLogWarnings = (
52
- props: CustomerIOPluginOptionsIOS
53
- ) => {
52
+ props?: CustomerIOPluginOptionsIOS,
53
+ ): CustomerIOPluginOptionsIOS | undefined => {
54
54
  // The deprecatedTopLevelProperties maps the top level properties
55
55
  // that are deprecated to the new ios.pushNotification.* properties
56
56
  // that should be used instead. The deprecated properties are
57
57
  // still available for backwards compatibility, but they will
58
58
  // be removed in the future.
59
59
 
60
+ if (!props) {
61
+ return props
62
+ }
63
+
60
64
  const deprecatedTopLevelProperties = {
61
65
  showPushAppInForeground: props.showPushAppInForeground,
62
66
  autoTrackPushEvents: props.autoTrackPushEvents,
@@ -68,7 +72,7 @@ const mergeDeprecatedPropertiesAndLogWarnings = (
68
72
  // loop over all the deprecated properties and log a warning if they are set
69
73
  Object.entries(deprecatedTopLevelProperties).forEach(([key, value]) => {
70
74
  if (value !== undefined) {
71
- console.warn(
75
+ logger.warn(
72
76
  `The ios.${key} property is deprecated. Please use ios.pushNotification.${key} instead.`
73
77
  );
74
78
 
@@ -82,7 +86,7 @@ const mergeDeprecatedPropertiesAndLogWarnings = (
82
86
  [propKey]: value,
83
87
  };
84
88
  } else {
85
- console.warn(
89
+ logger.warn(
86
90
  `The ios.${key} property is deprecated. Since the value of ios.pushNotification.${key} is set, it will be used.`
87
91
  );
88
92
  }
@@ -18,6 +18,7 @@ import { replaceCodeByRegex } from '../helpers/utils/codeInjection';
18
18
  import { FileManagement } from '../helpers/utils/fileManagement';
19
19
  import { patchNativeSDKInitializer } from '../helpers/utils/patchPluginNativeCode';
20
20
  import type { CustomerIOPluginOptionsIOS, NativeSDKConfig } from '../types/cio-types';
21
+ import { logger } from '../utils/logger';
21
22
  import { getIosNativeFilesPath } from '../utils/plugin';
22
23
  import { copyFileToXcode, getOrCreateCustomerIOGroup } from '../utils/xcode';
23
24
  import { isFcmPushProvider } from './utils';
@@ -31,13 +32,13 @@ const CIO_SDK_APP_DELEGATE_HANDLER_FILENAME = `${CIO_SDK_APP_DELEGATE_HANDLER_CL
31
32
  */
32
33
  const copyAndConfigureAppDelegateHandler = (
33
34
  config: ExportedConfigWithProps<XcodeProject>,
34
- sdkConfig: NativeSDKConfig | undefined,
35
- props: CustomerIOPluginOptionsIOS,
35
+ sdkConfig?: NativeSDKConfig,
36
+ props?: CustomerIOPluginOptionsIOS,
36
37
  ): ExportedConfigWithProps<XcodeProject> => {
37
38
  // Destination path in the iOS project
38
39
  const projectName = config.modRequest.projectName || '';
39
40
  if (!projectName) {
40
- console.warn(
41
+ logger.warn(
41
42
  'Project name is undefined, cannot copy CustomerIO files'
42
43
  );
43
44
  return config;
@@ -49,7 +50,7 @@ const copyAndConfigureAppDelegateHandler = (
49
50
  const iosProjectRoot = path.join(projectRoot, 'ios');
50
51
 
51
52
  const group = getOrCreateCustomerIOGroup(xcodeProject, projectName);
52
- if (props.pushNotification) {
53
+ if (props?.pushNotification) {
53
54
  // Copy CioSdkAppDelegateHandler.swift for full push notification + auto-init support
54
55
  copyAndConfigurePushAppDelegateHandler({
55
56
  xcodeProject,
@@ -193,8 +194,8 @@ const copyAndConfigureNativeSDKInitializer = ({
193
194
 
194
195
  export const withCIOIosSwift = (
195
196
  configOuter: ExpoConfig,
196
- sdkConfig: NativeSDKConfig | undefined,
197
- props: CustomerIOPluginOptionsIOS,
197
+ sdkConfig?: NativeSDKConfig,
198
+ props?: CustomerIOPluginOptionsIOS,
198
199
  ) => {
199
200
  // First, copy required swift files to iOS folder and add it to Xcode project
200
201
  configOuter = withXcodeProject(configOuter, async (config) => {
@@ -202,7 +203,7 @@ export const withCIOIosSwift = (
202
203
  });
203
204
 
204
205
  // Modify the AppDelegate based on configuration
205
- if (props.pushNotification) {
206
+ if (props?.pushNotification) {
206
207
  // With push notifications: delegate to CioSdkAppDelegateHandler for both push and auto-init
207
208
  return withAppDelegate(configOuter, async (config) => {
208
209
  return modifyAppDelegateWithPushAppDelegateHandler(config, props);
@@ -230,7 +231,7 @@ const modifyAppDelegateWithPushAppDelegateHandler = (
230
231
 
231
232
  // Check if modifications have already been applied
232
233
  if (appDelegateContent.includes(CIO_SDK_APP_DELEGATE_HANDLER_CLASS)) {
233
- console.log(
234
+ logger.info(
234
235
  'CustomerIO Swift AppDelegate changes already exist. Skipping...'
235
236
  );
236
237
  return config;
@@ -274,7 +275,7 @@ const modifyAppDelegateWithNativeSDKInitializer = (
274
275
 
275
276
  // Check if modifications have already been applied
276
277
  if (appDelegateContent.includes(CIO_NATIVE_SDK_INITIALIZE_CALL)) {
277
- console.log(
278
+ logger.info(
278
279
  'CustomerIO Swift AppDelegate changes already exist. Skipping...'
279
280
  );
280
281
  return config;
@@ -314,7 +315,7 @@ const addHandlerPropertyDeclaration = (content: string): string => {
314
315
  const match = content.match(classDeclarationRegex);
315
316
 
316
317
  if (!match) {
317
- console.warn('Could not find AppDelegate class declaration');
318
+ logger.warn('Could not find AppDelegate class declaration');
318
319
  return content;
319
320
  }
320
321
 
@@ -339,7 +340,7 @@ const modifyDidFinishLaunchingWithOptions = (content: string, codeToInject: stri
339
340
  const returnStatementMatch = content.match(returnStatementRegex);
340
341
 
341
342
  if (!returnStatementMatch) {
342
- console.warn(
343
+ logger.warn(
343
344
  'Could not find return statement with super.application in didFinishLaunchingWithOptions'
344
345
  );
345
346
  return content;
@@ -394,7 +395,7 @@ const addDidRegisterForRemoteNotificationsWithDeviceToken = (
394
395
  const classEndMatch = content.match(classEndRegex);
395
396
 
396
397
  if (!classEndMatch) {
397
- console.warn('Could not find end of AppDelegate class');
398
+ logger.warn('Could not find end of AppDelegate class');
398
399
  return content;
399
400
  }
400
401
 
@@ -452,7 +453,7 @@ const addDidFailToRegisterForRemoteNotificationsWithError = (
452
453
  const classEndMatch = content.match(classEndRegex);
453
454
 
454
455
  if (!classEndMatch) {
455
- console.warn('Could not find end of AppDelegate class');
456
+ logger.warn('Could not find end of AppDelegate class');
456
457
  return content;
457
458
  }
458
459
 
@@ -489,7 +490,7 @@ const addHandleDeeplinkInKilledState = (content: string): string => {
489
490
  const returnStatementMatch = content.match(returnStatementRegex);
490
491
 
491
492
  if (!returnStatementMatch) {
492
- console.warn('Could not find return statement with launchOptions');
493
+ logger.warn('Could not find return statement with launchOptions');
493
494
  return content;
494
495
  }
495
496
 
@@ -2,6 +2,7 @@ import type { ConfigPlugin, XcodeProject } from '@expo/config-plugins';
2
2
  import { IOSConfig, withXcodeProject } from '@expo/config-plugins';
3
3
 
4
4
  import type { CustomerIOPluginOptionsIOS } from '../types/cio-types';
5
+ import { logger } from '../utils/logger';
5
6
  import { FileManagement } from './../helpers/utils/fileManagement';
6
7
  import { isFcmPushProvider } from './utils';
7
8
 
@@ -15,7 +16,7 @@ export const withGoogleServicesJsonFile: ConfigPlugin<
15
16
  return props;
16
17
  }
17
18
 
18
- console.log(
19
+ logger.info(
19
20
  'Only specify Customer.io ios.pushNotification.googleServicesFile config if you are not already including' +
20
21
  ' GoogleService-Info.plist as part of Firebase integration'
21
22
  );
@@ -26,7 +27,7 @@ export const withGoogleServicesJsonFile: ConfigPlugin<
26
27
  const appName = props.modRequest.projectName;
27
28
 
28
29
  if (FileManagement.exists(`${iosPath}/GoogleService-Info.plist`)) {
29
- console.log(
30
+ logger.info(
30
31
  `File already exists: ${iosPath}/GoogleService-Info.plist. Skipping...`
31
32
  );
32
33
  return props;
@@ -37,7 +38,7 @@ export const withGoogleServicesJsonFile: ConfigPlugin<
37
38
  ) {
38
39
  // This is where RN Firebase potentially copies GoogleService-Info.plist
39
40
  // Do not copy if it's already done by Firebase to avoid conflict in Resources
40
- console.log(
41
+ logger.info(
41
42
  `File already exists: ${iosPath}/${appName}/GoogleService-Info.plist. Skipping...`
42
43
  );
43
44
  return props;
@@ -45,7 +46,7 @@ export const withGoogleServicesJsonFile: ConfigPlugin<
45
46
 
46
47
  if (googleServicesFile && FileManagement.exists(googleServicesFile)) {
47
48
  if (config.ios?.googleServicesFile) {
48
- console.warn(
49
+ logger.warn(
49
50
  'Specifying both Expo ios.googleServicesFile and Customer.io ios.pushNotification.googleServicesFile can cause a conflict' +
50
51
  ' duplicating GoogleService-Info.plist in the iOS project resources. Please remove Customer.io ios.pushNotification.googleServicesFile'
51
52
  );
@@ -59,12 +60,12 @@ export const withGoogleServicesJsonFile: ConfigPlugin<
59
60
 
60
61
  addFileToXcodeProject(props.modResults, 'GoogleService-Info.plist');
61
62
  } catch {
62
- console.error(
63
+ logger.error(
63
64
  `There was an error copying your GoogleService-Info.plist file. You can copy it manually into ${iosPath}/GoogleService-Info.plist`
64
65
  );
65
66
  }
66
67
  } else {
67
- console.error(
68
+ logger.error(
68
69
  `The Google Services file provided in ${googleServicesFile} doesn't seem to exist. You can copy it manually into ${iosPath}/GoogleService-Info.plist`
69
70
  );
70
71
  }
@@ -78,7 +79,7 @@ function addFileToXcodeProject(project: XcodeProject, fileName: string) {
78
79
  const filepath = fileName;
79
80
 
80
81
  if (!IOSConfig.XcodeUtils.ensureGroupRecursively(project, groupName)) {
81
- console.error(
82
+ logger.error(
82
83
  `Error copying GoogleService-Info.plist. Failed to find or create '${groupName}' group in Xcode.`
83
84
  );
84
85
  return;
@@ -9,7 +9,9 @@ import {
9
9
  import { replaceCodeByRegex } from '../helpers/utils/codeInjection';
10
10
  import { injectCIONotificationPodfileCode } from '../helpers/utils/injectCIOPodfileCode';
11
11
  import type { CustomerIOPluginOptionsIOS, RichPushConfig } from '../types/cio-types';
12
+ import { logger } from '../utils/logger';
12
13
  import { getIosNativeFilesPath } from '../utils/plugin';
14
+ import { validateRichPushConfig } from '../utils/validation';
13
15
  import { FileManagement } from './../helpers/utils/fileManagement';
14
16
  import { isExpoVersion53OrHigher, isFcmPushProvider } from './utils';
15
17
 
@@ -34,7 +36,7 @@ const addNotificationServiceExtension = async (
34
36
  }
35
37
  return xcodeProject;
36
38
  } catch (error: unknown) {
37
- console.error(error);
39
+ logger.error(String(error));
38
40
  return null;
39
41
  }
40
42
  };
@@ -120,7 +122,7 @@ const addRichPushXcodeProj = async (
120
122
  // Check if `CIO_NOTIFICATION_TARGET_NAME` group already exist in the project
121
123
  // If true then skip creating a new group to avoid duplicate folders
122
124
  if (xcodeProject.pbxTargetByName(CIO_NOTIFICATION_TARGET_NAME)) {
123
- console.warn(
125
+ logger.warn(
124
126
  `${CIO_NOTIFICATION_TARGET_NAME} already exists in project. Skipping...`
125
127
  );
126
128
  return;
@@ -194,7 +196,7 @@ const addRichPushXcodeProj = async (
194
196
  projObjects.PBXContainerItemProxy = projObjects.PBXTargetDependency || {};
195
197
 
196
198
  if (xcodeProject.pbxTargetByName(CIO_NOTIFICATION_TARGET_NAME)) {
197
- console.warn(
199
+ logger.warn(
198
200
  `${CIO_NOTIFICATION_TARGET_NAME} already exists in project. Skipping...`
199
201
  );
200
202
  return;
@@ -295,35 +297,30 @@ const updateNseEnv = (
295
297
  const cdpApiKey = richPushConfig?.cdpApiKey;
296
298
  const region = richPushConfig?.region;
297
299
 
298
- if (!cdpApiKey) {
299
- throw new Error(
300
- 'NotificationServiceExtension failed: cdpApiKey missing. Provide in config.cdpApiKey or ios.pushNotification.env.cdpApiKey.'
301
- );
300
+ if (!validateRichPushConfig(richPushConfig)) {
301
+ return;
302
302
  }
303
303
  envFileContent = replaceCodeByRegex(
304
304
  envFileContent,
305
305
  CDP_API_KEY_RE,
306
- cdpApiKey
306
+ cdpApiKey || 'MISSING_API_KEY',
307
307
  );
308
308
 
309
- if (region) {
310
- const regionMap = {
311
- us: 'Region.US',
312
- eu: 'Region.EU',
313
- };
314
- const mappedRegion =
315
- regionMap[region.toLowerCase() as keyof typeof regionMap] || '';
316
- if (!mappedRegion) {
317
- console.warn(
318
- `${region} is an invalid region. Please use the values from the docs: https://customer.io/docs/sdk/expo/getting-started/#configure-the-plugin`
319
- );
320
- } else {
321
- envFileContent = replaceCodeByRegex(
322
- envFileContent,
323
- REGION_RE,
324
- mappedRegion
325
- );
326
- }
309
+ // Simplify region mapping with case insensitive keys and fallback for invalid regions
310
+ const regionKey = region?.toLowerCase() ?? '';
311
+ const regionMap = {
312
+ us: 'Region.US',
313
+ eu: 'Region.EU',
314
+ } as const;
315
+ const mappedRegion = regionMap[regionKey as keyof typeof regionMap];
316
+ if (!mappedRegion) {
317
+ logger.warn(
318
+ `${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`
319
+ );
320
+ // Fallback to US if invalid region provided
321
+ envFileContent = replaceCodeByRegex(envFileContent, REGION_RE, regionMap.us);
322
+ } else {
323
+ envFileContent = replaceCodeByRegex(envFileContent, REGION_RE, mappedRegion);
327
324
  }
328
325
 
329
326
  FileManagement.writeFile(envFileName, envFileContent);
@@ -355,7 +352,7 @@ async function addPushNotificationFile(
355
352
  targetFile
356
353
  );
357
354
  } else {
358
- console.log(`${getTargetFile(targetFileName)} already exists. Skipping...`);
355
+ logger.info(`${getTargetFile(targetFileName)} already exists. Skipping...`);
359
356
  return;
360
357
  }
361
358
 
@@ -377,18 +374,17 @@ const updatePushFile = (
377
374
  let envFileContent = FileManagement.readFile(envFileName);
378
375
  const disableNotificationRegistration =
379
376
  options.pushNotification?.disableNotificationRegistration;
380
- const { cdpApiKey, region } = options.pushNotification?.env || {
381
- cdpApiKey: undefined,
377
+ const richPushConfig = options.pushNotification?.env;
378
+ const { cdpApiKey, region } = richPushConfig || {
379
+ cdpApiKey: 'MISSING_API_KEY',
382
380
  region: undefined,
383
381
  };
384
- if (!cdpApiKey) {
385
- throw new Error(
386
- 'Adding NotificationServiceExtension failed: ios.pushNotification.env.cdpApiKey is missing from app.config.js or app.json.'
387
- );
382
+ if (!validateRichPushConfig(richPushConfig)) {
383
+ return;
388
384
  }
389
385
 
390
386
  let snippet = '';
391
- // unless this property is explicity set to true, push notification
387
+ // unless this property is explicitly set to true, push notification
392
388
  // registration will be added to the AppDelegate
393
389
  if (disableNotificationRegistration !== true) {
394
390
  snippet = CIO_REGISTER_PUSHNOTIFICATION_SNIPPET;
@@ -398,7 +394,7 @@ const updatePushFile = (
398
394
  envFileContent = replaceCodeByRegex(
399
395
  envFileContent,
400
396
  /\{\{CDP_API_KEY\}\}/,
401
- cdpApiKey
397
+ cdpApiKey,
402
398
  );
403
399
 
404
400
  if (region) {
@@ -2,6 +2,7 @@ import type { ExportedConfigWithProps } from '@expo/config-plugins';
2
2
  import type { ApplicationProjectFile } from '@expo/config-plugins/build/android/Paths';
3
3
  import path from 'path';
4
4
  import { FileManagement } from '../helpers/utils/fileManagement';
5
+ import { logger } from './logger';
5
6
  import { getAndroidNativeFilesPath } from './plugin';
6
7
 
7
8
  // Generic utility to add import to Kotlin files
@@ -106,7 +107,7 @@ export const copyTemplateFile = (
106
107
  const destinationPath = path.join(packagePath, filename);
107
108
  FileManagement.writeFile(destinationPath, content);
108
109
  } catch (error) {
109
- console.warn(`Failed to copy ${filename} to Android project:`, error);
110
+ logger.warn(`Failed to copy ${filename} to Android project:`, error);
110
111
  throw error;
111
112
  }
112
113
  };