customerio-expo-plugin 0.0.5 → 1.0.0-alpha.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.
- package/lib/commonjs/analytics/injectAnalytics.js +31 -0
- package/lib/commonjs/analytics/injectAnalytics.js.map +1 -0
- package/lib/commonjs/android/withAppGoogleServices.js +22 -0
- package/lib/commonjs/android/withAppGoogleServices.js.map +1 -0
- package/lib/commonjs/android/withCIOAndroid.js +18 -0
- package/lib/commonjs/android/withCIOAndroid.js.map +1 -0
- package/lib/commonjs/android/withGistMavenRepository.js +21 -0
- package/lib/commonjs/android/withGistMavenRepository.js.map +1 -0
- package/lib/commonjs/android/withGoogleServicesJSON.js +34 -0
- package/lib/commonjs/android/withGoogleServicesJSON.js.map +1 -0
- package/lib/commonjs/android/withProjectGoogleServices.js +20 -0
- package/lib/commonjs/android/withProjectGoogleServices.js.map +1 -0
- package/lib/commonjs/helpers/constants/android.js +21 -0
- package/lib/commonjs/helpers/constants/android.js.map +1 -0
- package/lib/commonjs/helpers/constants/globals.d.js +2 -0
- package/lib/commonjs/helpers/constants/globals.d.js.map +1 -0
- package/lib/commonjs/helpers/constants/ios.js +140 -0
- package/lib/commonjs/helpers/constants/ios.js.map +1 -0
- package/{build/helpers/ios/CIONotificationService-Info.plist → lib/commonjs/helpers/native-files/ios/NotificationService-Info.plist} +2 -2
- package/{build/helpers/ios/CIONotificationService.h → lib/commonjs/helpers/native-files/ios/NotificationService.h} +0 -0
- package/{build/helpers/ios/CIONotificationService.m → lib/commonjs/helpers/native-files/ios/NotificationService.m} +2 -6
- package/{build/helpers/ios/CIONotificationService.swift → lib/commonjs/helpers/native-files/ios/NotificationService.swift} +0 -2
- package/{build/helpers → lib/commonjs/helpers/native-files}/ios/PushNotification.swift +1 -10
- package/lib/commonjs/helpers/utils/codeInjection.js +33 -0
- package/lib/commonjs/helpers/utils/codeInjection.js.map +1 -0
- package/lib/commonjs/helpers/utils/fileManagement.js +76 -0
- package/lib/commonjs/helpers/utils/fileManagement.js.map +1 -0
- package/lib/commonjs/helpers/utils/injectCIOPodfileCode.js +37 -0
- package/lib/commonjs/helpers/utils/injectCIOPodfileCode.js.map +1 -0
- package/lib/commonjs/index.js +23 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/ios/withAppDelegateModifications.js +85 -0
- package/lib/commonjs/ios/withAppDelegateModifications.js.map +1 -0
- package/lib/commonjs/ios/withAppDelegateXcodeProject.js +79 -0
- package/lib/commonjs/ios/withAppDelegateXcodeProject.js.map +1 -0
- package/lib/commonjs/ios/withCIOIos.js +23 -0
- package/lib/commonjs/ios/withCIOIos.js.map +1 -0
- package/lib/commonjs/ios/withNotificationsXcodeProject.js +158 -0
- package/lib/commonjs/ios/withNotificationsXcodeProject.js.map +1 -0
- package/lib/commonjs/ios/withXcodeProject.js +28 -0
- package/lib/commonjs/ios/withXcodeProject.js.map +1 -0
- package/lib/commonjs/types/cio-types.js +2 -0
- package/lib/commonjs/types/cio-types.js.map +1 -0
- package/lib/commonjs/version.js +9 -0
- package/lib/commonjs/version.js.map +1 -0
- package/lib/module/analytics/injectAnalytics.js +24 -0
- package/lib/module/analytics/injectAnalytics.js.map +1 -0
- package/lib/module/android/withAppGoogleServices.js +15 -0
- package/lib/module/android/withAppGoogleServices.js.map +1 -0
- package/lib/module/android/withCIOAndroid.js +12 -0
- package/lib/module/android/withCIOAndroid.js.map +1 -0
- package/lib/module/android/withGistMavenRepository.js +14 -0
- package/lib/module/android/withGistMavenRepository.js.map +1 -0
- package/lib/module/android/withGoogleServicesJSON.js +27 -0
- package/lib/module/android/withGoogleServicesJSON.js.map +1 -0
- package/lib/module/android/withProjectGoogleServices.js +13 -0
- package/lib/module/android/withProjectGoogleServices.js.map +1 -0
- package/lib/module/helpers/constants/android.js +8 -0
- package/lib/module/helpers/constants/android.js.map +1 -0
- package/lib/module/helpers/constants/globals.d.js +2 -0
- package/lib/module/helpers/constants/globals.d.js.map +1 -0
- package/lib/module/helpers/constants/ios.js +103 -0
- package/lib/module/helpers/constants/ios.js.map +1 -0
- package/lib/module/helpers/native-files/ios/NotificationService-Info.plist +31 -0
- package/lib/module/helpers/native-files/ios/NotificationService.h +5 -0
- package/lib/module/helpers/native-files/ios/NotificationService.m +26 -0
- package/lib/module/helpers/native-files/ios/NotificationService.swift +19 -0
- package/lib/module/helpers/native-files/ios/PushNotification.swift +47 -0
- package/lib/module/helpers/utils/codeInjection.js +24 -0
- package/lib/module/helpers/utils/codeInjection.js.map +1 -0
- package/lib/module/helpers/utils/fileManagement.js +69 -0
- package/lib/module/helpers/utils/fileManagement.js.map +1 -0
- package/lib/module/helpers/utils/injectCIOPodfileCode.js +30 -0
- package/lib/module/helpers/utils/injectCIOPodfileCode.js.map +1 -0
- package/lib/module/index.js +16 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/ios/withAppDelegateModifications.js +78 -0
- package/lib/module/ios/withAppDelegateModifications.js.map +1 -0
- package/lib/module/ios/withAppDelegateXcodeProject.js +71 -0
- package/lib/module/ios/withAppDelegateXcodeProject.js.map +1 -0
- package/lib/module/ios/withCIOIos.js +17 -0
- package/lib/module/ios/withCIOIos.js.map +1 -0
- package/lib/module/ios/withNotificationsXcodeProject.js +150 -0
- package/lib/module/ios/withNotificationsXcodeProject.js.map +1 -0
- package/lib/module/ios/withXcodeProject.js +21 -0
- package/lib/module/ios/withXcodeProject.js.map +1 -0
- package/lib/module/types/cio-types.js +2 -0
- package/lib/module/types/cio-types.js.map +1 -0
- package/lib/module/version.js +2 -0
- package/lib/module/version.js.map +1 -0
- package/lib/typescript/analytics/injectAnalytics.d.ts +3 -0
- package/lib/typescript/android/withAppGoogleServices.d.ts +3 -0
- package/lib/typescript/android/withCIOAndroid.d.ts +3 -0
- package/lib/typescript/android/withGistMavenRepository.d.ts +3 -0
- package/lib/typescript/android/withGoogleServicesJSON.d.ts +3 -0
- package/lib/typescript/android/withProjectGoogleServices.d.ts +3 -0
- package/lib/typescript/helpers/constants/android.d.ts +7 -0
- package/lib/typescript/helpers/constants/ios.d.ts +31 -0
- package/lib/typescript/helpers/utils/codeInjection.d.ts +4 -0
- package/lib/typescript/helpers/utils/fileManagement.d.ts +12 -0
- package/lib/typescript/helpers/utils/injectCIOPodfileCode.d.ts +2 -0
- package/lib/typescript/index.d.ts +4 -0
- package/lib/typescript/ios/withAppDelegateModifications.d.ts +2 -0
- package/lib/typescript/ios/withAppDelegateXcodeProject.d.ts +3 -0
- package/lib/typescript/ios/withCIOIos.d.ts +3 -0
- package/lib/typescript/ios/withNotificationsXcodeProject.d.ts +3 -0
- package/lib/typescript/ios/withXcodeProject.d.ts +3 -0
- package/lib/typescript/types/cio-types.d.ts +25 -0
- package/lib/typescript/version.d.ts +1 -0
- package/package.json +88 -13
- package/src/analytics/injectAnalytics.ts +36 -0
- package/src/android/withAppGoogleServices.ts +26 -0
- package/src/android/withCIOAndroid.ts +19 -0
- package/src/android/withGistMavenRepository.ts +26 -0
- package/src/android/withGoogleServicesJSON.ts +36 -0
- package/src/android/withProjectGoogleServices.ts +24 -0
- package/src/helpers/constants/android.ts +14 -0
- package/src/helpers/constants/globals.d.ts +8 -0
- package/src/helpers/constants/ios.ts +116 -0
- package/src/helpers/native-files/ios/NotificationService-Info.plist +31 -0
- package/src/helpers/native-files/ios/NotificationService.h +5 -0
- package/src/helpers/native-files/ios/NotificationService.m +26 -0
- package/src/helpers/native-files/ios/NotificationService.swift +19 -0
- package/src/helpers/native-files/ios/PushNotification.swift +47 -0
- package/src/helpers/utils/codeInjection.ts +46 -0
- package/src/helpers/utils/fileManagement.ts +87 -0
- package/src/helpers/utils/injectCIOPodfileCode.ts +53 -0
- package/src/index.ts +26 -0
- package/src/ios/withAppDelegateModifications.ts +166 -0
- package/src/ios/withAppDelegateXcodeProject.ts +89 -0
- package/src/ios/withCIOIos.ts +25 -0
- package/src/ios/withNotificationsXcodeProject.ts +237 -0
- package/src/ios/withXcodeProject.ts +25 -0
- package/src/types/cio-types.ts +31 -0
- package/src/version.ts +1 -0
- package/build/helpers/.DS_Store +0 -0
- package/build/helpers/ios/.DS_Store +0 -0
- package/build/package.json +0 -36
- package/build/src/android/withAppGoogleServices.js +0 -12
- package/build/src/android/withCIOAndroid.js +0 -15
- package/build/src/android/withGistMavenRepository.js +0 -12
- package/build/src/android/withGoogleServicesJSON.js +0 -24
- package/build/src/android/withProjectGoogleServices.js +0 -12
- package/build/src/helpers/constants/android.js +0 -9
- package/build/src/helpers/constants/ios.js +0 -102
- package/build/src/helpers/utils/codeInjection.js +0 -30
- package/build/src/helpers/utils/fileManagement.js +0 -40
- package/build/src/helpers/utils/injectCIOPodfileCode.js +0 -37
- package/build/src/index.js +0 -11
- package/build/src/ios/withAppDelegateModifications.js +0 -77
- package/build/src/ios/withAppDelegateXcodeProject.js +0 -78
- package/build/src/ios/withCIOIos.js +0 -15
- package/build/src/ios/withNotificationsXcodeProject.js +0 -133
- package/build/src/ios/withXcodeProject.js +0 -22
- package/build/src/types/cio-types.js +0 -8
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import {
|
|
2
|
+
readFile,
|
|
3
|
+
writeFile,
|
|
4
|
+
appendFile,
|
|
5
|
+
existsSync,
|
|
6
|
+
copyFileSync,
|
|
7
|
+
mkdirSync,
|
|
8
|
+
writeFileSync,
|
|
9
|
+
readFileSync,
|
|
10
|
+
MakeDirectoryOptions,
|
|
11
|
+
} from 'fs';
|
|
12
|
+
|
|
13
|
+
export class FileManagement {
|
|
14
|
+
static async read(path: string): Promise<string> {
|
|
15
|
+
return new Promise<string>((resolve, reject) => {
|
|
16
|
+
readFile(path, 'utf8', (err, data) => {
|
|
17
|
+
if (err || !data) {
|
|
18
|
+
reject(err);
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
resolve(data);
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
static async write(path: string, contents: string): Promise<void> {
|
|
27
|
+
return new Promise<void>((resolve, reject) => {
|
|
28
|
+
writeFile(path, contents, 'utf8', (err) => {
|
|
29
|
+
if (err) {
|
|
30
|
+
reject(err);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
resolve();
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
static async append(path: string, contents: string): Promise<void> {
|
|
39
|
+
return new Promise<void>((resolve, reject) => {
|
|
40
|
+
appendFile(path, contents, 'utf8', (err) => {
|
|
41
|
+
if (err) {
|
|
42
|
+
reject(err);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
resolve();
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
static exists(path: string) {
|
|
51
|
+
return existsSync(path);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
static copyFile(src: string, dest: string) {
|
|
55
|
+
try {
|
|
56
|
+
copyFileSync(src, dest);
|
|
57
|
+
} catch (err) {
|
|
58
|
+
console.log(`Error copying file from ${src} to ${dest}: `, err);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
static mkdir(path: string, options: MakeDirectoryOptions) {
|
|
63
|
+
try {
|
|
64
|
+
mkdirSync(path, options);
|
|
65
|
+
} catch (err) {
|
|
66
|
+
console.log(`Error creating directory ${path}: `, err);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
static writeFile(path: string, data: string) {
|
|
71
|
+
try {
|
|
72
|
+
writeFileSync(path, data);
|
|
73
|
+
} catch (err) {
|
|
74
|
+
console.log(`Error writing to file ${path}: `, err);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
static readFile(path: string) {
|
|
79
|
+
try {
|
|
80
|
+
return readFileSync(path, 'utf-8');
|
|
81
|
+
} catch (err) {
|
|
82
|
+
console.log(`Error reading file ${path}: `, err);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return '';
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CIO_PODFILE_REGEX,
|
|
3
|
+
CIO_PODFILE_SNIPPET,
|
|
4
|
+
CIO_PODFILE_POST_INSTALL_REGEX,
|
|
5
|
+
CIO_PODFILE_TARGET_NAMES_SNIPPET,
|
|
6
|
+
CIO_PODFILE_POST_INSTALL_SNIPPET,
|
|
7
|
+
CIO_PODFILE_POST_INSTALL_FALLBACK_SNIPPET,
|
|
8
|
+
CIO_PODFILE_NOTIFICATION_SNIPPET,
|
|
9
|
+
CIO_PODFILE_NOTIFICATION_REGEX,
|
|
10
|
+
CIO_CIO_TARGET_REGEX,
|
|
11
|
+
} from '../constants/ios';
|
|
12
|
+
import { FileManagement } from './fileManagement';
|
|
13
|
+
|
|
14
|
+
export async function injectCIOPodfileCode(iosPath: string) {
|
|
15
|
+
const filename = `${iosPath}/Podfile`;
|
|
16
|
+
const podfile = await FileManagement.read(filename);
|
|
17
|
+
const matches = podfile.match(CIO_PODFILE_REGEX);
|
|
18
|
+
const targetMatch = podfile.match(CIO_CIO_TARGET_REGEX);
|
|
19
|
+
|
|
20
|
+
if (!targetMatch) {
|
|
21
|
+
const lines = podfile.split('\n');
|
|
22
|
+
const index = lines.findIndex((line) =>
|
|
23
|
+
CIO_PODFILE_POST_INSTALL_REGEX.test(line)
|
|
24
|
+
);
|
|
25
|
+
let content: string[] = lines;
|
|
26
|
+
if (index > -1) {
|
|
27
|
+
content = [
|
|
28
|
+
...lines.slice(0, index - 1),
|
|
29
|
+
!matches ? CIO_PODFILE_SNIPPET : '',
|
|
30
|
+
CIO_PODFILE_TARGET_NAMES_SNIPPET,
|
|
31
|
+
...lines.slice(index - 1, index + 1),
|
|
32
|
+
CIO_PODFILE_POST_INSTALL_SNIPPET,
|
|
33
|
+
...lines.slice(index + 1),
|
|
34
|
+
];
|
|
35
|
+
} else {
|
|
36
|
+
content.push(CIO_PODFILE_POST_INSTALL_FALLBACK_SNIPPET);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
FileManagement.write(filename, content.join('\n'));
|
|
40
|
+
} else {
|
|
41
|
+
console.log('Customerio Podfile snippets already exists. Skipping...');
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export async function injectCIONotificationPodfileCode(iosPath: string) {
|
|
46
|
+
const filename = `${iosPath}/Podfile`;
|
|
47
|
+
const podfile = await FileManagement.read(filename);
|
|
48
|
+
const matches = podfile.match(CIO_PODFILE_NOTIFICATION_REGEX);
|
|
49
|
+
|
|
50
|
+
if (!matches) {
|
|
51
|
+
FileManagement.append(filename, CIO_PODFILE_NOTIFICATION_SNIPPET);
|
|
52
|
+
}
|
|
53
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { ExpoConfig } from '@expo/config-types';
|
|
2
|
+
|
|
3
|
+
import { withAnalytics } from './analytics/injectAnalytics';
|
|
4
|
+
import { withCIOAndroid } from './android/withCIOAndroid';
|
|
5
|
+
import { withCIOIos } from './ios/withCIOIos';
|
|
6
|
+
import type { CustomerIOPluginOptions } from './types/cio-types';
|
|
7
|
+
|
|
8
|
+
// Entry point for config plugin
|
|
9
|
+
function withCustomerIOPlugin(
|
|
10
|
+
config: ExpoConfig,
|
|
11
|
+
props: CustomerIOPluginOptions
|
|
12
|
+
) {
|
|
13
|
+
if (props.ios) {
|
|
14
|
+
config = withCIOIos(config, props.ios);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (props.android) {
|
|
18
|
+
config = withCIOAndroid(config, props.android);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
config = withAnalytics(config, props);
|
|
22
|
+
|
|
23
|
+
return config;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export default withCustomerIOPlugin;
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { ConfigPlugin, withAppDelegate } from '@expo/config-plugins';
|
|
2
|
+
import { getAppDelegateHeaderFilePath } from '@expo/config-plugins/build/ios/Paths';
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
CIO_APPDELEGATEDECLARATION_REGEX,
|
|
6
|
+
CIO_APPDELEGATEHEADER_REGEX,
|
|
7
|
+
CIO_APPDELEGATEHEADER_SNIPPET,
|
|
8
|
+
CIO_CONFIGURECIOSDKPUSHNOTIFICATION_SNIPPET,
|
|
9
|
+
CIO_DIDFAILTOREGISTERFORREMOTENOTIFICATIONSWITHERRORFULL_REGEX,
|
|
10
|
+
CIO_DIDFAILTOREGISTERFORREMOTENOTIFICATIONSWITHERROR_REGEX,
|
|
11
|
+
CIO_DIDFAILTOREGISTERFORREMOTENOTIFICATIONSWITHERROR_SNIPPET,
|
|
12
|
+
CIO_DIDFINISHLAUNCHINGMETHOD_REGEX,
|
|
13
|
+
CIO_DIDRECEIVENOTIFICATIONRESPONSEHANDLER_SNIPPET,
|
|
14
|
+
CIO_DIDREGISTERFORREMOTENOTIFICATIONSWITHDEVICETOKEN_REGEX,
|
|
15
|
+
CIO_DIDREGISTERFORREMOTENOTIFICATIONSWITHDEVICETOKEN_SNIPPET,
|
|
16
|
+
CIO_PUSHNOTIFICATIONHANDLERDECLARATION_SNIPPET,
|
|
17
|
+
CIO_WILLPRESENTNOTIFICATIONHANDLER_SNIPPET,
|
|
18
|
+
} from '../helpers/constants/ios';
|
|
19
|
+
import {
|
|
20
|
+
injectCodeByLineNumber,
|
|
21
|
+
injectCodeByMultiLineRegex,
|
|
22
|
+
injectCodeByMultiLineRegexAndReplaceLine,
|
|
23
|
+
} from '../helpers/utils/codeInjection';
|
|
24
|
+
import { FileManagement } from '../helpers/utils/fileManagement';
|
|
25
|
+
|
|
26
|
+
const pushCodeSnippets = [
|
|
27
|
+
CIO_DIDRECEIVENOTIFICATIONRESPONSEHANDLER_SNIPPET,
|
|
28
|
+
CIO_WILLPRESENTNOTIFICATIONHANDLER_SNIPPET,
|
|
29
|
+
];
|
|
30
|
+
|
|
31
|
+
const additionalMethodsForPushNotifications = `${pushCodeSnippets.join(
|
|
32
|
+
'\n'
|
|
33
|
+
)}\n`; // Join newlines and ensure a newline at the end.
|
|
34
|
+
|
|
35
|
+
const addImport = (stringContents: string, appName: string) => {
|
|
36
|
+
const importRegex = /^(#import .*)\n/gm;
|
|
37
|
+
const addedImport = getImportSnippet(appName);
|
|
38
|
+
|
|
39
|
+
const match = stringContents.match(importRegex);
|
|
40
|
+
let endOfMatchIndex: number;
|
|
41
|
+
if (!match || match.index === undefined) {
|
|
42
|
+
// No imports found, just add to start of file:
|
|
43
|
+
endOfMatchIndex = 0;
|
|
44
|
+
} else {
|
|
45
|
+
// Add after first import:
|
|
46
|
+
endOfMatchIndex = match.index + match[0].length;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
stringContents = injectCodeByLineNumber(
|
|
50
|
+
stringContents,
|
|
51
|
+
endOfMatchIndex,
|
|
52
|
+
addedImport
|
|
53
|
+
).join('\n');
|
|
54
|
+
|
|
55
|
+
return stringContents;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const addNotificationHandlerDeclaration = (stringContents: string) => {
|
|
59
|
+
stringContents = injectCodeByMultiLineRegex(
|
|
60
|
+
stringContents,
|
|
61
|
+
CIO_APPDELEGATEDECLARATION_REGEX,
|
|
62
|
+
CIO_PUSHNOTIFICATIONHANDLERDECLARATION_SNIPPET
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
return stringContents;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const addNotificationConfiguration = (stringContents: string) => {
|
|
69
|
+
stringContents = injectCodeByMultiLineRegex(
|
|
70
|
+
stringContents,
|
|
71
|
+
CIO_DIDFINISHLAUNCHINGMETHOD_REGEX,
|
|
72
|
+
CIO_CONFIGURECIOSDKPUSHNOTIFICATION_SNIPPET
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
return stringContents;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const addDidFailToRegisterForRemoteNotificationsWithError = (
|
|
79
|
+
stringContents: string
|
|
80
|
+
) => {
|
|
81
|
+
stringContents = injectCodeByMultiLineRegexAndReplaceLine(
|
|
82
|
+
stringContents,
|
|
83
|
+
CIO_DIDFAILTOREGISTERFORREMOTENOTIFICATIONSWITHERROR_REGEX,
|
|
84
|
+
CIO_DIDFAILTOREGISTERFORREMOTENOTIFICATIONSWITHERROR_SNIPPET
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
return stringContents;
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const AddDidRegisterForRemoteNotificationsWithDeviceToken = (
|
|
91
|
+
stringContents: string
|
|
92
|
+
) => {
|
|
93
|
+
stringContents = injectCodeByMultiLineRegexAndReplaceLine(
|
|
94
|
+
stringContents,
|
|
95
|
+
CIO_DIDREGISTERFORREMOTENOTIFICATIONSWITHDEVICETOKEN_REGEX,
|
|
96
|
+
CIO_DIDREGISTERFORREMOTENOTIFICATIONSWITHDEVICETOKEN_SNIPPET
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
return stringContents;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
const addAdditionalMethodsForPushNotifications = (stringContents: string) => {
|
|
103
|
+
stringContents = injectCodeByMultiLineRegex(
|
|
104
|
+
stringContents,
|
|
105
|
+
CIO_DIDFAILTOREGISTERFORREMOTENOTIFICATIONSWITHERRORFULL_REGEX,
|
|
106
|
+
additionalMethodsForPushNotifications
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
return stringContents;
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
const addAppdelegateHeaderModification = (stringContents: string) => {
|
|
113
|
+
stringContents = injectCodeByMultiLineRegexAndReplaceLine(
|
|
114
|
+
stringContents,
|
|
115
|
+
CIO_APPDELEGATEHEADER_REGEX,
|
|
116
|
+
CIO_APPDELEGATEHEADER_SNIPPET
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
return stringContents;
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
export const withAppDelegateModifications: ConfigPlugin<any> = (
|
|
123
|
+
configOuter
|
|
124
|
+
) => {
|
|
125
|
+
return withAppDelegate(configOuter, async (config) => {
|
|
126
|
+
let stringContents = config.modResults.contents;
|
|
127
|
+
const regex = new RegExp(
|
|
128
|
+
`#import <${config.modRequest.projectName}-Swift.h>`
|
|
129
|
+
);
|
|
130
|
+
const match = stringContents.match(regex);
|
|
131
|
+
|
|
132
|
+
if (!match) {
|
|
133
|
+
const headerPath = getAppDelegateHeaderFilePath(
|
|
134
|
+
config.modRequest.projectRoot
|
|
135
|
+
);
|
|
136
|
+
let headerContent = await FileManagement.read(headerPath);
|
|
137
|
+
headerContent = addAppdelegateHeaderModification(headerContent);
|
|
138
|
+
FileManagement.write(headerPath, headerContent);
|
|
139
|
+
|
|
140
|
+
stringContents = addImport(
|
|
141
|
+
stringContents,
|
|
142
|
+
config.modRequest.projectName as string
|
|
143
|
+
);
|
|
144
|
+
stringContents = addNotificationHandlerDeclaration(stringContents);
|
|
145
|
+
stringContents = addNotificationConfiguration(stringContents);
|
|
146
|
+
stringContents = addAdditionalMethodsForPushNotifications(stringContents);
|
|
147
|
+
stringContents =
|
|
148
|
+
addDidFailToRegisterForRemoteNotificationsWithError(stringContents);
|
|
149
|
+
stringContents =
|
|
150
|
+
AddDidRegisterForRemoteNotificationsWithDeviceToken(stringContents);
|
|
151
|
+
|
|
152
|
+
config.modResults.contents = stringContents;
|
|
153
|
+
} else {
|
|
154
|
+
console.log('Customerio AppDelegate changes already exist. Skipping...');
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return config;
|
|
158
|
+
});
|
|
159
|
+
};
|
|
160
|
+
function getImportSnippet(appName: string) {
|
|
161
|
+
return `
|
|
162
|
+
// Add swift bridge imports
|
|
163
|
+
#import <ExpoModulesCore-Swift.h>
|
|
164
|
+
#import <${appName}-Swift.h>
|
|
165
|
+
`;
|
|
166
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { ConfigPlugin, withXcodeProject } from '@expo/config-plugins';
|
|
2
|
+
import xcode from 'xcode';
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
DEFAULT_BUNDLE_VERSION,
|
|
6
|
+
LOCAL_PATH_TO_CIO_NSE_FILES,
|
|
7
|
+
} from '../helpers/constants/ios';
|
|
8
|
+
import type { CustomerIOPluginOptionsIOS } from '../types/cio-types';
|
|
9
|
+
import { FileManagement } from './../helpers/utils/fileManagement';
|
|
10
|
+
|
|
11
|
+
const addNotificationSwiftFile = async (
|
|
12
|
+
options: CustomerIOPluginOptionsIOS
|
|
13
|
+
) => {
|
|
14
|
+
const { iosPath, appName } = options;
|
|
15
|
+
const projPath = `${iosPath}/${appName}.xcodeproj/project.pbxproj`;
|
|
16
|
+
const xcodeProject = xcode.project(projPath);
|
|
17
|
+
|
|
18
|
+
xcodeProject.parse(async function (err: Error) {
|
|
19
|
+
const file = 'PushNotification.swift';
|
|
20
|
+
const getTargetFile = (filename: string) =>
|
|
21
|
+
`${iosPath}/${appName}/${filename}`;
|
|
22
|
+
if (err) {
|
|
23
|
+
throw new Error(`Error parsing iOS project: ${JSON.stringify(err)}`);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (!FileManagement.exists(getTargetFile(file))) {
|
|
27
|
+
FileManagement.mkdir(`${iosPath}/${appName}`, {
|
|
28
|
+
recursive: true,
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const targetFile = getTargetFile(file);
|
|
32
|
+
FileManagement.copyFile(
|
|
33
|
+
`${LOCAL_PATH_TO_CIO_NSE_FILES}/${file}`,
|
|
34
|
+
targetFile
|
|
35
|
+
);
|
|
36
|
+
} else {
|
|
37
|
+
console.log(`${getTargetFile(file)} already exists. Skipping...`);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export const withCioAppdelegateXcodeProject: ConfigPlugin<
|
|
43
|
+
CustomerIOPluginOptionsIOS
|
|
44
|
+
> = (configOuter, props) => {
|
|
45
|
+
return withXcodeProject(configOuter, async (config) => {
|
|
46
|
+
const { modRequest, ios, version: bundleShortVersion } = config;
|
|
47
|
+
const { appleTeamId, iosDeploymentTarget } = props;
|
|
48
|
+
|
|
49
|
+
if (ios === undefined)
|
|
50
|
+
throw new Error(
|
|
51
|
+
'Adding NotificationServiceExtension failed: ios config missing from app.config.js.'
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
const { projectName, platformProjectRoot } = modRequest;
|
|
55
|
+
const { bundleIdentifier, buildNumber } = ios;
|
|
56
|
+
|
|
57
|
+
if (bundleShortVersion === undefined) {
|
|
58
|
+
throw new Error(
|
|
59
|
+
'Adding NotificationServiceExtension failed: version missing from app.config.js'
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (bundleIdentifier === undefined) {
|
|
64
|
+
throw new Error(
|
|
65
|
+
'Adding NotificationServiceExtension failed: ios.bundleIdentifier missing from app.config.js'
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (projectName === undefined) {
|
|
70
|
+
throw new Error(
|
|
71
|
+
'Adding NotificationServiceExtension failed: name missing from app.config.js'
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const options = {
|
|
76
|
+
appleTeamId,
|
|
77
|
+
bundleIdentifier,
|
|
78
|
+
bundleShortVersion,
|
|
79
|
+
bundleVersion: buildNumber || DEFAULT_BUNDLE_VERSION,
|
|
80
|
+
iosPath: platformProjectRoot,
|
|
81
|
+
appName: projectName,
|
|
82
|
+
iosDeploymentTarget,
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
await addNotificationSwiftFile(options);
|
|
86
|
+
|
|
87
|
+
return config;
|
|
88
|
+
});
|
|
89
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ExpoConfig } from '@expo/config-types';
|
|
2
|
+
|
|
3
|
+
import type { CustomerIOPluginOptionsIOS } from '../types/cio-types';
|
|
4
|
+
import { withAppDelegateModifications } from './withAppDelegateModifications';
|
|
5
|
+
import { withCioAppdelegateXcodeProject } from './withAppDelegateXcodeProject';
|
|
6
|
+
import { withCioNotificationsXcodeProject } from './withNotificationsXcodeProject';
|
|
7
|
+
import { withCioXcodeProject } from './withXcodeProject';
|
|
8
|
+
|
|
9
|
+
export function withCIOIos(
|
|
10
|
+
config: ExpoConfig,
|
|
11
|
+
props: CustomerIOPluginOptionsIOS
|
|
12
|
+
) {
|
|
13
|
+
if (props.pushNotification?.useRichPush) {
|
|
14
|
+
config = withCioNotificationsXcodeProject(config, props);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (props.pushNotification) {
|
|
18
|
+
config = withAppDelegateModifications(config, props);
|
|
19
|
+
config = withCioAppdelegateXcodeProject(config, props);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
config = withCioXcodeProject(config, props);
|
|
23
|
+
|
|
24
|
+
return config;
|
|
25
|
+
}
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import { ConfigPlugin, withXcodeProject } from '@expo/config-plugins';
|
|
2
|
+
import xcode from 'xcode';
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
CIO_NOTIFICATION_TARGET_NAME,
|
|
6
|
+
DEFAULT_BUNDLE_VERSION,
|
|
7
|
+
LOCAL_PATH_TO_CIO_NSE_FILES,
|
|
8
|
+
} from '../helpers/constants/ios';
|
|
9
|
+
import { injectCodeByMultiLineRegex } from '../helpers/utils/codeInjection';
|
|
10
|
+
import { injectCIONotificationPodfileCode } from '../helpers/utils/injectCIOPodfileCode';
|
|
11
|
+
import type { CustomerIOPluginOptionsIOS } from '../types/cio-types';
|
|
12
|
+
import { FileManagement } from './../helpers/utils/fileManagement';
|
|
13
|
+
|
|
14
|
+
const PLIST_FILENAME = `${CIO_NOTIFICATION_TARGET_NAME}-Info.plist`;
|
|
15
|
+
|
|
16
|
+
const TARGETED_DEVICE_FAMILY = `"1,2"`;
|
|
17
|
+
|
|
18
|
+
const addNotificationServiceExtension = async (
|
|
19
|
+
options: CustomerIOPluginOptionsIOS
|
|
20
|
+
) => {
|
|
21
|
+
const {
|
|
22
|
+
appleTeamId,
|
|
23
|
+
bundleIdentifier,
|
|
24
|
+
bundleShortVersion,
|
|
25
|
+
bundleVersion,
|
|
26
|
+
iosPath,
|
|
27
|
+
appName,
|
|
28
|
+
iosDeploymentTarget,
|
|
29
|
+
} = options;
|
|
30
|
+
|
|
31
|
+
const projPath = `${iosPath}/${appName}.xcodeproj/project.pbxproj`;
|
|
32
|
+
|
|
33
|
+
const xcodeProject = xcode.project(projPath);
|
|
34
|
+
|
|
35
|
+
xcodeProject.parse(async function (err: Error) {
|
|
36
|
+
if (err) {
|
|
37
|
+
throw new Error(`Error parsing iOS project: ${JSON.stringify(err)}`);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
await injectCIONotificationPodfileCode(iosPath);
|
|
41
|
+
|
|
42
|
+
FileManagement.mkdir(`${iosPath}/${CIO_NOTIFICATION_TARGET_NAME}`, {
|
|
43
|
+
recursive: true,
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
const files = [
|
|
47
|
+
PLIST_FILENAME,
|
|
48
|
+
'NotificationService.h',
|
|
49
|
+
'NotificationService.swift',
|
|
50
|
+
'NotificationService.m',
|
|
51
|
+
];
|
|
52
|
+
|
|
53
|
+
const getTargetFile = (filename: string) =>
|
|
54
|
+
`${iosPath}/${CIO_NOTIFICATION_TARGET_NAME}/${filename}`;
|
|
55
|
+
|
|
56
|
+
files.forEach((filename) => {
|
|
57
|
+
const targetFile = getTargetFile(filename);
|
|
58
|
+
FileManagement.copyFile(
|
|
59
|
+
`${LOCAL_PATH_TO_CIO_NSE_FILES}/${filename}`,
|
|
60
|
+
targetFile
|
|
61
|
+
);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
/* MODIFY COPIED EXTENSION FILES */
|
|
65
|
+
const infoPlistTargetFile = getTargetFile(PLIST_FILENAME);
|
|
66
|
+
updateNseInfoPlist({
|
|
67
|
+
bundleVersion,
|
|
68
|
+
bundleShortVersion,
|
|
69
|
+
infoPlistTargetFile,
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// Create new PBXGroup for the extension
|
|
73
|
+
const extGroup = xcodeProject.addPbxGroup(
|
|
74
|
+
files,
|
|
75
|
+
CIO_NOTIFICATION_TARGET_NAME,
|
|
76
|
+
CIO_NOTIFICATION_TARGET_NAME
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
// Add the new PBXGroup to the top level group. This makes the
|
|
80
|
+
// files / folder appear in the file explorer in Xcode.
|
|
81
|
+
const groups = xcodeProject.hash.project.objects['PBXGroup'];
|
|
82
|
+
Object.keys(groups).forEach((key) => {
|
|
83
|
+
if (groups[key].name === undefined) {
|
|
84
|
+
xcodeProject.addToPbxGroup(extGroup.uuid, key);
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// WORK AROUND for codeProject.addTarget BUG
|
|
89
|
+
// Xcode projects don't contain these if there is only one target
|
|
90
|
+
// An upstream fix should be made to the code referenced in this link:
|
|
91
|
+
// - https://github.com/apache/cordova-node-xcode/blob/8b98cabc5978359db88dc9ff2d4c015cba40f150/lib/pbxProject.js#L860
|
|
92
|
+
const projObjects = xcodeProject.hash.project.objects;
|
|
93
|
+
projObjects['PBXTargetDependency'] =
|
|
94
|
+
projObjects['PBXTargetDependency'] || {};
|
|
95
|
+
projObjects['PBXContainerItemProxy'] =
|
|
96
|
+
projObjects['PBXTargetDependency'] || {};
|
|
97
|
+
|
|
98
|
+
if (xcodeProject.pbxTargetByName(CIO_NOTIFICATION_TARGET_NAME)) {
|
|
99
|
+
console.warn(
|
|
100
|
+
`${CIO_NOTIFICATION_TARGET_NAME} already exists in project. Skipping...`
|
|
101
|
+
);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Add the NSE target
|
|
106
|
+
// This also adds PBXTargetDependency and PBXContainerItemProxy
|
|
107
|
+
const nseTarget = xcodeProject.addTarget(
|
|
108
|
+
CIO_NOTIFICATION_TARGET_NAME,
|
|
109
|
+
'app_extension',
|
|
110
|
+
CIO_NOTIFICATION_TARGET_NAME,
|
|
111
|
+
`${bundleIdentifier}.richpush`
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
// Add build phases to the new target
|
|
115
|
+
xcodeProject.addBuildPhase(
|
|
116
|
+
['NotificationService.m', 'NotificationService.swift'],
|
|
117
|
+
'PBXSourcesBuildPhase',
|
|
118
|
+
'Sources',
|
|
119
|
+
nseTarget.uuid
|
|
120
|
+
);
|
|
121
|
+
xcodeProject.addBuildPhase(
|
|
122
|
+
[],
|
|
123
|
+
'PBXResourcesBuildPhase',
|
|
124
|
+
'Resources',
|
|
125
|
+
nseTarget.uuid
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
xcodeProject.addBuildPhase(
|
|
129
|
+
[],
|
|
130
|
+
'PBXFrameworksBuildPhase',
|
|
131
|
+
'Frameworks',
|
|
132
|
+
nseTarget.uuid
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
// Edit the Deployment info of the target
|
|
136
|
+
const configurations = xcodeProject.pbxXCBuildConfigurationSection();
|
|
137
|
+
for (const key in configurations) {
|
|
138
|
+
if (
|
|
139
|
+
typeof configurations[key].buildSettings !== 'undefined' &&
|
|
140
|
+
configurations[key].buildSettings.PRODUCT_NAME ===
|
|
141
|
+
`"${CIO_NOTIFICATION_TARGET_NAME}"`
|
|
142
|
+
) {
|
|
143
|
+
const buildSettingsObj = configurations[key].buildSettings;
|
|
144
|
+
buildSettingsObj.DEVELOPMENT_TEAM = appleTeamId;
|
|
145
|
+
buildSettingsObj.IPHONEOS_DEPLOYMENT_TARGET =
|
|
146
|
+
iosDeploymentTarget || '13.0';
|
|
147
|
+
buildSettingsObj.TARGETED_DEVICE_FAMILY = TARGETED_DEVICE_FAMILY;
|
|
148
|
+
buildSettingsObj.CODE_SIGN_STYLE = 'Automatic';
|
|
149
|
+
buildSettingsObj.SWIFT_VERSION = 4.2;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Add development team to the target & the main
|
|
154
|
+
xcodeProject.addTargetAttribute('DevelopmentTeam', appleTeamId, nseTarget);
|
|
155
|
+
xcodeProject.addTargetAttribute('DevelopmentTeam', appleTeamId);
|
|
156
|
+
|
|
157
|
+
FileManagement.writeFile(projPath, xcodeProject.writeSync());
|
|
158
|
+
});
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
export const withCioNotificationsXcodeProject: ConfigPlugin<
|
|
162
|
+
CustomerIOPluginOptionsIOS
|
|
163
|
+
> = (configOuter, props) => {
|
|
164
|
+
return withXcodeProject(configOuter, async (config) => {
|
|
165
|
+
const { modRequest, ios, version: bundleShortVersion } = config;
|
|
166
|
+
const { appleTeamId, iosDeploymentTarget } = props;
|
|
167
|
+
|
|
168
|
+
if (ios === undefined)
|
|
169
|
+
throw new Error(
|
|
170
|
+
'Adding NotificationServiceExtension failed: ios config missing from app.config.js or app.json.'
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
const { projectName, platformProjectRoot } = modRequest;
|
|
174
|
+
const { bundleIdentifier, buildNumber } = ios;
|
|
175
|
+
|
|
176
|
+
if (bundleShortVersion === undefined) {
|
|
177
|
+
throw new Error(
|
|
178
|
+
'Adding NotificationServiceExtension failed: version missing from app.config.js or app.json'
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (bundleIdentifier === undefined) {
|
|
183
|
+
throw new Error(
|
|
184
|
+
'Adding NotificationServiceExtension failed: ios.bundleIdentifier missing from app.config.js or app.json'
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (projectName === undefined) {
|
|
189
|
+
throw new Error(
|
|
190
|
+
'Adding NotificationServiceExtension failed: name missing from app.config.js or app.json'
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const options = {
|
|
195
|
+
appleTeamId,
|
|
196
|
+
bundleIdentifier,
|
|
197
|
+
bundleShortVersion,
|
|
198
|
+
bundleVersion: buildNumber || DEFAULT_BUNDLE_VERSION,
|
|
199
|
+
iosPath: platformProjectRoot,
|
|
200
|
+
appName: projectName,
|
|
201
|
+
iosDeploymentTarget,
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
await addNotificationServiceExtension(options);
|
|
205
|
+
|
|
206
|
+
return config;
|
|
207
|
+
});
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
const updateNseInfoPlist = (payload: {
|
|
211
|
+
bundleVersion?: string;
|
|
212
|
+
bundleShortVersion?: string;
|
|
213
|
+
infoPlistTargetFile: string;
|
|
214
|
+
}) => {
|
|
215
|
+
const BUNDLE_SHORT_VERSION_RE = /\{\{BUNDLE_SHORT_VERSION\}\}/;
|
|
216
|
+
const BUNDLE_VERSION_RE = /\{\{BUNDLE_VERSION\}\}/;
|
|
217
|
+
|
|
218
|
+
let plistFileString = FileManagement.readFile(payload.infoPlistTargetFile);
|
|
219
|
+
|
|
220
|
+
if (payload.bundleVersion) {
|
|
221
|
+
plistFileString = injectCodeByMultiLineRegex(
|
|
222
|
+
plistFileString,
|
|
223
|
+
BUNDLE_VERSION_RE,
|
|
224
|
+
payload.bundleVersion
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
if (payload.bundleShortVersion) {
|
|
229
|
+
plistFileString = injectCodeByMultiLineRegex(
|
|
230
|
+
plistFileString,
|
|
231
|
+
BUNDLE_SHORT_VERSION_RE,
|
|
232
|
+
payload.bundleShortVersion
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
FileManagement.writeFile(payload.infoPlistTargetFile, plistFileString);
|
|
237
|
+
};
|