customerio-expo-plugin 3.2.0 → 3.4.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.
Files changed (78) hide show
  1. package/package.json +8 -2
  2. package/plugin/lib/commonjs/helpers/constants/ios.js +76 -8
  3. package/plugin/lib/commonjs/helpers/constants/ios.js.map +1 -1
  4. package/plugin/lib/commonjs/helpers/native-files/ios/apn/CioSdkAppDelegateHandler.swift +1 -1
  5. package/plugin/lib/commonjs/helpers/native-files/ios/apn/NotificationService.swift +1 -1
  6. package/plugin/lib/commonjs/helpers/native-files/ios/apn/PushService.swift +1 -1
  7. package/plugin/lib/commonjs/helpers/native-files/ios/fcm/CioSdkAppDelegateHandler.swift +1 -1
  8. package/plugin/lib/commonjs/helpers/native-files/ios/fcm/NotificationService.swift +1 -1
  9. package/plugin/lib/commonjs/helpers/native-files/ios/fcm/PushService.swift +1 -1
  10. package/plugin/lib/commonjs/helpers/utils/injectCIOPodfileCode.js +20 -7
  11. package/plugin/lib/commonjs/helpers/utils/injectCIOPodfileCode.js.map +1 -1
  12. package/plugin/lib/commonjs/index.js +7 -0
  13. package/plugin/lib/commonjs/index.js.map +1 -1
  14. package/plugin/lib/commonjs/ios/withCIOIos.js +17 -0
  15. package/plugin/lib/commonjs/ios/withCIOIos.js.map +1 -1
  16. package/plugin/lib/commonjs/ios/withCIOIosSwift.js +24 -15
  17. package/plugin/lib/commonjs/ios/withCIOIosSwift.js.map +1 -1
  18. package/plugin/lib/commonjs/ios/withNotificationsXcodeProject.js +45 -11
  19. package/plugin/lib/commonjs/ios/withNotificationsXcodeProject.js.map +1 -1
  20. package/plugin/lib/commonjs/postInstallHelper.js +58 -11
  21. package/plugin/lib/commonjs/postInstallHelper.js.map +1 -1
  22. package/plugin/lib/commonjs/types/cio-types.js.map +1 -1
  23. package/plugin/lib/commonjs/utils/resolveRNSDK.js +97 -0
  24. package/plugin/lib/commonjs/utils/resolveRNSDK.js.map +1 -0
  25. package/plugin/lib/commonjs/utils/validation.js +13 -0
  26. package/plugin/lib/commonjs/utils/validation.js.map +1 -1
  27. package/plugin/lib/commonjs/utils/writeExpoVersion.js +56 -0
  28. package/plugin/lib/commonjs/utils/writeExpoVersion.js.map +1 -0
  29. package/plugin/lib/module/helpers/constants/ios.js +75 -8
  30. package/plugin/lib/module/helpers/constants/ios.js.map +1 -1
  31. package/plugin/lib/module/helpers/native-files/ios/apn/CioSdkAppDelegateHandler.swift +1 -1
  32. package/plugin/lib/module/helpers/native-files/ios/apn/NotificationService.swift +1 -1
  33. package/plugin/lib/module/helpers/native-files/ios/apn/PushService.swift +1 -1
  34. package/plugin/lib/module/helpers/native-files/ios/fcm/CioSdkAppDelegateHandler.swift +1 -1
  35. package/plugin/lib/module/helpers/native-files/ios/fcm/NotificationService.swift +1 -1
  36. package/plugin/lib/module/helpers/native-files/ios/fcm/PushService.swift +1 -1
  37. package/plugin/lib/module/helpers/utils/injectCIOPodfileCode.js +20 -7
  38. package/plugin/lib/module/helpers/utils/injectCIOPodfileCode.js.map +1 -1
  39. package/plugin/lib/module/index.js +7 -0
  40. package/plugin/lib/module/index.js.map +1 -1
  41. package/plugin/lib/module/ios/withCIOIos.js +17 -0
  42. package/plugin/lib/module/ios/withCIOIos.js.map +1 -1
  43. package/plugin/lib/module/ios/withCIOIosSwift.js +24 -15
  44. package/plugin/lib/module/ios/withCIOIosSwift.js.map +1 -1
  45. package/plugin/lib/module/ios/withNotificationsXcodeProject.js +45 -11
  46. package/plugin/lib/module/ios/withNotificationsXcodeProject.js.map +1 -1
  47. package/plugin/lib/module/postInstallHelper.js +58 -11
  48. package/plugin/lib/module/postInstallHelper.js.map +1 -1
  49. package/plugin/lib/module/types/cio-types.js.map +1 -1
  50. package/plugin/lib/module/utils/resolveRNSDK.js +88 -0
  51. package/plugin/lib/module/utils/resolveRNSDK.js.map +1 -0
  52. package/plugin/lib/module/utils/validation.js +13 -1
  53. package/plugin/lib/module/utils/validation.js.map +1 -1
  54. package/plugin/lib/module/utils/writeExpoVersion.js +48 -0
  55. package/plugin/lib/module/utils/writeExpoVersion.js.map +1 -0
  56. package/plugin/lib/typescript/helpers/constants/ios.d.ts +18 -0
  57. package/plugin/lib/typescript/helpers/utils/injectCIOPodfileCode.d.ts +11 -1
  58. package/plugin/lib/typescript/types/cio-types.d.ts +7 -0
  59. package/plugin/lib/typescript/utils/resolveRNSDK.d.ts +7 -0
  60. package/plugin/lib/typescript/utils/validation.d.ts +3 -2
  61. package/plugin/lib/typescript/utils/writeExpoVersion.d.ts +3 -0
  62. package/plugin/src/helpers/constants/ios.ts +87 -8
  63. package/plugin/src/helpers/native-files/ios/apn/CioSdkAppDelegateHandler.swift +1 -1
  64. package/plugin/src/helpers/native-files/ios/apn/NotificationService.swift +1 -1
  65. package/plugin/src/helpers/native-files/ios/apn/PushService.swift +1 -1
  66. package/plugin/src/helpers/native-files/ios/fcm/CioSdkAppDelegateHandler.swift +1 -1
  67. package/plugin/src/helpers/native-files/ios/fcm/NotificationService.swift +1 -1
  68. package/plugin/src/helpers/native-files/ios/fcm/PushService.swift +1 -1
  69. package/plugin/src/helpers/utils/injectCIOPodfileCode.ts +22 -10
  70. package/plugin/src/index.ts +7 -0
  71. package/plugin/src/ios/withCIOIos.ts +16 -0
  72. package/plugin/src/ios/withCIOIosSwift.ts +35 -12
  73. package/plugin/src/ios/withNotificationsXcodeProject.ts +56 -1
  74. package/plugin/src/postInstallHelper.js +75 -17
  75. package/plugin/src/types/cio-types.ts +8 -0
  76. package/plugin/src/utils/resolveRNSDK.ts +118 -0
  77. package/plugin/src/utils/validation.ts +18 -1
  78. package/plugin/src/utils/writeExpoVersion.ts +62 -0
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.resolveRNSDK = resolveRNSDK;
7
+ exports.tryReadRNVersion = tryReadRNVersion;
8
+ exports.tryResolveRNSDK = tryResolveRNSDK;
9
+ var _fs = _interopRequireDefault(require("fs"));
10
+ var _path = _interopRequireDefault(require("path"));
11
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
12
+ const RN_SDK_PACKAGE = 'customerio-reactnative';
13
+ const REACT_NATIVE_PACKAGE = 'react-native';
14
+ // Reads the installed react-native package's version starting from `fromDir`.
15
+ // Used to decide which autolinking flavor will resolve customerio-reactnative
16
+ // at pod install time, so our :path agrees with what autolinking emits:
17
+ // - RN <0.80 ships @react-native-community/cli, which uses a lexical
18
+ // resolution (no realpath following).
19
+ // - RN >=0.80 routes pod autolinking through expo-modules-autolinking,
20
+ // which realpaths.
21
+ // Returns null if react-native cannot be located or its package.json cannot
22
+ // be read; callers should default to the modern (realpath) behavior in that
23
+ // case since it has been the working path for the last several Expo SDKs.
24
+ function tryReadRNVersion(fromDir) {
25
+ try {
26
+ const direct = _path.default.join(fromDir, 'node_modules', REACT_NATIVE_PACKAGE, 'package.json');
27
+ if (_fs.default.existsSync(direct)) {
28
+ return readVersion(direct);
29
+ }
30
+ const resolveFrom = require('resolve-from');
31
+ const fallback = resolveFrom.silent(fromDir, `${REACT_NATIVE_PACKAGE}/package.json`);
32
+ if (fallback) {
33
+ return readVersion(fallback);
34
+ }
35
+ } catch {
36
+ // Fall through to null.
37
+ }
38
+ return null;
39
+ }
40
+ function readVersion(pkgJsonPath) {
41
+ try {
42
+ const pkg = JSON.parse(_fs.default.readFileSync(pkgJsonPath, 'utf-8'));
43
+ return typeof pkg.version === 'string' ? pkg.version : null;
44
+ } catch {
45
+ return null;
46
+ }
47
+ }
48
+
49
+ // Resolves the customerio-reactnative SDK location starting from `fromDir`.
50
+ //
51
+ // Probe-then-fallback so the result agrees with React Native autolinking
52
+ // across npm flat, pnpm, and yarn-workspace layouts:
53
+ // 1. `fromDir/node_modules/customerio-reactnative/package.json` — preferred.
54
+ // Works for npm flat, pnpm (the symlinked path; we never realpath it),
55
+ // and yarn workspaces with leaf node_modules. Matches what RN
56
+ // autolinking emits for its pod entry, so CocoaPods sees one
57
+ // consistent :path.
58
+ // 2. `resolve-from` walking up from `fromDir` — only used when (1) misses.
59
+ // Handles yarn classic workspaces where the dep is hoisted to a parent
60
+ // node_modules. yarn classic has no symlinks, so the realpath is fine.
61
+ //
62
+ // Returns null if neither finds the package, including the case where
63
+ // `resolve-from` itself can't be required (mirrors tryReadRNVersion's
64
+ // graceful-failure shape so callers can rely on the documented contract).
65
+ function tryResolveRNSDK(fromDir) {
66
+ try {
67
+ const directPkgJson = _path.default.join(fromDir, 'node_modules', RN_SDK_PACKAGE, 'package.json');
68
+ if (_fs.default.existsSync(directPkgJson)) {
69
+ return {
70
+ packageDir: _path.default.dirname(directPkgJson),
71
+ packageJsonPath: directPkgJson
72
+ };
73
+ }
74
+ const resolveFrom = require('resolve-from');
75
+ const fallbackPkgJson = resolveFrom.silent(fromDir, `${RN_SDK_PACKAGE}/package.json`);
76
+ if (fallbackPkgJson) {
77
+ return {
78
+ packageDir: _path.default.dirname(fallbackPkgJson),
79
+ packageJsonPath: fallbackPkgJson
80
+ };
81
+ }
82
+ } catch {
83
+ // Fall through to null. resolveRNSDK() turns this into a clear
84
+ // "customerio-reactnative was not found" error for the caller.
85
+ }
86
+ return null;
87
+ }
88
+
89
+ // Same as tryResolveRNSDK but throws a clear error when the package is missing.
90
+ function resolveRNSDK(fromDir) {
91
+ const resolved = tryResolveRNSDK(fromDir);
92
+ if (!resolved) {
93
+ throw new Error(`${RN_SDK_PACKAGE} was not found relative to ${fromDir}. ` + `Ensure it is installed in your project (or in a parent workspace's node_modules).`);
94
+ }
95
+ return resolved;
96
+ }
97
+ //# sourceMappingURL=resolveRNSDK.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_fs","_interopRequireDefault","require","_path","e","__esModule","default","RN_SDK_PACKAGE","REACT_NATIVE_PACKAGE","tryReadRNVersion","fromDir","direct","path","join","fs","existsSync","readVersion","resolveFrom","fallback","silent","pkgJsonPath","pkg","JSON","parse","readFileSync","version","tryResolveRNSDK","directPkgJson","packageDir","dirname","packageJsonPath","fallbackPkgJson","resolveRNSDK","resolved","Error"],"sources":["resolveRNSDK.ts"],"sourcesContent":["import fs from 'fs';\nimport path from 'path';\n\nconst RN_SDK_PACKAGE = 'customerio-reactnative';\nconst REACT_NATIVE_PACKAGE = 'react-native';\n\nexport type ResolvedRNSDK = {\n // Absolute path to the package directory.\n packageDir: string;\n // Absolute path to package.json inside that directory.\n packageJsonPath: string;\n};\n\n// Reads the installed react-native package's version starting from `fromDir`.\n// Used to decide which autolinking flavor will resolve customerio-reactnative\n// at pod install time, so our :path agrees with what autolinking emits:\n// - RN <0.80 ships @react-native-community/cli, which uses a lexical\n// resolution (no realpath following).\n// - RN >=0.80 routes pod autolinking through expo-modules-autolinking,\n// which realpaths.\n// Returns null if react-native cannot be located or its package.json cannot\n// be read; callers should default to the modern (realpath) behavior in that\n// case since it has been the working path for the last several Expo SDKs.\nexport function tryReadRNVersion(fromDir: string): string | null {\n try {\n const direct = path.join(\n fromDir,\n 'node_modules',\n REACT_NATIVE_PACKAGE,\n 'package.json'\n );\n if (fs.existsSync(direct)) {\n return readVersion(direct);\n }\n const resolveFrom = require('resolve-from');\n const fallback = resolveFrom.silent(\n fromDir,\n `${REACT_NATIVE_PACKAGE}/package.json`\n );\n if (fallback) {\n return readVersion(fallback);\n }\n } catch {\n // Fall through to null.\n }\n return null;\n}\n\nfunction readVersion(pkgJsonPath: string): string | null {\n try {\n const pkg = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf-8'));\n return typeof pkg.version === 'string' ? pkg.version : null;\n } catch {\n return null;\n }\n}\n\n// Resolves the customerio-reactnative SDK location starting from `fromDir`.\n//\n// Probe-then-fallback so the result agrees with React Native autolinking\n// across npm flat, pnpm, and yarn-workspace layouts:\n// 1. `fromDir/node_modules/customerio-reactnative/package.json` — preferred.\n// Works for npm flat, pnpm (the symlinked path; we never realpath it),\n// and yarn workspaces with leaf node_modules. Matches what RN\n// autolinking emits for its pod entry, so CocoaPods sees one\n// consistent :path.\n// 2. `resolve-from` walking up from `fromDir` — only used when (1) misses.\n// Handles yarn classic workspaces where the dep is hoisted to a parent\n// node_modules. yarn classic has no symlinks, so the realpath is fine.\n//\n// Returns null if neither finds the package, including the case where\n// `resolve-from` itself can't be required (mirrors tryReadRNVersion's\n// graceful-failure shape so callers can rely on the documented contract).\nexport function tryResolveRNSDK(fromDir: string): ResolvedRNSDK | null {\n try {\n const directPkgJson = path.join(\n fromDir,\n 'node_modules',\n RN_SDK_PACKAGE,\n 'package.json'\n );\n if (fs.existsSync(directPkgJson)) {\n return {\n packageDir: path.dirname(directPkgJson),\n packageJsonPath: directPkgJson,\n };\n }\n\n const resolveFrom = require('resolve-from');\n const fallbackPkgJson = resolveFrom.silent(\n fromDir,\n `${RN_SDK_PACKAGE}/package.json`\n );\n if (fallbackPkgJson) {\n return {\n packageDir: path.dirname(fallbackPkgJson),\n packageJsonPath: fallbackPkgJson,\n };\n }\n } catch {\n // Fall through to null. resolveRNSDK() turns this into a clear\n // \"customerio-reactnative was not found\" error for the caller.\n }\n\n return null;\n}\n\n// Same as tryResolveRNSDK but throws a clear error when the package is missing.\nexport function resolveRNSDK(fromDir: string): ResolvedRNSDK {\n const resolved = tryResolveRNSDK(fromDir);\n if (!resolved) {\n throw new Error(\n `${RN_SDK_PACKAGE} was not found relative to ${fromDir}. ` +\n `Ensure it is installed in your project (or in a parent workspace's node_modules).`\n );\n }\n return resolved;\n}\n"],"mappings":";;;;;;;;AAAA,IAAAA,GAAA,GAAAC,sBAAA,CAAAC,OAAA;AACA,IAAAC,KAAA,GAAAF,sBAAA,CAAAC,OAAA;AAAwB,SAAAD,uBAAAG,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAExB,MAAMG,cAAc,GAAG,wBAAwB;AAC/C,MAAMC,oBAAoB,GAAG,cAAc;AAS3C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAASC,gBAAgBA,CAACC,OAAe,EAAiB;EAC/D,IAAI;IACF,MAAMC,MAAM,GAAGC,aAAI,CAACC,IAAI,CACtBH,OAAO,EACP,cAAc,EACdF,oBAAoB,EACpB,cACF,CAAC;IACD,IAAIM,WAAE,CAACC,UAAU,CAACJ,MAAM,CAAC,EAAE;MACzB,OAAOK,WAAW,CAACL,MAAM,CAAC;IAC5B;IACA,MAAMM,WAAW,GAAGf,OAAO,CAAC,cAAc,CAAC;IAC3C,MAAMgB,QAAQ,GAAGD,WAAW,CAACE,MAAM,CACjCT,OAAO,EACP,GAAGF,oBAAoB,eACzB,CAAC;IACD,IAAIU,QAAQ,EAAE;MACZ,OAAOF,WAAW,CAACE,QAAQ,CAAC;IAC9B;EACF,CAAC,CAAC,MAAM;IACN;EAAA;EAEF,OAAO,IAAI;AACb;AAEA,SAASF,WAAWA,CAACI,WAAmB,EAAiB;EACvD,IAAI;IACF,MAAMC,GAAG,GAAGC,IAAI,CAACC,KAAK,CAACT,WAAE,CAACU,YAAY,CAACJ,WAAW,EAAE,OAAO,CAAC,CAAC;IAC7D,OAAO,OAAOC,GAAG,CAACI,OAAO,KAAK,QAAQ,GAAGJ,GAAG,CAACI,OAAO,GAAG,IAAI;EAC7D,CAAC,CAAC,MAAM;IACN,OAAO,IAAI;EACb;AACF;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAASC,eAAeA,CAAChB,OAAe,EAAwB;EACrE,IAAI;IACF,MAAMiB,aAAa,GAAGf,aAAI,CAACC,IAAI,CAC7BH,OAAO,EACP,cAAc,EACdH,cAAc,EACd,cACF,CAAC;IACD,IAAIO,WAAE,CAACC,UAAU,CAACY,aAAa,CAAC,EAAE;MAChC,OAAO;QACLC,UAAU,EAAEhB,aAAI,CAACiB,OAAO,CAACF,aAAa,CAAC;QACvCG,eAAe,EAAEH;MACnB,CAAC;IACH;IAEA,MAAMV,WAAW,GAAGf,OAAO,CAAC,cAAc,CAAC;IAC3C,MAAM6B,eAAe,GAAGd,WAAW,CAACE,MAAM,CACxCT,OAAO,EACP,GAAGH,cAAc,eACnB,CAAC;IACD,IAAIwB,eAAe,EAAE;MACnB,OAAO;QACLH,UAAU,EAAEhB,aAAI,CAACiB,OAAO,CAACE,eAAe,CAAC;QACzCD,eAAe,EAAEC;MACnB,CAAC;IACH;EACF,CAAC,CAAC,MAAM;IACN;IACA;EAAA;EAGF,OAAO,IAAI;AACb;;AAEA;AACO,SAASC,YAAYA,CAACtB,OAAe,EAAiB;EAC3D,MAAMuB,QAAQ,GAAGP,eAAe,CAAChB,OAAO,CAAC;EACzC,IAAI,CAACuB,QAAQ,EAAE;IACb,MAAM,IAAIC,KAAK,CACb,GAAG3B,cAAc,8BAA8BG,OAAO,IAAI,GAC1D,mFACF,CAAC;EACH;EACA,OAAOuB,QAAQ;AACjB","ignoreList":[]}
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.validateNativeSDKConfig = validateNativeSDKConfig;
7
+ exports.validatePushNotificationOptions = validatePushNotificationOptions;
7
8
  exports.validateRequired = validateRequired;
8
9
  exports.validateRichPushConfig = validateRichPushConfig;
9
10
  exports.validateString = validateString;
@@ -84,4 +85,16 @@ function validateRichPushConfig(config) {
84
85
  isValid = validateRegion(config === null || config === void 0 ? void 0 : config.region, 'region', context) && isValid;
85
86
  return isValid;
86
87
  }
88
+ function validatePushNotificationOptions(options) {
89
+ const context = 'PushNotification';
90
+ let isValid = true;
91
+ const appGroupId = options.appGroupId;
92
+ if (appGroupId !== undefined) {
93
+ isValid = validateString(appGroupId, 'appGroupId', context) && isValid;
94
+ if (isValid && !appGroupId.startsWith('group.')) {
95
+ _logger.logger.warn(`${context}: appGroupId "${appGroupId}" does not start with "group." — ensure this matches your Apple App Group entitlement.`);
96
+ }
97
+ }
98
+ return isValid;
99
+ }
87
100
  //# sourceMappingURL=validation.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["_logger","require","validate","isValid","messageFactory","message","process","env","CUSTOMERIO_STRICT_MODE","Error","logger","format","warn","isUndefined","value","undefined","validateRequired","fieldName","context","validateString","trim","validateBoolean","validateEnum","allowedValues","lowerValue","toLowerCase","lowerAllowedValues","map","v","includes","valuesStr","join","validateRegion","validateNativeSDKConfig","config","cdpApiKey","region","screenViewUse","logLevel","autoTrackDeviceAttributes","trackApplicationLifecycleEvents","siteId","migrationSiteId","validateRichPushConfig"],"sources":["validation.ts"],"sourcesContent":["import type { NativeSDKConfig, RichPushConfig } from '../types/cio-types';\nimport { logger } from './logger';\n\n/**\n * Validates a condition and handles errors based on CUSTOMERIO_STRICT_MODE flag.\n * @param isValid - Function that returns true if validation passes\n * @param messageFactory - Function that returns the error message if validation fails\n * @returns true if validation passes, false if it fails\n */\nfunction validate(isValid: () => boolean, messageFactory: () => string): boolean {\n if (isValid()) {\n return true;\n }\n\n // Throw errors unless explicitly disabled, default to strict validation\n const message = messageFactory();\n // Throw an error if strict mode is enabled, log a warning otherwise\n if (process.env.CUSTOMERIO_STRICT_MODE === 'true') {\n throw new Error(logger.format(message));\n } else {\n logger.warn(message);\n }\n return false;\n}\n\nfunction isUndefined(value: unknown): boolean {\n return value === undefined;\n}\n\nfunction validateRequired(value: unknown, fieldName: string, context: string): boolean {\n return validate(\n () => !isUndefined(value) && value !== null,\n () => `${context}: ${fieldName} is required, received: ${value}`\n );\n}\n\nfunction validateString(value: unknown, fieldName: string, context: string): boolean {\n return validate(\n () => isUndefined(value) || (typeof value === 'string' && value.trim() !== ''),\n () => `${context}: ${fieldName} must be a non-empty string, received: ${typeof value === 'string' ? `\"${value}\"` : value}`\n );\n}\n\nfunction validateBoolean(value: unknown, fieldName: string, context: string): boolean {\n return validate(\n () => isUndefined(value) || typeof value === 'boolean',\n () => `${context}: ${fieldName} must be a boolean, received: ${value}`\n );\n}\n\nfunction validateEnum<T extends string>(\n value: unknown,\n fieldName: string,\n allowedValues: readonly T[],\n context: string\n): boolean {\n if (isUndefined(value)) return true;\n\n // First validate it's a string\n if (!validateString(value, fieldName, context)) {\n return false;\n }\n\n // Then validate it's in the allowed values\n return validate(\n () => {\n const lowerValue = (value as string).toLowerCase();\n const lowerAllowedValues = allowedValues.map(v => v.toLowerCase());\n return lowerAllowedValues.includes(lowerValue);\n },\n () => {\n const valuesStr = allowedValues.map(v => `\"${v}\"`).join(', ');\n return `${context}: ${fieldName} must be one of ${valuesStr}, received: ${value}`;\n }\n );\n}\n\nfunction validateRegion(value: unknown, fieldName: string, context: string): boolean {\n return validateEnum(value, fieldName, ['US', 'EU'], context);\n}\n\nfunction validateNativeSDKConfig(config: NativeSDKConfig): boolean {\n const context = 'NativeSDKConfig';\n\n let isValid = true;\n\n isValid = validateRequired(config.cdpApiKey, 'cdpApiKey', context) && isValid;\n isValid = validateString(config.cdpApiKey, 'cdpApiKey', context) && isValid;\n isValid = validateRegion(config.region, 'region', context) && isValid;\n isValid = validateEnum(config.screenViewUse, 'screenViewUse', ['all', 'inapp'], context) && isValid;\n isValid = validateEnum(config.logLevel, 'logLevel', ['none', 'error', 'info', 'debug'], context) && isValid;\n isValid = validateBoolean(config.autoTrackDeviceAttributes, 'autoTrackDeviceAttributes', context) && isValid;\n isValid = validateBoolean(config.trackApplicationLifecycleEvents, 'trackApplicationLifecycleEvents', context) && isValid;\n isValid = validateString(config.siteId, 'siteId', context) && isValid;\n isValid = validateString(config.migrationSiteId, 'migrationSiteId', context) && isValid;\n\n return isValid;\n}\n\nfunction validateRichPushConfig(config: RichPushConfig | undefined): boolean {\n const context = 'NotificationServiceExtension';\n\n let isValid = true;\n\n isValid = validateRequired(config?.cdpApiKey, 'cdpApiKey', context) && isValid;\n isValid = validateString(config?.cdpApiKey, 'cdpApiKey', context) && isValid;\n isValid = validateRegion(config?.region, 'region', context) && isValid;\n\n return isValid;\n}\n\nexport {\n validateNativeSDKConfig,\n validateRequired,\n validateRichPushConfig,\n validateString\n};\n\n"],"mappings":";;;;;;;;;AACA,IAAAA,OAAA,GAAAC,OAAA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,SAASC,QAAQA,CAACC,OAAsB,EAAEC,cAA4B,EAAW;EAC/E,IAAID,OAAO,CAAC,CAAC,EAAE;IACb,OAAO,IAAI;EACb;;EAEA;EACA,MAAME,OAAO,GAAGD,cAAc,CAAC,CAAC;EAChC;EACA,IAAIE,OAAO,CAACC,GAAG,CAACC,sBAAsB,KAAK,MAAM,EAAE;IACjD,MAAM,IAAIC,KAAK,CAACC,cAAM,CAACC,MAAM,CAACN,OAAO,CAAC,CAAC;EACzC,CAAC,MAAM;IACLK,cAAM,CAACE,IAAI,CAACP,OAAO,CAAC;EACtB;EACA,OAAO,KAAK;AACd;AAEA,SAASQ,WAAWA,CAACC,KAAc,EAAW;EAC5C,OAAOA,KAAK,KAAKC,SAAS;AAC5B;AAEA,SAASC,gBAAgBA,CAACF,KAAc,EAAEG,SAAiB,EAAEC,OAAe,EAAW;EACrF,OAAOhB,QAAQ,CACb,MAAM,CAACW,WAAW,CAACC,KAAK,CAAC,IAAIA,KAAK,KAAK,IAAI,EAC3C,MAAM,GAAGI,OAAO,KAAKD,SAAS,2BAA2BH,KAAK,EAChE,CAAC;AACH;AAEA,SAASK,cAAcA,CAACL,KAAc,EAAEG,SAAiB,EAAEC,OAAe,EAAW;EACnF,OAAOhB,QAAQ,CACb,MAAMW,WAAW,CAACC,KAAK,CAAC,IAAK,OAAOA,KAAK,KAAK,QAAQ,IAAIA,KAAK,CAACM,IAAI,CAAC,CAAC,KAAK,EAAG,EAC9E,MAAM,GAAGF,OAAO,KAAKD,SAAS,0CAA0C,OAAOH,KAAK,KAAK,QAAQ,GAAG,IAAIA,KAAK,GAAG,GAAGA,KAAK,EAC1H,CAAC;AACH;AAEA,SAASO,eAAeA,CAACP,KAAc,EAAEG,SAAiB,EAAEC,OAAe,EAAW;EACpF,OAAOhB,QAAQ,CACb,MAAMW,WAAW,CAACC,KAAK,CAAC,IAAI,OAAOA,KAAK,KAAK,SAAS,EACtD,MAAM,GAAGI,OAAO,KAAKD,SAAS,iCAAiCH,KAAK,EACtE,CAAC;AACH;AAEA,SAASQ,YAAYA,CACnBR,KAAc,EACdG,SAAiB,EACjBM,aAA2B,EAC3BL,OAAe,EACN;EACT,IAAIL,WAAW,CAACC,KAAK,CAAC,EAAE,OAAO,IAAI;;EAEnC;EACA,IAAI,CAACK,cAAc,CAACL,KAAK,EAAEG,SAAS,EAAEC,OAAO,CAAC,EAAE;IAC9C,OAAO,KAAK;EACd;;EAEA;EACA,OAAOhB,QAAQ,CACb,MAAM;IACJ,MAAMsB,UAAU,GAAIV,KAAK,CAAYW,WAAW,CAAC,CAAC;IAClD,MAAMC,kBAAkB,GAAGH,aAAa,CAACI,GAAG,CAACC,CAAC,IAAIA,CAAC,CAACH,WAAW,CAAC,CAAC,CAAC;IAClE,OAAOC,kBAAkB,CAACG,QAAQ,CAACL,UAAU,CAAC;EAChD,CAAC,EACD,MAAM;IACJ,MAAMM,SAAS,GAAGP,aAAa,CAACI,GAAG,CAACC,CAAC,IAAI,IAAIA,CAAC,GAAG,CAAC,CAACG,IAAI,CAAC,IAAI,CAAC;IAC7D,OAAO,GAAGb,OAAO,KAAKD,SAAS,mBAAmBa,SAAS,eAAehB,KAAK,EAAE;EACnF,CACF,CAAC;AACH;AAEA,SAASkB,cAAcA,CAAClB,KAAc,EAAEG,SAAiB,EAAEC,OAAe,EAAW;EACnF,OAAOI,YAAY,CAACR,KAAK,EAAEG,SAAS,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,EAAEC,OAAO,CAAC;AAC9D;AAEA,SAASe,uBAAuBA,CAACC,MAAuB,EAAW;EACjE,MAAMhB,OAAO,GAAG,iBAAiB;EAEjC,IAAIf,OAAO,GAAG,IAAI;EAElBA,OAAO,GAAGa,gBAAgB,CAACkB,MAAM,CAACC,SAAS,EAAE,WAAW,EAAEjB,OAAO,CAAC,IAAIf,OAAO;EAC7EA,OAAO,GAAGgB,cAAc,CAACe,MAAM,CAACC,SAAS,EAAE,WAAW,EAAEjB,OAAO,CAAC,IAAIf,OAAO;EAC3EA,OAAO,GAAG6B,cAAc,CAACE,MAAM,CAACE,MAAM,EAAE,QAAQ,EAAElB,OAAO,CAAC,IAAIf,OAAO;EACrEA,OAAO,GAAGmB,YAAY,CAACY,MAAM,CAACG,aAAa,EAAE,eAAe,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,EAAEnB,OAAO,CAAC,IAAIf,OAAO;EACnGA,OAAO,GAAGmB,YAAY,CAACY,MAAM,CAACI,QAAQ,EAAE,UAAU,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAEpB,OAAO,CAAC,IAAIf,OAAO;EAC3GA,OAAO,GAAGkB,eAAe,CAACa,MAAM,CAACK,yBAAyB,EAAE,2BAA2B,EAAErB,OAAO,CAAC,IAAIf,OAAO;EAC5GA,OAAO,GAAGkB,eAAe,CAACa,MAAM,CAACM,+BAA+B,EAAE,iCAAiC,EAAEtB,OAAO,CAAC,IAAIf,OAAO;EACxHA,OAAO,GAAGgB,cAAc,CAACe,MAAM,CAACO,MAAM,EAAE,QAAQ,EAAEvB,OAAO,CAAC,IAAIf,OAAO;EACrEA,OAAO,GAAGgB,cAAc,CAACe,MAAM,CAACQ,eAAe,EAAE,iBAAiB,EAAExB,OAAO,CAAC,IAAIf,OAAO;EAEvF,OAAOA,OAAO;AAChB;AAEA,SAASwC,sBAAsBA,CAACT,MAAkC,EAAW;EAC3E,MAAMhB,OAAO,GAAG,8BAA8B;EAE9C,IAAIf,OAAO,GAAG,IAAI;EAElBA,OAAO,GAAGa,gBAAgB,CAACkB,MAAM,aAANA,MAAM,uBAANA,MAAM,CAAEC,SAAS,EAAE,WAAW,EAAEjB,OAAO,CAAC,IAAIf,OAAO;EAC9EA,OAAO,GAAGgB,cAAc,CAACe,MAAM,aAANA,MAAM,uBAANA,MAAM,CAAEC,SAAS,EAAE,WAAW,EAAEjB,OAAO,CAAC,IAAIf,OAAO;EAC5EA,OAAO,GAAG6B,cAAc,CAACE,MAAM,aAANA,MAAM,uBAANA,MAAM,CAAEE,MAAM,EAAE,QAAQ,EAAElB,OAAO,CAAC,IAAIf,OAAO;EAEtE,OAAOA,OAAO;AAChB","ignoreList":[]}
1
+ {"version":3,"names":["_logger","require","validate","isValid","messageFactory","message","process","env","CUSTOMERIO_STRICT_MODE","Error","logger","format","warn","isUndefined","value","undefined","validateRequired","fieldName","context","validateString","trim","validateBoolean","validateEnum","allowedValues","lowerValue","toLowerCase","lowerAllowedValues","map","v","includes","valuesStr","join","validateRegion","validateNativeSDKConfig","config","cdpApiKey","region","screenViewUse","logLevel","autoTrackDeviceAttributes","trackApplicationLifecycleEvents","siteId","migrationSiteId","validateRichPushConfig","validatePushNotificationOptions","options","appGroupId","startsWith"],"sources":["validation.ts"],"sourcesContent":["import type { CustomerIOPluginPushNotificationOptions, NativeSDKConfig, RichPushConfig } from '../types/cio-types';\nimport { logger } from './logger';\n\n/**\n * Validates a condition and handles errors based on CUSTOMERIO_STRICT_MODE flag.\n * @param isValid - Function that returns true if validation passes\n * @param messageFactory - Function that returns the error message if validation fails\n * @returns true if validation passes, false if it fails\n */\nfunction validate(isValid: () => boolean, messageFactory: () => string): boolean {\n if (isValid()) {\n return true;\n }\n\n // Throw errors unless explicitly disabled, default to strict validation\n const message = messageFactory();\n // Throw an error if strict mode is enabled, log a warning otherwise\n if (process.env.CUSTOMERIO_STRICT_MODE === 'true') {\n throw new Error(logger.format(message));\n } else {\n logger.warn(message);\n }\n return false;\n}\n\nfunction isUndefined(value: unknown): boolean {\n return value === undefined;\n}\n\nfunction validateRequired(value: unknown, fieldName: string, context: string): boolean {\n return validate(\n () => !isUndefined(value) && value !== null,\n () => `${context}: ${fieldName} is required, received: ${value}`\n );\n}\n\nfunction validateString(value: unknown, fieldName: string, context: string): boolean {\n return validate(\n () => isUndefined(value) || (typeof value === 'string' && value.trim() !== ''),\n () => `${context}: ${fieldName} must be a non-empty string, received: ${typeof value === 'string' ? `\"${value}\"` : value}`\n );\n}\n\nfunction validateBoolean(value: unknown, fieldName: string, context: string): boolean {\n return validate(\n () => isUndefined(value) || typeof value === 'boolean',\n () => `${context}: ${fieldName} must be a boolean, received: ${value}`\n );\n}\n\nfunction validateEnum<T extends string>(\n value: unknown,\n fieldName: string,\n allowedValues: readonly T[],\n context: string\n): boolean {\n if (isUndefined(value)) return true;\n\n // First validate it's a string\n if (!validateString(value, fieldName, context)) {\n return false;\n }\n\n // Then validate it's in the allowed values\n return validate(\n () => {\n const lowerValue = (value as string).toLowerCase();\n const lowerAllowedValues = allowedValues.map(v => v.toLowerCase());\n return lowerAllowedValues.includes(lowerValue);\n },\n () => {\n const valuesStr = allowedValues.map(v => `\"${v}\"`).join(', ');\n return `${context}: ${fieldName} must be one of ${valuesStr}, received: ${value}`;\n }\n );\n}\n\nfunction validateRegion(value: unknown, fieldName: string, context: string): boolean {\n return validateEnum(value, fieldName, ['US', 'EU'], context);\n}\n\nfunction validateNativeSDKConfig(config: NativeSDKConfig): boolean {\n const context = 'NativeSDKConfig';\n\n let isValid = true;\n\n isValid = validateRequired(config.cdpApiKey, 'cdpApiKey', context) && isValid;\n isValid = validateString(config.cdpApiKey, 'cdpApiKey', context) && isValid;\n isValid = validateRegion(config.region, 'region', context) && isValid;\n isValid = validateEnum(config.screenViewUse, 'screenViewUse', ['all', 'inapp'], context) && isValid;\n isValid = validateEnum(config.logLevel, 'logLevel', ['none', 'error', 'info', 'debug'], context) && isValid;\n isValid = validateBoolean(config.autoTrackDeviceAttributes, 'autoTrackDeviceAttributes', context) && isValid;\n isValid = validateBoolean(config.trackApplicationLifecycleEvents, 'trackApplicationLifecycleEvents', context) && isValid;\n isValid = validateString(config.siteId, 'siteId', context) && isValid;\n isValid = validateString(config.migrationSiteId, 'migrationSiteId', context) && isValid;\n\n return isValid;\n}\n\nfunction validateRichPushConfig(config: RichPushConfig | undefined): boolean {\n const context = 'NotificationServiceExtension';\n\n let isValid = true;\n\n isValid = validateRequired(config?.cdpApiKey, 'cdpApiKey', context) && isValid;\n isValid = validateString(config?.cdpApiKey, 'cdpApiKey', context) && isValid;\n isValid = validateRegion(config?.region, 'region', context) && isValid;\n\n return isValid;\n}\n\nfunction validatePushNotificationOptions(options: CustomerIOPluginPushNotificationOptions): boolean {\n const context = 'PushNotification';\n\n let isValid = true;\n\n const appGroupId = options.appGroupId;\n if (appGroupId !== undefined) {\n isValid = validateString(appGroupId, 'appGroupId', context) && isValid;\n if (isValid && !appGroupId.startsWith('group.')) {\n logger.warn(`${context}: appGroupId \"${appGroupId}\" does not start with \"group.\" — ensure this matches your Apple App Group entitlement.`);\n }\n }\n\n return isValid;\n}\n\nexport {\n validateNativeSDKConfig,\n validatePushNotificationOptions,\n validateRequired,\n validateRichPushConfig,\n validateString\n};\n\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.withExpoVersion = void 0;
7
+ exports.writeExpoVersion = writeExpoVersion;
8
+ var _fs = _interopRequireDefault(require("fs"));
9
+ var _logger = require("./logger");
10
+ var _plugin = require("./plugin");
11
+ var _resolveRNSDK = require("./resolveRNSDK");
12
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
13
+ // Writes the plugin's version into customerio-reactnative/package.json under
14
+ // the `expoVersion` key. The RN SDK reads this at runtime (customerio-cdp.ts)
15
+ // to set its User-Agent `packageSource` to "Expo" instead of "ReactNative".
16
+ //
17
+ // We rely on the postinstall hook (postInstallHelper.js) for the same write
18
+ // at install time, but call this from the plugin entry as a fallback for
19
+ // installs where postinstall does not run cleanly — most notably pnpm
20
+ // monorepos and any CI that uses --ignore-scripts.
21
+ //
22
+ // The write is idempotent: we no-op when the value is already correct.
23
+ function writeExpoVersion(projectRoot) {
24
+ let resolved;
25
+ try {
26
+ resolved = (0, _resolveRNSDK.tryResolveRNSDK)(projectRoot);
27
+ } catch (error) {
28
+ _logger.logger.warn(`Could not locate customerio-reactnative to write expoVersion. ` + `User-Agent attribution may be incorrect. Original error: ${error}`);
29
+ return;
30
+ }
31
+ if (!resolved) {
32
+ return;
33
+ }
34
+ try {
35
+ const pluginVersion = (0, _plugin.getPluginVersion)();
36
+ const pkg = JSON.parse(_fs.default.readFileSync(resolved.packageJsonPath, 'utf8'));
37
+ if (pkg.expoVersion === pluginVersion) {
38
+ return;
39
+ }
40
+ pkg.expoVersion = pluginVersion;
41
+ _fs.default.writeFileSync(resolved.packageJsonPath, JSON.stringify(pkg, null, 2));
42
+ } catch (error) {
43
+ _logger.logger.warn(`Failed to write expoVersion into ${resolved.packageJsonPath}. ` + `User-Agent attribution may be incorrect. Original error: ${error}`);
44
+ }
45
+ }
46
+ const withExpoVersion = config => {
47
+ var _internal;
48
+ // _internal.projectRoot is set by Expo when running through prebuild;
49
+ // fall back to process.cwd() for any path that calls the plugin in
50
+ // a non-prebuild context.
51
+ const projectRoot = ((_internal = config._internal) === null || _internal === void 0 ? void 0 : _internal.projectRoot) || process.cwd();
52
+ writeExpoVersion(projectRoot);
53
+ return config;
54
+ };
55
+ exports.withExpoVersion = withExpoVersion;
56
+ //# sourceMappingURL=writeExpoVersion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_fs","_interopRequireDefault","require","_logger","_plugin","_resolveRNSDK","e","__esModule","default","writeExpoVersion","projectRoot","resolved","tryResolveRNSDK","error","logger","warn","pluginVersion","getPluginVersion","pkg","JSON","parse","fs","readFileSync","packageJsonPath","expoVersion","writeFileSync","stringify","withExpoVersion","config","_internal","process","cwd","exports"],"sources":["writeExpoVersion.ts"],"sourcesContent":["import fs from 'fs';\nimport type { ConfigPlugin } from '@expo/config-plugins';\n\nimport { logger } from './logger';\nimport { getPluginVersion } from './plugin';\nimport { tryResolveRNSDK } from './resolveRNSDK';\n\n// Writes the plugin's version into customerio-reactnative/package.json under\n// the `expoVersion` key. The RN SDK reads this at runtime (customerio-cdp.ts)\n// to set its User-Agent `packageSource` to \"Expo\" instead of \"ReactNative\".\n//\n// We rely on the postinstall hook (postInstallHelper.js) for the same write\n// at install time, but call this from the plugin entry as a fallback for\n// installs where postinstall does not run cleanly — most notably pnpm\n// monorepos and any CI that uses --ignore-scripts.\n//\n// The write is idempotent: we no-op when the value is already correct.\nexport function writeExpoVersion(projectRoot: string): void {\n let resolved;\n try {\n resolved = tryResolveRNSDK(projectRoot);\n } catch (error) {\n logger.warn(\n `Could not locate customerio-reactnative to write expoVersion. ` +\n `User-Agent attribution may be incorrect. Original error: ${error}`\n );\n return;\n }\n\n if (!resolved) {\n return;\n }\n\n try {\n const pluginVersion = getPluginVersion();\n const pkg = JSON.parse(fs.readFileSync(resolved.packageJsonPath, 'utf8'));\n if (pkg.expoVersion === pluginVersion) {\n return;\n }\n pkg.expoVersion = pluginVersion;\n fs.writeFileSync(\n resolved.packageJsonPath,\n JSON.stringify(pkg, null, 2)\n );\n } catch (error) {\n logger.warn(\n `Failed to write expoVersion into ${resolved.packageJsonPath}. ` +\n `User-Agent attribution may be incorrect. Original error: ${error}`\n );\n }\n}\n\nexport const withExpoVersion: ConfigPlugin = (config) => {\n // _internal.projectRoot is set by Expo when running through prebuild;\n // fall back to process.cwd() for any path that calls the plugin in\n // a non-prebuild context.\n const projectRoot =\n (config as unknown as { _internal?: { projectRoot?: string } })._internal?.projectRoot ||\n process.cwd();\n writeExpoVersion(projectRoot);\n return config;\n};\n"],"mappings":";;;;;;;AAAA,IAAAA,GAAA,GAAAC,sBAAA,CAAAC,OAAA;AAGA,IAAAC,OAAA,GAAAD,OAAA;AACA,IAAAE,OAAA,GAAAF,OAAA;AACA,IAAAG,aAAA,GAAAH,OAAA;AAAiD,SAAAD,uBAAAK,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAEjD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAASG,gBAAgBA,CAACC,WAAmB,EAAQ;EAC1D,IAAIC,QAAQ;EACZ,IAAI;IACFA,QAAQ,GAAG,IAAAC,6BAAe,EAACF,WAAW,CAAC;EACzC,CAAC,CAAC,OAAOG,KAAK,EAAE;IACdC,cAAM,CAACC,IAAI,CACT,gEAAgE,GAChE,4DAA4DF,KAAK,EACnE,CAAC;IACD;EACF;EAEA,IAAI,CAACF,QAAQ,EAAE;IACb;EACF;EAEA,IAAI;IACF,MAAMK,aAAa,GAAG,IAAAC,wBAAgB,EAAC,CAAC;IACxC,MAAMC,GAAG,GAAGC,IAAI,CAACC,KAAK,CAACC,WAAE,CAACC,YAAY,CAACX,QAAQ,CAACY,eAAe,EAAE,MAAM,CAAC,CAAC;IACzE,IAAIL,GAAG,CAACM,WAAW,KAAKR,aAAa,EAAE;MACrC;IACF;IACAE,GAAG,CAACM,WAAW,GAAGR,aAAa;IAC/BK,WAAE,CAACI,aAAa,CACdd,QAAQ,CAACY,eAAe,EACxBJ,IAAI,CAACO,SAAS,CAACR,GAAG,EAAE,IAAI,EAAE,CAAC,CAC7B,CAAC;EACH,CAAC,CAAC,OAAOL,KAAK,EAAE;IACdC,cAAM,CAACC,IAAI,CACT,oCAAoCJ,QAAQ,CAACY,eAAe,IAAI,GAChE,4DAA4DV,KAAK,EACnE,CAAC;EACH;AACF;AAEO,MAAMc,eAA6B,GAAIC,MAAM,IAAK;EAAA,IAAAC,SAAA;EACvD;EACA;EACA;EACA,MAAMnB,WAAW,GACf,EAAAmB,SAAA,GAACD,MAAM,CAAyDC,SAAS,cAAAA,SAAA,uBAAzEA,SAAA,CAA2EnB,WAAW,KACtFoB,OAAO,CAACC,GAAG,CAAC,CAAC;EACftB,gBAAgB,CAACC,WAAW,CAAC;EAC7B,OAAOkB,MAAM;AACf,CAAC;AAACI,OAAA,CAAAL,eAAA,GAAAA,eAAA","ignoreList":[]}
@@ -1,14 +1,81 @@
1
+ import fs from 'fs';
2
+ import * as semver from 'semver';
1
3
  const path = require('path');
2
- const resolveFrom = require('resolve-from');
3
- export function getRelativePathToRNSDK(iosPath) {
4
- // Root path of the Expo project
5
- const rootAppPath = path.dirname(iosPath);
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
- // Path of the cio RN package.json file. Example: test-app/node_modules/customerio-reactnative/package.json
8
- const pluginPackageJsonPath = resolveFrom.silent(rootAppPath, `customerio-reactnative/package.json`);
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
- // Example: ../node_modules/customerio-reactnative
11
- return path.relative(iosPath, path.dirname(pluginPackageJsonPath));
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":"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CpC,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":[]}
@@ -42,7 +42,7 @@ public class CioSdkAppDelegateHandler: NSObject {
42
42
  MessagingPushAPN.initialize(
43
43
  withConfig: MessagingPushConfigBuilder()
44
44
  .autoFetchDeviceToken({{AUTO_FETCH_DEVICE_TOKEN}})
45
- .showPushAppInForeground({{SHOW_PUSH_APP_IN_FOREGROUND}})
45
+ {{APP_GROUP_ID_BUILDER_LINE}} .showPushAppInForeground({{SHOW_PUSH_APP_IN_FOREGROUND}})
46
46
  .autoTrackPushEvents({{AUTO_TRACK_PUSH_EVENTS}})
47
47
  .build()
48
48
  )
@@ -12,7 +12,7 @@ public class NotificationServiceCioManager : NSObject {
12
12
  MessagingPushAPN.initializeForExtension(
13
13
  withConfig: MessagingPushConfigBuilder(cdpApiKey: Env.customerIOCdpApiKey)
14
14
  .region(Env.customerIORegion)
15
- .build()
15
+ {{APP_GROUP_ID_BUILDER_LINE}} .build()
16
16
  )
17
17
 
18
18
  MessagingPush.shared.didReceive(request, withContentHandler: contentHandler)
@@ -15,7 +15,7 @@ public class CIOAppPushNotificationsHandler : NSObject {
15
15
  MessagingPushAPN.initialize(
16
16
  withConfig: MessagingPushConfigBuilder()
17
17
  .autoFetchDeviceToken({{AUTO_FETCH_DEVICE_TOKEN}})
18
- .showPushAppInForeground({{SHOW_PUSH_APP_IN_FOREGROUND}})
18
+ {{APP_GROUP_ID_BUILDER_LINE}} .showPushAppInForeground({{SHOW_PUSH_APP_IN_FOREGROUND}})
19
19
  .autoTrackPushEvents({{AUTO_TRACK_PUSH_EVENTS}})
20
20
  .build()
21
21
  )
@@ -52,7 +52,7 @@ public class CioSdkAppDelegateHandler: NSObject {
52
52
  MessagingPushFCM.initialize(
53
53
  withConfig: MessagingPushConfigBuilder()
54
54
  .autoFetchDeviceToken({{AUTO_FETCH_DEVICE_TOKEN}})
55
- .showPushAppInForeground({{SHOW_PUSH_APP_IN_FOREGROUND}})
55
+ {{APP_GROUP_ID_BUILDER_LINE}} .showPushAppInForeground({{SHOW_PUSH_APP_IN_FOREGROUND}})
56
56
  .autoTrackPushEvents({{AUTO_TRACK_PUSH_EVENTS}})
57
57
  .build()
58
58
  )
@@ -12,7 +12,7 @@ public class NotificationServiceCioManager : NSObject {
12
12
  MessagingPushFCM.initializeForExtension(
13
13
  withConfig: MessagingPushConfigBuilder(cdpApiKey: Env.customerIOCdpApiKey)
14
14
  .region(Env.customerIORegion)
15
- .build()
15
+ {{APP_GROUP_ID_BUILDER_LINE}} .build()
16
16
  )
17
17
 
18
18
  MessagingPush.shared.didReceive(request, withContentHandler: contentHandler)
@@ -23,7 +23,7 @@ public class CIOAppPushNotificationsHandler : NSObject {
23
23
  MessagingPushFCM.initialize(
24
24
  withConfig: MessagingPushConfigBuilder()
25
25
  .autoFetchDeviceToken({{AUTO_FETCH_DEVICE_TOKEN}})
26
- .showPushAppInForeground({{SHOW_PUSH_APP_IN_FOREGROUND}})
26
+ {{APP_GROUP_ID_BUILDER_LINE}} .showPushAppInForeground({{SHOW_PUSH_APP_IN_FOREGROUND}})
27
27
  .autoTrackPushEvents({{AUTO_TRACK_PUSH_EVENTS}})
28
28
  .build()
29
29
  )
@@ -2,20 +2,30 @@ 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 app pod line for the Podfile (single subspec or :subspecs with location). Exported for tests. */
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 path = getRelativePathToRNSDK(iosPath);
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 => '${path}'`;
22
+ return `pod 'customerio-reactnative/${subspec}', :path => '${resolvedPath}'`;
13
23
  }
14
24
  if (!hasPush) {
15
- return `pod 'customerio-reactnative', :subspecs => ['location'], :path => '${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 => '${path}'`;
28
+ return `pod 'customerio-reactnative', :subspecs => ['${pushSubspec}', 'location'], :path => '${resolvedPath}'`;
19
29
  }
20
30
  export async function injectCIOPodfileCode(iosPath, isFcmPushProvider, options) {
21
31
  const blockStart = '# --- CustomerIO Host App START ---';
@@ -46,11 +56,14 @@ export async function injectCIONotificationPodfileCode(iosPath, useFrameworks, i
46
56
  const blockEnd = '# --- CustomerIO Notification END ---';
47
57
  const matches = podfile.match(new RegExp(blockStart));
48
58
  if (!matches) {
59
+ const resolvedPath = getRelativePathToRNSDK(iosPath);
60
+ const subspec = isFcmPushProvider ? 'fcm' : 'apn';
61
+ const useFrameworksLine = useFrameworks === 'static' ? 'use_frameworks! :linkage => :static' : '';
49
62
  const snippetToInjectInPodfile = `
50
63
  ${blockStart}
51
64
  target 'NotificationService' do
52
- ${useFrameworks === 'static' ? 'use_frameworks! :linkage => :static' : ''}
53
- pod 'customerio-reactnative-richpush/${isFcmPushProvider ? 'fcm' : 'apn'}', :path => '${getRelativePathToRNSDK(iosPath)}'
65
+ ${useFrameworksLine}
66
+ pod 'customerio-reactnative-richpush/${subspec}', :path => '${resolvedPath}'
54
67
  end
55
68
  ${blockEnd}
56
69
  `.trim();
@@ -1 +1 @@
1
- {"version":3,"names":["logger","getRelativePathToRNSDK","injectCodeByRegex","FileManagement","buildHostAppPodSnippet","iosPath","isFcmPushProvider","options","path","locationEnabled","hasPush","subspec","pushSubspec","injectCIOPodfileCode","blockStart","blockEnd","filename","podfile","read","matches","match","RegExp","lineInPodfileToInjectSnippetBefore","podLine","snippetToInjectInPodfile","trim","write","join","info","injectCIONotificationPodfileCode","useFrameworks","append"],"sources":["injectCIOPodfileCode.ts"],"sourcesContent":["import type { CustomerIOPluginOptionsIOS } from '../../types/cio-types';\nimport { logger } from '../../utils/logger';\nimport { getRelativePathToRNSDK } from '../constants/ios';\nimport { injectCodeByRegex } from './codeInjection';\nimport { FileManagement } from './fileManagement';\n\nexport type InjectCIOPodfileOptions = {\n /** When true, add the location subspec. When false/omit, use single push subspec only. */\n locationEnabled?: boolean;\n /** When false and locationEnabled, inject only :subspecs => ['location']. When true, use push + location. */\n hasPush?: boolean;\n};\n\n/** Builds the host app pod line for the Podfile (single subspec or :subspecs with location). Exported for tests. */\nexport function buildHostAppPodSnippet(\n iosPath: string,\n isFcmPushProvider: boolean,\n options?: InjectCIOPodfileOptions\n): string {\n const path = getRelativePathToRNSDK(iosPath);\n const locationEnabled = options?.locationEnabled === true;\n const hasPush = options?.hasPush !== false;\n\n if (!locationEnabled) {\n const subspec = isFcmPushProvider ? 'fcm' : 'apn';\n return `pod 'customerio-reactnative/${subspec}', :path => '${path}'`;\n }\n\n if (!hasPush) {\n return `pod 'customerio-reactnative', :subspecs => ['location'], :path => '${path}'`;\n }\n\n const pushSubspec = isFcmPushProvider ? 'fcm' : 'apn';\n return `pod 'customerio-reactnative', :subspecs => ['${pushSubspec}', 'location'], :path => '${path}'`;\n}\n\nexport async function injectCIOPodfileCode(\n iosPath: string,\n isFcmPushProvider: boolean,\n options?: InjectCIOPodfileOptions\n) {\n const blockStart = '# --- CustomerIO Host App START ---';\n const blockEnd = '# --- CustomerIO Host App END ---';\n\n const filename = `${iosPath}/Podfile`;\n const podfile = await FileManagement.read(filename);\n const matches = podfile.match(new RegExp(blockStart));\n\n if (!matches) {\n // We need to decide what line of code in the Podfile to insert our native code.\n // The \"post_install\" line is always present in an Expo project Podfile so it's reliable.\n // Find that line in the Podfile and then we will insert our code above that line.\n const lineInPodfileToInjectSnippetBefore = /post_install do \\|installer\\|/;\n\n const podLine = buildHostAppPodSnippet(iosPath, isFcmPushProvider, options);\n\n const snippetToInjectInPodfile = `\n${blockStart}\n ${podLine}\n${blockEnd}\n`.trim();\n\n FileManagement.write(\n filename,\n injectCodeByRegex(\n podfile,\n lineInPodfileToInjectSnippetBefore,\n snippetToInjectInPodfile\n ).join('\\n')\n );\n } else {\n logger.info('CustomerIO Podfile snippets already exists. Skipping...');\n }\n}\n\nexport async function injectCIONotificationPodfileCode(\n iosPath: string,\n useFrameworks: CustomerIOPluginOptionsIOS['useFrameworks'],\n isFcmPushProvider: boolean\n) {\n const filename = `${iosPath}/Podfile`;\n const podfile = await FileManagement.read(filename);\n\n const blockStart = '# --- CustomerIO Notification START ---';\n const blockEnd = '# --- CustomerIO Notification END ---';\n\n const matches = podfile.match(new RegExp(blockStart));\n\n if (!matches) {\n const snippetToInjectInPodfile = `\n${blockStart}\ntarget 'NotificationService' do\n ${useFrameworks === 'static' ? 'use_frameworks! :linkage => :static' : ''}\n pod 'customerio-reactnative-richpush/${isFcmPushProvider ? 'fcm' : 'apn'\n }', :path => '${getRelativePathToRNSDK(iosPath)}'\nend\n${blockEnd}\n`.trim();\n\n FileManagement.append(filename, snippetToInjectInPodfile);\n }\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["logger","getRelativePathToRNSDK","injectCodeByRegex","FileManagement","buildHostAppPodSnippet","iosPath","isFcmPushProvider","options","resolvedPath","locationEnabled","hasPush","subspec","pushSubspec","injectCIOPodfileCode","blockStart","blockEnd","filename","podfile","read","matches","match","RegExp","lineInPodfileToInjectSnippetBefore","podLine","snippetToInjectInPodfile","trim","write","join","info","injectCIONotificationPodfileCode","useFrameworks","useFrameworksLine","append"],"sources":["injectCIOPodfileCode.ts"],"sourcesContent":["import type { CustomerIOPluginOptionsIOS } from '../../types/cio-types';\nimport { logger } from '../../utils/logger';\nimport { getRelativePathToRNSDK } from '../constants/ios';\nimport { injectCodeByRegex } from './codeInjection';\nimport { FileManagement } from './fileManagement';\n\nexport type InjectCIOPodfileOptions = {\n /** When true, add the location subspec. When false/omit, use single push subspec only. */\n locationEnabled?: boolean;\n /** When false and locationEnabled, inject only :subspecs => ['location']. When true, use push + location. */\n hasPush?: boolean;\n};\n\n/** Builds the host-app pod snippet for the Podfile.\n *\n * The :path is resolved at prebuild time by `getRelativePathToRNSDK`,\n * which dispatches on the installed React Native version so the path\n * matches what RN pod autolinking will emit (lexical for RN <0.80,\n * realpath for RN >=0.80). Baking the resolved string directly avoids\n * any Ruby/install-time logic in the Podfile and keeps the snippet\n * trivially diff-able.\n *\n * Exported for tests.\n */\nexport function buildHostAppPodSnippet(\n iosPath: string,\n isFcmPushProvider: boolean,\n options?: InjectCIOPodfileOptions\n): string {\n const resolvedPath = getRelativePathToRNSDK(iosPath);\n const locationEnabled = options?.locationEnabled === true;\n const hasPush = options?.hasPush !== false;\n\n if (!locationEnabled) {\n const subspec = isFcmPushProvider ? 'fcm' : 'apn';\n return `pod 'customerio-reactnative/${subspec}', :path => '${resolvedPath}'`;\n }\n if (!hasPush) {\n return `pod 'customerio-reactnative', :subspecs => ['location'], :path => '${resolvedPath}'`;\n }\n const pushSubspec = isFcmPushProvider ? 'fcm' : 'apn';\n return `pod 'customerio-reactnative', :subspecs => ['${pushSubspec}', 'location'], :path => '${resolvedPath}'`;\n}\n\nexport async function injectCIOPodfileCode(\n iosPath: string,\n isFcmPushProvider: boolean,\n options?: InjectCIOPodfileOptions\n) {\n const blockStart = '# --- CustomerIO Host App START ---';\n const blockEnd = '# --- CustomerIO Host App END ---';\n\n const filename = `${iosPath}/Podfile`;\n const podfile = await FileManagement.read(filename);\n const matches = podfile.match(new RegExp(blockStart));\n\n if (!matches) {\n // We need to decide what line of code in the Podfile to insert our native code.\n // The \"post_install\" line is always present in an Expo project Podfile so it's reliable.\n // Find that line in the Podfile and then we will insert our code above that line.\n const lineInPodfileToInjectSnippetBefore = /post_install do \\|installer\\|/;\n\n const podLine = buildHostAppPodSnippet(iosPath, isFcmPushProvider, options);\n\n const snippetToInjectInPodfile = `\n${blockStart}\n ${podLine}\n${blockEnd}\n`.trim();\n\n FileManagement.write(\n filename,\n injectCodeByRegex(\n podfile,\n lineInPodfileToInjectSnippetBefore,\n snippetToInjectInPodfile\n ).join('\\n')\n );\n } else {\n logger.info('CustomerIO Podfile snippets already exists. Skipping...');\n }\n}\n\nexport async function injectCIONotificationPodfileCode(\n iosPath: string,\n useFrameworks: CustomerIOPluginOptionsIOS['useFrameworks'],\n isFcmPushProvider: boolean\n) {\n const filename = `${iosPath}/Podfile`;\n const podfile = await FileManagement.read(filename);\n\n const blockStart = '# --- CustomerIO Notification START ---';\n const blockEnd = '# --- CustomerIO Notification END ---';\n\n const matches = podfile.match(new RegExp(blockStart));\n\n if (!matches) {\n const resolvedPath = getRelativePathToRNSDK(iosPath);\n const subspec = isFcmPushProvider ? 'fcm' : 'apn';\n const useFrameworksLine =\n useFrameworks === 'static' ? 'use_frameworks! :linkage => :static' : '';\n\n const snippetToInjectInPodfile = `\n${blockStart}\ntarget 'NotificationService' do\n ${useFrameworksLine}\n pod 'customerio-reactnative-richpush/${subspec}', :path => '${resolvedPath}'\nend\n${blockEnd}\n`.trim();\n\n FileManagement.append(filename, snippetToInjectInPodfile);\n }\n}\n"],"mappings":"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","ignoreList":[]}
@@ -1,6 +1,7 @@
1
1
  import { withCIOAndroid } from './android/withCIOAndroid';
2
2
  import { isExpoVersion53OrHigher } from './ios/utils';
3
3
  import { withCIOIos } from './ios/withCIOIos';
4
+ import { withExpoVersion } from './utils/writeExpoVersion';
4
5
  // Entry point for config plugin
5
6
  function withCustomerIOPlugin(config, props) {
6
7
  // Check if config is being used with unsupported Expo version
@@ -8,6 +9,12 @@ function withCustomerIOPlugin(config, props) {
8
9
  throw new Error('CustomerIO auto initialization (config property) requires Expo SDK 53 or higher. ' + 'Please upgrade to Expo SDK 53+ or use manual initialization instead. ' + 'See documentation for manual setup instructions.');
9
10
  }
10
11
 
12
+ // Belt-and-suspenders write of the plugin version into the RN SDK's
13
+ // package.json. The postinstall hook does the same write at install time;
14
+ // this covers installs where postinstall didn't run cleanly (pnpm with
15
+ // strict store layouts, --ignore-scripts, cached CI installs, etc).
16
+ config = withExpoVersion(config);
17
+
11
18
  // Apply platform specific modifications
12
19
  config = withCIOIos(config, props.config, props.ios, props.location);
13
20
  config = withCIOAndroid(config, props.config, props.android, props.location);
@@ -1 +1 @@
1
- {"version":3,"names":["withCIOAndroid","isExpoVersion53OrHigher","withCIOIos","withCustomerIOPlugin","config","props","Error","ios","location","android"],"sources":["index.ts"],"sourcesContent":["import type { ExpoConfig } from '@expo/config-types';\n\nimport { withCIOAndroid } from './android/withCIOAndroid';\nimport { isExpoVersion53OrHigher } from './ios/utils';\nimport { withCIOIos } from './ios/withCIOIos';\nimport type {\n CustomerIOPluginOptions,\n LocationTrackingMode,\n NativeSDKConfig,\n} from './types/cio-types';\n\nexport type { LocationTrackingMode, NativeSDKConfig };\n\n// Entry point for config plugin\nfunction withCustomerIOPlugin(\n config: ExpoConfig,\n props: CustomerIOPluginOptions\n) {\n // Check if config is being used with unsupported Expo version\n if (props.config && !isExpoVersion53OrHigher(config)) {\n throw new Error(\n 'CustomerIO auto initialization (config property) requires Expo SDK 53 or higher. ' +\n 'Please upgrade to Expo SDK 53+ or use manual initialization instead. ' +\n 'See documentation for manual setup instructions.'\n );\n }\n\n // Apply platform specific modifications\n config = withCIOIos(config, props.config, props.ios, props.location);\n config = withCIOAndroid(config, props.config, props.android, props.location);\n\n return config;\n}\n\nexport default withCustomerIOPlugin;\n"],"mappings":"AAEA,SAASA,cAAc,QAAQ,0BAA0B;AACzD,SAASC,uBAAuB,QAAQ,aAAa;AACrD,SAASC,UAAU,QAAQ,kBAAkB;AAS7C;AACA,SAASC,oBAAoBA,CAC3BC,MAAkB,EAClBC,KAA8B,EAC9B;EACA;EACA,IAAIA,KAAK,CAACD,MAAM,IAAI,CAACH,uBAAuB,CAACG,MAAM,CAAC,EAAE;IACpD,MAAM,IAAIE,KAAK,CACb,mFAAmF,GACnF,uEAAuE,GACvE,kDACF,CAAC;EACH;;EAEA;EACAF,MAAM,GAAGF,UAAU,CAACE,MAAM,EAAEC,KAAK,CAACD,MAAM,EAAEC,KAAK,CAACE,GAAG,EAAEF,KAAK,CAACG,QAAQ,CAAC;EACpEJ,MAAM,GAAGJ,cAAc,CAACI,MAAM,EAAEC,KAAK,CAACD,MAAM,EAAEC,KAAK,CAACI,OAAO,EAAEJ,KAAK,CAACG,QAAQ,CAAC;EAE5E,OAAOJ,MAAM;AACf;AAEA,eAAeD,oBAAoB","ignoreList":[]}
1
+ {"version":3,"names":["withCIOAndroid","isExpoVersion53OrHigher","withCIOIos","withExpoVersion","withCustomerIOPlugin","config","props","Error","ios","location","android"],"sources":["index.ts"],"sourcesContent":["import type { ExpoConfig } from '@expo/config-types';\n\nimport { withCIOAndroid } from './android/withCIOAndroid';\nimport { isExpoVersion53OrHigher } from './ios/utils';\nimport { withCIOIos } from './ios/withCIOIos';\nimport type {\n CustomerIOPluginOptions,\n LocationTrackingMode,\n NativeSDKConfig,\n} from './types/cio-types';\nimport { withExpoVersion } from './utils/writeExpoVersion';\n\nexport type { LocationTrackingMode, NativeSDKConfig };\n\n// Entry point for config plugin\nfunction withCustomerIOPlugin(\n config: ExpoConfig,\n props: CustomerIOPluginOptions\n) {\n // Check if config is being used with unsupported Expo version\n if (props.config && !isExpoVersion53OrHigher(config)) {\n throw new Error(\n 'CustomerIO auto initialization (config property) requires Expo SDK 53 or higher. ' +\n 'Please upgrade to Expo SDK 53+ or use manual initialization instead. ' +\n 'See documentation for manual setup instructions.'\n );\n }\n\n // Belt-and-suspenders write of the plugin version into the RN SDK's\n // package.json. The postinstall hook does the same write at install time;\n // this covers installs where postinstall didn't run cleanly (pnpm with\n // strict store layouts, --ignore-scripts, cached CI installs, etc).\n config = withExpoVersion(config);\n\n // Apply platform specific modifications\n config = withCIOIos(config, props.config, props.ios, props.location);\n config = withCIOAndroid(config, props.config, props.android, props.location);\n\n return config;\n}\n\nexport default withCustomerIOPlugin;\n"],"mappings":"AAEA,SAASA,cAAc,QAAQ,0BAA0B;AACzD,SAASC,uBAAuB,QAAQ,aAAa;AACrD,SAASC,UAAU,QAAQ,kBAAkB;AAM7C,SAASC,eAAe,QAAQ,0BAA0B;AAI1D;AACA,SAASC,oBAAoBA,CAC3BC,MAAkB,EAClBC,KAA8B,EAC9B;EACA;EACA,IAAIA,KAAK,CAACD,MAAM,IAAI,CAACJ,uBAAuB,CAACI,MAAM,CAAC,EAAE;IACpD,MAAM,IAAIE,KAAK,CACb,mFAAmF,GACnF,uEAAuE,GACvE,kDACF,CAAC;EACH;;EAEA;EACA;EACA;EACA;EACAF,MAAM,GAAGF,eAAe,CAACE,MAAM,CAAC;;EAEhC;EACAA,MAAM,GAAGH,UAAU,CAACG,MAAM,EAAEC,KAAK,CAACD,MAAM,EAAEC,KAAK,CAACE,GAAG,EAAEF,KAAK,CAACG,QAAQ,CAAC;EACpEJ,MAAM,GAAGL,cAAc,CAACK,MAAM,EAAEC,KAAK,CAACD,MAAM,EAAEC,KAAK,CAACI,OAAO,EAAEJ,KAAK,CAACG,QAAQ,CAAC;EAE5E,OAAOJ,MAAM;AACf;AAEA,eAAeD,oBAAoB","ignoreList":[]}