customerio-expo-plugin 2.5.0 → 2.7.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 +13 -31
- package/plugin/app.plugin.js +1 -1
- package/plugin/lib/commonjs/android/withAndroidManifestUpdates.js +56 -15
- package/plugin/lib/commonjs/android/withAndroidManifestUpdates.js.map +1 -1
- package/plugin/lib/commonjs/android/withCIOAndroid.js +7 -2
- package/plugin/lib/commonjs/android/withCIOAndroid.js.map +1 -1
- package/plugin/lib/commonjs/android/withGoogleServicesJSON.js +1 -1
- package/plugin/lib/commonjs/android/withGoogleServicesJSON.js.map +1 -1
- package/plugin/lib/commonjs/android/withMainApplicationModifications.js +45 -0
- package/plugin/lib/commonjs/android/withMainApplicationModifications.js.map +1 -0
- package/plugin/lib/commonjs/android/withNotificationChannelMetadata.js +1 -1
- package/plugin/lib/commonjs/android/withNotificationChannelMetadata.js.map +1 -1
- package/plugin/lib/commonjs/android/withProjectStrings.js +14 -7
- package/plugin/lib/commonjs/android/withProjectStrings.js.map +1 -1
- package/plugin/lib/commonjs/helpers/constants/android.js +7 -1
- package/plugin/lib/commonjs/helpers/constants/android.js.map +1 -1
- package/plugin/lib/commonjs/helpers/constants/common.js +18 -0
- package/plugin/lib/commonjs/helpers/constants/common.js.map +1 -0
- package/plugin/lib/commonjs/helpers/constants/ios.js +7 -7
- package/plugin/lib/commonjs/helpers/constants/ios.js.map +1 -1
- package/plugin/lib/commonjs/helpers/native-files/android/CustomerIOSDKInitializer.kt +64 -0
- package/plugin/lib/commonjs/helpers/native-files/ios/CustomerIOSDKInitializer.swift +54 -0
- package/plugin/lib/commonjs/helpers/utils/injectCIOPodfileCode.js +2 -2
- package/plugin/lib/commonjs/helpers/utils/injectCIOPodfileCode.js.map +1 -1
- package/plugin/lib/commonjs/helpers/utils/patchPluginNativeCode.js +62 -0
- package/plugin/lib/commonjs/helpers/utils/patchPluginNativeCode.js.map +1 -0
- package/plugin/lib/commonjs/index.js +13 -2
- package/plugin/lib/commonjs/index.js.map +1 -1
- package/plugin/lib/commonjs/ios/utils.js +1 -1
- package/plugin/lib/commonjs/ios/utils.js.map +1 -1
- package/plugin/lib/commonjs/ios/withAppDelegateModifications.js +1 -1
- package/plugin/lib/commonjs/ios/withAppDelegateModifications.js.map +1 -1
- package/plugin/lib/commonjs/ios/withCIOIos.js +17 -11
- package/plugin/lib/commonjs/ios/withCIOIos.js.map +1 -1
- package/plugin/lib/commonjs/ios/withCIOIosSwift.js +133 -49
- package/plugin/lib/commonjs/ios/withCIOIosSwift.js.map +1 -1
- package/plugin/lib/commonjs/ios/withGoogleServicesJsonFile.js +1 -1
- package/plugin/lib/commonjs/ios/withGoogleServicesJsonFile.js.map +1 -1
- package/plugin/lib/commonjs/ios/withNotificationsXcodeProject.js +17 -19
- package/plugin/lib/commonjs/ios/withNotificationsXcodeProject.js.map +1 -1
- package/plugin/lib/commonjs/ios/withXcodeProject.js +1 -1
- package/plugin/lib/commonjs/ios/withXcodeProject.js.map +1 -1
- package/plugin/lib/commonjs/postInstallHelper.js.map +1 -1
- package/plugin/lib/commonjs/types/cio-types.js.map +1 -1
- package/plugin/lib/commonjs/utils/android.js +109 -0
- package/plugin/lib/commonjs/utils/android.js.map +1 -0
- package/plugin/lib/commonjs/utils/config.js +43 -0
- package/plugin/lib/commonjs/utils/config.js.map +1 -0
- package/plugin/lib/commonjs/utils/plugin.js +49 -0
- package/plugin/lib/commonjs/utils/plugin.js.map +1 -0
- package/plugin/lib/commonjs/utils/validation.js +44 -0
- package/plugin/lib/commonjs/utils/validation.js.map +1 -0
- package/plugin/lib/commonjs/utils/xcode.js +67 -0
- package/plugin/lib/commonjs/utils/xcode.js.map +1 -0
- package/plugin/lib/module/android/withAndroidManifestUpdates.js +55 -14
- package/plugin/lib/module/android/withAndroidManifestUpdates.js.map +1 -1
- package/plugin/lib/module/android/withCIOAndroid.js +7 -2
- package/plugin/lib/module/android/withCIOAndroid.js.map +1 -1
- package/plugin/lib/module/android/withGoogleServicesJSON.js +1 -1
- package/plugin/lib/module/android/withGoogleServicesJSON.js.map +1 -1
- package/plugin/lib/module/android/withMainApplicationModifications.js +38 -0
- package/plugin/lib/module/android/withMainApplicationModifications.js.map +1 -0
- package/plugin/lib/module/android/withNotificationChannelMetadata.js +1 -1
- package/plugin/lib/module/android/withNotificationChannelMetadata.js.map +1 -1
- package/plugin/lib/module/android/withProjectStrings.js +13 -6
- package/plugin/lib/module/android/withProjectStrings.js.map +1 -1
- package/plugin/lib/module/helpers/constants/android.js +6 -0
- package/plugin/lib/module/helpers/constants/android.js.map +1 -1
- package/plugin/lib/module/helpers/constants/common.js +12 -0
- package/plugin/lib/module/helpers/constants/common.js.map +1 -0
- package/plugin/lib/module/helpers/constants/ios.js +6 -6
- package/plugin/lib/module/helpers/constants/ios.js.map +1 -1
- package/plugin/lib/module/helpers/native-files/android/CustomerIOSDKInitializer.kt +64 -0
- package/plugin/lib/module/helpers/native-files/ios/CustomerIOSDKInitializer.swift +54 -0
- package/plugin/lib/module/helpers/utils/injectCIOPodfileCode.js +2 -2
- package/plugin/lib/module/helpers/utils/injectCIOPodfileCode.js.map +1 -1
- package/plugin/lib/module/helpers/utils/patchPluginNativeCode.js +57 -0
- package/plugin/lib/module/helpers/utils/patchPluginNativeCode.js.map +1 -0
- package/plugin/lib/module/index.js +14 -2
- package/plugin/lib/module/index.js.map +1 -1
- package/plugin/lib/module/ios/utils.js +1 -2
- package/plugin/lib/module/ios/utils.js.map +1 -1
- package/plugin/lib/module/ios/withAppDelegateModifications.js +3 -3
- package/plugin/lib/module/ios/withAppDelegateModifications.js.map +1 -1
- package/plugin/lib/module/ios/withCIOIos.js +17 -11
- package/plugin/lib/module/ios/withCIOIos.js.map +1 -1
- package/plugin/lib/module/ios/withCIOIosSwift.js +134 -50
- package/plugin/lib/module/ios/withCIOIosSwift.js.map +1 -1
- package/plugin/lib/module/ios/withGoogleServicesJsonFile.js +2 -2
- package/plugin/lib/module/ios/withGoogleServicesJsonFile.js.map +1 -1
- package/plugin/lib/module/ios/withNotificationsXcodeProject.js +18 -20
- package/plugin/lib/module/ios/withNotificationsXcodeProject.js.map +1 -1
- package/plugin/lib/module/ios/withXcodeProject.js +1 -1
- package/plugin/lib/module/ios/withXcodeProject.js.map +1 -1
- package/plugin/lib/module/postInstallHelper.js.map +1 -1
- package/plugin/lib/module/types/cio-types.js.map +1 -1
- package/plugin/lib/module/utils/android.js +100 -0
- package/plugin/lib/module/utils/android.js.map +1 -0
- package/plugin/lib/module/utils/config.js +38 -0
- package/plugin/lib/module/utils/config.js.map +1 -0
- package/plugin/lib/module/utils/plugin.js +38 -0
- package/plugin/lib/module/utils/plugin.js.map +1 -0
- package/plugin/lib/module/utils/validation.js +39 -0
- package/plugin/lib/module/utils/validation.js.map +1 -0
- package/plugin/lib/module/utils/xcode.js +60 -0
- package/plugin/lib/module/utils/xcode.js.map +1 -0
- package/plugin/lib/typescript/android/withAndroidManifestUpdates.d.ts +1 -0
- package/plugin/lib/typescript/android/withCIOAndroid.d.ts +2 -2
- package/plugin/lib/typescript/android/withMainApplicationModifications.d.ts +3 -0
- package/plugin/lib/typescript/android/withProjectStrings.d.ts +2 -1
- package/plugin/lib/typescript/helpers/constants/android.d.ts +3 -0
- package/plugin/lib/typescript/helpers/constants/common.d.ts +11 -0
- package/plugin/lib/typescript/helpers/constants/ios.d.ts +3 -1
- package/plugin/lib/typescript/helpers/utils/patchPluginNativeCode.d.ts +7 -0
- package/plugin/lib/typescript/ios/utils.d.ts +2 -2
- package/plugin/lib/typescript/ios/withCIOIos.d.ts +2 -2
- package/plugin/lib/typescript/ios/withCIOIosSwift.d.ts +3 -3
- package/plugin/lib/typescript/types/cio-types.d.ts +46 -6
- package/plugin/lib/typescript/utils/android.d.ts +5 -0
- package/plugin/lib/typescript/utils/config.d.ts +8 -0
- package/plugin/lib/typescript/utils/plugin.d.ts +4 -0
- package/plugin/lib/typescript/utils/validation.d.ts +3 -0
- package/plugin/lib/typescript/utils/xcode.d.ts +28 -0
- package/plugin/src/android/withAndroidManifestUpdates.ts +70 -21
- package/plugin/src/android/withCIOAndroid.ts +8 -2
- package/plugin/src/android/withGoogleServicesJSON.ts +2 -2
- package/plugin/src/android/withMainApplicationModifications.ts +50 -0
- package/plugin/src/android/withNotificationChannelMetadata.ts +7 -3
- package/plugin/src/android/withProjectStrings.ts +20 -10
- package/plugin/src/helpers/constants/android.ts +7 -0
- package/plugin/src/helpers/constants/common.ts +12 -0
- package/plugin/src/helpers/constants/ios.ts +11 -13
- package/plugin/src/helpers/native-files/android/CustomerIOSDKInitializer.kt +64 -0
- package/plugin/src/helpers/native-files/ios/CustomerIOSDKInitializer.swift +54 -0
- package/plugin/src/helpers/utils/injectCIOPodfileCode.ts +8 -7
- package/plugin/src/helpers/utils/patchPluginNativeCode.ts +97 -0
- package/plugin/src/index.ts +18 -2
- package/plugin/src/ios/utils.ts +5 -5
- package/plugin/src/ios/withAppDelegateModifications.ts +11 -8
- package/plugin/src/ios/withCIOIos.ts +19 -11
- package/plugin/src/ios/withCIOIosSwift.ts +195 -73
- package/plugin/src/ios/withGoogleServicesJsonFile.ts +7 -10
- package/plugin/src/ios/withNotificationsXcodeProject.ts +25 -26
- package/plugin/src/ios/withXcodeProject.ts +1 -1
- package/plugin/src/postInstallHelper.js +1 -1
- package/plugin/src/types/cio-types.ts +48 -8
- package/plugin/src/utils/android.ts +112 -0
- package/plugin/src/utils/config.ts +53 -0
- package/plugin/src/utils/plugin.ts +46 -0
- package/plugin/src/utils/validation.ts +54 -0
- package/plugin/src/utils/xcode.ts +74 -0
- package/plugin/lib/commonjs/helpers/constants/globals.d.js +0 -2
- package/plugin/lib/commonjs/helpers/constants/globals.d.js.map +0 -1
- package/plugin/lib/commonjs/helpers/utils/pluginUtils.js +0 -26
- package/plugin/lib/commonjs/helpers/utils/pluginUtils.js.map +0 -1
- package/plugin/lib/module/helpers/constants/globals.d.js +0 -2
- package/plugin/lib/module/helpers/constants/globals.d.js.map +0 -1
- package/plugin/lib/module/helpers/utils/pluginUtils.js +0 -19
- package/plugin/lib/module/helpers/utils/pluginUtils.js.map +0 -1
- package/plugin/lib/typescript/helpers/utils/pluginUtils.d.ts +0 -4
- package/plugin/src/helpers/constants/globals.d.ts +0 -8
- package/plugin/src/helpers/utils/pluginUtils.ts +0 -22
|
@@ -1,11 +1,17 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Properties set by the user in their app config file (e.g: app.json or app.plugin.js)
|
|
3
|
+
* @public
|
|
4
|
+
*/
|
|
2
5
|
export type CustomerIOPluginProperties = {
|
|
3
6
|
// (iOS only) Environment name and bundle identifier
|
|
4
7
|
devTeam: string;
|
|
5
8
|
iosDeploymentTarget: string;
|
|
6
9
|
};
|
|
7
10
|
|
|
8
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Plugin options for iOS platform configuration
|
|
13
|
+
* @public
|
|
14
|
+
*/
|
|
9
15
|
export type CustomerIOPluginOptionsIOS = {
|
|
10
16
|
iosPath: string;
|
|
11
17
|
devTeam?: string;
|
|
@@ -51,6 +57,10 @@ export type CustomerIOPluginOptionsIOS = {
|
|
|
51
57
|
disableNotificationRegistration?: boolean;
|
|
52
58
|
};
|
|
53
59
|
|
|
60
|
+
/**
|
|
61
|
+
* Plugin options for Android platform configuration
|
|
62
|
+
* @public
|
|
63
|
+
*/
|
|
54
64
|
export type CustomerIOPluginOptionsAndroid = {
|
|
55
65
|
androidPath: string;
|
|
56
66
|
googleServicesFile?: string;
|
|
@@ -64,11 +74,44 @@ export type CustomerIOPluginOptionsAndroid = {
|
|
|
64
74
|
};
|
|
65
75
|
};
|
|
66
76
|
|
|
77
|
+
/**
|
|
78
|
+
* SDK configuration options for auto initialization
|
|
79
|
+
* @public
|
|
80
|
+
*/
|
|
81
|
+
export type NativeSDKConfig = {
|
|
82
|
+
cdpApiKey: string; // Required
|
|
83
|
+
region?: 'US' | 'EU'; // Default: 'US'. The workspace region set for your workspace on the Customer.io dashboard
|
|
84
|
+
autoTrackDeviceAttributes?: boolean; // Default: true
|
|
85
|
+
trackApplicationLifecycleEvents?: boolean; // Default: true
|
|
86
|
+
screenViewUse?: 'all' | 'inapp'; // Default: 'all'. 'all': sent to server + in-app messages, 'inapp': in-app messages only
|
|
87
|
+
logLevel?: 'none' | 'error' | 'info' | 'debug'; // Default: 'debug'. Controls SDK logging verbosity
|
|
88
|
+
siteId?: string; // Optional, if only siteId defined, migrationSiteId = siteId
|
|
89
|
+
migrationSiteId?: string; // Optional, if only migrationSiteId defined, siteId should be null
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Combined plugin options for both iOS and Android platforms
|
|
94
|
+
* @public
|
|
95
|
+
*/
|
|
67
96
|
export type CustomerIOPluginOptions = {
|
|
97
|
+
config?: NativeSDKConfig; // If defined, enables auto initialization of native SDK
|
|
68
98
|
android: CustomerIOPluginOptionsAndroid;
|
|
69
99
|
ios: CustomerIOPluginOptionsIOS;
|
|
70
100
|
};
|
|
71
101
|
|
|
102
|
+
/**
|
|
103
|
+
* Rich push configuration used to initialize Notification Service Extension (NSE) on the native side
|
|
104
|
+
* @public
|
|
105
|
+
*/
|
|
106
|
+
export type RichPushConfig = {
|
|
107
|
+
cdpApiKey: string;
|
|
108
|
+
region?: string;
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Push notification configuration options
|
|
113
|
+
* @public
|
|
114
|
+
*/
|
|
72
115
|
export type CustomerIOPluginPushNotificationOptions = {
|
|
73
116
|
provider?: 'apn' | 'fcm';
|
|
74
117
|
googleServicesFile?: string;
|
|
@@ -80,11 +123,8 @@ export type CustomerIOPluginPushNotificationOptions = {
|
|
|
80
123
|
handleDeeplinkInKilledState?: boolean;
|
|
81
124
|
|
|
82
125
|
/**
|
|
83
|
-
*
|
|
84
|
-
*
|
|
126
|
+
* Rich push config should match the values used to initialize SDK in the app.
|
|
127
|
+
* Optional if `config` is provided at the top level.
|
|
85
128
|
*/
|
|
86
|
-
env
|
|
87
|
-
cdpApiKey: string;
|
|
88
|
-
region: string;
|
|
89
|
-
};
|
|
129
|
+
env?: RichPushConfig;
|
|
90
130
|
};
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import type { ExportedConfigWithProps } from '@expo/config-plugins';
|
|
2
|
+
import type { ApplicationProjectFile } from '@expo/config-plugins/build/android/Paths';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { FileManagement } from '../helpers/utils/fileManagement';
|
|
5
|
+
import { getAndroidNativeFilesPath } from './plugin';
|
|
6
|
+
|
|
7
|
+
// Generic utility to add import to Kotlin files
|
|
8
|
+
export const addImportToFile = (content: string, importStatement: string): string => {
|
|
9
|
+
if (content.includes(importStatement)) {
|
|
10
|
+
return content;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const importRegex = /^import\s+[^\s\n]+.*$/gm;
|
|
14
|
+
const imports = [...content.matchAll(importRegex)];
|
|
15
|
+
|
|
16
|
+
if (imports.length === 0) {
|
|
17
|
+
const packageRegex = /package\s+[^\s;]+[;\s]*\n/;
|
|
18
|
+
const packageMatch = content.match(packageRegex);
|
|
19
|
+
if (!packageMatch) return content;
|
|
20
|
+
|
|
21
|
+
const insertPosition = (packageMatch.index ?? 0) + packageMatch[0].length;
|
|
22
|
+
return content.substring(0, insertPosition) + `\n${importStatement}\n` + content.substring(insertPosition);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const lastImport = imports[imports.length - 1];
|
|
26
|
+
const insertPosition = (lastImport.index ?? 0) + lastImport[0].length;
|
|
27
|
+
return content.substring(0, insertPosition) + `\n\n${importStatement}` + content.substring(insertPosition);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
// Find matching bracket position (simplified version inspired by the library method)
|
|
31
|
+
const findMatchingBracketPosition = (content: string, bracket: string, startPos: number): number => {
|
|
32
|
+
const openBracket = bracket;
|
|
33
|
+
const closeBracket = bracket === '{' ? '}' : bracket === '(' ? ')' : ']';
|
|
34
|
+
|
|
35
|
+
let depth = 0;
|
|
36
|
+
let foundOpen = false;
|
|
37
|
+
|
|
38
|
+
for (let i = startPos; i < content.length; i++) {
|
|
39
|
+
const char = content[i];
|
|
40
|
+
if (char === openBracket) {
|
|
41
|
+
foundOpen = true;
|
|
42
|
+
depth++;
|
|
43
|
+
} else if (char === closeBracket) {
|
|
44
|
+
depth--;
|
|
45
|
+
if (foundOpen && depth === 0) {
|
|
46
|
+
return i;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return -1;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
// Generic utility to add code to end of a method (before closing brace)
|
|
54
|
+
export const addCodeToMethod = (content: string, methodRegex: RegExp, codeToAdd: string): string => {
|
|
55
|
+
const methodMatch = content.match(methodRegex);
|
|
56
|
+
if (!methodMatch || methodMatch.index === undefined) return content;
|
|
57
|
+
|
|
58
|
+
const methodStart = methodMatch.index;
|
|
59
|
+
const methodContent = methodMatch[0];
|
|
60
|
+
|
|
61
|
+
// Find the opening brace position within the method match
|
|
62
|
+
const openBraceIndex = methodContent.indexOf('{');
|
|
63
|
+
if (openBraceIndex === -1) return content;
|
|
64
|
+
|
|
65
|
+
// Find the matching closing brace
|
|
66
|
+
const absoluteOpenBracePos = methodStart + openBraceIndex;
|
|
67
|
+
const closeBracePos = findMatchingBracketPosition(content, '{', absoluteOpenBracePos);
|
|
68
|
+
if (closeBracePos === -1) return content;
|
|
69
|
+
|
|
70
|
+
// Detect indentation of the method's opening brace line
|
|
71
|
+
const linesUpToOpenBrace = content.substring(0, absoluteOpenBracePos).split('\n');
|
|
72
|
+
const braceLine = linesUpToOpenBrace[linesUpToOpenBrace.length - 1];
|
|
73
|
+
const methodIndentMatch = braceLine.match(/^(\s*)/);
|
|
74
|
+
const methodIndent = methodIndentMatch ? methodIndentMatch[1] : '';
|
|
75
|
+
// Assume one indentation level is two spaces if not detected from next line
|
|
76
|
+
let indentLevel = ' ';
|
|
77
|
+
// Try to detect indentation from the next line after the opening brace
|
|
78
|
+
const afterBrace = content.substring(absoluteOpenBracePos + 1, closeBracePos);
|
|
79
|
+
const afterBraceLines = afterBrace.split('\n').filter(l => l.trim().length > 0);
|
|
80
|
+
if (afterBraceLines.length > 0) {
|
|
81
|
+
const nextLineIndentMatch = afterBraceLines[0].match(/^(\s*)/);
|
|
82
|
+
if (nextLineIndentMatch && nextLineIndentMatch[1].length > methodIndent.length) {
|
|
83
|
+
indentLevel = nextLineIndentMatch[1].slice(methodIndent.length);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
const finalIndent = methodIndent + indentLevel;
|
|
87
|
+
// Insert code just before the closing brace, with detected indentation
|
|
88
|
+
return content.substring(0, closeBracePos) + '\n' + finalIndent + codeToAdd + '\n' + methodIndent + content.substring(closeBracePos);
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
// Copy template file to Android project with content transformation
|
|
92
|
+
export const copyTemplateFile = (
|
|
93
|
+
expoConfig: ExportedConfigWithProps<ApplicationProjectFile>,
|
|
94
|
+
filename: string,
|
|
95
|
+
classPackage: string,
|
|
96
|
+
patchContent: (content: string) => string,
|
|
97
|
+
): void => {
|
|
98
|
+
const projectRoot = expoConfig.modRequest.projectRoot;
|
|
99
|
+
const mainSourceDir = path.join(projectRoot, 'android/app/src/main/java');
|
|
100
|
+
const packagePath = path.join(mainSourceDir, classPackage.replace(/\./g, '/'));
|
|
101
|
+
|
|
102
|
+
try {
|
|
103
|
+
FileManagement.mkdir(packagePath, { recursive: true });
|
|
104
|
+
const sourcePath = path.join(getAndroidNativeFilesPath(), filename);
|
|
105
|
+
const content = patchContent(FileManagement.readFile(sourcePath));
|
|
106
|
+
const destinationPath = path.join(packagePath, filename);
|
|
107
|
+
FileManagement.writeFile(destinationPath, content);
|
|
108
|
+
} catch (error) {
|
|
109
|
+
console.warn(`Failed to copy ${filename} to Android project:`, error);
|
|
110
|
+
throw error;
|
|
111
|
+
}
|
|
112
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { CustomerIOPluginOptionsIOS, NativeSDKConfig, RichPushConfig } from '../types/cio-types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Merges config values with env values for backward compatibility.
|
|
5
|
+
* If env is provided, it takes precedence. If nativeConfig is provided but env is not,
|
|
6
|
+
* nativeConfig values are used. This prioritizes existing env configuration for backward compatibility.
|
|
7
|
+
*/
|
|
8
|
+
function mergeConfigWithEnvValues(
|
|
9
|
+
props: CustomerIOPluginOptionsIOS,
|
|
10
|
+
nativeConfig?: NativeSDKConfig
|
|
11
|
+
): RichPushConfig | undefined {
|
|
12
|
+
const nativeCdpApiKey = nativeConfig?.cdpApiKey;
|
|
13
|
+
const nativeRegion = nativeConfig?.region;
|
|
14
|
+
|
|
15
|
+
const envConfig = props.pushNotification?.env;
|
|
16
|
+
const envCdpApiKey = envConfig?.cdpApiKey;
|
|
17
|
+
const envRegion = envConfig?.region;
|
|
18
|
+
|
|
19
|
+
// Check for conflicts between env and nativeConfig
|
|
20
|
+
if (nativeCdpApiKey && envCdpApiKey) {
|
|
21
|
+
if (nativeCdpApiKey !== envCdpApiKey || nativeRegion?.toLowerCase() !== envRegion?.toLowerCase()) {
|
|
22
|
+
const errorMessage = `Configuration conflict: 'config' and 'ios.pushNotification.env' values must match when both are provided.\n` +
|
|
23
|
+
` config.cdpApiKey: "${nativeCdpApiKey}"\n` +
|
|
24
|
+
` env.cdpApiKey: "${envCdpApiKey}"\n` +
|
|
25
|
+
` config.region: "${nativeRegion}"\n` +
|
|
26
|
+
` env.region: "${envRegion}"`;
|
|
27
|
+
|
|
28
|
+
console.error(errorMessage);
|
|
29
|
+
throw new Error(errorMessage);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Values match - warn about redundant configuration
|
|
33
|
+
console.warn(
|
|
34
|
+
`Both 'config' and 'ios.pushNotification.env' are provided with matching values. ` +
|
|
35
|
+
`Consider removing 'ios.pushNotification.env' since 'config' is already specified.`
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Return config (values are guaranteed to be the same if both exist)
|
|
40
|
+
const cdpApiKey = nativeCdpApiKey || envCdpApiKey;
|
|
41
|
+
const region = nativeRegion || envRegion;
|
|
42
|
+
|
|
43
|
+
if (cdpApiKey) {
|
|
44
|
+
return {
|
|
45
|
+
cdpApiKey,
|
|
46
|
+
region,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export { mergeConfigWithEnvValues };
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
|
|
4
|
+
const findPluginPackageRoot = (): string => {
|
|
5
|
+
const finder = require('find-package-json');
|
|
6
|
+
const f = finder(__dirname);
|
|
7
|
+
const root = f.next().filename;
|
|
8
|
+
return path.dirname(root);
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const pluginPackageRoot = findPluginPackageRoot();
|
|
12
|
+
|
|
13
|
+
// Returns path to plugin's native template files directory
|
|
14
|
+
export const getNativeFilesPath = (): string => {
|
|
15
|
+
return path.join(
|
|
16
|
+
pluginPackageRoot,
|
|
17
|
+
'plugin/src/helpers/native-files/'
|
|
18
|
+
);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
// Returns path to plugin's Android native template files
|
|
22
|
+
export const getAndroidNativeFilesPath = (): string => {
|
|
23
|
+
return path.join(getNativeFilesPath(), 'android');
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
// Returns path to plugin's iOS native template files
|
|
27
|
+
export const getIosNativeFilesPath = (): string => {
|
|
28
|
+
return path.join(getNativeFilesPath(), 'ios');
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// Reads the version of the plugin from its `package.json` and returns it as a string.
|
|
32
|
+
export const getPluginVersion = (): string => {
|
|
33
|
+
const packageJsonPath = path.resolve(
|
|
34
|
+
pluginPackageRoot,
|
|
35
|
+
'package.json'
|
|
36
|
+
);
|
|
37
|
+
if (!fs.existsSync(packageJsonPath)) {
|
|
38
|
+
throw new Error(`package.json not found at ${packageJsonPath}`);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
42
|
+
if (!packageJson.version) {
|
|
43
|
+
throw new Error(`"version" field is missing in ${packageJsonPath}`);
|
|
44
|
+
}
|
|
45
|
+
return packageJson.version;
|
|
46
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { NativeSDKConfig } from '../types/cio-types';
|
|
2
|
+
|
|
3
|
+
function validateRequired(value: unknown, fieldName: string, context: string): void {
|
|
4
|
+
if (value === undefined || value === null) {
|
|
5
|
+
throw new Error(`${context}: ${fieldName} is required, received: ${value}`);
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function validateString(value: unknown, fieldName: string, context: string): void {
|
|
10
|
+
if (value !== undefined && (typeof value !== 'string' || value.trim() === '')) {
|
|
11
|
+
throw new Error(`${context}: ${fieldName} must be a non-empty string, received: ${typeof value === 'string' ? `"${value}"` : value}`);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function validateBoolean(value: unknown, fieldName: string, context: string): void {
|
|
16
|
+
if (value !== undefined && typeof value !== 'boolean') {
|
|
17
|
+
throw new Error(`${context}: ${fieldName} must be a boolean, received: ${value}`);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function validateEnum<T extends string>(
|
|
22
|
+
value: unknown,
|
|
23
|
+
fieldName: string,
|
|
24
|
+
allowedValues: readonly T[],
|
|
25
|
+
context: string
|
|
26
|
+
): void {
|
|
27
|
+
if (value === undefined) return;
|
|
28
|
+
|
|
29
|
+
validateString(value, fieldName, context);
|
|
30
|
+
|
|
31
|
+
const lowerValue = (value as string).toLowerCase();
|
|
32
|
+
const lowerAllowedValues = allowedValues.map(v => v.toLowerCase());
|
|
33
|
+
if (!lowerAllowedValues.includes(lowerValue)) {
|
|
34
|
+
const valuesStr = allowedValues.map(v => `"${v}"`).join(', ');
|
|
35
|
+
throw new Error(`${context}: ${fieldName} must be one of ${valuesStr}, received: ${value}`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function validateNativeSDKConfig(config: NativeSDKConfig): void {
|
|
40
|
+
const context = 'NativeSDKConfig';
|
|
41
|
+
|
|
42
|
+
validateRequired(config.cdpApiKey, 'cdpApiKey', context);
|
|
43
|
+
validateString(config.cdpApiKey, 'cdpApiKey', context);
|
|
44
|
+
|
|
45
|
+
validateEnum(config.region, 'region', ['US', 'EU'] as const, context);
|
|
46
|
+
validateEnum(config.screenViewUse, 'screenViewUse', ['all', 'inapp'] as const, context);
|
|
47
|
+
validateEnum(config.logLevel, 'logLevel', ['none', 'error', 'info', 'debug'] as const, context);
|
|
48
|
+
validateBoolean(config.autoTrackDeviceAttributes, 'autoTrackDeviceAttributes', context);
|
|
49
|
+
validateBoolean(config.trackApplicationLifecycleEvents, 'trackApplicationLifecycleEvents', context);
|
|
50
|
+
validateString(config.siteId, 'siteId', context);
|
|
51
|
+
validateString(config.migrationSiteId, 'migrationSiteId', context);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export { validateNativeSDKConfig };
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { XcodeProject } from "@expo/config-plugins";
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { FileManagement } from "../helpers/utils/fileManagement";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Gets an existing CustomerIO group or creates a new one in the Xcode project
|
|
7
|
+
* @param xcodeProject The Xcode project instance
|
|
8
|
+
* @param projectName The iOS project name
|
|
9
|
+
* @returns The CustomerIO group reference
|
|
10
|
+
*/
|
|
11
|
+
export function getOrCreateCustomerIOGroup(
|
|
12
|
+
xcodeProject: XcodeProject,
|
|
13
|
+
projectName: string,
|
|
14
|
+
): XcodeProject['pbxCreateGroup'] {
|
|
15
|
+
// Check if CustomerIO group already exists
|
|
16
|
+
let customerIOGroup = xcodeProject.pbxGroupByName('CustomerIO');
|
|
17
|
+
if (customerIOGroup) {
|
|
18
|
+
return customerIOGroup;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Create new CustomerIO group and add it to the project
|
|
22
|
+
customerIOGroup = xcodeProject.pbxCreateGroup('CustomerIO');
|
|
23
|
+
const projectGroupKey = xcodeProject.findPBXGroupKey({ name: projectName });
|
|
24
|
+
xcodeProject.addToPbxGroup(customerIOGroup, projectGroupKey);
|
|
25
|
+
return customerIOGroup;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Copies template file to iOS project, applies transformations, and registers with Xcode
|
|
30
|
+
* @param params.xcodeProject Xcode project instance
|
|
31
|
+
* @param params.iosProjectRoot iOS project root path
|
|
32
|
+
* @param params.projectName iOS project name
|
|
33
|
+
* @param params.sourceFilePath Source template file path
|
|
34
|
+
* @param params.targetFileName Target file name
|
|
35
|
+
* @param params.transform Content transformation function
|
|
36
|
+
* @param params.customerIOGroup CustomerIO group (auto-created if not provided)
|
|
37
|
+
* @returns Destination file path
|
|
38
|
+
*/
|
|
39
|
+
export function copyFileToXcode({
|
|
40
|
+
xcodeProject,
|
|
41
|
+
iosProjectRoot,
|
|
42
|
+
projectName,
|
|
43
|
+
sourceFilePath,
|
|
44
|
+
targetFileName,
|
|
45
|
+
transform,
|
|
46
|
+
customerIOGroup = getOrCreateCustomerIOGroup(xcodeProject, projectName),
|
|
47
|
+
}: {
|
|
48
|
+
xcodeProject: XcodeProject;
|
|
49
|
+
iosProjectRoot: string;
|
|
50
|
+
projectName: string;
|
|
51
|
+
sourceFilePath: string;
|
|
52
|
+
targetFileName: string;
|
|
53
|
+
transform: (content: string) => string;
|
|
54
|
+
customerIOGroup?: XcodeProject['pbxCreateGroup'];
|
|
55
|
+
}): string {
|
|
56
|
+
// Construct the full destination path within the iOS project directory
|
|
57
|
+
const destinationPath = path.join(
|
|
58
|
+
iosProjectRoot,
|
|
59
|
+
projectName,
|
|
60
|
+
targetFileName
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
try {
|
|
64
|
+
// Read template, apply transformations, and write to project
|
|
65
|
+
const content = transform(FileManagement.readFile(sourceFilePath));
|
|
66
|
+
FileManagement.writeFile(destinationPath, content);
|
|
67
|
+
// Register file with Xcode project
|
|
68
|
+
xcodeProject.addSourceFile(`${projectName}/${targetFileName}`, null, customerIOGroup);
|
|
69
|
+
return destinationPath;
|
|
70
|
+
} catch (error) {
|
|
71
|
+
console.warn(`Failed to add ${targetFileName} to Xcode project:`, error);
|
|
72
|
+
throw error;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["globals.d.ts"],"sourcesContent":["declare module 'xcode' {\n interface xcode {\n project(projPath: string): any;\n }\n\n const xcode: xcode;\n export default xcode;\n}\n"],"mappings":"","ignoreList":[]}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.getPluginVersion = void 0;
|
|
7
|
-
var _fs = _interopRequireDefault(require("fs"));
|
|
8
|
-
var _path = _interopRequireDefault(require("path"));
|
|
9
|
-
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
10
|
-
/**
|
|
11
|
-
* Reads the version of the plugin from its `package.json` and returns it as a string.
|
|
12
|
-
*/
|
|
13
|
-
const getPluginVersion = () => {
|
|
14
|
-
// Always resolves relative to the utility file's location
|
|
15
|
-
const packageJsonPath = _path.default.resolve(__dirname, '../../../../../package.json');
|
|
16
|
-
if (!_fs.default.existsSync(packageJsonPath)) {
|
|
17
|
-
throw new Error(`package.json not found at ${packageJsonPath}`);
|
|
18
|
-
}
|
|
19
|
-
const packageJson = JSON.parse(_fs.default.readFileSync(packageJsonPath, 'utf8'));
|
|
20
|
-
if (!packageJson.version) {
|
|
21
|
-
throw new Error(`"version" field is missing in ${packageJsonPath}`);
|
|
22
|
-
}
|
|
23
|
-
return packageJson.version;
|
|
24
|
-
};
|
|
25
|
-
exports.getPluginVersion = getPluginVersion;
|
|
26
|
-
//# sourceMappingURL=pluginUtils.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["_fs","_interopRequireDefault","require","_path","e","__esModule","default","getPluginVersion","packageJsonPath","path","resolve","__dirname","fs","existsSync","Error","packageJson","JSON","parse","readFileSync","version","exports"],"sources":["pluginUtils.ts"],"sourcesContent":["import fs from 'fs';\nimport path from 'path';\n\n/**\n * Reads the version of the plugin from its `package.json` and returns it as a string.\n */\nexport const getPluginVersion = (): string => {\n // Always resolves relative to the utility file's location\n const packageJsonPath = path.resolve(__dirname, '../../../../../package.json');\n\n if (!fs.existsSync(packageJsonPath)) {\n throw new Error(`package.json not found at ${packageJsonPath}`);\n }\n\n const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));\n\n if (!packageJson.version) {\n throw new Error(`\"version\" field is missing in ${packageJsonPath}`);\n }\n\n return packageJson.version;\n};\n"],"mappings":";;;;;;AAAA,IAAAA,GAAA,GAAAC,sBAAA,CAAAC,OAAA;AACA,IAAAC,KAAA,GAAAF,sBAAA,CAAAC,OAAA;AAAwB,SAAAD,uBAAAG,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAExB;AACA;AACA;AACO,MAAMG,gBAAgB,GAAGA,CAAA,KAAc;EAC5C;EACA,MAAMC,eAAe,GAAGC,aAAI,CAACC,OAAO,CAACC,SAAS,EAAE,6BAA6B,CAAC;EAE9E,IAAI,CAACC,WAAE,CAACC,UAAU,CAACL,eAAe,CAAC,EAAE;IACnC,MAAM,IAAIM,KAAK,CAAC,6BAA6BN,eAAe,EAAE,CAAC;EACjE;EAEA,MAAMO,WAAW,GAAGC,IAAI,CAACC,KAAK,CAACL,WAAE,CAACM,YAAY,CAACV,eAAe,EAAE,MAAM,CAAC,CAAC;EAExE,IAAI,CAACO,WAAW,CAACI,OAAO,EAAE;IACxB,MAAM,IAAIL,KAAK,CAAC,iCAAiCN,eAAe,EAAE,CAAC;EACrE;EAEA,OAAOO,WAAW,CAACI,OAAO;AAC5B,CAAC;AAACC,OAAA,CAAAb,gBAAA,GAAAA,gBAAA","ignoreList":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["globals.d.ts"],"sourcesContent":["declare module 'xcode' {\n interface xcode {\n project(projPath: string): any;\n }\n\n const xcode: xcode;\n export default xcode;\n}\n"],"mappings":"","ignoreList":[]}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Reads the version of the plugin from its `package.json` and returns it as a string.
|
|
6
|
-
*/
|
|
7
|
-
export const getPluginVersion = () => {
|
|
8
|
-
// Always resolves relative to the utility file's location
|
|
9
|
-
const packageJsonPath = path.resolve(__dirname, '../../../../../package.json');
|
|
10
|
-
if (!fs.existsSync(packageJsonPath)) {
|
|
11
|
-
throw new Error(`package.json not found at ${packageJsonPath}`);
|
|
12
|
-
}
|
|
13
|
-
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
14
|
-
if (!packageJson.version) {
|
|
15
|
-
throw new Error(`"version" field is missing in ${packageJsonPath}`);
|
|
16
|
-
}
|
|
17
|
-
return packageJson.version;
|
|
18
|
-
};
|
|
19
|
-
//# sourceMappingURL=pluginUtils.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["fs","path","getPluginVersion","packageJsonPath","resolve","__dirname","existsSync","Error","packageJson","JSON","parse","readFileSync","version"],"sources":["pluginUtils.ts"],"sourcesContent":["import fs from 'fs';\nimport path from 'path';\n\n/**\n * Reads the version of the plugin from its `package.json` and returns it as a string.\n */\nexport const getPluginVersion = (): string => {\n // Always resolves relative to the utility file's location\n const packageJsonPath = path.resolve(__dirname, '../../../../../package.json');\n\n if (!fs.existsSync(packageJsonPath)) {\n throw new Error(`package.json not found at ${packageJsonPath}`);\n }\n\n const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));\n\n if (!packageJson.version) {\n throw new Error(`\"version\" field is missing in ${packageJsonPath}`);\n }\n\n return packageJson.version;\n};\n"],"mappings":"AAAA,OAAOA,EAAE,MAAM,IAAI;AACnB,OAAOC,IAAI,MAAM,MAAM;;AAEvB;AACA;AACA;AACA,OAAO,MAAMC,gBAAgB,GAAGA,CAAA,KAAc;EAC5C;EACA,MAAMC,eAAe,GAAGF,IAAI,CAACG,OAAO,CAACC,SAAS,EAAE,6BAA6B,CAAC;EAE9E,IAAI,CAACL,EAAE,CAACM,UAAU,CAACH,eAAe,CAAC,EAAE;IACnC,MAAM,IAAII,KAAK,CAAC,6BAA6BJ,eAAe,EAAE,CAAC;EACjE;EAEA,MAAMK,WAAW,GAAGC,IAAI,CAACC,KAAK,CAACV,EAAE,CAACW,YAAY,CAACR,eAAe,EAAE,MAAM,CAAC,CAAC;EAExE,IAAI,CAACK,WAAW,CAACI,OAAO,EAAE;IACxB,MAAM,IAAIL,KAAK,CAAC,iCAAiCJ,eAAe,EAAE,CAAC;EACrE;EAEA,OAAOK,WAAW,CAACI,OAAO;AAC5B,CAAC","ignoreList":[]}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Reads the version of the plugin from its `package.json` and returns it as a string.
|
|
6
|
-
*/
|
|
7
|
-
export const getPluginVersion = (): string => {
|
|
8
|
-
// Always resolves relative to the utility file's location
|
|
9
|
-
const packageJsonPath = path.resolve(__dirname, '../../../../../package.json');
|
|
10
|
-
|
|
11
|
-
if (!fs.existsSync(packageJsonPath)) {
|
|
12
|
-
throw new Error(`package.json not found at ${packageJsonPath}`);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
16
|
-
|
|
17
|
-
if (!packageJson.version) {
|
|
18
|
-
throw new Error(`"version" field is missing in ${packageJsonPath}`);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
return packageJson.version;
|
|
22
|
-
};
|