customerio-expo-plugin 3.3.0 → 3.5.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 +8 -1
- package/plugin/lib/commonjs/android/withAndroidManifestUpdates.js +64 -59
- package/plugin/lib/commonjs/android/withAndroidManifestUpdates.js.map +1 -1
- package/plugin/lib/commonjs/android/withAppGoogleServices.js +10 -7
- package/plugin/lib/commonjs/android/withAppGoogleServices.js.map +1 -1
- package/plugin/lib/commonjs/android/withGoogleServicesJSON.js +18 -21
- package/plugin/lib/commonjs/android/withGoogleServicesJSON.js.map +1 -1
- package/plugin/lib/commonjs/android/withLocationGradleProperties.js +16 -12
- package/plugin/lib/commonjs/android/withLocationGradleProperties.js.map +1 -1
- package/plugin/lib/commonjs/android/withMainApplicationModifications.js +19 -12
- package/plugin/lib/commonjs/android/withMainApplicationModifications.js.map +1 -1
- package/plugin/lib/commonjs/android/withNotificationChannelMetadata.js +2 -1
- package/plugin/lib/commonjs/android/withNotificationChannelMetadata.js.map +1 -1
- package/plugin/lib/commonjs/android/withProjectBuildGradle.js +29 -25
- package/plugin/lib/commonjs/android/withProjectBuildGradle.js.map +1 -1
- package/plugin/lib/commonjs/android/withProjectGoogleServices.js +9 -5
- package/plugin/lib/commonjs/android/withProjectGoogleServices.js.map +1 -1
- package/plugin/lib/commonjs/helpers/constants/ios.js +76 -8
- package/plugin/lib/commonjs/helpers/constants/ios.js.map +1 -1
- package/plugin/lib/commonjs/helpers/utils/injectCIOPodfileCode.js +76 -31
- package/plugin/lib/commonjs/helpers/utils/injectCIOPodfileCode.js.map +1 -1
- package/plugin/lib/commonjs/index.js +7 -0
- package/plugin/lib/commonjs/index.js.map +1 -1
- package/plugin/lib/commonjs/ios/withAppDelegateModifications.js +47 -33
- package/plugin/lib/commonjs/ios/withAppDelegateModifications.js.map +1 -1
- package/plugin/lib/commonjs/ios/withCIOIosSwift.js +44 -54
- package/plugin/lib/commonjs/ios/withCIOIosSwift.js.map +1 -1
- package/plugin/lib/commonjs/ios/withGoogleServicesJsonFile.js +46 -30
- package/plugin/lib/commonjs/ios/withGoogleServicesJsonFile.js.map +1 -1
- package/plugin/lib/commonjs/ios/withNotificationsXcodeProject.js +192 -122
- package/plugin/lib/commonjs/ios/withNotificationsXcodeProject.js.map +1 -1
- package/plugin/lib/commonjs/postInstallHelper.js +58 -11
- package/plugin/lib/commonjs/postInstallHelper.js.map +1 -1
- package/plugin/lib/commonjs/utils/resolveRNSDK.js +97 -0
- package/plugin/lib/commonjs/utils/resolveRNSDK.js.map +1 -0
- package/plugin/lib/commonjs/utils/writeExpoVersion.js +56 -0
- package/plugin/lib/commonjs/utils/writeExpoVersion.js.map +1 -0
- package/plugin/lib/module/android/withAndroidManifestUpdates.js +61 -58
- package/plugin/lib/module/android/withAndroidManifestUpdates.js.map +1 -1
- package/plugin/lib/module/android/withAppGoogleServices.js +9 -7
- package/plugin/lib/module/android/withAppGoogleServices.js.map +1 -1
- package/plugin/lib/module/android/withGoogleServicesJSON.js +17 -21
- package/plugin/lib/module/android/withGoogleServicesJSON.js.map +1 -1
- package/plugin/lib/module/android/withLocationGradleProperties.js +15 -12
- package/plugin/lib/module/android/withLocationGradleProperties.js.map +1 -1
- package/plugin/lib/module/android/withMainApplicationModifications.js +18 -12
- package/plugin/lib/module/android/withMainApplicationModifications.js.map +1 -1
- package/plugin/lib/module/android/withNotificationChannelMetadata.js +1 -1
- package/plugin/lib/module/android/withNotificationChannelMetadata.js.map +1 -1
- package/plugin/lib/module/android/withProjectBuildGradle.js +28 -25
- package/plugin/lib/module/android/withProjectBuildGradle.js.map +1 -1
- package/plugin/lib/module/android/withProjectGoogleServices.js +8 -5
- package/plugin/lib/module/android/withProjectGoogleServices.js.map +1 -1
- package/plugin/lib/module/helpers/constants/ios.js +75 -8
- package/plugin/lib/module/helpers/constants/ios.js.map +1 -1
- package/plugin/lib/module/helpers/utils/injectCIOPodfileCode.js +74 -31
- package/plugin/lib/module/helpers/utils/injectCIOPodfileCode.js.map +1 -1
- package/plugin/lib/module/index.js +7 -0
- package/plugin/lib/module/index.js.map +1 -1
- package/plugin/lib/module/ios/withAppDelegateModifications.js +45 -33
- package/plugin/lib/module/ios/withAppDelegateModifications.js.map +1 -1
- package/plugin/lib/module/ios/withCIOIosSwift.js +42 -54
- package/plugin/lib/module/ios/withCIOIosSwift.js.map +1 -1
- package/plugin/lib/module/ios/withGoogleServicesJsonFile.js +45 -30
- package/plugin/lib/module/ios/withGoogleServicesJsonFile.js.map +1 -1
- package/plugin/lib/module/ios/withNotificationsXcodeProject.js +187 -122
- package/plugin/lib/module/ios/withNotificationsXcodeProject.js.map +1 -1
- package/plugin/lib/module/postInstallHelper.js +58 -11
- package/plugin/lib/module/postInstallHelper.js.map +1 -1
- package/plugin/lib/module/utils/resolveRNSDK.js +88 -0
- package/plugin/lib/module/utils/resolveRNSDK.js.map +1 -0
- package/plugin/lib/module/utils/writeExpoVersion.js +48 -0
- package/plugin/lib/module/utils/writeExpoVersion.js.map +1 -0
- package/plugin/lib/typescript/android/withAndroidManifestUpdates.d.ts +2 -0
- package/plugin/lib/typescript/android/withAppGoogleServices.d.ts +1 -0
- package/plugin/lib/typescript/android/withGoogleServicesJSON.d.ts +1 -0
- package/plugin/lib/typescript/android/withLocationGradleProperties.d.ts +2 -0
- package/plugin/lib/typescript/android/withMainApplicationModifications.d.ts +6 -0
- package/plugin/lib/typescript/android/withNotificationChannelMetadata.d.ts +5 -0
- package/plugin/lib/typescript/android/withProjectBuildGradle.d.ts +9 -0
- package/plugin/lib/typescript/android/withProjectGoogleServices.d.ts +1 -0
- package/plugin/lib/typescript/helpers/constants/ios.d.ts +18 -0
- package/plugin/lib/typescript/helpers/utils/injectCIOPodfileCode.d.ts +25 -1
- package/plugin/lib/typescript/ios/withAppDelegateModifications.d.ts +13 -0
- package/plugin/lib/typescript/ios/withCIOIosSwift.d.ts +11 -0
- package/plugin/lib/typescript/ios/withGoogleServicesJsonFile.d.ts +14 -1
- package/plugin/lib/typescript/ios/withNotificationsXcodeProject.d.ts +53 -2
- package/plugin/lib/typescript/utils/resolveRNSDK.d.ts +7 -0
- package/plugin/lib/typescript/utils/writeExpoVersion.d.ts +3 -0
- package/plugin/src/android/withAndroidManifestUpdates.ts +83 -73
- package/plugin/src/android/withAppGoogleServices.ts +13 -11
- package/plugin/src/android/withGoogleServicesJSON.ts +30 -28
- package/plugin/src/android/withLocationGradleProperties.ts +23 -17
- package/plugin/src/android/withMainApplicationModifications.ts +25 -15
- package/plugin/src/android/withNotificationChannelMetadata.ts +1 -1
- package/plugin/src/android/withProjectBuildGradle.ts +37 -27
- package/plugin/src/android/withProjectGoogleServices.ts +14 -9
- package/plugin/src/helpers/constants/ios.ts +87 -8
- package/plugin/src/helpers/utils/injectCIOPodfileCode.ts +97 -50
- package/plugin/src/index.ts +7 -0
- package/plugin/src/ios/withAppDelegateModifications.ts +61 -48
- package/plugin/src/ios/withCIOIosSwift.ts +58 -62
- package/plugin/src/ios/withGoogleServicesJsonFile.ts +66 -48
- package/plugin/src/ios/withNotificationsXcodeProject.ts +257 -207
- package/plugin/src/postInstallHelper.js +75 -17
- package/plugin/src/utils/resolveRNSDK.ts +118 -0
- package/plugin/src/utils/writeExpoVersion.ts +62 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["withGradleProperties","CUSTOMERIO_LOCATION_ENABLED_KEY","
|
|
1
|
+
{"version":3,"names":["withGradleProperties","CUSTOMERIO_LOCATION_ENABLED_KEY","modifyGradleProperties","items","existingIndex","findIndex","item","type","key","newItem","value","push","withLocationGradleProperties","config","props","_props$location","location","enabled","modResults"],"sources":["withLocationGradleProperties.ts"],"sourcesContent":["import type { ConfigPlugin } from '@expo/config-plugins';\nimport { withGradleProperties } from '@expo/config-plugins';\nimport type { PropertiesItem } from '@expo/config-plugins/build/android/Properties';\n\nimport type { CustomerIOPluginLocationOptions } from '../types/cio-types';\n\nconst CUSTOMERIO_LOCATION_ENABLED_KEY = 'customerio_location_enabled';\n\nexport function modifyGradleProperties(\n items: PropertiesItem[]\n): PropertiesItem[] {\n const existingIndex = items.findIndex(\n (item) => item.type === 'property' && item.key === CUSTOMERIO_LOCATION_ENABLED_KEY\n );\n\n const newItem: PropertiesItem = {\n type: 'property',\n key: CUSTOMERIO_LOCATION_ENABLED_KEY,\n value: 'true',\n };\n\n if (existingIndex >= 0) {\n items[existingIndex] = newItem;\n } else {\n items.push(newItem);\n }\n\n return items;\n}\n\n/**\n * Adds or updates customerio_location_enabled in android/gradle.properties when location.enabled is true.\n * The Customer.io React Native SDK reads this to enable the location native module.\n */\nexport const withLocationGradleProperties: ConfigPlugin<{\n location?: CustomerIOPluginLocationOptions;\n}> = (config, props) => {\n if (props?.location?.enabled !== true) {\n return config;\n }\n\n return withGradleProperties(config, (config) => {\n const items = config.modResults as PropertiesItem[];\n config.modResults = modifyGradleProperties(items);\n return config;\n });\n};\n"],"mappings":"AACA,SAASA,oBAAoB,QAAQ,sBAAsB;AAK3D,MAAMC,+BAA+B,GAAG,6BAA6B;AAErE,OAAO,SAASC,sBAAsBA,CACpCC,KAAuB,EACL;EAClB,MAAMC,aAAa,GAAGD,KAAK,CAACE,SAAS,CAClCC,IAAI,IAAKA,IAAI,CAACC,IAAI,KAAK,UAAU,IAAID,IAAI,CAACE,GAAG,KAAKP,+BACrD,CAAC;EAED,MAAMQ,OAAuB,GAAG;IAC9BF,IAAI,EAAE,UAAU;IAChBC,GAAG,EAAEP,+BAA+B;IACpCS,KAAK,EAAE;EACT,CAAC;EAED,IAAIN,aAAa,IAAI,CAAC,EAAE;IACtBD,KAAK,CAACC,aAAa,CAAC,GAAGK,OAAO;EAChC,CAAC,MAAM;IACLN,KAAK,CAACQ,IAAI,CAACF,OAAO,CAAC;EACrB;EAEA,OAAON,KAAK;AACd;;AAEA;AACA;AACA;AACA;AACA,OAAO,MAAMS,4BAEX,GAAGA,CAACC,MAAM,EAAEC,KAAK,KAAK;EAAA,IAAAC,eAAA;EACtB,IAAI,CAAAD,KAAK,aAALA,KAAK,gBAAAC,eAAA,GAALD,KAAK,CAAEE,QAAQ,cAAAD,eAAA,uBAAfA,eAAA,CAAiBE,OAAO,MAAK,IAAI,EAAE;IACrC,OAAOJ,MAAM;EACf;EAEA,OAAOb,oBAAoB,CAACa,MAAM,EAAGA,MAAM,IAAK;IAC9C,MAAMV,KAAK,GAAGU,MAAM,CAACK,UAA8B;IACnDL,MAAM,CAACK,UAAU,GAAGhB,sBAAsB,CAACC,KAAK,CAAC;IACjD,OAAOU,MAAM;EACf,CAAC,CAAC;AACJ,CAAC","ignoreList":[]}
|
|
@@ -26,30 +26,36 @@ const getLocationInitOptions = (location, sdkConfig) => {
|
|
|
26
26
|
trackingMode: sdkConfig === null || sdkConfig === void 0 || (_sdkConfig$location = sdkConfig.location) === null || _sdkConfig$location === void 0 ? void 0 : _sdkConfig$location.trackingMode
|
|
27
27
|
};
|
|
28
28
|
};
|
|
29
|
+
const SDK_INITIALIZER_CLASS = 'CustomerIOSDKInitializer';
|
|
30
|
+
const SDK_INITIALIZER_PACKAGE = 'io.customer.sdk.expo';
|
|
31
|
+
const SDK_INITIALIZER_FILE = `${SDK_INITIALIZER_CLASS}.kt`;
|
|
32
|
+
const SDK_INITIALIZER_IMPORT = `import ${SDK_INITIALIZER_PACKAGE}.${SDK_INITIALIZER_CLASS}`;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Pure string transform: given the existing MainApplication contents, returns the contents
|
|
36
|
+
* with the CustomerIOSDKInitializer import and onCreate call injected (idempotent — if the
|
|
37
|
+
* initialize call is already present, the call-injection step is skipped).
|
|
38
|
+
*/
|
|
39
|
+
export function injectCustomerIOInitializerIntoMainApplication(contents) {
|
|
40
|
+
let next = addImportToFile(contents, SDK_INITIALIZER_IMPORT);
|
|
41
|
+
if (!next.includes(CIO_NATIVE_SDK_INITIALIZE_CALL)) {
|
|
42
|
+
next = addCodeToMethod(next, CIO_MAINAPPLICATION_ONCREATE_REGEX, CIO_NATIVE_SDK_INITIALIZE_SNIPPET);
|
|
43
|
+
}
|
|
44
|
+
return next;
|
|
45
|
+
}
|
|
29
46
|
|
|
30
47
|
/**
|
|
31
48
|
* Setup CustomerIOSDKInitializer for Android auto initialization
|
|
32
49
|
*/
|
|
33
50
|
const setupCustomerIOSDKInitializer = (config, sdkConfig, location) => {
|
|
34
|
-
const SDK_INITIALIZER_CLASS = 'CustomerIOSDKInitializer';
|
|
35
|
-
const SDK_INITIALIZER_PACKAGE = 'io.customer.sdk.expo';
|
|
36
|
-
const SDK_INITIALIZER_FILE = `${SDK_INITIALIZER_CLASS}.kt`;
|
|
37
|
-
const SDK_INITIALIZER_IMPORT = `import ${SDK_INITIALIZER_PACKAGE}.${SDK_INITIALIZER_CLASS}`;
|
|
38
51
|
const locationOptions = getLocationInitOptions(location, sdkConfig);
|
|
39
|
-
let content = config.modResults.contents;
|
|
40
52
|
try {
|
|
41
53
|
// Always regenerate the CustomerIOSDKInitializer file to reflect config changes
|
|
42
54
|
copyTemplateFile(config, SDK_INITIALIZER_FILE, SDK_INITIALIZER_PACKAGE, content => patchNativeSDKInitializer(content, PLATFORM.ANDROID, sdkConfig, locationOptions));
|
|
43
|
-
|
|
44
|
-
content = addImportToFile(content, SDK_INITIALIZER_IMPORT);
|
|
45
|
-
// Add initialization code to onCreate if not already present
|
|
46
|
-
if (!content.includes(CIO_NATIVE_SDK_INITIALIZE_CALL)) {
|
|
47
|
-
content = addCodeToMethod(content, CIO_MAINAPPLICATION_ONCREATE_REGEX, CIO_NATIVE_SDK_INITIALIZE_SNIPPET);
|
|
48
|
-
}
|
|
55
|
+
return injectCustomerIOInitializerIntoMainApplication(config.modResults.contents);
|
|
49
56
|
} catch (error) {
|
|
50
57
|
logger.warn(`Could not setup ${SDK_INITIALIZER_CLASS}:`, error);
|
|
51
58
|
return config.modResults.contents;
|
|
52
59
|
}
|
|
53
|
-
return content;
|
|
54
60
|
};
|
|
55
61
|
//# sourceMappingURL=withMainApplicationModifications.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["withMainApplication","CIO_MAINAPPLICATION_ONCREATE_REGEX","CIO_NATIVE_SDK_INITIALIZE_CALL","CIO_NATIVE_SDK_INITIALIZE_SNIPPET","PLATFORM","patchNativeSDKInitializer","addCodeToMethod","addImportToFile","copyTemplateFile","logger","withMainApplicationModifications","configOuter","sdkConfig","location","config","content","setupCustomerIOSDKInitializer","modResults","contents","getLocationInitOptions","_sdkConfig$location","enabled","trackingMode","SDK_INITIALIZER_CLASS","SDK_INITIALIZER_PACKAGE","SDK_INITIALIZER_FILE","SDK_INITIALIZER_IMPORT","
|
|
1
|
+
{"version":3,"names":["withMainApplication","CIO_MAINAPPLICATION_ONCREATE_REGEX","CIO_NATIVE_SDK_INITIALIZE_CALL","CIO_NATIVE_SDK_INITIALIZE_SNIPPET","PLATFORM","patchNativeSDKInitializer","addCodeToMethod","addImportToFile","copyTemplateFile","logger","withMainApplicationModifications","configOuter","sdkConfig","location","config","content","setupCustomerIOSDKInitializer","modResults","contents","getLocationInitOptions","_sdkConfig$location","enabled","trackingMode","SDK_INITIALIZER_CLASS","SDK_INITIALIZER_PACKAGE","SDK_INITIALIZER_FILE","SDK_INITIALIZER_IMPORT","injectCustomerIOInitializerIntoMainApplication","next","includes","locationOptions","ANDROID","error","warn"],"sources":["withMainApplicationModifications.ts"],"sourcesContent":["import type { ConfigPlugin, ExportedConfigWithProps } from '@expo/config-plugins';\nimport { withMainApplication } from '@expo/config-plugins';\nimport type { ApplicationProjectFile } from '@expo/config-plugins/build/android/Paths';\nimport { CIO_MAINAPPLICATION_ONCREATE_REGEX, CIO_NATIVE_SDK_INITIALIZE_CALL, CIO_NATIVE_SDK_INITIALIZE_SNIPPET } from '../helpers/constants/android';\nimport { PLATFORM } from '../helpers/constants/common';\nimport { patchNativeSDKInitializer } from '../helpers/utils/patchPluginNativeCode';\nimport type {\n CustomerIOPluginLocationOptions,\n NativeSDKConfig,\n} from '../types/cio-types';\nimport { addCodeToMethod, addImportToFile, copyTemplateFile } from '../utils/android';\nimport { logger } from '../utils/logger';\n\ntype MainApplicationModParams = {\n sdkConfig: NativeSDKConfig;\n location?: CustomerIOPluginLocationOptions;\n};\n\nexport const withMainApplicationModifications: ConfigPlugin<MainApplicationModParams> = (configOuter, { sdkConfig, location }) => {\n return withMainApplication(configOuter, async (config) => {\n const content = setupCustomerIOSDKInitializer(config, sdkConfig, location);\n config.modResults.contents = content;\n return config;\n });\n};\n\n/**\n * Build location options for native initializer from plugin config.\n * trackingMode comes from config.location.trackingMode (only used when location.enabled is true).\n */\nconst getLocationInitOptions = (\n location?: CustomerIOPluginLocationOptions,\n sdkConfig?: NativeSDKConfig\n) => ({\n enabled: location?.enabled === true,\n trackingMode: sdkConfig?.location?.trackingMode,\n});\n\nconst SDK_INITIALIZER_CLASS = 'CustomerIOSDKInitializer';\nconst SDK_INITIALIZER_PACKAGE = 'io.customer.sdk.expo';\nconst SDK_INITIALIZER_FILE = `${SDK_INITIALIZER_CLASS}.kt`;\nconst SDK_INITIALIZER_IMPORT = `import ${SDK_INITIALIZER_PACKAGE}.${SDK_INITIALIZER_CLASS}`;\n\n/**\n * Pure string transform: given the existing MainApplication contents, returns the contents\n * with the CustomerIOSDKInitializer import and onCreate call injected (idempotent — if the\n * initialize call is already present, the call-injection step is skipped).\n */\nexport function injectCustomerIOInitializerIntoMainApplication(\n contents: string\n): string {\n let next = addImportToFile(contents, SDK_INITIALIZER_IMPORT);\n if (!next.includes(CIO_NATIVE_SDK_INITIALIZE_CALL)) {\n next = addCodeToMethod(\n next,\n CIO_MAINAPPLICATION_ONCREATE_REGEX,\n CIO_NATIVE_SDK_INITIALIZE_SNIPPET\n );\n }\n return next;\n}\n\n/**\n * Setup CustomerIOSDKInitializer for Android auto initialization\n */\nconst setupCustomerIOSDKInitializer = (\n config: ExportedConfigWithProps<ApplicationProjectFile>,\n sdkConfig: NativeSDKConfig,\n location?: CustomerIOPluginLocationOptions,\n): string => {\n const locationOptions = getLocationInitOptions(location, sdkConfig);\n\n try {\n // Always regenerate the CustomerIOSDKInitializer file to reflect config changes\n copyTemplateFile(config, SDK_INITIALIZER_FILE, SDK_INITIALIZER_PACKAGE, (content) =>\n patchNativeSDKInitializer(content, PLATFORM.ANDROID, sdkConfig, locationOptions)\n );\n return injectCustomerIOInitializerIntoMainApplication(config.modResults.contents);\n } catch (error) {\n logger.warn(`Could not setup ${SDK_INITIALIZER_CLASS}:`, error);\n return config.modResults.contents;\n }\n};\n"],"mappings":"AACA,SAASA,mBAAmB,QAAQ,sBAAsB;AAE1D,SAASC,kCAAkC,EAAEC,8BAA8B,EAAEC,iCAAiC,QAAQ,8BAA8B;AACpJ,SAASC,QAAQ,QAAQ,6BAA6B;AACtD,SAASC,yBAAyB,QAAQ,wCAAwC;AAKlF,SAASC,eAAe,EAAEC,eAAe,EAAEC,gBAAgB,QAAQ,kBAAkB;AACrF,SAASC,MAAM,QAAQ,iBAAiB;AAOxC,OAAO,MAAMC,gCAAwE,GAAGA,CAACC,WAAW,EAAE;EAAEC,SAAS;EAAEC;AAAS,CAAC,KAAK;EAChI,OAAOb,mBAAmB,CAACW,WAAW,EAAE,MAAOG,MAAM,IAAK;IACxD,MAAMC,OAAO,GAAGC,6BAA6B,CAACF,MAAM,EAAEF,SAAS,EAAEC,QAAQ,CAAC;IAC1EC,MAAM,CAACG,UAAU,CAACC,QAAQ,GAAGH,OAAO;IACpC,OAAOD,MAAM;EACf,CAAC,CAAC;AACJ,CAAC;;AAED;AACA;AACA;AACA;AACA,MAAMK,sBAAsB,GAAGA,CAC7BN,QAA0C,EAC1CD,SAA2B;EAAA,IAAAQ,mBAAA;EAAA,OACvB;IACJC,OAAO,EAAE,CAAAR,QAAQ,aAARA,QAAQ,uBAARA,QAAQ,CAAEQ,OAAO,MAAK,IAAI;IACnCC,YAAY,EAAEV,SAAS,aAATA,SAAS,gBAAAQ,mBAAA,GAATR,SAAS,CAAEC,QAAQ,cAAAO,mBAAA,uBAAnBA,mBAAA,CAAqBE;EACrC,CAAC;AAAA,CAAC;AAEF,MAAMC,qBAAqB,GAAG,0BAA0B;AACxD,MAAMC,uBAAuB,GAAG,sBAAsB;AACtD,MAAMC,oBAAoB,GAAG,GAAGF,qBAAqB,KAAK;AAC1D,MAAMG,sBAAsB,GAAG,UAAUF,uBAAuB,IAAID,qBAAqB,EAAE;;AAE3F;AACA;AACA;AACA;AACA;AACA,OAAO,SAASI,8CAA8CA,CAC5DT,QAAgB,EACR;EACR,IAAIU,IAAI,GAAGrB,eAAe,CAACW,QAAQ,EAAEQ,sBAAsB,CAAC;EAC5D,IAAI,CAACE,IAAI,CAACC,QAAQ,CAAC3B,8BAA8B,CAAC,EAAE;IAClD0B,IAAI,GAAGtB,eAAe,CACpBsB,IAAI,EACJ3B,kCAAkC,EAClCE,iCACF,CAAC;EACH;EACA,OAAOyB,IAAI;AACb;;AAEA;AACA;AACA;AACA,MAAMZ,6BAA6B,GAAGA,CACpCF,MAAuD,EACvDF,SAA0B,EAC1BC,QAA0C,KAC/B;EACX,MAAMiB,eAAe,GAAGX,sBAAsB,CAACN,QAAQ,EAAED,SAAS,CAAC;EAEnE,IAAI;IACF;IACAJ,gBAAgB,CAACM,MAAM,EAAEW,oBAAoB,EAAED,uBAAuB,EAAGT,OAAO,IAC9EV,yBAAyB,CAACU,OAAO,EAAEX,QAAQ,CAAC2B,OAAO,EAAEnB,SAAS,EAAEkB,eAAe,CACjF,CAAC;IACD,OAAOH,8CAA8C,CAACb,MAAM,CAACG,UAAU,CAACC,QAAQ,CAAC;EACnF,CAAC,CAAC,OAAOc,KAAK,EAAE;IACdvB,MAAM,CAACwB,IAAI,CAAC,mBAAmBV,qBAAqB,GAAG,EAAES,KAAK,CAAC;IAC/D,OAAOlB,MAAM,CAACG,UAAU,CAACC,QAAQ;EACnC;AACF,CAAC","ignoreList":[]}
|
|
@@ -2,7 +2,7 @@ import { withAndroidManifest } from '@expo/config-plugins';
|
|
|
2
2
|
/**
|
|
3
3
|
* Adds a metadata entry to the Android manifest if it doesn't already exist
|
|
4
4
|
*/
|
|
5
|
-
const addMetadataIfNotExists = (application, name, value) => {
|
|
5
|
+
export const addMetadataIfNotExists = (application, name, value) => {
|
|
6
6
|
// Initialize meta-data array if it doesn't exist
|
|
7
7
|
if (!application['meta-data']) {
|
|
8
8
|
application['meta-data'] = [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["withAndroidManifest","addMetadataIfNotExists","application","name","value","hasMetadata","some","metadata","$","push","withNotificationChannelMetadata","config","props","manifestProps","_props$pushNotificati","modResults","manifest","channel","pushNotification","id","importance","undefined","String"],"sources":["withNotificationChannelMetadata.ts"],"sourcesContent":["import type { ConfigPlugin } from '@expo/config-plugins';\nimport { withAndroidManifest } from '@expo/config-plugins';\nimport type { ManifestApplication } from '@expo/config-plugins/build/android/Manifest';\n\nimport type { CustomerIOPluginOptionsAndroid } from '../types/cio-types';\n\n/**\n * Adds a metadata entry to the Android manifest if it doesn't already exist\n */\
|
|
1
|
+
{"version":3,"names":["withAndroidManifest","addMetadataIfNotExists","application","name","value","hasMetadata","some","metadata","$","push","withNotificationChannelMetadata","config","props","manifestProps","_props$pushNotificati","modResults","manifest","channel","pushNotification","id","importance","undefined","String"],"sources":["withNotificationChannelMetadata.ts"],"sourcesContent":["import type { ConfigPlugin } from '@expo/config-plugins';\nimport { withAndroidManifest } from '@expo/config-plugins';\nimport type { ManifestApplication } from '@expo/config-plugins/build/android/Manifest';\n\nimport type { CustomerIOPluginOptionsAndroid } from '../types/cio-types';\n\n/**\n * Adds a metadata entry to the Android manifest if it doesn't already exist\n */\nexport const addMetadataIfNotExists = (\n application: ManifestApplication,\n name: string,\n value: string\n): void => {\n // Initialize meta-data array if it doesn't exist\n if (!application['meta-data']) {\n application['meta-data'] = [];\n }\n\n // Check if metadata already exists\n const hasMetadata = application['meta-data'].some(\n (metadata) => metadata.$['android:name'] === name\n );\n\n // Add metadata if it doesn't exist\n if (!hasMetadata) {\n application['meta-data'].push({\n $: {\n 'android:name': name,\n 'android:value': value,\n },\n });\n }\n};\n\nexport const withNotificationChannelMetadata: ConfigPlugin<\n CustomerIOPluginOptionsAndroid\n> = (config, props) => {\n return withAndroidManifest(config, (manifestProps) => {\n const application = manifestProps.modResults.manifest\n .application as ManifestApplication[];\n const channel = props.pushNotification?.channel;\n\n // Only proceed if channel configuration exists\n if (\n channel &&\n (channel.id || channel.name || channel.importance !== undefined)\n ) {\n if (channel.id) {\n addMetadataIfNotExists(\n application[0],\n 'io.customer.notification_channel_id',\n channel.id\n );\n }\n\n if (channel.name) {\n addMetadataIfNotExists(\n application[0],\n 'io.customer.notification_channel_name',\n channel.name\n );\n }\n\n if (channel.importance !== undefined) {\n addMetadataIfNotExists(\n application[0],\n 'io.customer.notification_channel_importance',\n String(channel.importance)\n );\n }\n }\n\n manifestProps.modResults.manifest.application = application;\n return manifestProps;\n });\n};\n"],"mappings":"AACA,SAASA,mBAAmB,QAAQ,sBAAsB;AAK1D;AACA;AACA;AACA,OAAO,MAAMC,sBAAsB,GAAGA,CACpCC,WAAgC,EAChCC,IAAY,EACZC,KAAa,KACJ;EACT;EACA,IAAI,CAACF,WAAW,CAAC,WAAW,CAAC,EAAE;IAC7BA,WAAW,CAAC,WAAW,CAAC,GAAG,EAAE;EAC/B;;EAEA;EACA,MAAMG,WAAW,GAAGH,WAAW,CAAC,WAAW,CAAC,CAACI,IAAI,CAC9CC,QAAQ,IAAKA,QAAQ,CAACC,CAAC,CAAC,cAAc,CAAC,KAAKL,IAC/C,CAAC;;EAED;EACA,IAAI,CAACE,WAAW,EAAE;IAChBH,WAAW,CAAC,WAAW,CAAC,CAACO,IAAI,CAAC;MAC5BD,CAAC,EAAE;QACD,cAAc,EAAEL,IAAI;QACpB,eAAe,EAAEC;MACnB;IACF,CAAC,CAAC;EACJ;AACF,CAAC;AAED,OAAO,MAAMM,+BAEZ,GAAGA,CAACC,MAAM,EAAEC,KAAK,KAAK;EACrB,OAAOZ,mBAAmB,CAACW,MAAM,EAAGE,aAAa,IAAK;IAAA,IAAAC,qBAAA;IACpD,MAAMZ,WAAW,GAAGW,aAAa,CAACE,UAAU,CAACC,QAAQ,CAClDd,WAAoC;IACvC,MAAMe,OAAO,IAAAH,qBAAA,GAAGF,KAAK,CAACM,gBAAgB,cAAAJ,qBAAA,uBAAtBA,qBAAA,CAAwBG,OAAO;;IAE/C;IACA,IACEA,OAAO,KACNA,OAAO,CAACE,EAAE,IAAIF,OAAO,CAACd,IAAI,IAAIc,OAAO,CAACG,UAAU,KAAKC,SAAS,CAAC,EAChE;MACA,IAAIJ,OAAO,CAACE,EAAE,EAAE;QACdlB,sBAAsB,CACpBC,WAAW,CAAC,CAAC,CAAC,EACd,qCAAqC,EACrCe,OAAO,CAACE,EACV,CAAC;MACH;MAEA,IAAIF,OAAO,CAACd,IAAI,EAAE;QAChBF,sBAAsB,CACpBC,WAAW,CAAC,CAAC,CAAC,EACd,uCAAuC,EACvCe,OAAO,CAACd,IACV,CAAC;MACH;MAEA,IAAIc,OAAO,CAACG,UAAU,KAAKC,SAAS,EAAE;QACpCpB,sBAAsB,CACpBC,WAAW,CAAC,CAAC,CAAC,EACd,6CAA6C,EAC7CoB,MAAM,CAACL,OAAO,CAACG,UAAU,CAC3B,CAAC;MACH;IACF;IAEAP,aAAa,CAACE,UAAU,CAACC,QAAQ,CAACd,WAAW,GAAGA,WAAW;IAC3D,OAAOW,aAAa;EACtB,CAAC,CAAC;AACJ,CAAC","ignoreList":[]}
|
|
@@ -17,6 +17,31 @@ function shouldDisableAndroid16Support(config, androidOptions) {
|
|
|
17
17
|
return isExpoVersion53OrLower(config);
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
/**
|
|
21
|
+
* Pure string transform: injects an androidx resolution-strategy block into the
|
|
22
|
+
* project-level build.gradle's `allprojects { ... }` section when
|
|
23
|
+
* `disableAndroid16Support` is true. Idempotent — returns input unchanged if the
|
|
24
|
+
* snippet is already present, or if the flag is false.
|
|
25
|
+
*/
|
|
26
|
+
export function modifyProjectBuildGradleAndroid16Support(contents, options) {
|
|
27
|
+
if (!options.disableAndroid16Support) {
|
|
28
|
+
return contents;
|
|
29
|
+
}
|
|
30
|
+
if (contents.includes('androidx.core:core-ktx:1.13.1')) {
|
|
31
|
+
return contents;
|
|
32
|
+
}
|
|
33
|
+
const resolutionStrategy = `
|
|
34
|
+
configurations.all {
|
|
35
|
+
resolutionStrategy {
|
|
36
|
+
// Disable Android 16 support by forcing older androidx versions
|
|
37
|
+
// Compatible with API 35 and AGP 8.8.2 (prevents API 36/AGP 8.9.1+ requirement)
|
|
38
|
+
force 'androidx.core:core-ktx:1.13.1'
|
|
39
|
+
force 'androidx.lifecycle:lifecycle-process:2.8.7'
|
|
40
|
+
}
|
|
41
|
+
}`;
|
|
42
|
+
return contents.replace(/allprojects\s*\{/, `allprojects {${resolutionStrategy}`);
|
|
43
|
+
}
|
|
44
|
+
|
|
20
45
|
/**
|
|
21
46
|
* Adds dependency resolution strategy to force specific androidx versions.
|
|
22
47
|
* This disables Android 16 support for apps using Expo SDK 53 or older gradle versions.
|
|
@@ -29,31 +54,9 @@ function shouldDisableAndroid16Support(config, androidOptions) {
|
|
|
29
54
|
*/
|
|
30
55
|
export function withProjectBuildGradle(config, androidOptions) {
|
|
31
56
|
return withExpoProjectBuildGradle(config, config => {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// Check if Android 16 support should be disabled
|
|
37
|
-
if (!shouldDisableAndroid16Support(config, androidOptions)) {
|
|
38
|
-
return config;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// Skip if already applied
|
|
42
|
-
if (modResults.contents.includes('androidx.core:core-ktx:1.13.1')) {
|
|
43
|
-
return config;
|
|
44
|
-
}
|
|
45
|
-
const resolutionStrategy = `
|
|
46
|
-
configurations.all {
|
|
47
|
-
resolutionStrategy {
|
|
48
|
-
// Disable Android 16 support by forcing older androidx versions
|
|
49
|
-
// Compatible with API 35 and AGP 8.8.2 (prevents API 36/AGP 8.9.1+ requirement)
|
|
50
|
-
force 'androidx.core:core-ktx:1.13.1'
|
|
51
|
-
force 'androidx.lifecycle:lifecycle-process:2.8.7'
|
|
52
|
-
}
|
|
53
|
-
}`;
|
|
54
|
-
|
|
55
|
-
// Add resolution strategy inside allprojects block
|
|
56
|
-
modResults.contents = modResults.contents.replace(/allprojects\s*\{/, `allprojects {${resolutionStrategy}`);
|
|
57
|
+
config.modResults.contents = modifyProjectBuildGradleAndroid16Support(config.modResults.contents, {
|
|
58
|
+
disableAndroid16Support: shouldDisableAndroid16Support(config, androidOptions)
|
|
59
|
+
});
|
|
57
60
|
return config;
|
|
58
61
|
});
|
|
59
62
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["withProjectBuildGradle","withExpoProjectBuildGradle","isExpoVersion53OrLower","shouldDisableAndroid16Support","config","androidOptions","disableAndroid16Support","undefined","
|
|
1
|
+
{"version":3,"names":["withProjectBuildGradle","withExpoProjectBuildGradle","isExpoVersion53OrLower","shouldDisableAndroid16Support","config","androidOptions","disableAndroid16Support","undefined","modifyProjectBuildGradleAndroid16Support","contents","options","includes","resolutionStrategy","replace","modResults"],"sources":["withProjectBuildGradle.ts"],"sourcesContent":["import { withProjectBuildGradle as withExpoProjectBuildGradle } from '@expo/config-plugins';\nimport type { ExpoConfig } from '@expo/config-types';\nimport { isExpoVersion53OrLower } from '../ios/utils';\nimport type { CustomerIOPluginOptionsAndroid } from '../types/cio-types';\n\n/**\n * Determines if the androidx dependency fix should be applied based on config and Expo version.\n * The fix disables Android 16 support by downgrading androidx dependencies.\n * @param config The Expo config\n * @param androidOptions The Android plugin options\n * @returns true if the fix should be applied (Android 16 disabled)\n */\nfunction shouldDisableAndroid16Support(\n config: ExpoConfig,\n androidOptions?: CustomerIOPluginOptionsAndroid\n): boolean {\n // If user explicitly sets the option, respect their choice\n if (androidOptions?.disableAndroid16Support !== undefined) {\n return androidOptions.disableAndroid16Support;\n }\n\n // Auto-detect: Disable Android 16 for Expo SDK 53 or lower, enable for 54+\n return isExpoVersion53OrLower(config);\n}\n\n/**\n * Pure string transform: injects an androidx resolution-strategy block into the\n * project-level build.gradle's `allprojects { ... }` section when\n * `disableAndroid16Support` is true. Idempotent — returns input unchanged if the\n * snippet is already present, or if the flag is false.\n */\nexport function modifyProjectBuildGradleAndroid16Support(\n contents: string,\n options: { disableAndroid16Support: boolean }\n): string {\n if (!options.disableAndroid16Support) {\n return contents;\n }\n\n if (contents.includes('androidx.core:core-ktx:1.13.1')) {\n return contents;\n }\n\n const resolutionStrategy = `\n configurations.all {\n resolutionStrategy {\n // Disable Android 16 support by forcing older androidx versions\n // Compatible with API 35 and AGP 8.8.2 (prevents API 36/AGP 8.9.1+ requirement)\n force 'androidx.core:core-ktx:1.13.1'\n force 'androidx.lifecycle:lifecycle-process:2.8.7'\n }\n }`;\n\n return contents.replace(\n /allprojects\\s*\\{/,\n `allprojects {${resolutionStrategy}`\n );\n}\n\n/**\n * Adds dependency resolution strategy to force specific androidx versions.\n * This disables Android 16 support for apps using Expo SDK 53 or older gradle versions.\n *\n * The fix prevents newer androidx versions that require Android API 36 and AGP 8.9.1+\n * from being pulled in. Expo SDK 53 uses Android API 35 and AGP 8.8.2, so we force\n * compatible versions.\n *\n * Expo SDK 54+ should support newer gradle versions and won't need this fix.\n */\nexport function withProjectBuildGradle(\n config: ExpoConfig,\n androidOptions?: CustomerIOPluginOptionsAndroid\n): ExpoConfig {\n return withExpoProjectBuildGradle(config, (config) => {\n config.modResults.contents = modifyProjectBuildGradleAndroid16Support(\n config.modResults.contents,\n { disableAndroid16Support: shouldDisableAndroid16Support(config, androidOptions) }\n );\n return config;\n });\n}\n"],"mappings":"AAAA,SAASA,sBAAsB,IAAIC,0BAA0B,QAAQ,sBAAsB;AAE3F,SAASC,sBAAsB,QAAQ,cAAc;AAGrD;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASC,6BAA6BA,CACpCC,MAAkB,EAClBC,cAA+C,EACtC;EACT;EACA,IAAI,CAAAA,cAAc,aAAdA,cAAc,uBAAdA,cAAc,CAAEC,uBAAuB,MAAKC,SAAS,EAAE;IACzD,OAAOF,cAAc,CAACC,uBAAuB;EAC/C;;EAEA;EACA,OAAOJ,sBAAsB,CAACE,MAAM,CAAC;AACvC;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASI,wCAAwCA,CACtDC,QAAgB,EAChBC,OAA6C,EACrC;EACR,IAAI,CAACA,OAAO,CAACJ,uBAAuB,EAAE;IACpC,OAAOG,QAAQ;EACjB;EAEA,IAAIA,QAAQ,CAACE,QAAQ,CAAC,+BAA+B,CAAC,EAAE;IACtD,OAAOF,QAAQ;EACjB;EAEA,MAAMG,kBAAkB,GAAG;AAC7B;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM;EAEJ,OAAOH,QAAQ,CAACI,OAAO,CACrB,kBAAkB,EAClB,gBAAgBD,kBAAkB,EACpC,CAAC;AACH;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASZ,sBAAsBA,CACpCI,MAAkB,EAClBC,cAA+C,EACnC;EACZ,OAAOJ,0BAA0B,CAACG,MAAM,EAAGA,MAAM,IAAK;IACpDA,MAAM,CAACU,UAAU,CAACL,QAAQ,GAAGD,wCAAwC,CACnEJ,MAAM,CAACU,UAAU,CAACL,QAAQ,EAC1B;MAAEH,uBAAuB,EAAEH,6BAA6B,CAACC,MAAM,EAAEC,cAAc;IAAE,CACnF,CAAC;IACD,OAAOD,MAAM;EACf,CAAC,CAAC;AACJ","ignoreList":[]}
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import { withProjectBuildGradle } from '@expo/config-plugins';
|
|
2
2
|
import { CIO_PROJECT_BUILDSCRIPTS_REGEX, CIO_PROJECT_GOOGLE_SNIPPET } from './../helpers/constants/android';
|
|
3
|
+
export function modifyProjectBuildGradleForGoogleServices(contents) {
|
|
4
|
+
const regex = new RegExp(CIO_PROJECT_GOOGLE_SNIPPET);
|
|
5
|
+
if (regex.test(contents)) {
|
|
6
|
+
return contents;
|
|
7
|
+
}
|
|
8
|
+
return contents.replace(CIO_PROJECT_BUILDSCRIPTS_REGEX, `$1\n${CIO_PROJECT_GOOGLE_SNIPPET}`);
|
|
9
|
+
}
|
|
3
10
|
export const withProjectGoogleServices = configOuter => {
|
|
4
11
|
return withProjectBuildGradle(configOuter, props => {
|
|
5
|
-
|
|
6
|
-
const match = props.modResults.contents.match(regex);
|
|
7
|
-
if (!match) {
|
|
8
|
-
props.modResults.contents = props.modResults.contents.replace(CIO_PROJECT_BUILDSCRIPTS_REGEX, `$1\n${CIO_PROJECT_GOOGLE_SNIPPET}`);
|
|
9
|
-
}
|
|
12
|
+
props.modResults.contents = modifyProjectBuildGradleForGoogleServices(props.modResults.contents);
|
|
10
13
|
return props;
|
|
11
14
|
});
|
|
12
15
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["withProjectBuildGradle","CIO_PROJECT_BUILDSCRIPTS_REGEX","CIO_PROJECT_GOOGLE_SNIPPET","
|
|
1
|
+
{"version":3,"names":["withProjectBuildGradle","CIO_PROJECT_BUILDSCRIPTS_REGEX","CIO_PROJECT_GOOGLE_SNIPPET","modifyProjectBuildGradleForGoogleServices","contents","regex","RegExp","test","replace","withProjectGoogleServices","configOuter","props","modResults"],"sources":["withProjectGoogleServices.ts"],"sourcesContent":["import type { ConfigPlugin } from '@expo/config-plugins';\nimport { withProjectBuildGradle } from '@expo/config-plugins';\n\nimport {\n CIO_PROJECT_BUILDSCRIPTS_REGEX,\n CIO_PROJECT_GOOGLE_SNIPPET,\n} from './../helpers/constants/android';\nimport type { CustomerIOPluginOptionsAndroid } from './../types/cio-types';\n\nexport function modifyProjectBuildGradleForGoogleServices(contents: string): string {\n const regex = new RegExp(CIO_PROJECT_GOOGLE_SNIPPET);\n if (regex.test(contents)) {\n return contents;\n }\n return contents.replace(\n CIO_PROJECT_BUILDSCRIPTS_REGEX,\n `$1\\n${CIO_PROJECT_GOOGLE_SNIPPET}`\n );\n}\n\nexport const withProjectGoogleServices: ConfigPlugin<\n CustomerIOPluginOptionsAndroid\n> = (configOuter) => {\n return withProjectBuildGradle(configOuter, (props) => {\n props.modResults.contents = modifyProjectBuildGradleForGoogleServices(\n props.modResults.contents\n );\n return props;\n });\n};\n"],"mappings":"AACA,SAASA,sBAAsB,QAAQ,sBAAsB;AAE7D,SACEC,8BAA8B,EAC9BC,0BAA0B,QACrB,gCAAgC;AAGvC,OAAO,SAASC,yCAAyCA,CAACC,QAAgB,EAAU;EAClF,MAAMC,KAAK,GAAG,IAAIC,MAAM,CAACJ,0BAA0B,CAAC;EACpD,IAAIG,KAAK,CAACE,IAAI,CAACH,QAAQ,CAAC,EAAE;IACxB,OAAOA,QAAQ;EACjB;EACA,OAAOA,QAAQ,CAACI,OAAO,CACrBP,8BAA8B,EAC9B,OAAOC,0BAA0B,EACnC,CAAC;AACH;AAEA,OAAO,MAAMO,yBAEZ,GAAIC,WAAW,IAAK;EACnB,OAAOV,sBAAsB,CAACU,WAAW,EAAGC,KAAK,IAAK;IACpDA,KAAK,CAACC,UAAU,CAACR,QAAQ,GAAGD,yCAAyC,CACnEQ,KAAK,CAACC,UAAU,CAACR,QACnB,CAAC;IACD,OAAOO,KAAK;EACd,CAAC,CAAC;AACJ,CAAC","ignoreList":[]}
|
|
@@ -1,14 +1,81 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import * as semver from 'semver';
|
|
1
3
|
const path = require('path');
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
import { resolveRNSDK, tryReadRNVersion } from '../../utils/resolveRNSDK';
|
|
5
|
+
|
|
6
|
+
// Threshold at which React Native pod autolinking moves from
|
|
7
|
+
// @react-native-community/cli (lexical, symlink-preserving) to
|
|
8
|
+
// expo-modules-autolinking (realpath). The two flavors emit different
|
|
9
|
+
// :path strings on pnpm/yarn-symlink layouts, so to keep CocoaPods happy
|
|
10
|
+
// we must match whichever flavor will resolve the same package later.
|
|
11
|
+
const RN_REALPATH_AUTOLINKING_MIN_VERSION = '0.80.0';
|
|
12
|
+
const PLUGIN_LOG_PREFIX = '[CustomerIO Plugin]';
|
|
6
13
|
|
|
7
|
-
|
|
8
|
-
|
|
14
|
+
// Always-on so the trail shows up in customer-shared `expo prebuild`
|
|
15
|
+
// output without needing a separate verbose-mode opt-in.
|
|
16
|
+
function pluginLog(message) {
|
|
17
|
+
// eslint-disable-next-line no-console
|
|
18
|
+
console.log(`${PLUGIN_LOG_PREFIX} ${message}`);
|
|
19
|
+
}
|
|
9
20
|
|
|
10
|
-
|
|
11
|
-
|
|
21
|
+
/**
|
|
22
|
+
* Returns the relative path from the iOS project dir to the installed
|
|
23
|
+
* customerio-reactnative directory, in the exact form React Native pod
|
|
24
|
+
* autolinking will emit for the same package. The two autolinking
|
|
25
|
+
* flavors disagree on path shape under pnpm/yarn symlinks:
|
|
26
|
+
*
|
|
27
|
+
* - RN <0.80 (`@react-native-community/cli`): walks node_modules
|
|
28
|
+
* lexically, preserves symlinks. We keep the symlink path too —
|
|
29
|
+
* `tryResolveRNSDK` already does this without calling realpath.
|
|
30
|
+
*
|
|
31
|
+
* - RN >=0.80 (`expo-modules-autolinking`): realpaths the package
|
|
32
|
+
* via Node, emitting the underlying `.pnpm/...` (or yarn-classic)
|
|
33
|
+
* path. We match by realpath'ing the resolved directory.
|
|
34
|
+
*
|
|
35
|
+
* Decision points are logged so a customer's prebuild output is enough
|
|
36
|
+
* to triage path-resolution issues without a follow-up "set
|
|
37
|
+
* CUSTOMERIO_DEBUG_MODE and rerun" round-trip.
|
|
38
|
+
*/
|
|
39
|
+
export function getRelativePathToRNSDK(iosPath) {
|
|
40
|
+
const rootAppPath = path.dirname(iosPath);
|
|
41
|
+
pluginLog(`Resolving customerio-reactnative for Podfile (iosPath=${iosPath}, projectRoot=${rootAppPath})`);
|
|
42
|
+
const {
|
|
43
|
+
packageDir
|
|
44
|
+
} = resolveRNSDK(rootAppPath);
|
|
45
|
+
pluginLog(`customerio-reactnative resolved to: ${packageDir}`);
|
|
46
|
+
const rnVersion = tryReadRNVersion(rootAppPath);
|
|
47
|
+
pluginLog(`Detected react-native version: ${rnVersion ?? 'unknown'}`);
|
|
48
|
+
const useLexical = shouldUseLexicalPath(rnVersion);
|
|
49
|
+
pluginLog(useLexical ? `RN <${RN_REALPATH_AUTOLINKING_MIN_VERSION} — using lexical/symlink path to match @react-native-community/cli autolinking` : `RN >=${RN_REALPATH_AUTOLINKING_MIN_VERSION} or unknown — using realpath to match expo-modules-autolinking`);
|
|
50
|
+
let absolutePath;
|
|
51
|
+
if (useLexical) {
|
|
52
|
+
absolutePath = packageDir;
|
|
53
|
+
} else {
|
|
54
|
+
try {
|
|
55
|
+
absolutePath = fs.realpathSync(packageDir);
|
|
56
|
+
if (absolutePath !== packageDir) {
|
|
57
|
+
pluginLog(`Realpath differs from resolved dir: ${absolutePath}`);
|
|
58
|
+
}
|
|
59
|
+
} catch (err) {
|
|
60
|
+
pluginLog(`realpathSync failed (${err instanceof Error ? err.message : String(err)}); falling back to symlink path`);
|
|
61
|
+
absolutePath = packageDir;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
const relativePath = path.relative(iosPath, absolutePath);
|
|
65
|
+
pluginLog(`Final Podfile :path => '${relativePath}'`);
|
|
66
|
+
return relativePath;
|
|
67
|
+
}
|
|
68
|
+
function shouldUseLexicalPath(rnVersion) {
|
|
69
|
+
if (!rnVersion) {
|
|
70
|
+
// Modern Expo (realpath) has been the working path for the last few
|
|
71
|
+
// SDKs, so it's the safer default when RN can't be detected.
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
const coerced = semver.valid(rnVersion) || semver.coerce(rnVersion);
|
|
75
|
+
if (!coerced) {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
return semver.lt(coerced, RN_REALPATH_AUTOLINKING_MIN_VERSION);
|
|
12
79
|
}
|
|
13
80
|
export const IOS_DEPLOYMENT_TARGET = '13.0';
|
|
14
81
|
export const GROUP_IDENTIFIER_TEMPLATE_REGEX = /{{GROUP_IDENTIFIER}}/gm;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["path","require","resolveFrom","getRelativePathToRNSDK","iosPath","rootAppPath","dirname","pluginPackageJsonPath","silent","relative","IOS_DEPLOYMENT_TARGET","GROUP_IDENTIFIER_TEMPLATE_REGEX","BUNDLE_SHORT_VERSION_TEMPLATE_REGEX","BUNDLE_VERSION_TEMPLATE_REGEX","CIO_DIDFINISHLAUNCHINGMETHOD_REGEX","CIO_DIDFAILTOREGISTERFORREMOTENOTIFICATIONSWITHERROR_REGEX","CIO_DIDFAILTOREGISTERFORREMOTENOTIFICATIONSWITHERRORFULL_REGEX","CIO_DIDREGISTERFORREMOTENOTIFICATIONSWITHDEVICETOKEN_REGEX","CIO_APPDELEGATEDECLARATION_REGEX","CIO_APPDELEGATEHEADER_REGEX","CIO_RCTBRIDGE_DEEPLINK_MODIFIEDOPTIONS_REGEX","CIO_LAUNCHOPTIONS_DEEPLINK_MODIFIEDOPTIONS_REGEX","CIO_DEEPLINK_COMMENT_REGEX","DEFAULT_BUNDLE_VERSION","DEFAULT_BUNDLE_SHORT_VERSION","CIO_TARGET_NAME","CIO_NOTIFICATION_TARGET_NAME","CIO_APPDELEGATEHEADER_IMPORT_SNIPPET","CIO_APPDELEGATEHEADER_USER_NOTIFICATION_CENTER_SNIPPET","CIO_PUSHNOTIFICATIONHANDLERDECLARATION_SNIPPET","CIO_RCTBRIDGE_DEEPLINK_MODIFIEDOPTIONS_SNIPPET","CIO_LAUNCHOPTIONS_MODIFIEDOPTIONS_SNIPPET","CIO_DIDFAILTOREGISTERFORREMOTENOTIFICATIONSWITHERROR_SNIPPET","CIO_DIDREGISTERFORREMOTENOTIFICATIONSWITHDEVICETOKEN_SNIPPET","CIO_CONFIGURECIOSDKPUSHNOTIFICATION_SNIPPET","CIO_INITIALIZECIOSDK_SNIPPET","CIO_CONFIGUREDEEPLINK_KILLEDSTATE_SNIPPET","CIO_CONFIGUREDEEPLINK_KILLEDSTATE_SWIFT_SNIPPET","CIO_REGISTER_PUSHNOTIFICATION_SNIPPET","CIO_REGISTER_PUSHNOTIFICATION_SNIPPET_v2","CIO_REGISTER_PUSH_NOTIFICATION_PLACEHOLDER","CIO_MESSAGING_PUSH_APP_DELEGATE_INIT_REGEX","CIO_NATIVE_SDK_INITIALIZE_CALL","CIO_NATIVE_SDK_INITIALIZE_SNIPPET"],"sources":["ios.ts"],"sourcesContent":["const path = require('path');\nconst resolveFrom = require('resolve-from');\n\nexport function getRelativePathToRNSDK(iosPath: string) {\n // Root path of the Expo project\n const rootAppPath = path.dirname(iosPath);\n\n // Path of the cio RN package.json file. Example: test-app/node_modules/customerio-reactnative/package.json\n const pluginPackageJsonPath = resolveFrom.silent(\n rootAppPath,\n `customerio-reactnative/package.json`\n );\n\n // Example: ../node_modules/customerio-reactnative\n return path.relative(iosPath, path.dirname(pluginPackageJsonPath));\n}\n\nexport const IOS_DEPLOYMENT_TARGET = '13.0';\nexport const GROUP_IDENTIFIER_TEMPLATE_REGEX = /{{GROUP_IDENTIFIER}}/gm;\nexport const BUNDLE_SHORT_VERSION_TEMPLATE_REGEX = /{{BUNDLE_SHORT_VERSION}}/gm;\nexport const BUNDLE_VERSION_TEMPLATE_REGEX = /{{BUNDLE_VERSION}}/gm;\nexport const CIO_DIDFINISHLAUNCHINGMETHOD_REGEX =\n /.*\\[super(\\s)application:application(\\s)didFinishLaunchingWithOptions:launchOptions\\];/;\n\nexport const CIO_DIDFAILTOREGISTERFORREMOTENOTIFICATIONSWITHERROR_REGEX =\n /return \\[super application:application didFailToRegisterForRemoteNotificationsWithError:error\\];/;\n\nexport const CIO_DIDFAILTOREGISTERFORREMOTENOTIFICATIONSWITHERRORFULL_REGEX =\n /(- \\(void\\)application:\\(UIApplication \\*\\)application didFailToRegisterForRemoteNotificationsWithError:\\(NSError \\*\\)error(\\s|\\n)*?\\{)(.|\\n){2}.*\\n\\}/;\n\nexport const CIO_DIDREGISTERFORREMOTENOTIFICATIONSWITHDEVICETOKEN_REGEX =\n /return \\[super application:application didRegisterForRemoteNotificationsWithDeviceToken:deviceToken\\];/;\n\nexport const CIO_APPDELEGATEDECLARATION_REGEX =\n /@implementation AppDelegate(.|\\n)/;\n\nexport const CIO_APPDELEGATEHEADER_REGEX =\n /(@interface AppDelegate\\s*:\\s*EXAppDelegateWrapper\\s*)(<([^>]+)>)?/;\n\nexport const CIO_RCTBRIDGE_DEEPLINK_MODIFIEDOPTIONS_REGEX =\n /^\\s*RCTBridge\\s*\\*\\s*\\w+\\s*=\\s*\\[\\s*self\\.reactDelegate\\s+createBridgeWithDelegate:self\\s+launchOptions:launchOptions\\s*\\];\\s*$/gm;\n\nexport const CIO_LAUNCHOPTIONS_DEEPLINK_MODIFIEDOPTIONS_REGEX =\n /^\\s*return\\s\\[\\s*super\\s*application:\\s*application\\s*didFinishLaunchingWithOptions\\s*:\\s*launchOptions\\s*\\];/gm;\n\nexport const CIO_DEEPLINK_COMMENT_REGEX =\n /\\sDeep link workaround for app killed state start/gm;\nexport const DEFAULT_BUNDLE_VERSION = '1';\nexport const DEFAULT_BUNDLE_SHORT_VERSION = '1.0';\nexport const CIO_TARGET_NAME = 'CustomerIOSDK';\nexport const CIO_NOTIFICATION_TARGET_NAME = 'NotificationService';\n\nexport const CIO_APPDELEGATEHEADER_IMPORT_SNIPPET = `#import <UserNotifications/UserNotifications.h>`;\nexport const CIO_APPDELEGATEHEADER_USER_NOTIFICATION_CENTER_SNIPPET =\n 'UNUserNotificationCenterDelegate';\nexport const CIO_PUSHNOTIFICATIONHANDLERDECLARATION_SNIPPET = `\nCIOAppPushNotificationsHandler* pnHandlerObj = [[CIOAppPushNotificationsHandler alloc] init];\n`;\nexport const CIO_RCTBRIDGE_DEEPLINK_MODIFIEDOPTIONS_SNIPPET = `\nRCTBridge *bridge = [self.reactDelegate createBridgeWithDelegate:self launchOptions:modifiedLaunchOptions];\n`;\n\nexport const CIO_LAUNCHOPTIONS_MODIFIEDOPTIONS_SNIPPET = `\nreturn [super application:application didFinishLaunchingWithOptions:modifiedLaunchOptions];`;\n\nexport const CIO_DIDFAILTOREGISTERFORREMOTENOTIFICATIONSWITHERROR_SNIPPET = `\n [super application:application didFailToRegisterForRemoteNotificationsWithError:error];\n [pnHandlerObj application:application error:error];\n`;\n\nexport const CIO_DIDREGISTERFORREMOTENOTIFICATIONSWITHDEVICETOKEN_SNIPPET = `\n [super application:application didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];\n return [pnHandlerObj application:application deviceToken:deviceToken];\n`;\n\nexport const CIO_CONFIGURECIOSDKPUSHNOTIFICATION_SNIPPET = `\n // Register for push notifications\n [pnHandlerObj registerPushNotification];\n`;\n\nexport const CIO_INITIALIZECIOSDK_SNIPPET = ` \n [pnHandlerObj initializeCioSdk];\n\n// Code to make the CIO SDK compatible with expo-notifications package.\n// \n// The CIO SDK and expo-notifications both need to handle when a push gets clicked. However, iOS only allows one click handler to be set per app.\n// To get around this limitation, we set the CIO SDK as the click handler. The CIO SDK sets itself up so that when another SDK or host iOS app \n// sets itself as the click handler, the CIO SDK will still be able to handle when the push gets clicked, even though it's not the designated \n// click handler in iOS at runtime. \n// \n// This should work for most SDKs. However, expo-notifications is unique in it's implementation. It will not setup push click handling it if detects \n// that another SDK or host iOS app has already set itself as the click handler:\n// https://github.com/expo/expo/blob/1b29637bec0b9888e8bc8c310476293a3e2d9786/packages/expo-notifications/ios/EXNotifications/Notifications/EXNotificationCenterDelegate.m#L31-L37\n// ...to get around this, we must manually set it as the click handler after the CIO SDK. That's what this code block does.\n//\n// Note: Initialize the native iOS SDK and setup SDK push click handling before running this code. \n# if __has_include(<EXNotifications/EXNotificationCenterDelegate.h>)\n // Creating a new instance, as the comments in expo-notifications suggests, does not work. With this code, if you send a CIO push to device and click on it,\n // no push metrics reporting will occur.\n // EXNotificationCenterDelegate *notificationCenterDelegate = [[EXNotificationCenterDelegate alloc] init];\n\n // ...instead, get the singleton reference from Expo. \n id<UNUserNotificationCenterDelegate> notificationCenterDelegate = (id<UNUserNotificationCenterDelegate>) [EXModuleRegistryProvider getSingletonModuleForClass:[EXNotificationCenterDelegate class]];\n UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];\n center.delegate = notificationCenterDelegate;\n# endif\n`;\n\nexport const CIO_CONFIGUREDEEPLINK_KILLEDSTATE_SNIPPET = `\n// Deep link workaround for app killed state start\nNSMutableDictionary *modifiedLaunchOptions = [NSMutableDictionary dictionaryWithDictionary:launchOptions];\n if (launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]) {\n NSDictionary *pushContent = launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey];\n if (pushContent[@\"CIO\"] && pushContent[@\"CIO\"][@\"push\"] && pushContent[@\"CIO\"][@\"push\"][@\"link\"]) {\n NSString *initialURL = pushContent[@\"CIO\"][@\"push\"][@\"link\"];\n if (!launchOptions[UIApplicationLaunchOptionsURLKey]) {\n modifiedLaunchOptions[UIApplicationLaunchOptionsURLKey] = [NSURL URLWithString:initialURL];\n }\n }\n }\n//Deep link workaround for app killed state ends\n`;\n\nexport const CIO_CONFIGUREDEEPLINK_KILLEDSTATE_SWIFT_SNIPPET = `\n // Deep link workaround for app killed state start\n var modifiedLaunchOptions = launchOptions\n if let launchOptions = launchOptions,\n let pushContent = launchOptions[UIApplication.LaunchOptionsKey.remoteNotification] as? [AnyHashable: Any],\n let cio = pushContent[\"CIO\"] as? [String: Any],\n let push = cio[\"push\"] as? [String: Any],\n let link = push[\"link\"] as? String,\n !launchOptions.keys.contains(UIApplication.LaunchOptionsKey.url) {\n \n var mutableLaunchOptions = launchOptions\n mutableLaunchOptions[UIApplication.LaunchOptionsKey.url] = URL(string: link)\n modifiedLaunchOptions = mutableLaunchOptions\n }\n // Deep link workaround for app killed state ends\n`;\n\nexport const CIO_REGISTER_PUSHNOTIFICATION_SNIPPET = `\n@objc(registerPushNotification)\n public func registerPushNotification() {\n\n let center = UNUserNotificationCenter.current()\n center.requestAuthorization(options: [.sound, .alert, .badge]) { (granted, error) in\n if error == nil{\n DispatchQueue.main.async {\n UIApplication.shared.registerForRemoteNotifications()\n }\n }\n }\n }`;\n\nexport const CIO_REGISTER_PUSHNOTIFICATION_SNIPPET_v2 = `\n let center = UNUserNotificationCenter.current()\n center.requestAuthorization(options: [.sound, .alert, .badge]) { (granted, error) in\n if error == nil{\n DispatchQueue.main.async {\n UIApplication.shared.registerForRemoteNotifications()\n }\n }\n }`;\n\nexport const CIO_REGISTER_PUSH_NOTIFICATION_PLACEHOLDER = /\\{\\{REGISTER_SNIPPET\\}\\}/;\n// Regex to match MessagingPush initialization in AppDelegate (different from NSE initialization)\nexport const CIO_MESSAGING_PUSH_APP_DELEGATE_INIT_REGEX = /(MessagingPush(?:APN|FCM)\\.initialize)/;\nexport const CIO_NATIVE_SDK_INITIALIZE_CALL = 'CustomerIOSDKInitializer.initialize()';\nexport const CIO_NATIVE_SDK_INITIALIZE_SNIPPET = `// Auto Initialize Native Customer.io SDK\n ${CIO_NATIVE_SDK_INITIALIZE_CALL}\n `;\n"],"mappings":"AAAA,MAAMA,IAAI,GAAGC,OAAO,CAAC,MAAM,CAAC;AAC5B,MAAMC,WAAW,GAAGD,OAAO,CAAC,cAAc,CAAC;AAE3C,OAAO,SAASE,sBAAsBA,CAACC,OAAe,EAAE;EACtD;EACA,MAAMC,WAAW,GAAGL,IAAI,CAACM,OAAO,CAACF,OAAO,CAAC;;EAEzC;EACA,MAAMG,qBAAqB,GAAGL,WAAW,CAACM,MAAM,CAC9CH,WAAW,EACX,qCACF,CAAC;;EAED;EACA,OAAOL,IAAI,CAACS,QAAQ,CAACL,OAAO,EAAEJ,IAAI,CAACM,OAAO,CAACC,qBAAqB,CAAC,CAAC;AACpE;AAEA,OAAO,MAAMG,qBAAqB,GAAG,MAAM;AAC3C,OAAO,MAAMC,+BAA+B,GAAG,wBAAwB;AACvE,OAAO,MAAMC,mCAAmC,GAAG,4BAA4B;AAC/E,OAAO,MAAMC,6BAA6B,GAAG,sBAAsB;AACnE,OAAO,MAAMC,kCAAkC,GAC7C,wFAAwF;AAE1F,OAAO,MAAMC,0DAA0D,GACrE,kGAAkG;AAEpG,OAAO,MAAMC,8DAA8D,GACzE,wJAAwJ;AAE1J,OAAO,MAAMC,0DAA0D,GACrE,wGAAwG;AAE1G,OAAO,MAAMC,gCAAgC,GAC3C,mCAAmC;AAErC,OAAO,MAAMC,2BAA2B,GACtC,oEAAoE;AAEtE,OAAO,MAAMC,4CAA4C,GACvD,mIAAmI;AAErI,OAAO,MAAMC,gDAAgD,GAC3D,iHAAiH;AAEnH,OAAO,MAAMC,0BAA0B,GACrC,qDAAqD;AACvD,OAAO,MAAMC,sBAAsB,GAAG,GAAG;AACzC,OAAO,MAAMC,4BAA4B,GAAG,KAAK;AACjD,OAAO,MAAMC,eAAe,GAAG,eAAe;AAC9C,OAAO,MAAMC,4BAA4B,GAAG,qBAAqB;AAEjE,OAAO,MAAMC,oCAAoC,GAAG,iDAAiD;AACrG,OAAO,MAAMC,sDAAsD,GACjE,kCAAkC;AACpC,OAAO,MAAMC,8CAA8C,GAAG;AAC9D;AACA,CAAC;AACD,OAAO,MAAMC,8CAA8C,GAAG;AAC9D;AACA,CAAC;AAED,OAAO,MAAMC,yCAAyC,GAAG;AACzD,4FAA4F;AAE5F,OAAO,MAAMC,4DAA4D,GAAG;AAC5E;AACA;AACA,CAAC;AAED,OAAO,MAAMC,4DAA4D,GAAG;AAC5E;AACA;AACA,CAAC;AAED,OAAO,MAAMC,2CAA2C,GAAG;AAC3D;AACA;AACA,CAAC;AAED,OAAO,MAAMC,4BAA4B,GAAG;AAC5C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;AAED,OAAO,MAAMC,yCAAyC,GAAG;AACzD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;AAED,OAAO,MAAMC,+CAA+C,GAAG;AAC/D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;AAED,OAAO,MAAMC,qCAAqC,GAAG;AACrD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI;AAEJ,OAAO,MAAMC,wCAAwC,GAAG;AACxD;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM;AAEN,OAAO,MAAMC,0CAA0C,GAAG,0BAA0B;AACpF;AACA,OAAO,MAAMC,0CAA0C,GAAG,wCAAwC;AAClG,OAAO,MAAMC,8BAA8B,GAAG,uCAAuC;AACrF,OAAO,MAAMC,iCAAiC,GAAG;AACjD,MAAMD,8BAA8B;AACpC,KAAK","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["fs","semver","path","require","resolveRNSDK","tryReadRNVersion","RN_REALPATH_AUTOLINKING_MIN_VERSION","PLUGIN_LOG_PREFIX","pluginLog","message","console","log","getRelativePathToRNSDK","iosPath","rootAppPath","dirname","packageDir","rnVersion","useLexical","shouldUseLexicalPath","absolutePath","realpathSync","err","Error","String","relativePath","relative","coerced","valid","coerce","lt","IOS_DEPLOYMENT_TARGET","GROUP_IDENTIFIER_TEMPLATE_REGEX","BUNDLE_SHORT_VERSION_TEMPLATE_REGEX","BUNDLE_VERSION_TEMPLATE_REGEX","CIO_DIDFINISHLAUNCHINGMETHOD_REGEX","CIO_DIDFAILTOREGISTERFORREMOTENOTIFICATIONSWITHERROR_REGEX","CIO_DIDFAILTOREGISTERFORREMOTENOTIFICATIONSWITHERRORFULL_REGEX","CIO_DIDREGISTERFORREMOTENOTIFICATIONSWITHDEVICETOKEN_REGEX","CIO_APPDELEGATEDECLARATION_REGEX","CIO_APPDELEGATEHEADER_REGEX","CIO_RCTBRIDGE_DEEPLINK_MODIFIEDOPTIONS_REGEX","CIO_LAUNCHOPTIONS_DEEPLINK_MODIFIEDOPTIONS_REGEX","CIO_DEEPLINK_COMMENT_REGEX","DEFAULT_BUNDLE_VERSION","DEFAULT_BUNDLE_SHORT_VERSION","CIO_TARGET_NAME","CIO_NOTIFICATION_TARGET_NAME","CIO_APPDELEGATEHEADER_IMPORT_SNIPPET","CIO_APPDELEGATEHEADER_USER_NOTIFICATION_CENTER_SNIPPET","CIO_PUSHNOTIFICATIONHANDLERDECLARATION_SNIPPET","CIO_RCTBRIDGE_DEEPLINK_MODIFIEDOPTIONS_SNIPPET","CIO_LAUNCHOPTIONS_MODIFIEDOPTIONS_SNIPPET","CIO_DIDFAILTOREGISTERFORREMOTENOTIFICATIONSWITHERROR_SNIPPET","CIO_DIDREGISTERFORREMOTENOTIFICATIONSWITHDEVICETOKEN_SNIPPET","CIO_CONFIGURECIOSDKPUSHNOTIFICATION_SNIPPET","CIO_INITIALIZECIOSDK_SNIPPET","CIO_CONFIGUREDEEPLINK_KILLEDSTATE_SNIPPET","CIO_CONFIGUREDEEPLINK_KILLEDSTATE_SWIFT_SNIPPET","CIO_REGISTER_PUSHNOTIFICATION_SNIPPET","CIO_REGISTER_PUSHNOTIFICATION_SNIPPET_v2","CIO_REGISTER_PUSH_NOTIFICATION_PLACEHOLDER","CIO_MESSAGING_PUSH_APP_DELEGATE_INIT_REGEX","CIO_NATIVE_SDK_INITIALIZE_CALL","CIO_NATIVE_SDK_INITIALIZE_SNIPPET"],"sources":["ios.ts"],"sourcesContent":["import fs from 'fs';\nimport * as semver from 'semver';\n\nconst path = require('path');\nimport { resolveRNSDK, tryReadRNVersion } from '../../utils/resolveRNSDK';\n\n// Threshold at which React Native pod autolinking moves from\n// @react-native-community/cli (lexical, symlink-preserving) to\n// expo-modules-autolinking (realpath). The two flavors emit different\n// :path strings on pnpm/yarn-symlink layouts, so to keep CocoaPods happy\n// we must match whichever flavor will resolve the same package later.\nconst RN_REALPATH_AUTOLINKING_MIN_VERSION = '0.80.0';\n\nconst PLUGIN_LOG_PREFIX = '[CustomerIO Plugin]';\n\n// Always-on so the trail shows up in customer-shared `expo prebuild`\n// output without needing a separate verbose-mode opt-in.\nfunction pluginLog(message: string): void {\n // eslint-disable-next-line no-console\n console.log(`${PLUGIN_LOG_PREFIX} ${message}`);\n}\n\n/**\n * Returns the relative path from the iOS project dir to the installed\n * customerio-reactnative directory, in the exact form React Native pod\n * autolinking will emit for the same package. The two autolinking\n * flavors disagree on path shape under pnpm/yarn symlinks:\n *\n * - RN <0.80 (`@react-native-community/cli`): walks node_modules\n * lexically, preserves symlinks. We keep the symlink path too —\n * `tryResolveRNSDK` already does this without calling realpath.\n *\n * - RN >=0.80 (`expo-modules-autolinking`): realpaths the package\n * via Node, emitting the underlying `.pnpm/...` (or yarn-classic)\n * path. We match by realpath'ing the resolved directory.\n *\n * Decision points are logged so a customer's prebuild output is enough\n * to triage path-resolution issues without a follow-up \"set\n * CUSTOMERIO_DEBUG_MODE and rerun\" round-trip.\n */\nexport function getRelativePathToRNSDK(iosPath: string) {\n const rootAppPath = path.dirname(iosPath);\n pluginLog(\n `Resolving customerio-reactnative for Podfile (iosPath=${iosPath}, projectRoot=${rootAppPath})`\n );\n\n const { packageDir } = resolveRNSDK(rootAppPath);\n pluginLog(`customerio-reactnative resolved to: ${packageDir}`);\n\n const rnVersion = tryReadRNVersion(rootAppPath);\n pluginLog(`Detected react-native version: ${rnVersion ?? 'unknown'}`);\n\n const useLexical = shouldUseLexicalPath(rnVersion);\n pluginLog(\n useLexical\n ? `RN <${RN_REALPATH_AUTOLINKING_MIN_VERSION} — using lexical/symlink path to match @react-native-community/cli autolinking`\n : `RN >=${RN_REALPATH_AUTOLINKING_MIN_VERSION} or unknown — using realpath to match expo-modules-autolinking`\n );\n\n let absolutePath: string;\n if (useLexical) {\n absolutePath = packageDir;\n } else {\n try {\n absolutePath = fs.realpathSync(packageDir);\n if (absolutePath !== packageDir) {\n pluginLog(`Realpath differs from resolved dir: ${absolutePath}`);\n }\n } catch (err) {\n pluginLog(\n `realpathSync failed (${\n err instanceof Error ? err.message : String(err)\n }); falling back to symlink path`\n );\n absolutePath = packageDir;\n }\n }\n\n const relativePath = path.relative(iosPath, absolutePath);\n pluginLog(`Final Podfile :path => '${relativePath}'`);\n return relativePath;\n}\n\nfunction shouldUseLexicalPath(rnVersion: string | null): boolean {\n if (!rnVersion) {\n // Modern Expo (realpath) has been the working path for the last few\n // SDKs, so it's the safer default when RN can't be detected.\n return false;\n }\n const coerced = semver.valid(rnVersion) || semver.coerce(rnVersion);\n if (!coerced) {\n return false;\n }\n return semver.lt(coerced, RN_REALPATH_AUTOLINKING_MIN_VERSION);\n}\n\nexport const IOS_DEPLOYMENT_TARGET = '13.0';\nexport const GROUP_IDENTIFIER_TEMPLATE_REGEX = /{{GROUP_IDENTIFIER}}/gm;\nexport const BUNDLE_SHORT_VERSION_TEMPLATE_REGEX = /{{BUNDLE_SHORT_VERSION}}/gm;\nexport const BUNDLE_VERSION_TEMPLATE_REGEX = /{{BUNDLE_VERSION}}/gm;\nexport const CIO_DIDFINISHLAUNCHINGMETHOD_REGEX =\n /.*\\[super(\\s)application:application(\\s)didFinishLaunchingWithOptions:launchOptions\\];/;\n\nexport const CIO_DIDFAILTOREGISTERFORREMOTENOTIFICATIONSWITHERROR_REGEX =\n /return \\[super application:application didFailToRegisterForRemoteNotificationsWithError:error\\];/;\n\nexport const CIO_DIDFAILTOREGISTERFORREMOTENOTIFICATIONSWITHERRORFULL_REGEX =\n /(- \\(void\\)application:\\(UIApplication \\*\\)application didFailToRegisterForRemoteNotificationsWithError:\\(NSError \\*\\)error(\\s|\\n)*?\\{)(.|\\n){2}.*\\n\\}/;\n\nexport const CIO_DIDREGISTERFORREMOTENOTIFICATIONSWITHDEVICETOKEN_REGEX =\n /return \\[super application:application didRegisterForRemoteNotificationsWithDeviceToken:deviceToken\\];/;\n\nexport const CIO_APPDELEGATEDECLARATION_REGEX =\n /@implementation AppDelegate(.|\\n)/;\n\nexport const CIO_APPDELEGATEHEADER_REGEX =\n /(@interface AppDelegate\\s*:\\s*EXAppDelegateWrapper\\s*)(<([^>]+)>)?/;\n\nexport const CIO_RCTBRIDGE_DEEPLINK_MODIFIEDOPTIONS_REGEX =\n /^\\s*RCTBridge\\s*\\*\\s*\\w+\\s*=\\s*\\[\\s*self\\.reactDelegate\\s+createBridgeWithDelegate:self\\s+launchOptions:launchOptions\\s*\\];\\s*$/gm;\n\nexport const CIO_LAUNCHOPTIONS_DEEPLINK_MODIFIEDOPTIONS_REGEX =\n /^\\s*return\\s\\[\\s*super\\s*application:\\s*application\\s*didFinishLaunchingWithOptions\\s*:\\s*launchOptions\\s*\\];/gm;\n\nexport const CIO_DEEPLINK_COMMENT_REGEX =\n /\\sDeep link workaround for app killed state start/gm;\nexport const DEFAULT_BUNDLE_VERSION = '1';\nexport const DEFAULT_BUNDLE_SHORT_VERSION = '1.0';\nexport const CIO_TARGET_NAME = 'CustomerIOSDK';\nexport const CIO_NOTIFICATION_TARGET_NAME = 'NotificationService';\n\nexport const CIO_APPDELEGATEHEADER_IMPORT_SNIPPET = `#import <UserNotifications/UserNotifications.h>`;\nexport const CIO_APPDELEGATEHEADER_USER_NOTIFICATION_CENTER_SNIPPET =\n 'UNUserNotificationCenterDelegate';\nexport const CIO_PUSHNOTIFICATIONHANDLERDECLARATION_SNIPPET = `\nCIOAppPushNotificationsHandler* pnHandlerObj = [[CIOAppPushNotificationsHandler alloc] init];\n`;\nexport const CIO_RCTBRIDGE_DEEPLINK_MODIFIEDOPTIONS_SNIPPET = `\nRCTBridge *bridge = [self.reactDelegate createBridgeWithDelegate:self launchOptions:modifiedLaunchOptions];\n`;\n\nexport const CIO_LAUNCHOPTIONS_MODIFIEDOPTIONS_SNIPPET = `\nreturn [super application:application didFinishLaunchingWithOptions:modifiedLaunchOptions];`;\n\nexport const CIO_DIDFAILTOREGISTERFORREMOTENOTIFICATIONSWITHERROR_SNIPPET = `\n [super application:application didFailToRegisterForRemoteNotificationsWithError:error];\n [pnHandlerObj application:application error:error];\n`;\n\nexport const CIO_DIDREGISTERFORREMOTENOTIFICATIONSWITHDEVICETOKEN_SNIPPET = `\n [super application:application didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];\n return [pnHandlerObj application:application deviceToken:deviceToken];\n`;\n\nexport const CIO_CONFIGURECIOSDKPUSHNOTIFICATION_SNIPPET = `\n // Register for push notifications\n [pnHandlerObj registerPushNotification];\n`;\n\nexport const CIO_INITIALIZECIOSDK_SNIPPET = ` \n [pnHandlerObj initializeCioSdk];\n\n// Code to make the CIO SDK compatible with expo-notifications package.\n// \n// The CIO SDK and expo-notifications both need to handle when a push gets clicked. However, iOS only allows one click handler to be set per app.\n// To get around this limitation, we set the CIO SDK as the click handler. The CIO SDK sets itself up so that when another SDK or host iOS app \n// sets itself as the click handler, the CIO SDK will still be able to handle when the push gets clicked, even though it's not the designated \n// click handler in iOS at runtime. \n// \n// This should work for most SDKs. However, expo-notifications is unique in it's implementation. It will not setup push click handling it if detects \n// that another SDK or host iOS app has already set itself as the click handler:\n// https://github.com/expo/expo/blob/1b29637bec0b9888e8bc8c310476293a3e2d9786/packages/expo-notifications/ios/EXNotifications/Notifications/EXNotificationCenterDelegate.m#L31-L37\n// ...to get around this, we must manually set it as the click handler after the CIO SDK. That's what this code block does.\n//\n// Note: Initialize the native iOS SDK and setup SDK push click handling before running this code. \n# if __has_include(<EXNotifications/EXNotificationCenterDelegate.h>)\n // Creating a new instance, as the comments in expo-notifications suggests, does not work. With this code, if you send a CIO push to device and click on it,\n // no push metrics reporting will occur.\n // EXNotificationCenterDelegate *notificationCenterDelegate = [[EXNotificationCenterDelegate alloc] init];\n\n // ...instead, get the singleton reference from Expo. \n id<UNUserNotificationCenterDelegate> notificationCenterDelegate = (id<UNUserNotificationCenterDelegate>) [EXModuleRegistryProvider getSingletonModuleForClass:[EXNotificationCenterDelegate class]];\n UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];\n center.delegate = notificationCenterDelegate;\n# endif\n`;\n\nexport const CIO_CONFIGUREDEEPLINK_KILLEDSTATE_SNIPPET = `\n// Deep link workaround for app killed state start\nNSMutableDictionary *modifiedLaunchOptions = [NSMutableDictionary dictionaryWithDictionary:launchOptions];\n if (launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]) {\n NSDictionary *pushContent = launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey];\n if (pushContent[@\"CIO\"] && pushContent[@\"CIO\"][@\"push\"] && pushContent[@\"CIO\"][@\"push\"][@\"link\"]) {\n NSString *initialURL = pushContent[@\"CIO\"][@\"push\"][@\"link\"];\n if (!launchOptions[UIApplicationLaunchOptionsURLKey]) {\n modifiedLaunchOptions[UIApplicationLaunchOptionsURLKey] = [NSURL URLWithString:initialURL];\n }\n }\n }\n//Deep link workaround for app killed state ends\n`;\n\nexport const CIO_CONFIGUREDEEPLINK_KILLEDSTATE_SWIFT_SNIPPET = `\n // Deep link workaround for app killed state start\n var modifiedLaunchOptions = launchOptions\n if let launchOptions = launchOptions,\n let pushContent = launchOptions[UIApplication.LaunchOptionsKey.remoteNotification] as? [AnyHashable: Any],\n let cio = pushContent[\"CIO\"] as? [String: Any],\n let push = cio[\"push\"] as? [String: Any],\n let link = push[\"link\"] as? String,\n !launchOptions.keys.contains(UIApplication.LaunchOptionsKey.url) {\n \n var mutableLaunchOptions = launchOptions\n mutableLaunchOptions[UIApplication.LaunchOptionsKey.url] = URL(string: link)\n modifiedLaunchOptions = mutableLaunchOptions\n }\n // Deep link workaround for app killed state ends\n`;\n\nexport const CIO_REGISTER_PUSHNOTIFICATION_SNIPPET = `\n@objc(registerPushNotification)\n public func registerPushNotification() {\n\n let center = UNUserNotificationCenter.current()\n center.requestAuthorization(options: [.sound, .alert, .badge]) { (granted, error) in\n if error == nil{\n DispatchQueue.main.async {\n UIApplication.shared.registerForRemoteNotifications()\n }\n }\n }\n }`;\n\nexport const CIO_REGISTER_PUSHNOTIFICATION_SNIPPET_v2 = `\n let center = UNUserNotificationCenter.current()\n center.requestAuthorization(options: [.sound, .alert, .badge]) { (granted, error) in\n if error == nil{\n DispatchQueue.main.async {\n UIApplication.shared.registerForRemoteNotifications()\n }\n }\n }`;\n\nexport const CIO_REGISTER_PUSH_NOTIFICATION_PLACEHOLDER = /\\{\\{REGISTER_SNIPPET\\}\\}/;\n// Regex to match MessagingPush initialization in AppDelegate (different from NSE initialization)\nexport const CIO_MESSAGING_PUSH_APP_DELEGATE_INIT_REGEX = /(MessagingPush(?:APN|FCM)\\.initialize)/;\nexport const CIO_NATIVE_SDK_INITIALIZE_CALL = 'CustomerIOSDKInitializer.initialize()';\nexport const CIO_NATIVE_SDK_INITIALIZE_SNIPPET = `// Auto Initialize Native Customer.io SDK\n ${CIO_NATIVE_SDK_INITIALIZE_CALL}\n `;\n"],"mappings":"AAAA,OAAOA,EAAE,MAAM,IAAI;AACnB,OAAO,KAAKC,MAAM,MAAM,QAAQ;AAEhC,MAAMC,IAAI,GAAGC,OAAO,CAAC,MAAM,CAAC;AAC5B,SAASC,YAAY,EAAEC,gBAAgB,QAAQ,0BAA0B;;AAEzE;AACA;AACA;AACA;AACA;AACA,MAAMC,mCAAmC,GAAG,QAAQ;AAEpD,MAAMC,iBAAiB,GAAG,qBAAqB;;AAE/C;AACA;AACA,SAASC,SAASA,CAACC,OAAe,EAAQ;EACxC;EACAC,OAAO,CAACC,GAAG,CAAC,GAAGJ,iBAAiB,IAAIE,OAAO,EAAE,CAAC;AAChD;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASG,sBAAsBA,CAACC,OAAe,EAAE;EACtD,MAAMC,WAAW,GAAGZ,IAAI,CAACa,OAAO,CAACF,OAAO,CAAC;EACzCL,SAAS,CACP,yDAAyDK,OAAO,iBAAiBC,WAAW,GAC9F,CAAC;EAED,MAAM;IAAEE;EAAW,CAAC,GAAGZ,YAAY,CAACU,WAAW,CAAC;EAChDN,SAAS,CAAC,uCAAuCQ,UAAU,EAAE,CAAC;EAE9D,MAAMC,SAAS,GAAGZ,gBAAgB,CAACS,WAAW,CAAC;EAC/CN,SAAS,CAAC,kCAAkCS,SAAS,IAAI,SAAS,EAAE,CAAC;EAErE,MAAMC,UAAU,GAAGC,oBAAoB,CAACF,SAAS,CAAC;EAClDT,SAAS,CACPU,UAAU,GACN,OAAOZ,mCAAmC,gFAAgF,GAC1H,QAAQA,mCAAmC,gEACjD,CAAC;EAED,IAAIc,YAAoB;EACxB,IAAIF,UAAU,EAAE;IACdE,YAAY,GAAGJ,UAAU;EAC3B,CAAC,MAAM;IACL,IAAI;MACFI,YAAY,GAAGpB,EAAE,CAACqB,YAAY,CAACL,UAAU,CAAC;MAC1C,IAAII,YAAY,KAAKJ,UAAU,EAAE;QAC/BR,SAAS,CAAC,uCAAuCY,YAAY,EAAE,CAAC;MAClE;IACF,CAAC,CAAC,OAAOE,GAAG,EAAE;MACZd,SAAS,CACP,wBACEc,GAAG,YAAYC,KAAK,GAAGD,GAAG,CAACb,OAAO,GAAGe,MAAM,CAACF,GAAG,CAAC,iCAEpD,CAAC;MACDF,YAAY,GAAGJ,UAAU;IAC3B;EACF;EAEA,MAAMS,YAAY,GAAGvB,IAAI,CAACwB,QAAQ,CAACb,OAAO,EAAEO,YAAY,CAAC;EACzDZ,SAAS,CAAC,2BAA2BiB,YAAY,GAAG,CAAC;EACrD,OAAOA,YAAY;AACrB;AAEA,SAASN,oBAAoBA,CAACF,SAAwB,EAAW;EAC/D,IAAI,CAACA,SAAS,EAAE;IACd;IACA;IACA,OAAO,KAAK;EACd;EACA,MAAMU,OAAO,GAAG1B,MAAM,CAAC2B,KAAK,CAACX,SAAS,CAAC,IAAIhB,MAAM,CAAC4B,MAAM,CAACZ,SAAS,CAAC;EACnE,IAAI,CAACU,OAAO,EAAE;IACZ,OAAO,KAAK;EACd;EACA,OAAO1B,MAAM,CAAC6B,EAAE,CAACH,OAAO,EAAErB,mCAAmC,CAAC;AAChE;AAEA,OAAO,MAAMyB,qBAAqB,GAAG,MAAM;AAC3C,OAAO,MAAMC,+BAA+B,GAAG,wBAAwB;AACvE,OAAO,MAAMC,mCAAmC,GAAG,4BAA4B;AAC/E,OAAO,MAAMC,6BAA6B,GAAG,sBAAsB;AACnE,OAAO,MAAMC,kCAAkC,GAC7C,wFAAwF;AAE1F,OAAO,MAAMC,0DAA0D,GACrE,kGAAkG;AAEpG,OAAO,MAAMC,8DAA8D,GACzE,wJAAwJ;AAE1J,OAAO,MAAMC,0DAA0D,GACrE,wGAAwG;AAE1G,OAAO,MAAMC,gCAAgC,GAC3C,mCAAmC;AAErC,OAAO,MAAMC,2BAA2B,GACtC,oEAAoE;AAEtE,OAAO,MAAMC,4CAA4C,GACvD,mIAAmI;AAErI,OAAO,MAAMC,gDAAgD,GAC3D,iHAAiH;AAEnH,OAAO,MAAMC,0BAA0B,GACrC,qDAAqD;AACvD,OAAO,MAAMC,sBAAsB,GAAG,GAAG;AACzC,OAAO,MAAMC,4BAA4B,GAAG,KAAK;AACjD,OAAO,MAAMC,eAAe,GAAG,eAAe;AAC9C,OAAO,MAAMC,4BAA4B,GAAG,qBAAqB;AAEjE,OAAO,MAAMC,oCAAoC,GAAG,iDAAiD;AACrG,OAAO,MAAMC,sDAAsD,GACjE,kCAAkC;AACpC,OAAO,MAAMC,8CAA8C,GAAG;AAC9D;AACA,CAAC;AACD,OAAO,MAAMC,8CAA8C,GAAG;AAC9D;AACA,CAAC;AAED,OAAO,MAAMC,yCAAyC,GAAG;AACzD,4FAA4F;AAE5F,OAAO,MAAMC,4DAA4D,GAAG;AAC5E;AACA;AACA,CAAC;AAED,OAAO,MAAMC,4DAA4D,GAAG;AAC5E;AACA;AACA,CAAC;AAED,OAAO,MAAMC,2CAA2C,GAAG;AAC3D;AACA;AACA,CAAC;AAED,OAAO,MAAMC,4BAA4B,GAAG;AAC5C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;AAED,OAAO,MAAMC,yCAAyC,GAAG;AACzD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;AAED,OAAO,MAAMC,+CAA+C,GAAG;AAC/D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;AAED,OAAO,MAAMC,qCAAqC,GAAG;AACrD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI;AAEJ,OAAO,MAAMC,wCAAwC,GAAG;AACxD;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM;AAEN,OAAO,MAAMC,0CAA0C,GAAG,0BAA0B;AACpF;AACA,OAAO,MAAMC,0CAA0C,GAAG,wCAAwC;AAClG,OAAO,MAAMC,8BAA8B,GAAG,uCAAuC;AACrF,OAAO,MAAMC,iCAAiC,GAAG;AACjD,MAAMD,8BAA8B;AACpC,KAAK","ignoreList":[]}
|
|
@@ -2,59 +2,102 @@ import { logger } from '../../utils/logger';
|
|
|
2
2
|
import { getRelativePathToRNSDK } from '../constants/ios';
|
|
3
3
|
import { injectCodeByRegex } from './codeInjection';
|
|
4
4
|
import { FileManagement } from './fileManagement';
|
|
5
|
-
/** Builds the host
|
|
5
|
+
/** Builds the host-app pod snippet for the Podfile.
|
|
6
|
+
*
|
|
7
|
+
* The :path is resolved at prebuild time by `getRelativePathToRNSDK`,
|
|
8
|
+
* which dispatches on the installed React Native version so the path
|
|
9
|
+
* matches what RN pod autolinking will emit (lexical for RN <0.80,
|
|
10
|
+
* realpath for RN >=0.80). Baking the resolved string directly avoids
|
|
11
|
+
* any Ruby/install-time logic in the Podfile and keeps the snippet
|
|
12
|
+
* trivially diff-able.
|
|
13
|
+
*
|
|
14
|
+
* Exported for tests.
|
|
15
|
+
*/
|
|
6
16
|
export function buildHostAppPodSnippet(iosPath, isFcmPushProvider, options) {
|
|
7
|
-
const
|
|
17
|
+
const resolvedPath = getRelativePathToRNSDK(iosPath);
|
|
8
18
|
const locationEnabled = (options === null || options === void 0 ? void 0 : options.locationEnabled) === true;
|
|
9
19
|
const hasPush = (options === null || options === void 0 ? void 0 : options.hasPush) !== false;
|
|
10
20
|
if (!locationEnabled) {
|
|
11
21
|
const subspec = isFcmPushProvider ? 'fcm' : 'apn';
|
|
12
|
-
return `pod 'customerio-reactnative/${subspec}', :path => '${
|
|
22
|
+
return `pod 'customerio-reactnative/${subspec}', :path => '${resolvedPath}'`;
|
|
13
23
|
}
|
|
14
24
|
if (!hasPush) {
|
|
15
|
-
return `pod 'customerio-reactnative', :subspecs => ['location'], :path => '${
|
|
25
|
+
return `pod 'customerio-reactnative', :subspecs => ['location'], :path => '${resolvedPath}'`;
|
|
16
26
|
}
|
|
17
27
|
const pushSubspec = isFcmPushProvider ? 'fcm' : 'apn';
|
|
18
|
-
return `pod 'customerio-reactnative', :subspecs => ['${pushSubspec}', 'location'], :path => '${
|
|
28
|
+
return `pod 'customerio-reactnative', :subspecs => ['${pushSubspec}', 'location'], :path => '${resolvedPath}'`;
|
|
29
|
+
}
|
|
30
|
+
const HOST_APP_BLOCK_START = '# --- CustomerIO Host App START ---';
|
|
31
|
+
const HOST_APP_BLOCK_END = '# --- CustomerIO Host App END ---';
|
|
32
|
+
const NOTIFICATION_BLOCK_START = '# --- CustomerIO Notification START ---';
|
|
33
|
+
const NOTIFICATION_BLOCK_END = '# --- CustomerIO Notification END ---';
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Pure string transform: given the existing Podfile contents, returns the
|
|
37
|
+
* Podfile with the CustomerIO host-app block injected before the Expo
|
|
38
|
+
* `post_install do |installer|` anchor. Idempotent — returns input unchanged
|
|
39
|
+
* if the block is already present.
|
|
40
|
+
*/
|
|
41
|
+
export function injectHostAppPodfileCode(podfileContent, iosPath, isFcmPushProvider, options) {
|
|
42
|
+
if (podfileContent.match(new RegExp(HOST_APP_BLOCK_START))) {
|
|
43
|
+
return podfileContent;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// We need to decide what line of code in the Podfile to insert our native code.
|
|
47
|
+
// The "post_install" line is always present in an Expo project Podfile so it's reliable.
|
|
48
|
+
// Find that line in the Podfile and then we will insert our code above that line.
|
|
49
|
+
const lineInPodfileToInjectSnippetBefore = /post_install do \|installer\|/;
|
|
50
|
+
const podLine = buildHostAppPodSnippet(iosPath, isFcmPushProvider, options);
|
|
51
|
+
const snippetToInjectInPodfile = `
|
|
52
|
+
${HOST_APP_BLOCK_START}
|
|
53
|
+
${podLine}
|
|
54
|
+
${HOST_APP_BLOCK_END}
|
|
55
|
+
`.trim();
|
|
56
|
+
return injectCodeByRegex(podfileContent, lineInPodfileToInjectSnippetBefore, snippetToInjectInPodfile).join('\n');
|
|
19
57
|
}
|
|
20
58
|
export async function injectCIOPodfileCode(iosPath, isFcmPushProvider, options) {
|
|
21
|
-
const blockStart = '# --- CustomerIO Host App START ---';
|
|
22
|
-
const blockEnd = '# --- CustomerIO Host App END ---';
|
|
23
59
|
const filename = `${iosPath}/Podfile`;
|
|
24
60
|
const podfile = await FileManagement.read(filename);
|
|
25
|
-
const
|
|
26
|
-
if (
|
|
27
|
-
|
|
28
|
-
// The "post_install" line is always present in an Expo project Podfile so it's reliable.
|
|
29
|
-
// Find that line in the Podfile and then we will insert our code above that line.
|
|
30
|
-
const lineInPodfileToInjectSnippetBefore = /post_install do \|installer\|/;
|
|
31
|
-
const podLine = buildHostAppPodSnippet(iosPath, isFcmPushProvider, options);
|
|
32
|
-
const snippetToInjectInPodfile = `
|
|
33
|
-
${blockStart}
|
|
34
|
-
${podLine}
|
|
35
|
-
${blockEnd}
|
|
36
|
-
`.trim();
|
|
37
|
-
FileManagement.write(filename, injectCodeByRegex(podfile, lineInPodfileToInjectSnippetBefore, snippetToInjectInPodfile).join('\n'));
|
|
61
|
+
const next = injectHostAppPodfileCode(podfile, iosPath, isFcmPushProvider, options);
|
|
62
|
+
if (next !== podfile) {
|
|
63
|
+
FileManagement.write(filename, next);
|
|
38
64
|
} else {
|
|
39
65
|
logger.info('CustomerIO Podfile snippets already exists. Skipping...');
|
|
40
66
|
}
|
|
41
67
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Pure string transform: given the existing Podfile contents, returns the
|
|
71
|
+
* Podfile with the rich-push NotificationService target block appended at
|
|
72
|
+
* the end. Idempotent — returns input unchanged if the block is already
|
|
73
|
+
* present.
|
|
74
|
+
*/
|
|
75
|
+
export function appendNotificationTargetToPodfile(podfileContent, iosPath, isFcmPushProvider, useFrameworks) {
|
|
76
|
+
if (podfileContent.match(new RegExp(NOTIFICATION_BLOCK_START))) {
|
|
77
|
+
return podfileContent;
|
|
78
|
+
}
|
|
79
|
+
const snippetToAppend = `
|
|
80
|
+
${NOTIFICATION_BLOCK_START}
|
|
51
81
|
target 'NotificationService' do
|
|
52
82
|
${useFrameworks === 'static' ? 'use_frameworks! :linkage => :static' : ''}
|
|
53
83
|
pod 'customerio-reactnative-richpush/${isFcmPushProvider ? 'fcm' : 'apn'}', :path => '${getRelativePathToRNSDK(iosPath)}'
|
|
54
84
|
end
|
|
55
|
-
${
|
|
85
|
+
${NOTIFICATION_BLOCK_END}
|
|
56
86
|
`.trim();
|
|
57
|
-
|
|
87
|
+
|
|
88
|
+
// Mirror FileManagement.append: append directly with no separator (real
|
|
89
|
+
// Podfiles end with a trailing newline, so the appended block starts on a
|
|
90
|
+
// fresh line in practice).
|
|
91
|
+
return `${podfileContent}${snippetToAppend}`;
|
|
92
|
+
}
|
|
93
|
+
export async function injectCIONotificationPodfileCode(iosPath, useFrameworks, isFcmPushProvider) {
|
|
94
|
+
const filename = `${iosPath}/Podfile`;
|
|
95
|
+
const podfile = await FileManagement.read(filename);
|
|
96
|
+
const next = appendNotificationTargetToPodfile(podfile, iosPath, isFcmPushProvider, useFrameworks);
|
|
97
|
+
if (next !== podfile) {
|
|
98
|
+
// FileManagement.append matches what the previous direct-append did.
|
|
99
|
+
// Slice off the leading content (already on disk) and append only the new tail.
|
|
100
|
+
FileManagement.append(filename, next.slice(podfile.length));
|
|
58
101
|
}
|
|
59
102
|
}
|
|
60
103
|
//# sourceMappingURL=injectCIOPodfileCode.js.map
|