@callstack/react-native-brownfield 2.2.0 → 3.0.0-rc.1

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 (223) hide show
  1. package/lib/commonjs/expo-config-plugin/android/constants.js +2 -0
  2. package/lib/commonjs/expo-config-plugin/android/constants.js.map +1 -0
  3. package/lib/commonjs/expo-config-plugin/android/gradleHelpers.js +2 -0
  4. package/lib/commonjs/expo-config-plugin/android/gradleHelpers.js.map +1 -0
  5. package/lib/commonjs/expo-config-plugin/android/index.js +2 -0
  6. package/lib/commonjs/expo-config-plugin/android/index.js.map +1 -0
  7. package/lib/commonjs/expo-config-plugin/android/withAndroidModuleFiles.js +2 -0
  8. package/lib/commonjs/expo-config-plugin/android/withAndroidModuleFiles.js.map +1 -0
  9. package/lib/commonjs/expo-config-plugin/android/withBrownfieldAndroid.js +2 -0
  10. package/lib/commonjs/expo-config-plugin/android/withBrownfieldAndroid.js.map +1 -0
  11. package/lib/commonjs/expo-config-plugin/app.plugin.js +2 -0
  12. package/lib/commonjs/expo-config-plugin/app.plugin.js.map +1 -0
  13. package/lib/commonjs/expo-config-plugin/errors/SourceModificationError.js +2 -0
  14. package/lib/commonjs/expo-config-plugin/errors/SourceModificationError.js.map +1 -0
  15. package/lib/commonjs/expo-config-plugin/index.js +2 -0
  16. package/lib/commonjs/expo-config-plugin/index.js.map +1 -0
  17. package/lib/commonjs/expo-config-plugin/ios/index.js +2 -0
  18. package/lib/commonjs/expo-config-plugin/ios/index.js.map +1 -0
  19. package/lib/commonjs/expo-config-plugin/ios/podfileHelpers.js +31 -0
  20. package/lib/commonjs/expo-config-plugin/ios/podfileHelpers.js.map +1 -0
  21. package/lib/commonjs/expo-config-plugin/ios/withBrownfieldIos.js +2 -0
  22. package/lib/commonjs/expo-config-plugin/ios/withBrownfieldIos.js.map +1 -0
  23. package/lib/commonjs/expo-config-plugin/ios/withIosFrameworkFiles.js +2 -0
  24. package/lib/commonjs/expo-config-plugin/ios/withIosFrameworkFiles.js.map +1 -0
  25. package/lib/commonjs/expo-config-plugin/ios/xcodeHelpers.js +2 -0
  26. package/lib/commonjs/expo-config-plugin/ios/xcodeHelpers.js.map +1 -0
  27. package/lib/commonjs/expo-config-plugin/logging.js +2 -0
  28. package/lib/commonjs/expo-config-plugin/logging.js.map +1 -0
  29. package/lib/commonjs/expo-config-plugin/template/android/AndroidManifest.xml +4 -0
  30. package/lib/commonjs/expo-config-plugin/template/android/ReactNativeHostManager.kt +54 -0
  31. package/lib/commonjs/expo-config-plugin/template/android/build.gradle.kts +90 -0
  32. package/lib/commonjs/expo-config-plugin/template/android/consumer-rules.pro +0 -0
  33. package/lib/commonjs/expo-config-plugin/template/android/gradle.properties +8 -0
  34. package/lib/commonjs/expo-config-plugin/template/android/proguard-rules.pro +21 -0
  35. package/lib/commonjs/expo-config-plugin/template/engine.js +2 -0
  36. package/lib/commonjs/expo-config-plugin/template/engine.js.map +1 -0
  37. package/lib/commonjs/expo-config-plugin/template/ios/FrameworkInterface.swift +8 -0
  38. package/lib/commonjs/expo-config-plugin/template/ios/Info.plist +22 -0
  39. package/lib/commonjs/expo-config-plugin/template/ios/PodfileTargetBlock.rb +4 -0
  40. package/lib/commonjs/expo-config-plugin/template/ios/ReactNativeHostManager.swift +63 -0
  41. package/lib/commonjs/expo-config-plugin/template/ios/patchExpoPre55.sh +20 -0
  42. package/lib/commonjs/expo-config-plugin/types/BrownfieldPluginConfig.js +2 -0
  43. package/lib/commonjs/expo-config-plugin/types/BrownfieldPluginConfig.js.map +1 -0
  44. package/lib/commonjs/expo-config-plugin/types/RenderedTemplateFile.js +2 -0
  45. package/lib/commonjs/expo-config-plugin/types/RenderedTemplateFile.js.map +1 -0
  46. package/lib/commonjs/expo-config-plugin/types/android/BrownfieldPluginAndroidConfig.js +2 -0
  47. package/lib/commonjs/expo-config-plugin/types/android/BrownfieldPluginAndroidConfig.js.map +1 -0
  48. package/lib/commonjs/expo-config-plugin/types/index.js +2 -0
  49. package/lib/commonjs/expo-config-plugin/types/index.js.map +1 -0
  50. package/lib/commonjs/expo-config-plugin/types/ios/BrownfieldPluginIosConfig.js +2 -0
  51. package/lib/commonjs/expo-config-plugin/types/ios/BrownfieldPluginIosConfig.js.map +1 -0
  52. package/lib/commonjs/expo-config-plugin/withBrownfield.js +2 -0
  53. package/lib/commonjs/expo-config-plugin/withBrownfield.js.map +1 -0
  54. package/lib/module/expo-config-plugin/android/constants.js +2 -0
  55. package/lib/module/expo-config-plugin/android/constants.js.map +1 -0
  56. package/lib/module/expo-config-plugin/android/gradleHelpers.js +2 -0
  57. package/lib/module/expo-config-plugin/android/gradleHelpers.js.map +1 -0
  58. package/lib/module/expo-config-plugin/android/index.js +2 -0
  59. package/lib/module/expo-config-plugin/android/index.js.map +1 -0
  60. package/lib/module/expo-config-plugin/android/withAndroidModuleFiles.js +2 -0
  61. package/lib/module/expo-config-plugin/android/withAndroidModuleFiles.js.map +1 -0
  62. package/lib/module/expo-config-plugin/android/withBrownfieldAndroid.js +2 -0
  63. package/lib/module/expo-config-plugin/android/withBrownfieldAndroid.js.map +1 -0
  64. package/lib/module/expo-config-plugin/app.plugin.js +2 -0
  65. package/lib/module/expo-config-plugin/app.plugin.js.map +1 -0
  66. package/lib/module/expo-config-plugin/errors/SourceModificationError.js +2 -0
  67. package/lib/module/expo-config-plugin/errors/SourceModificationError.js.map +1 -0
  68. package/lib/module/expo-config-plugin/index.js +2 -0
  69. package/lib/module/expo-config-plugin/index.js.map +1 -0
  70. package/lib/module/expo-config-plugin/ios/index.js +2 -0
  71. package/lib/module/expo-config-plugin/ios/index.js.map +1 -0
  72. package/lib/module/expo-config-plugin/ios/podfileHelpers.js +31 -0
  73. package/lib/module/expo-config-plugin/ios/podfileHelpers.js.map +1 -0
  74. package/lib/module/expo-config-plugin/ios/withBrownfieldIos.js +2 -0
  75. package/lib/module/expo-config-plugin/ios/withBrownfieldIos.js.map +1 -0
  76. package/lib/module/expo-config-plugin/ios/withIosFrameworkFiles.js +2 -0
  77. package/lib/module/expo-config-plugin/ios/withIosFrameworkFiles.js.map +1 -0
  78. package/lib/module/expo-config-plugin/ios/xcodeHelpers.js +2 -0
  79. package/lib/module/expo-config-plugin/ios/xcodeHelpers.js.map +1 -0
  80. package/lib/module/expo-config-plugin/logging.js +2 -0
  81. package/lib/module/expo-config-plugin/logging.js.map +1 -0
  82. package/lib/module/expo-config-plugin/template/android/AndroidManifest.xml +4 -0
  83. package/lib/module/expo-config-plugin/template/android/ReactNativeHostManager.kt +54 -0
  84. package/lib/module/expo-config-plugin/template/android/build.gradle.kts +90 -0
  85. package/lib/module/expo-config-plugin/template/android/consumer-rules.pro +0 -0
  86. package/lib/module/expo-config-plugin/template/android/gradle.properties +8 -0
  87. package/lib/module/expo-config-plugin/template/android/proguard-rules.pro +21 -0
  88. package/lib/module/expo-config-plugin/template/engine.js +2 -0
  89. package/lib/module/expo-config-plugin/template/engine.js.map +1 -0
  90. package/lib/module/expo-config-plugin/template/ios/FrameworkInterface.swift +8 -0
  91. package/lib/module/expo-config-plugin/template/ios/Info.plist +22 -0
  92. package/lib/module/expo-config-plugin/template/ios/PodfileTargetBlock.rb +4 -0
  93. package/lib/module/expo-config-plugin/template/ios/ReactNativeHostManager.swift +63 -0
  94. package/lib/module/expo-config-plugin/template/ios/patchExpoPre55.sh +20 -0
  95. package/lib/module/expo-config-plugin/types/BrownfieldPluginConfig.js +2 -0
  96. package/lib/module/expo-config-plugin/types/BrownfieldPluginConfig.js.map +1 -0
  97. package/lib/module/expo-config-plugin/types/RenderedTemplateFile.js +2 -0
  98. package/lib/module/expo-config-plugin/types/RenderedTemplateFile.js.map +1 -0
  99. package/lib/module/expo-config-plugin/types/android/BrownfieldPluginAndroidConfig.js +2 -0
  100. package/lib/module/expo-config-plugin/types/android/BrownfieldPluginAndroidConfig.js.map +1 -0
  101. package/lib/module/expo-config-plugin/types/index.js +2 -0
  102. package/lib/module/expo-config-plugin/types/index.js.map +1 -0
  103. package/lib/module/expo-config-plugin/types/ios/BrownfieldPluginIosConfig.js +2 -0
  104. package/lib/module/expo-config-plugin/types/ios/BrownfieldPluginIosConfig.js.map +1 -0
  105. package/lib/module/expo-config-plugin/withBrownfield.js +2 -0
  106. package/lib/module/expo-config-plugin/withBrownfield.js.map +1 -0
  107. package/lib/typescript/commonjs/src/expo-config-plugin/android/constants.d.ts +3 -0
  108. package/lib/typescript/commonjs/src/expo-config-plugin/android/constants.d.ts.map +1 -0
  109. package/lib/typescript/commonjs/src/expo-config-plugin/android/gradleHelpers.d.ts +14 -0
  110. package/lib/typescript/commonjs/src/expo-config-plugin/android/gradleHelpers.d.ts.map +1 -0
  111. package/lib/typescript/commonjs/src/expo-config-plugin/android/index.d.ts +4 -0
  112. package/lib/typescript/commonjs/src/expo-config-plugin/android/index.d.ts.map +1 -0
  113. package/lib/typescript/commonjs/src/expo-config-plugin/android/withAndroidModuleFiles.d.ts +24 -0
  114. package/lib/typescript/commonjs/src/expo-config-plugin/android/withAndroidModuleFiles.d.ts.map +1 -0
  115. package/lib/typescript/commonjs/src/expo-config-plugin/android/withBrownfieldAndroid.d.ts +13 -0
  116. package/lib/typescript/commonjs/src/expo-config-plugin/android/withBrownfieldAndroid.d.ts.map +1 -0
  117. package/lib/typescript/commonjs/src/expo-config-plugin/app.plugin.d.ts +9 -0
  118. package/lib/typescript/commonjs/src/expo-config-plugin/app.plugin.d.ts.map +1 -0
  119. package/lib/typescript/commonjs/src/expo-config-plugin/errors/SourceModificationError.d.ts +3 -0
  120. package/lib/typescript/commonjs/src/expo-config-plugin/errors/SourceModificationError.d.ts.map +1 -0
  121. package/lib/typescript/commonjs/src/expo-config-plugin/index.d.ts +7 -0
  122. package/lib/typescript/commonjs/src/expo-config-plugin/index.d.ts.map +1 -0
  123. package/lib/typescript/commonjs/src/expo-config-plugin/ios/index.d.ts +5 -0
  124. package/lib/typescript/commonjs/src/expo-config-plugin/ios/index.d.ts.map +1 -0
  125. package/lib/typescript/commonjs/src/expo-config-plugin/ios/podfileHelpers.d.ts +8 -0
  126. package/lib/typescript/commonjs/src/expo-config-plugin/ios/podfileHelpers.d.ts.map +1 -0
  127. package/lib/typescript/commonjs/src/expo-config-plugin/ios/withBrownfieldIos.d.ts +14 -0
  128. package/lib/typescript/commonjs/src/expo-config-plugin/ios/withBrownfieldIos.d.ts.map +1 -0
  129. package/lib/typescript/commonjs/src/expo-config-plugin/ios/withIosFrameworkFiles.d.ts +19 -0
  130. package/lib/typescript/commonjs/src/expo-config-plugin/ios/withIosFrameworkFiles.d.ts.map +1 -0
  131. package/lib/typescript/commonjs/src/expo-config-plugin/ios/xcodeHelpers.d.ts +33 -0
  132. package/lib/typescript/commonjs/src/expo-config-plugin/ios/xcodeHelpers.d.ts.map +1 -0
  133. package/lib/typescript/commonjs/src/expo-config-plugin/logging.d.ts +9 -0
  134. package/lib/typescript/commonjs/src/expo-config-plugin/logging.d.ts.map +1 -0
  135. package/lib/typescript/commonjs/src/expo-config-plugin/template/engine.d.ts +9 -0
  136. package/lib/typescript/commonjs/src/expo-config-plugin/template/engine.d.ts.map +1 -0
  137. package/lib/typescript/commonjs/src/expo-config-plugin/types/BrownfieldPluginConfig.d.ts +53 -0
  138. package/lib/typescript/commonjs/src/expo-config-plugin/types/BrownfieldPluginConfig.d.ts.map +1 -0
  139. package/lib/typescript/commonjs/src/expo-config-plugin/types/RenderedTemplateFile.d.ts +5 -0
  140. package/lib/typescript/commonjs/src/expo-config-plugin/types/RenderedTemplateFile.d.ts.map +1 -0
  141. package/lib/typescript/commonjs/src/expo-config-plugin/types/android/BrownfieldPluginAndroidConfig.d.ts +50 -0
  142. package/lib/typescript/commonjs/src/expo-config-plugin/types/android/BrownfieldPluginAndroidConfig.d.ts.map +1 -0
  143. package/lib/typescript/commonjs/src/expo-config-plugin/types/index.d.ts +5 -0
  144. package/lib/typescript/commonjs/src/expo-config-plugin/types/index.d.ts.map +1 -0
  145. package/lib/typescript/commonjs/src/expo-config-plugin/types/ios/BrownfieldPluginIosConfig.d.ts +36 -0
  146. package/lib/typescript/commonjs/src/expo-config-plugin/types/ios/BrownfieldPluginIosConfig.d.ts.map +1 -0
  147. package/lib/typescript/commonjs/src/expo-config-plugin/withBrownfield.d.ts +5 -0
  148. package/lib/typescript/commonjs/src/expo-config-plugin/withBrownfield.d.ts.map +1 -0
  149. package/lib/typescript/module/src/expo-config-plugin/android/constants.d.ts +3 -0
  150. package/lib/typescript/module/src/expo-config-plugin/android/constants.d.ts.map +1 -0
  151. package/lib/typescript/module/src/expo-config-plugin/android/gradleHelpers.d.ts +14 -0
  152. package/lib/typescript/module/src/expo-config-plugin/android/gradleHelpers.d.ts.map +1 -0
  153. package/lib/typescript/module/src/expo-config-plugin/android/index.d.ts +4 -0
  154. package/lib/typescript/module/src/expo-config-plugin/android/index.d.ts.map +1 -0
  155. package/lib/typescript/module/src/expo-config-plugin/android/withAndroidModuleFiles.d.ts +24 -0
  156. package/lib/typescript/module/src/expo-config-plugin/android/withAndroidModuleFiles.d.ts.map +1 -0
  157. package/lib/typescript/module/src/expo-config-plugin/android/withBrownfieldAndroid.d.ts +13 -0
  158. package/lib/typescript/module/src/expo-config-plugin/android/withBrownfieldAndroid.d.ts.map +1 -0
  159. package/lib/typescript/module/src/expo-config-plugin/app.plugin.d.ts +9 -0
  160. package/lib/typescript/module/src/expo-config-plugin/app.plugin.d.ts.map +1 -0
  161. package/lib/typescript/module/src/expo-config-plugin/errors/SourceModificationError.d.ts +3 -0
  162. package/lib/typescript/module/src/expo-config-plugin/errors/SourceModificationError.d.ts.map +1 -0
  163. package/lib/typescript/module/src/expo-config-plugin/index.d.ts +7 -0
  164. package/lib/typescript/module/src/expo-config-plugin/index.d.ts.map +1 -0
  165. package/lib/typescript/module/src/expo-config-plugin/ios/index.d.ts +5 -0
  166. package/lib/typescript/module/src/expo-config-plugin/ios/index.d.ts.map +1 -0
  167. package/lib/typescript/module/src/expo-config-plugin/ios/podfileHelpers.d.ts +8 -0
  168. package/lib/typescript/module/src/expo-config-plugin/ios/podfileHelpers.d.ts.map +1 -0
  169. package/lib/typescript/module/src/expo-config-plugin/ios/withBrownfieldIos.d.ts +14 -0
  170. package/lib/typescript/module/src/expo-config-plugin/ios/withBrownfieldIos.d.ts.map +1 -0
  171. package/lib/typescript/module/src/expo-config-plugin/ios/withIosFrameworkFiles.d.ts +19 -0
  172. package/lib/typescript/module/src/expo-config-plugin/ios/withIosFrameworkFiles.d.ts.map +1 -0
  173. package/lib/typescript/module/src/expo-config-plugin/ios/xcodeHelpers.d.ts +33 -0
  174. package/lib/typescript/module/src/expo-config-plugin/ios/xcodeHelpers.d.ts.map +1 -0
  175. package/lib/typescript/module/src/expo-config-plugin/logging.d.ts +9 -0
  176. package/lib/typescript/module/src/expo-config-plugin/logging.d.ts.map +1 -0
  177. package/lib/typescript/module/src/expo-config-plugin/template/engine.d.ts +9 -0
  178. package/lib/typescript/module/src/expo-config-plugin/template/engine.d.ts.map +1 -0
  179. package/lib/typescript/module/src/expo-config-plugin/types/BrownfieldPluginConfig.d.ts +53 -0
  180. package/lib/typescript/module/src/expo-config-plugin/types/BrownfieldPluginConfig.d.ts.map +1 -0
  181. package/lib/typescript/module/src/expo-config-plugin/types/RenderedTemplateFile.d.ts +5 -0
  182. package/lib/typescript/module/src/expo-config-plugin/types/RenderedTemplateFile.d.ts.map +1 -0
  183. package/lib/typescript/module/src/expo-config-plugin/types/android/BrownfieldPluginAndroidConfig.d.ts +50 -0
  184. package/lib/typescript/module/src/expo-config-plugin/types/android/BrownfieldPluginAndroidConfig.d.ts.map +1 -0
  185. package/lib/typescript/module/src/expo-config-plugin/types/index.d.ts +5 -0
  186. package/lib/typescript/module/src/expo-config-plugin/types/index.d.ts.map +1 -0
  187. package/lib/typescript/module/src/expo-config-plugin/types/ios/BrownfieldPluginIosConfig.d.ts +36 -0
  188. package/lib/typescript/module/src/expo-config-plugin/types/ios/BrownfieldPluginIosConfig.d.ts.map +1 -0
  189. package/lib/typescript/module/src/expo-config-plugin/withBrownfield.d.ts +5 -0
  190. package/lib/typescript/module/src/expo-config-plugin/withBrownfield.d.ts.map +1 -0
  191. package/package.json +15 -3
  192. package/src/expo-config-plugin/android/constants.ts +2 -0
  193. package/src/expo-config-plugin/android/gradleHelpers.ts +72 -0
  194. package/src/expo-config-plugin/android/index.ts +6 -0
  195. package/src/expo-config-plugin/android/withAndroidModuleFiles.ts +139 -0
  196. package/src/expo-config-plugin/android/withBrownfieldAndroid.ts +48 -0
  197. package/src/expo-config-plugin/app.plugin.ts +10 -0
  198. package/src/expo-config-plugin/errors/SourceModificationError.ts +1 -0
  199. package/src/expo-config-plugin/index.ts +8 -0
  200. package/src/expo-config-plugin/ios/index.ts +7 -0
  201. package/src/expo-config-plugin/ios/podfileHelpers.ts +104 -0
  202. package/src/expo-config-plugin/ios/withBrownfieldIos.ts +95 -0
  203. package/src/expo-config-plugin/ios/withIosFrameworkFiles.ts +95 -0
  204. package/src/expo-config-plugin/ios/xcodeHelpers.ts +359 -0
  205. package/src/expo-config-plugin/logging.ts +29 -0
  206. package/src/expo-config-plugin/template/android/AndroidManifest.xml +4 -0
  207. package/src/expo-config-plugin/template/android/ReactNativeHostManager.kt +54 -0
  208. package/src/expo-config-plugin/template/android/build.gradle.kts +90 -0
  209. package/src/expo-config-plugin/template/android/consumer-rules.pro +0 -0
  210. package/src/expo-config-plugin/template/android/gradle.properties +8 -0
  211. package/src/expo-config-plugin/template/android/proguard-rules.pro +21 -0
  212. package/src/expo-config-plugin/template/engine.ts +26 -0
  213. package/src/expo-config-plugin/template/ios/FrameworkInterface.swift +8 -0
  214. package/src/expo-config-plugin/template/ios/Info.plist +22 -0
  215. package/src/expo-config-plugin/template/ios/PodfileTargetBlock.rb +4 -0
  216. package/src/expo-config-plugin/template/ios/ReactNativeHostManager.swift +63 -0
  217. package/src/expo-config-plugin/template/ios/patchExpoPre55.sh +20 -0
  218. package/src/expo-config-plugin/types/BrownfieldPluginConfig.ts +67 -0
  219. package/src/expo-config-plugin/types/RenderedTemplateFile.ts +4 -0
  220. package/src/expo-config-plugin/types/android/BrownfieldPluginAndroidConfig.ts +58 -0
  221. package/src/expo-config-plugin/types/index.ts +6 -0
  222. package/src/expo-config-plugin/types/ios/BrownfieldPluginIosConfig.ts +41 -0
  223. package/src/expo-config-plugin/withBrownfield.ts +112 -0
@@ -0,0 +1,359 @@
1
+ import path from 'node:path';
2
+
3
+ import type { ModProps, XcodeProject } from '@expo/config-plugins';
4
+
5
+ import { Logger } from '../logging';
6
+ import type { ResolvedBrownfieldPluginIosConfig } from '../types';
7
+ import { SourceModificationError } from '../errors/SourceModificationError';
8
+ import { getFrameworkSourceFiles } from './withIosFrameworkFiles';
9
+ import { renderTemplate } from '../template/engine';
10
+
11
+ /**
12
+ * Adds a new Framework target to the Xcode project for Brownfield packaging
13
+ * @throws If target creation fails
14
+ * @param project The Xcode project to modify
15
+ * @param options Framework target options
16
+ */
17
+ export function addFrameworkTarget(
18
+ project: XcodeProject,
19
+ modRequest: ModProps<XcodeProject>,
20
+ options: ResolvedBrownfieldPluginIosConfig
21
+ ): {
22
+ frameworkTargetUUID: string;
23
+ targetAlreadyExists: boolean;
24
+ } {
25
+ const { frameworkName, bundleIdentifier } = options;
26
+
27
+ // check if target already exists
28
+ const existingTarget = project.pbxTargetByName(frameworkName);
29
+ if (existingTarget) {
30
+ Logger.logDebug(
31
+ `Framework target "${frameworkName}" already exists, skipping creation`
32
+ );
33
+
34
+ const frameworkTargetUUID = Object.entries(
35
+ project.pbxNativeTargetSection()
36
+ ).find(
37
+ ([_key, value]) =>
38
+ (value as any)?.productReference === existingTarget.productReference
39
+ )?.[0];
40
+
41
+ if (!frameworkTargetUUID) {
42
+ throw new SourceModificationError(
43
+ `Failed to find framework target UUID for ${frameworkName}, although it can be resolved by name`
44
+ );
45
+ }
46
+
47
+ return {
48
+ frameworkTargetUUID,
49
+ targetAlreadyExists: true,
50
+ };
51
+ }
52
+
53
+ Logger.logDebug(`Adding iOS framework target: ${frameworkName}`);
54
+
55
+ // create the framework target using 'framework' target type
56
+ const frameworkTarget = project.addTarget(
57
+ frameworkName,
58
+ 'framework',
59
+ frameworkName,
60
+ bundleIdentifier
61
+ );
62
+
63
+ if (!frameworkTarget) {
64
+ throw new SourceModificationError(
65
+ `Failed to create framework target: ${frameworkName}`
66
+ );
67
+ }
68
+
69
+ // get the target UUID for later use
70
+ // const targetUuid = frameworkTarget.uuid;
71
+ const frameworkBuildConfigurations =
72
+ project.pbxXCConfigurationList()[
73
+ frameworkTarget.pbxNativeTarget.buildConfigurationList
74
+ ];
75
+ const debugFrameworkConfigKey: string =
76
+ frameworkBuildConfigurations.buildConfigurations.find(
77
+ ({ comment }: { comment: string }) => comment === 'Debug'
78
+ ).value;
79
+ const releaseFrameworkConfigKey: string =
80
+ frameworkBuildConfigurations.buildConfigurations.find(
81
+ ({ comment }: { comment: string }) => comment === 'Release'
82
+ ).value;
83
+
84
+ // update build settings on the existing configuration list
85
+ const debugSettings = getFrameworkBuildSettings(
86
+ {
87
+ configuration: 'Debug',
88
+ },
89
+ options
90
+ );
91
+ const releaseSettings = getFrameworkBuildSettings(
92
+ {
93
+ configuration: 'Release',
94
+ },
95
+ options
96
+ );
97
+
98
+ var configs = project.pbxXCBuildConfigurationSection();
99
+
100
+ // look for existing configs for the framework target
101
+ for (const configName in configs) {
102
+ let sourceBuildSettings =
103
+ configName === releaseFrameworkConfigKey
104
+ ? releaseSettings
105
+ : configName === debugFrameworkConfigKey
106
+ ? debugSettings
107
+ : null;
108
+
109
+ // if we have matching settings, apply them
110
+ if (sourceBuildSettings) {
111
+ const destinationBuildSettings = configs[configName].buildSettings;
112
+ for (const key in sourceBuildSettings) {
113
+ destinationBuildSettings[key] = sourceBuildSettings[key];
114
+ }
115
+
116
+ Logger.logDebug(
117
+ `Updated build settings for ${configName} configuration of target ${frameworkName}`
118
+ );
119
+ }
120
+ }
121
+
122
+ // Update build settings for the target
123
+ Object.entries(debugSettings).forEach(([key, value]) => {
124
+ project.updateBuildProperty(key, value, 'Debug', frameworkName);
125
+ });
126
+ Object.entries(releaseSettings).forEach(([key, value]) => {
127
+ project.updateBuildProperty(key, value, 'Release', frameworkName);
128
+ });
129
+
130
+ // create the framework group in the project
131
+ const filePaths = getFrameworkSourceFiles(options).map(
132
+ (file) => file.relativePath
133
+ );
134
+ const groupPath = path.join(modRequest.platformProjectRoot, frameworkName);
135
+
136
+ Logger.logDebug(
137
+ `Creating PBX group '${frameworkName}' under path '${groupPath}' with files: ${filePaths.join(', ')}`
138
+ );
139
+
140
+ const frameworkGroup = project.addPbxGroup(
141
+ filePaths,
142
+ frameworkName,
143
+ groupPath
144
+ );
145
+
146
+ // add the group to the main group using the proper API
147
+ const mainGroupKey = project.getFirstProject().firstProject.mainGroup;
148
+ project.addToPbxGroup(frameworkGroup.uuid, mainGroupKey);
149
+
150
+ Logger.logInfo(`Successfully added framework target: ${frameworkName}`);
151
+
152
+ return {
153
+ frameworkTargetUUID: frameworkTarget.uuid,
154
+ targetAlreadyExists: false,
155
+ };
156
+ }
157
+
158
+ export function addSourceFilesBuildPhase(
159
+ project: XcodeProject,
160
+ frameworkTargetUUID: string,
161
+ options: ResolvedBrownfieldPluginIosConfig
162
+ ) {
163
+ const filePaths = getFrameworkSourceFiles(options).map(
164
+ (file) => file.relativePath
165
+ );
166
+
167
+ const sourceFiles = filePaths.filter(
168
+ (filePath) => !filePath.endsWith('.plist')
169
+ );
170
+
171
+ project.addBuildPhase(
172
+ sourceFiles,
173
+ 'PBXSourcesBuildPhase',
174
+ options.frameworkName,
175
+ frameworkTargetUUID,
176
+ 'framework',
177
+ '""'
178
+ );
179
+ }
180
+
181
+ /**
182
+ * Returns build settings for the framework target
183
+ * @param options The user configuration
184
+ * @returns Build settings object
185
+ */
186
+ function getFrameworkBuildSettings(
187
+ {
188
+ configuration,
189
+ }: {
190
+ /** Build configuration name ("Debug" or "Release") */
191
+ configuration: 'Debug' | 'Release';
192
+ },
193
+ {
194
+ bundleIdentifier,
195
+ deploymentTarget,
196
+ frameworkName,
197
+ frameworkVersion,
198
+ buildSettings: customBuildSettings,
199
+ }: ResolvedBrownfieldPluginIosConfig
200
+ ): Record<string, string | boolean | number> {
201
+ const isDebug = configuration === 'Debug';
202
+
203
+ return {
204
+ // settings required as per https://oss.callstack.com/react-native-brownfield/docs/getting-started/ios#required-build-settings
205
+ BUILD_LIBRARY_FOR_DISTRIBUTION: 'YES',
206
+ USER_SCRIPT_SANDBOXING: 'NO',
207
+ SKIP_INSTALL: 'NO',
208
+ ENABLE_MODULE_VERIFIER: 'NO',
209
+
210
+ // basic settings
211
+ PRODUCT_BUNDLE_IDENTIFIER: `"${bundleIdentifier}"`,
212
+ IPHONEOS_DEPLOYMENT_TARGET: deploymentTarget,
213
+
214
+ // Swift settings - use modern Swift version (5.0+) to avoid legacy Swift 3.x migration prompts
215
+ SWIFT_VERSION: '5.0',
216
+ TARGETED_DEVICE_FAMILY: `"1,2"`,
217
+ INFOPLIST_FILE: `${frameworkName}/Info.plist`,
218
+ CURRENT_PROJECT_VERSION: `"${frameworkVersion}"`,
219
+ PRODUCT_NAME: '"$(TARGET_NAME)"',
220
+ SWIFT_OPTIMIZATION_LEVEL: isDebug ? '-Onone' : '-O',
221
+
222
+ // custom build settings
223
+ ...customBuildSettings,
224
+ };
225
+ }
226
+
227
+ /**
228
+ * Finds the "Bundle React Native code and images" build phase from the main app target
229
+ * and adds it to the framework target's build phases
230
+ * @param project The Xcode project
231
+ * @param targetUuid The UUID of the framework target
232
+ */
233
+ export function copyBundleReactNativePhase(
234
+ project: XcodeProject,
235
+ targetUuid: string
236
+ ): void {
237
+ const buildPhaseName = 'Bundle React Native code and images';
238
+
239
+ // Find the existing shell script build phase
240
+ const shellScriptPhases =
241
+ project.hash.project.objects.PBXShellScriptBuildPhase;
242
+ if (!shellScriptPhases) {
243
+ throw new SourceModificationError(
244
+ `No shell script build phases found, skipping ${buildPhaseName}`
245
+ );
246
+ }
247
+
248
+ // find the phase by name
249
+ let existingPhaseUuid: string | null = null;
250
+ for (const key of Object.keys(shellScriptPhases)) {
251
+ if (key.endsWith('_comment')) continue;
252
+ const phase = shellScriptPhases[key];
253
+ if (phase.name === `"${buildPhaseName}"` || phase.name === buildPhaseName) {
254
+ existingPhaseUuid = key;
255
+ break;
256
+ }
257
+ }
258
+
259
+ if (!existingPhaseUuid) {
260
+ throw new SourceModificationError(
261
+ `Could not find "${buildPhaseName}" build phase, skipping`
262
+ );
263
+ }
264
+
265
+ // add the phase reference to the framework target's buildPhases array
266
+ const nativeTargets = project.hash.project.objects.PBXNativeTarget;
267
+ if (nativeTargets && nativeTargets[targetUuid]) {
268
+ const target = nativeTargets[targetUuid];
269
+ if (target.buildPhases) {
270
+ // check if phase is already added
271
+ if (
272
+ !target.buildPhases.some(
273
+ (phase: { value: string }) => phase.value === existingPhaseUuid
274
+ )
275
+ ) {
276
+ target.buildPhases.push({
277
+ value: existingPhaseUuid,
278
+ comment: buildPhaseName,
279
+ });
280
+
281
+ Logger.logDebug(
282
+ `Added "${buildPhaseName}" build phase to framework target ${target.name}`
283
+ );
284
+ }
285
+ }
286
+ }
287
+ }
288
+
289
+ export function addExpoPre55ShellPatchScriptPhase(
290
+ project: XcodeProject,
291
+ {
292
+ frameworkName,
293
+ frameworkTargetUUID,
294
+ }: {
295
+ frameworkName: string;
296
+ frameworkTargetUUID: string;
297
+ }
298
+ ) {
299
+ project.addBuildPhase(
300
+ [
301
+ // no associated files
302
+ ],
303
+ 'PBXShellScriptBuildPhase',
304
+ 'Patch ExpoModulesProvider',
305
+ frameworkTargetUUID,
306
+ {
307
+ shellPath: '/bin/sh',
308
+ shellScript: renderTemplate('ios', 'patchExpoPre55.sh', {
309
+ '{{FRAMEWORK_NAME}}': frameworkName,
310
+ }),
311
+ }
312
+ );
313
+ }
314
+
315
+ /**
316
+ * Makes sure the patch expo modules provider phase is after the expo configure phase,
317
+ * otherwise the patched file would be overwritten by the expo configure phase
318
+ * @param project The Xcode project
319
+ * @param frameworkTargetUUID The UUID of the framework target
320
+ * @returns True if the build phases were modified, false otherwise
321
+ */
322
+ export function ensureExpoPre55ShellPatchScriptPhaseIsOrdered(
323
+ project: XcodeProject,
324
+ frameworkTargetUUID: string
325
+ ) {
326
+ let modified = false;
327
+ const nativeTargetSection = project.pbxNativeTargetSection();
328
+
329
+ const buildPhases: { value: string; comment?: string }[] =
330
+ nativeTargetSection[frameworkTargetUUID].buildPhases;
331
+
332
+ const expoConfigurePhaseIndex = buildPhases.findIndex(
333
+ (phase) =>
334
+ (phase as any)?.comment?.toLowerCase() ===
335
+ '[Expo] Configure project'.toLowerCase()
336
+ );
337
+
338
+ const patchExpoModulesProviderPhaseIndex = buildPhases.findIndex(
339
+ (phase) =>
340
+ (phase as any)?.comment?.toLowerCase() ===
341
+ 'Patch ExpoModulesProvider'.toLowerCase()
342
+ );
343
+
344
+ // ensure patch expo modules provider phase is after expo configure phase
345
+ if (patchExpoModulesProviderPhaseIndex < expoConfigurePhaseIndex) {
346
+ const element = buildPhases.splice(
347
+ patchExpoModulesProviderPhaseIndex,
348
+ 1
349
+ )[0]; // pop the element at patchExpoModulesProviderPhaseIndex
350
+ buildPhases.splice(expoConfigurePhaseIndex, 0, element); // insert the element at expoConfigurePhaseIndex ("after")
351
+ modified = true;
352
+ }
353
+
354
+ nativeTargetSection[frameworkTargetUUID].buildPhases = buildPhases;
355
+
356
+ project.writeSync();
357
+
358
+ return modified;
359
+ }
@@ -0,0 +1,29 @@
1
+ const LOG_TAG = '[react-native-brownfield]';
2
+
3
+ export class Logger {
4
+ private static debug: boolean = false;
5
+
6
+ static setIsDebug(enabled: boolean) {
7
+ this.debug = enabled;
8
+ }
9
+
10
+ static logInfo(message: string, ...args: any[]) {
11
+ console.log(`${LOG_TAG} ${message}`, ...args);
12
+ }
13
+
14
+ static logDebug(message: string, ...args: any[]) {
15
+ if (!this.debug) {
16
+ return;
17
+ }
18
+
19
+ console.debug(`${LOG_TAG} ${message}`, ...args);
20
+ }
21
+
22
+ static logWarning(message: string, ...args: any[]) {
23
+ console.warn(`${LOG_TAG} ${message}`, ...args);
24
+ }
25
+
26
+ static logError(message: string, ...args: any[]) {
27
+ console.error(`${LOG_TAG} ${message}`, ...args);
28
+ }
29
+ }
@@ -0,0 +1,4 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android">
3
+
4
+ </manifest>
@@ -0,0 +1,54 @@
1
+ package {{PACKAGE_NAME}}
2
+
3
+ import android.app.Application
4
+ import android.content.res.Configuration
5
+ import com.callstack.reactnativebrownfield.OnJSBundleLoaded
6
+ import com.callstack.reactnativebrownfield.ReactNativeBrownfield
7
+ import com.facebook.react.PackageList
8
+ import com.facebook.react.ReactHost
9
+ import com.facebook.react.ReactNativeApplicationEntryPoint.loadReactNative
10
+ import com.facebook.react.ReactPackage
11
+ import com.facebook.react.defaults.DefaultReactNativeHost
12
+ import expo.modules.ApplicationLifecycleDispatcher
13
+ import expo.modules.ExpoReactHostFactory
14
+ import expo.modules.ReactNativeHostWrapper
15
+
16
+ object ReactNativeHostManager {
17
+ fun initialize(application: Application, onJSBundleLoaded: OnJSBundleLoaded? = null) {
18
+ loadReactNative(application)
19
+
20
+ ApplicationLifecycleDispatcher.onApplicationCreate(application)
21
+
22
+ val reactNativeHost = ReactNativeHostWrapper(
23
+ application,
24
+ object : DefaultReactNativeHost(application) {
25
+ override fun getUseDeveloperSupport(): Boolean {
26
+ return BuildConfig.DEBUG
27
+ }
28
+
29
+ override fun getPackages(): List<ReactPackage> {
30
+ return PackageList(application).packages
31
+ }
32
+
33
+ override fun getJSMainModuleName(): String {
34
+ return ".expo/.virtual-metro-entry"
35
+ }
36
+
37
+ override fun getBundleAssetName(): String = "index.android.bundle"
38
+ })
39
+
40
+
41
+ val reactHost: ReactHost by lazy {
42
+ ExpoReactHostFactory.createFromReactNativeHost(
43
+ context = application.applicationContext,
44
+ reactNativeHost = reactNativeHost
45
+ )
46
+ }
47
+
48
+ ReactNativeBrownfield.initialize(application, reactHost, onJSBundleLoaded)
49
+ }
50
+
51
+ fun onConfigurationChanged(application: Application, newConfig: Configuration) {
52
+ ApplicationLifecycleDispatcher.onConfigurationChanged(application, newConfig)
53
+ }
54
+ }
@@ -0,0 +1,90 @@
1
+ import groovy.json.JsonOutput
2
+ import groovy.json.JsonSlurper
3
+
4
+ plugins {
5
+ id("com.android.library")
6
+ id("org.jetbrains.kotlin.android")
7
+ id("com.callstack.react.brownfield")
8
+ `maven-publish`
9
+ id("com.facebook.react")
10
+ }
11
+
12
+ publishing {
13
+ publications {
14
+ create<MavenPublication>("mavenAar") {
15
+ groupId = "{{GROUP_ID}}"
16
+ artifactId = "{{ARTIFACT_ID}}"
17
+ version = "{{ARTIFACT_VERSION}}"
18
+ afterEvaluate {
19
+ from(components.getByName("default"))
20
+ }
21
+ }
22
+ }
23
+
24
+ repositories {
25
+ mavenLocal() // publishes to the local Maven repository (~/.m2/repository by default)
26
+ }
27
+ }
28
+
29
+ react {
30
+ autolinkLibrariesWithApp()
31
+ }
32
+
33
+ android {
34
+ namespace = "{{PACKAGE_NAME}}"
35
+ compileSdk = {{COMPILE_SDK_VERSION}}
36
+
37
+ defaultConfig {
38
+ minSdk = {{MIN_SDK_VERSION}}
39
+
40
+ buildConfigField(
41
+ "boolean",
42
+ "IS_EDGE_TO_EDGE_ENABLED",
43
+ properties["edgeToEdgeEnabled"].toString()
44
+ )
45
+ buildConfigField(
46
+ "boolean",
47
+ "IS_NEW_ARCHITECTURE_ENABLED",
48
+ properties["newArchEnabled"].toString()
49
+ )
50
+ buildConfigField("boolean", "IS_HERMES_ENABLED", properties["hermesEnabled"].toString())
51
+
52
+ testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
53
+ consumerProguardFiles("consumer-rules.pro")
54
+ }
55
+
56
+ buildFeatures {
57
+ buildConfig = true
58
+ }
59
+
60
+ buildTypes {
61
+ release {
62
+ isMinifyEnabled = false
63
+ proguardFiles(
64
+ getDefaultProguardFile("proguard-android-optimize.txt"),
65
+ "proguard-rules.pro"
66
+ )
67
+ }
68
+ }
69
+ compileOptions {
70
+ sourceCompatibility = JavaVersion.VERSION_17
71
+ targetCompatibility = JavaVersion.VERSION_17
72
+ }
73
+ kotlinOptions {
74
+ jvmTarget = "17"
75
+ }
76
+
77
+ publishing {
78
+ multipleVariants {
79
+ allVariants()
80
+ }
81
+ }
82
+ }
83
+
84
+ dependencies {
85
+ api("com.facebook.react:react-android:{{RN_VERSION}}")
86
+ api("com.facebook.react:hermes-android:{{RN_VERSION}}")
87
+
88
+ api("io.coil-kt.coil3:coil-compose:3.2.0")
89
+ api("io.coil-kt.coil3:coil-network-okhttp:3.2.0")
90
+ }
@@ -0,0 +1,8 @@
1
+ android.useAndroidX=true
2
+
3
+ reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64
4
+ newArchEnabled=true
5
+ hermesEnabled=true
6
+ edgeToEdgeEnabled=false
7
+
8
+ org.gradle.caching=true
@@ -0,0 +1,21 @@
1
+ # Add project specific ProGuard rules here.
2
+ # You can control the set of applied configuration files using the
3
+ # proguardFiles setting in build.gradle.
4
+ #
5
+ # For more details, see
6
+ # http://developer.android.com/guide/developing/tools/proguard.html
7
+
8
+ # If your project uses WebView with JS, uncomment the following
9
+ # and specify the fully qualified class name to the JavaScript interface
10
+ # class:
11
+ #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12
+ # public *;
13
+ #}
14
+
15
+ # Uncomment this to preserve the line number information for
16
+ # debugging stack traces.
17
+ #-keepattributes SourceFile,LineNumberTable
18
+
19
+ # If you keep the line number information, uncomment this to
20
+ # hide the original source file name.
21
+ #-renamesourcefileattribute SourceFile
@@ -0,0 +1,26 @@
1
+ import path from 'node:path';
2
+ import fs from 'node:fs';
3
+
4
+ /**
5
+ * Renders a template file for the specified platform with given parameters
6
+ * @param platform The platform name (specifies the subdirectory of template/)
7
+ * @param name The template file name (with extension)
8
+ * @param params The params to be replaced in the template
9
+ * @returns The rendered template content
10
+ */
11
+ export function renderTemplate(
12
+ platform: 'ios' | 'android',
13
+ name: string,
14
+ params?: Record<`{{${string}}}`, unknown>
15
+ ): string {
16
+ const templatePath = path.join(__dirname, platform, name);
17
+
18
+ let templateContent = fs.readFileSync(templatePath, 'utf8');
19
+
20
+ for (const [key, value] of Object.entries(params ?? {})) {
21
+ const regex = new RegExp(key, 'g');
22
+ templateContent = templateContent.replace(regex, String(value));
23
+ }
24
+
25
+ return templateContent;
26
+ }
@@ -0,0 +1,8 @@
1
+ // Export helpers from @callstack/react-native-brownfield library
2
+ @_exported import ReactBrownfield
3
+ @_exported import Brownie
4
+
5
+ // Initializes a Bundle instance that points at the framework target.
6
+ public let ReactNativeBundle = Bundle(for: InternalClassForBundle.self)
7
+
8
+ class InternalClassForBundle {}
@@ -0,0 +1,22 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>CFBundleDevelopmentRegion</key>
6
+ <string>$(DEVELOPMENT_LANGUAGE)</string>
7
+ <key>CFBundleExecutable</key>
8
+ <string>$(EXECUTABLE_NAME)</string>
9
+ <key>CFBundleIdentifier</key>
10
+ <string>{{BUNDLE_IDENTIFIER}}</string>
11
+ <key>CFBundleInfoDictionaryVersion</key>
12
+ <string>6.0</string>
13
+ <key>CFBundleName</key>
14
+ <string>$(PRODUCT_NAME)</string>
15
+ <key>CFBundlePackageType</key>
16
+ <string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
17
+ <key>CFBundleShortVersionString</key>
18
+ <string>$(MARKETING_VERSION)</string>
19
+ <key>CFBundleVersion</key>
20
+ <string>$(CURRENT_PROJECT_VERSION)</string>
21
+ </dict>
22
+ </plist>
@@ -0,0 +1,4 @@
1
+ # Brownfield framework target for packaging as XCFramework
2
+ target '{{FRAMEWORK_NAME}}' do
3
+ inherit! :complete
4
+ end