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
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { NativeSDKConfig } from '../../types/cio-types';
|
|
2
|
+
import { type Platform } from '../constants/common';
|
|
3
|
+
/**
|
|
4
|
+
* Shared utility function to perform common SDK config replacements
|
|
5
|
+
* for both iOS and Android template files
|
|
6
|
+
*/
|
|
7
|
+
export declare function patchNativeSDKInitializer(rawContent: string, platform: Platform, sdkConfig: NativeSDKConfig): string;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { CustomerIOPluginOptionsIOS } from '../types/cio-types';
|
|
2
1
|
import type { ExpoConfig } from '@expo/config-types';
|
|
2
|
+
import type { CustomerIOPluginOptionsIOS } from '../types/cio-types';
|
|
3
3
|
/**
|
|
4
|
-
* Returns
|
|
4
|
+
* Returns true if FCM is configured to be used as push provider
|
|
5
5
|
* @param iosOptions The plugin iOS configuration options
|
|
6
6
|
* @returns true if FCM is configured to be used as push provider
|
|
7
7
|
*/
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { ExpoConfig } from '@expo/config-types';
|
|
2
|
-
import type { CustomerIOPluginOptionsIOS } from '../types/cio-types';
|
|
3
|
-
export declare function withCIOIos(config: ExpoConfig, props: CustomerIOPluginOptionsIOS): ExpoConfig;
|
|
2
|
+
import type { CustomerIOPluginOptionsIOS, NativeSDKConfig } from '../types/cio-types';
|
|
3
|
+
export declare function withCIOIos(config: ExpoConfig, sdkConfig: NativeSDKConfig | undefined, props: CustomerIOPluginOptionsIOS): ExpoConfig;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { CustomerIOPluginOptionsIOS } from '../types/cio-types';
|
|
3
|
-
export declare const withCIOIosSwift:
|
|
1
|
+
import type { ExpoConfig } from '@expo/config-types';
|
|
2
|
+
import type { CustomerIOPluginOptionsIOS, NativeSDKConfig } from '../types/cio-types';
|
|
3
|
+
export declare const withCIOIosSwift: (configOuter: ExpoConfig, sdkConfig: NativeSDKConfig | undefined, props: CustomerIOPluginOptionsIOS) => ExpoConfig;
|
|
@@ -1,7 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Properties set by the user in their app config file (e.g: app.json or app.plugin.js)
|
|
3
|
+
* @public
|
|
4
|
+
*/
|
|
1
5
|
export type CustomerIOPluginProperties = {
|
|
2
6
|
devTeam: string;
|
|
3
7
|
iosDeploymentTarget: string;
|
|
4
8
|
};
|
|
9
|
+
/**
|
|
10
|
+
* Plugin options for iOS platform configuration
|
|
11
|
+
* @public
|
|
12
|
+
*/
|
|
5
13
|
export type CustomerIOPluginOptionsIOS = {
|
|
6
14
|
iosPath: string;
|
|
7
15
|
devTeam?: string;
|
|
@@ -38,6 +46,10 @@ export type CustomerIOPluginOptionsIOS = {
|
|
|
38
46
|
*/
|
|
39
47
|
disableNotificationRegistration?: boolean;
|
|
40
48
|
};
|
|
49
|
+
/**
|
|
50
|
+
* Plugin options for Android platform configuration
|
|
51
|
+
* @public
|
|
52
|
+
*/
|
|
41
53
|
export type CustomerIOPluginOptionsAndroid = {
|
|
42
54
|
androidPath: string;
|
|
43
55
|
googleServicesFile?: string;
|
|
@@ -50,10 +62,41 @@ export type CustomerIOPluginOptionsAndroid = {
|
|
|
50
62
|
};
|
|
51
63
|
};
|
|
52
64
|
};
|
|
65
|
+
/**
|
|
66
|
+
* SDK configuration options for auto initialization
|
|
67
|
+
* @public
|
|
68
|
+
*/
|
|
69
|
+
export type NativeSDKConfig = {
|
|
70
|
+
cdpApiKey: string;
|
|
71
|
+
region?: 'US' | 'EU';
|
|
72
|
+
autoTrackDeviceAttributes?: boolean;
|
|
73
|
+
trackApplicationLifecycleEvents?: boolean;
|
|
74
|
+
screenViewUse?: 'all' | 'inapp';
|
|
75
|
+
logLevel?: 'none' | 'error' | 'info' | 'debug';
|
|
76
|
+
siteId?: string;
|
|
77
|
+
migrationSiteId?: string;
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* Combined plugin options for both iOS and Android platforms
|
|
81
|
+
* @public
|
|
82
|
+
*/
|
|
53
83
|
export type CustomerIOPluginOptions = {
|
|
84
|
+
config?: NativeSDKConfig;
|
|
54
85
|
android: CustomerIOPluginOptionsAndroid;
|
|
55
86
|
ios: CustomerIOPluginOptionsIOS;
|
|
56
87
|
};
|
|
88
|
+
/**
|
|
89
|
+
* Rich push configuration used to initialize Notification Service Extension (NSE) on the native side
|
|
90
|
+
* @public
|
|
91
|
+
*/
|
|
92
|
+
export type RichPushConfig = {
|
|
93
|
+
cdpApiKey: string;
|
|
94
|
+
region?: string;
|
|
95
|
+
};
|
|
96
|
+
/**
|
|
97
|
+
* Push notification configuration options
|
|
98
|
+
* @public
|
|
99
|
+
*/
|
|
57
100
|
export type CustomerIOPluginPushNotificationOptions = {
|
|
58
101
|
provider?: 'apn' | 'fcm';
|
|
59
102
|
googleServicesFile?: string;
|
|
@@ -64,11 +107,8 @@ export type CustomerIOPluginPushNotificationOptions = {
|
|
|
64
107
|
disableNotificationRegistration?: boolean;
|
|
65
108
|
handleDeeplinkInKilledState?: boolean;
|
|
66
109
|
/**
|
|
67
|
-
*
|
|
68
|
-
*
|
|
110
|
+
* Rich push config should match the values used to initialize SDK in the app.
|
|
111
|
+
* Optional if `config` is provided at the top level.
|
|
69
112
|
*/
|
|
70
|
-
env
|
|
71
|
-
cdpApiKey: string;
|
|
72
|
-
region: string;
|
|
73
|
-
};
|
|
113
|
+
env?: RichPushConfig;
|
|
74
114
|
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ExportedConfigWithProps } from '@expo/config-plugins';
|
|
2
|
+
import type { ApplicationProjectFile } from '@expo/config-plugins/build/android/Paths';
|
|
3
|
+
export declare const addImportToFile: (content: string, importStatement: string) => string;
|
|
4
|
+
export declare const addCodeToMethod: (content: string, methodRegex: RegExp, codeToAdd: string) => string;
|
|
5
|
+
export declare const copyTemplateFile: (expoConfig: ExportedConfigWithProps<ApplicationProjectFile>, filename: string, classPackage: string, patchContent: (content: string) => string) => void;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { CustomerIOPluginOptionsIOS, NativeSDKConfig, RichPushConfig } from '../types/cio-types';
|
|
2
|
+
/**
|
|
3
|
+
* Merges config values with env values for backward compatibility.
|
|
4
|
+
* If env is provided, it takes precedence. If nativeConfig is provided but env is not,
|
|
5
|
+
* nativeConfig values are used. This prioritizes existing env configuration for backward compatibility.
|
|
6
|
+
*/
|
|
7
|
+
declare function mergeConfigWithEnvValues(props: CustomerIOPluginOptionsIOS, nativeConfig?: NativeSDKConfig): RichPushConfig | undefined;
|
|
8
|
+
export { mergeConfigWithEnvValues };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { XcodeProject } from "@expo/config-plugins";
|
|
2
|
+
/**
|
|
3
|
+
* Gets an existing CustomerIO group or creates a new one in the Xcode project
|
|
4
|
+
* @param xcodeProject The Xcode project instance
|
|
5
|
+
* @param projectName The iOS project name
|
|
6
|
+
* @returns The CustomerIO group reference
|
|
7
|
+
*/
|
|
8
|
+
export declare function getOrCreateCustomerIOGroup(xcodeProject: XcodeProject, projectName: string): XcodeProject['pbxCreateGroup'];
|
|
9
|
+
/**
|
|
10
|
+
* Copies template file to iOS project, applies transformations, and registers with Xcode
|
|
11
|
+
* @param params.xcodeProject Xcode project instance
|
|
12
|
+
* @param params.iosProjectRoot iOS project root path
|
|
13
|
+
* @param params.projectName iOS project name
|
|
14
|
+
* @param params.sourceFilePath Source template file path
|
|
15
|
+
* @param params.targetFileName Target file name
|
|
16
|
+
* @param params.transform Content transformation function
|
|
17
|
+
* @param params.customerIOGroup CustomerIO group (auto-created if not provided)
|
|
18
|
+
* @returns Destination file path
|
|
19
|
+
*/
|
|
20
|
+
export declare function copyFileToXcode({ xcodeProject, iosProjectRoot, projectName, sourceFilePath, targetFileName, transform, customerIOGroup, }: {
|
|
21
|
+
xcodeProject: XcodeProject;
|
|
22
|
+
iosProjectRoot: string;
|
|
23
|
+
projectName: string;
|
|
24
|
+
sourceFilePath: string;
|
|
25
|
+
targetFileName: string;
|
|
26
|
+
transform: (content: string) => string;
|
|
27
|
+
customerIOGroup?: XcodeProject['pbxCreateGroup'];
|
|
28
|
+
}): string;
|
|
@@ -4,44 +4,93 @@ import type { ManifestApplication } from '@expo/config-plugins/build/android/Man
|
|
|
4
4
|
|
|
5
5
|
import type { CustomerIOPluginOptionsAndroid } from '../types/cio-types';
|
|
6
6
|
|
|
7
|
+
// Default low priority for Firebase messaging service when setHighPriorityPushHandler is false
|
|
8
|
+
export const DEFAULT_LOW_PRIORITY = -10;
|
|
9
|
+
|
|
10
|
+
|
|
7
11
|
export const withAndroidManifestUpdates: ConfigPlugin<
|
|
8
12
|
CustomerIOPluginOptionsAndroid
|
|
9
|
-
> = (configOuter) => {
|
|
13
|
+
> = (configOuter, options) => {
|
|
10
14
|
return withAndroidManifest(configOuter, (props) => {
|
|
11
15
|
const application = props.modResults.manifest
|
|
12
16
|
.application as ManifestApplication[];
|
|
13
17
|
const customerIOMessagingpush =
|
|
14
18
|
'io.customer.messagingpush.CustomerIOFirebaseMessagingService';
|
|
15
19
|
|
|
16
|
-
if (!application[0]
|
|
17
|
-
application[0]
|
|
20
|
+
if (!application[0].service) {
|
|
21
|
+
application[0].service = [];
|
|
18
22
|
}
|
|
19
23
|
|
|
20
|
-
const
|
|
21
|
-
(service) => service['
|
|
24
|
+
const existingServiceIndex = application[0].service.findIndex(
|
|
25
|
+
(service) => service.$['android:name'] === customerIOMessagingpush
|
|
22
26
|
);
|
|
23
27
|
|
|
24
|
-
if (
|
|
25
|
-
|
|
28
|
+
if (existingServiceIndex === -1) {
|
|
29
|
+
// Intent filter structure for Firebase messaging service
|
|
30
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
31
|
+
const intentFilter: any = {
|
|
32
|
+
action: [
|
|
33
|
+
{
|
|
34
|
+
$: {
|
|
35
|
+
'android:name': 'com.google.firebase.MESSAGING_EVENT',
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
// Handle priority based on setHighPriorityPushHandler value
|
|
42
|
+
if (options.setHighPriorityPushHandler === true) {
|
|
43
|
+
// High priority - no priority attribute means default high priority
|
|
44
|
+
console.log(
|
|
45
|
+
'Successfully set CustomerIO push handler as high priority in AndroidManifest.xml'
|
|
46
|
+
);
|
|
47
|
+
} else if (options.setHighPriorityPushHandler === false) {
|
|
48
|
+
// Low priority - set fixed priority
|
|
49
|
+
intentFilter.$ = {
|
|
50
|
+
'android:priority': DEFAULT_LOW_PRIORITY.toString(),
|
|
51
|
+
};
|
|
52
|
+
console.log(
|
|
53
|
+
`Successfully set CustomerIO push handler as low priority (${DEFAULT_LOW_PRIORITY}) in AndroidManifest.xml`
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
application[0].service.push({
|
|
26
58
|
'$': {
|
|
27
59
|
'android:name': customerIOMessagingpush,
|
|
28
60
|
'android:exported': 'false',
|
|
29
61
|
},
|
|
30
|
-
'intent-filter': [
|
|
31
|
-
{
|
|
32
|
-
action: [
|
|
33
|
-
{
|
|
34
|
-
$: {
|
|
35
|
-
'android:name': 'com.google.firebase.MESSAGING_EVENT',
|
|
36
|
-
},
|
|
37
|
-
},
|
|
38
|
-
],
|
|
39
|
-
},
|
|
40
|
-
],
|
|
62
|
+
'intent-filter': [intentFilter],
|
|
41
63
|
});
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
64
|
+
} else if (options.setHighPriorityPushHandler === true) {
|
|
65
|
+
// Service exists, need to ensure it becomes high priority (remove priority attribute)
|
|
66
|
+
const existingService = application[0].service[existingServiceIndex];
|
|
67
|
+
|
|
68
|
+
if (existingService['intent-filter'] && existingService['intent-filter'].length > 0) {
|
|
69
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
70
|
+
const intentFilter = existingService['intent-filter'][0] as any;
|
|
71
|
+
if (intentFilter.$ && intentFilter.$['android:priority']) {
|
|
72
|
+
delete intentFilter.$['android:priority'];
|
|
73
|
+
console.log(
|
|
74
|
+
'Successfully updated existing CustomerIO push handler to high priority in AndroidManifest.xml'
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
} else if (options.setHighPriorityPushHandler === false) {
|
|
79
|
+
// Service exists, update to low priority
|
|
80
|
+
const existingService = application[0].service[existingServiceIndex];
|
|
81
|
+
|
|
82
|
+
// Update existing service intent-filter with fixed priority
|
|
83
|
+
if (existingService['intent-filter'] && existingService['intent-filter'].length > 0) {
|
|
84
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
85
|
+
const intentFilter = existingService['intent-filter'][0] as any;
|
|
86
|
+
if (!intentFilter.$) {
|
|
87
|
+
intentFilter.$ = {};
|
|
88
|
+
}
|
|
89
|
+
intentFilter.$['android:priority'] = DEFAULT_LOW_PRIORITY.toString();
|
|
90
|
+
console.log(
|
|
91
|
+
`Successfully updated existing CustomerIO push handler to low priority (${DEFAULT_LOW_PRIORITY}) in AndroidManifest.xml`
|
|
92
|
+
);
|
|
93
|
+
}
|
|
45
94
|
}
|
|
46
95
|
|
|
47
96
|
props.modResults.manifest.application = application;
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import type { ExpoConfig } from '@expo/config-types';
|
|
2
2
|
|
|
3
|
-
import type { CustomerIOPluginOptionsAndroid } from '../types/cio-types';
|
|
3
|
+
import type { CustomerIOPluginOptionsAndroid, NativeSDKConfig } from '../types/cio-types';
|
|
4
4
|
import { withAndroidManifestUpdates } from './withAndroidManifestUpdates';
|
|
5
5
|
import { withAppGoogleServices } from './withAppGoogleServices';
|
|
6
6
|
import { withGistMavenRepository } from './withGistMavenRepository';
|
|
7
7
|
import { withGoogleServicesJSON } from './withGoogleServicesJSON';
|
|
8
|
+
import { withMainApplicationModifications } from './withMainApplicationModifications';
|
|
8
9
|
import { withNotificationChannelMetadata } from './withNotificationChannelMetadata';
|
|
9
10
|
import { withProjectGoogleServices } from './withProjectGoogleServices';
|
|
10
11
|
import { withProjectStrings } from './withProjectStrings';
|
|
11
12
|
|
|
12
13
|
export function withCIOAndroid(
|
|
13
14
|
config: ExpoConfig,
|
|
15
|
+
sdkConfig: NativeSDKConfig | undefined,
|
|
14
16
|
props: CustomerIOPluginOptionsAndroid
|
|
15
17
|
): ExpoConfig {
|
|
16
18
|
config = withGistMavenRepository(config, props);
|
|
@@ -18,12 +20,16 @@ export function withCIOAndroid(
|
|
|
18
20
|
config = withAppGoogleServices(config, props);
|
|
19
21
|
config = withGoogleServicesJSON(config, props);
|
|
20
22
|
config = withProjectStrings(config);
|
|
21
|
-
if (props.setHighPriorityPushHandler) {
|
|
23
|
+
if (props.setHighPriorityPushHandler !== undefined) {
|
|
22
24
|
config = withAndroidManifestUpdates(config, props);
|
|
23
25
|
}
|
|
24
26
|
if (props.pushNotification?.channel) {
|
|
25
27
|
config = withNotificationChannelMetadata(config, props);
|
|
26
28
|
}
|
|
29
|
+
// Add auto initialization if sdkConfig is provided
|
|
30
|
+
if (sdkConfig) {
|
|
31
|
+
config = withMainApplicationModifications(config, sdkConfig);
|
|
32
|
+
}
|
|
27
33
|
|
|
28
34
|
return config;
|
|
29
35
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
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 { FileManagement } from './../helpers/utils/fileManagement';
|
|
5
5
|
import type { CustomerIOPluginOptionsAndroid } from './../types/cio-types';
|
|
@@ -20,7 +20,7 @@ export const withGoogleServicesJSON: ConfigPlugin<
|
|
|
20
20
|
googleServicesFile,
|
|
21
21
|
`${androidPath}/app/google-services.json`
|
|
22
22
|
);
|
|
23
|
-
} catch
|
|
23
|
+
} catch {
|
|
24
24
|
console.log(
|
|
25
25
|
`There was an error copying your google-services.json file. You can copy it manually into ${androidPath}/app/google-services.json`
|
|
26
26
|
);
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { ConfigPlugin, ExportedConfigWithProps } from '@expo/config-plugins';
|
|
2
|
+
import { withMainApplication } from '@expo/config-plugins';
|
|
3
|
+
import type { ApplicationProjectFile } from '@expo/config-plugins/build/android/Paths';
|
|
4
|
+
import { CIO_MAINAPPLICATION_ONCREATE_REGEX, CIO_NATIVE_SDK_INITIALIZE_CALL, CIO_NATIVE_SDK_INITIALIZE_SNIPPET } from '../helpers/constants/android';
|
|
5
|
+
import { PLATFORM } from '../helpers/constants/common';
|
|
6
|
+
import { patchNativeSDKInitializer } from '../helpers/utils/patchPluginNativeCode';
|
|
7
|
+
import type { NativeSDKConfig } from '../types/cio-types';
|
|
8
|
+
import { addCodeToMethod, addImportToFile, copyTemplateFile } from '../utils/android';
|
|
9
|
+
|
|
10
|
+
export const withMainApplicationModifications: ConfigPlugin<NativeSDKConfig> = (configOuter, sdkConfig) => {
|
|
11
|
+
return withMainApplication(configOuter, async (config) => {
|
|
12
|
+
const content = setupCustomerIOSDKInitializer(config, sdkConfig);
|
|
13
|
+
config.modResults.contents = content;
|
|
14
|
+
return config;
|
|
15
|
+
});
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Setup CustomerIOSDKInitializer for Android auto initialization
|
|
20
|
+
*/
|
|
21
|
+
const setupCustomerIOSDKInitializer = (
|
|
22
|
+
config: ExportedConfigWithProps<ApplicationProjectFile>,
|
|
23
|
+
sdkConfig: NativeSDKConfig,
|
|
24
|
+
): string => {
|
|
25
|
+
const SDK_INITIALIZER_CLASS = 'CustomerIOSDKInitializer';
|
|
26
|
+
const SDK_INITIALIZER_PACKAGE = 'io.customer.sdk.expo';
|
|
27
|
+
|
|
28
|
+
const SDK_INITIALIZER_FILE = `${SDK_INITIALIZER_CLASS}.kt`;
|
|
29
|
+
const SDK_INITIALIZER_IMPORT = `import ${SDK_INITIALIZER_PACKAGE}.${SDK_INITIALIZER_CLASS}`;
|
|
30
|
+
|
|
31
|
+
let content = config.modResults.contents;
|
|
32
|
+
|
|
33
|
+
try {
|
|
34
|
+
// Always regenerate the CustomerIOSDKInitializer file to reflect config changes
|
|
35
|
+
copyTemplateFile(config, SDK_INITIALIZER_FILE, SDK_INITIALIZER_PACKAGE, (content) =>
|
|
36
|
+
patchNativeSDKInitializer(content, PLATFORM.ANDROID, sdkConfig)
|
|
37
|
+
);
|
|
38
|
+
// Add import if not already present
|
|
39
|
+
content = addImportToFile(content, SDK_INITIALIZER_IMPORT);
|
|
40
|
+
// Add initialization code to onCreate if not already present
|
|
41
|
+
if (!content.includes(CIO_NATIVE_SDK_INITIALIZE_CALL)) {
|
|
42
|
+
content = addCodeToMethod(content, CIO_MAINAPPLICATION_ONCREATE_REGEX, CIO_NATIVE_SDK_INITIALIZE_SNIPPET);
|
|
43
|
+
}
|
|
44
|
+
} catch (error) {
|
|
45
|
+
console.warn(`Could not setup ${SDK_INITIALIZER_CLASS}:`, error);
|
|
46
|
+
return config.modResults.contents;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return content;
|
|
50
|
+
};
|
|
@@ -19,7 +19,7 @@ const addMetadataIfNotExists = (
|
|
|
19
19
|
|
|
20
20
|
// Check if metadata already exists
|
|
21
21
|
const hasMetadata = application['meta-data'].some(
|
|
22
|
-
(metadata) => metadata['
|
|
22
|
+
(metadata) => metadata.$['android:name'] === name
|
|
23
23
|
);
|
|
24
24
|
|
|
25
25
|
// Add metadata if it doesn't exist
|
|
@@ -37,11 +37,15 @@ export const withNotificationChannelMetadata: ConfigPlugin<
|
|
|
37
37
|
CustomerIOPluginOptionsAndroid
|
|
38
38
|
> = (config, props) => {
|
|
39
39
|
return withAndroidManifest(config, (manifestProps) => {
|
|
40
|
-
const application = manifestProps.modResults.manifest
|
|
40
|
+
const application = manifestProps.modResults.manifest
|
|
41
|
+
.application as ManifestApplication[];
|
|
41
42
|
const channel = props.pushNotification?.channel;
|
|
42
43
|
|
|
43
44
|
// Only proceed if channel configuration exists
|
|
44
|
-
if (
|
|
45
|
+
if (
|
|
46
|
+
channel &&
|
|
47
|
+
(channel.id || channel.name || channel.importance !== undefined)
|
|
48
|
+
) {
|
|
45
49
|
if (channel.id) {
|
|
46
50
|
addMetadataIfNotExists(
|
|
47
51
|
application[0],
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import type { ConfigPlugin } from '@expo/config-plugins';
|
|
2
2
|
import { withStringsXml } from '@expo/config-plugins';
|
|
3
|
-
import {
|
|
3
|
+
import type { ResourceXML } from '@expo/config-plugins/build/android/Resources';
|
|
4
|
+
import { getPluginVersion } from '../utils/plugin';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Adds or updates string resources in Android's strings.xml required by the plugin
|
|
7
8
|
*/
|
|
8
|
-
export const withProjectStrings: ConfigPlugin = (
|
|
9
|
-
return withStringsXml(
|
|
9
|
+
export const withProjectStrings: ConfigPlugin = (configOuter) => {
|
|
10
|
+
return withStringsXml(configOuter, (config) => {
|
|
10
11
|
const stringsXml = config.modResults;
|
|
11
12
|
const pluginVersion = getPluginVersion();
|
|
12
13
|
|
|
@@ -17,7 +18,10 @@ export const withProjectStrings: ConfigPlugin = (config) => {
|
|
|
17
18
|
// can be generated correctly for Expo apps
|
|
18
19
|
addStringsToXml(stringsXml, [
|
|
19
20
|
{ name: 'customer_io_react_native_sdk_client_source', value: 'Expo' },
|
|
20
|
-
{
|
|
21
|
+
{
|
|
22
|
+
name: 'customer_io_react_native_sdk_client_version',
|
|
23
|
+
value: pluginVersion,
|
|
24
|
+
},
|
|
21
25
|
]);
|
|
22
26
|
|
|
23
27
|
return config;
|
|
@@ -31,25 +35,31 @@ export const withProjectStrings: ConfigPlugin = (config) => {
|
|
|
31
35
|
* @returns Updated strings.xml object
|
|
32
36
|
*/
|
|
33
37
|
export function addStringsToXml(
|
|
34
|
-
stringsXml:
|
|
35
|
-
stringResources: { name: string
|
|
38
|
+
stringsXml: ResourceXML,
|
|
39
|
+
stringResources: { name: string; value: string }[]
|
|
36
40
|
) {
|
|
37
41
|
// Ensure the resource exists
|
|
38
42
|
if (!stringsXml.resources) {
|
|
39
43
|
stringsXml.resources = { string: [] };
|
|
40
44
|
}
|
|
45
|
+
// Ensure the string array exists
|
|
46
|
+
if (!stringsXml.resources.string) {
|
|
47
|
+
stringsXml.resources.string = [];
|
|
48
|
+
}
|
|
41
49
|
|
|
50
|
+
// Get a reference to the string array after ensuring it exists
|
|
51
|
+
const stringArray = stringsXml.resources.string;
|
|
42
52
|
stringResources.forEach(({ name, value }) => {
|
|
43
|
-
const existingStringIndex =
|
|
44
|
-
(item
|
|
53
|
+
const existingStringIndex = stringArray.findIndex(
|
|
54
|
+
(item) => item.$?.name === name
|
|
45
55
|
);
|
|
46
56
|
|
|
47
57
|
if (existingStringIndex !== -1) {
|
|
48
58
|
// Update the existing string
|
|
49
|
-
|
|
59
|
+
stringArray[existingStringIndex]._ = value;
|
|
50
60
|
} else {
|
|
51
61
|
// Add a new string resource
|
|
52
|
-
|
|
62
|
+
stringArray.push({
|
|
53
63
|
$: { name },
|
|
54
64
|
_: value,
|
|
55
65
|
});
|
|
@@ -12,3 +12,10 @@ export const CIO_APP_GOOGLE_SNIPPET =
|
|
|
12
12
|
'apply plugin: "com.google.gms.google-services" // Google Services plugin';
|
|
13
13
|
export const CIO_PROJECT_GOOGLE_SNIPPET =
|
|
14
14
|
' classpath "com.google.gms:google-services:4.3.13" // Google Services plugin';
|
|
15
|
+
|
|
16
|
+
export const CIO_MAINAPPLICATION_ONCREATE_REGEX = /override\s+fun\s+onCreate\s*\(\s*\)\s*\{[\s\S]*?\}/;
|
|
17
|
+
// Actual method call, also used to detect if Customer.io auto initialization is already present
|
|
18
|
+
export const CIO_NATIVE_SDK_INITIALIZE_CALL = 'CustomerIOSDKInitializer.initialize(this)';
|
|
19
|
+
// Complete code snippet to inject into MainActivity.onCreate()
|
|
20
|
+
export const CIO_NATIVE_SDK_INITIALIZE_SNIPPET = `// Auto Initialize Native Customer.io SDK
|
|
21
|
+
${CIO_NATIVE_SDK_INITIALIZE_CALL}`;
|
|
@@ -1,23 +1,15 @@
|
|
|
1
|
-
const finder = require('find-package-json');
|
|
2
1
|
const path = require('path');
|
|
3
2
|
const resolveFrom = require('resolve-from');
|
|
4
3
|
|
|
5
|
-
const f = finder(__dirname);
|
|
6
|
-
let pluginPackageRoot = f.next().filename;
|
|
7
|
-
// This is the path to the root of the customerio-expo-plugin package
|
|
8
|
-
pluginPackageRoot = path.dirname(pluginPackageRoot);
|
|
9
|
-
|
|
10
|
-
export const LOCAL_PATH_TO_CIO_NSE_FILES = path.join(
|
|
11
|
-
pluginPackageRoot,
|
|
12
|
-
'plugin/src/helpers/native-files/ios'
|
|
13
|
-
);
|
|
14
|
-
|
|
15
4
|
export function getRelativePathToRNSDK(iosPath: string) {
|
|
16
5
|
// Root path of the Expo project
|
|
17
6
|
const rootAppPath = path.dirname(iosPath);
|
|
18
7
|
|
|
19
8
|
// Path of the cio RN package.json file. Example: test-app/node_modules/customerio-reactnative/package.json
|
|
20
|
-
const pluginPackageJsonPath = resolveFrom.silent(
|
|
9
|
+
const pluginPackageJsonPath = resolveFrom.silent(
|
|
10
|
+
rootAppPath,
|
|
11
|
+
`customerio-reactnative/package.json`
|
|
12
|
+
);
|
|
21
13
|
|
|
22
14
|
// Example: ../node_modules/customerio-reactnative
|
|
23
15
|
return path.relative(iosPath, path.dirname(pluginPackageJsonPath));
|
|
@@ -170,4 +162,10 @@ export const CIO_REGISTER_PUSHNOTIFICATION_SNIPPET_v2 = `
|
|
|
170
162
|
}
|
|
171
163
|
}`;
|
|
172
164
|
|
|
173
|
-
export const CIO_REGISTER_PUSH_NOTIFICATION_PLACEHOLDER = /\{\{REGISTER_SNIPPET\}\}/;
|
|
165
|
+
export const CIO_REGISTER_PUSH_NOTIFICATION_PLACEHOLDER = /\{\{REGISTER_SNIPPET\}\}/;
|
|
166
|
+
// Regex to match MessagingPush initialization in AppDelegate (different from NSE initialization)
|
|
167
|
+
export const CIO_MESSAGING_PUSH_APP_DELEGATE_INIT_REGEX = /(MessagingPush(?:APN|FCM)\.initialize)/;
|
|
168
|
+
export const CIO_NATIVE_SDK_INITIALIZE_CALL = 'CustomerIOSDKInitializer.initialize()';
|
|
169
|
+
export const CIO_NATIVE_SDK_INITIALIZE_SNIPPET = `// Auto Initialize Native Customer.io SDK
|
|
170
|
+
${CIO_NATIVE_SDK_INITIALIZE_CALL}
|
|
171
|
+
`;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
package io.customer.sdk.expo
|
|
2
|
+
|
|
3
|
+
import android.app.Application
|
|
4
|
+
import io.customer.datapipelines.config.ScreenView
|
|
5
|
+
import io.customer.messaginginapp.MessagingInAppModuleConfig
|
|
6
|
+
import io.customer.messaginginapp.ModuleMessagingInApp
|
|
7
|
+
import io.customer.messagingpush.MessagingPushModuleConfig
|
|
8
|
+
import io.customer.messagingpush.ModuleMessagingPushFCM
|
|
9
|
+
import io.customer.reactnative.sdk.messaginginapp.ReactInAppEventListener
|
|
10
|
+
import io.customer.sdk.CustomerIOBuilder
|
|
11
|
+
import io.customer.sdk.core.util.CioLogLevel
|
|
12
|
+
import io.customer.sdk.data.model.Region
|
|
13
|
+
|
|
14
|
+
object CustomerIOSDKInitializer {
|
|
15
|
+
fun initialize(application: Application) = with(
|
|
16
|
+
CustomerIOBuilder(application, "{{CDP_API_KEY}}")
|
|
17
|
+
) {
|
|
18
|
+
val siteId: String? = {{SITE_ID}}
|
|
19
|
+
val migrationSiteId: String? = {{MIGRATION_SITE_ID}}
|
|
20
|
+
val region = Region.getRegion({{REGION}})
|
|
21
|
+
|
|
22
|
+
setIfDefined({{LOG_LEVEL}}, CustomerIOBuilder::logLevel) { CioLogLevel.getLogLevel(it) }
|
|
23
|
+
setIfDefined(region, CustomerIOBuilder::region)
|
|
24
|
+
setIfDefined({{AUTO_TRACK_DEVICE_ATTRIBUTES}}, CustomerIOBuilder::autoTrackDeviceAttributes)
|
|
25
|
+
setIfDefined({{TRACK_APPLICATION_LIFECYCLE_EVENTS}}, CustomerIOBuilder::trackApplicationLifecycleEvents)
|
|
26
|
+
setIfDefined({{SCREEN_VIEW_USE}}, CustomerIOBuilder::screenViewUse) { ScreenView.getScreenView(it) }
|
|
27
|
+
setIfDefined(migrationSiteId, CustomerIOBuilder::migrationSiteId)
|
|
28
|
+
|
|
29
|
+
// Add messaging modules if siteId is provided
|
|
30
|
+
if (!(siteId.isNullOrBlank())) {
|
|
31
|
+
addCustomerIOModule(
|
|
32
|
+
ModuleMessagingInApp(
|
|
33
|
+
MessagingInAppModuleConfig.Builder(siteId, region)
|
|
34
|
+
.setEventListener(ReactInAppEventListener())
|
|
35
|
+
.build()
|
|
36
|
+
)
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
addCustomerIOModule(
|
|
40
|
+
ModuleMessagingPushFCM(
|
|
41
|
+
MessagingPushModuleConfig.Builder().build()
|
|
42
|
+
)
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
build()
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Apply a value after transforming it, only if both the original and transformed values are non-nil
|
|
50
|
+
private inline fun <R, T> CustomerIOBuilder.setIfDefined(
|
|
51
|
+
value: R?,
|
|
52
|
+
block: CustomerIOBuilder.(T) -> CustomerIOBuilder,
|
|
53
|
+
transform: (R) -> T,
|
|
54
|
+
): CustomerIOBuilder = value?.let { block(transform(it)) } ?: this
|
|
55
|
+
|
|
56
|
+
// Apply a value to a setter only if it's non-nil
|
|
57
|
+
private inline fun <T> CustomerIOBuilder.setIfDefined(
|
|
58
|
+
value: T?,
|
|
59
|
+
block: CustomerIOBuilder.(T) -> CustomerIOBuilder,
|
|
60
|
+
): CustomerIOBuilder = setIfDefined(
|
|
61
|
+
value = value,
|
|
62
|
+
block = block,
|
|
63
|
+
transform = { it },
|
|
64
|
+
)
|