@callstack/react-native-brownfield 3.15.0 → 4.1.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 (114) hide show
  1. package/gradle-plugin/brownfield/config/detekt/detekt.yml +1 -1
  2. package/gradle-plugin/brownfield/gradle.properties +1 -1
  3. package/gradle-plugin/brownfield/gradlew +0 -0
  4. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/expo/utils/LocalMavenUtils.kt +2 -5
  5. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/ProjectConfigurations.kt +3 -5
  6. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt +21 -26
  7. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNSourceSets.kt +23 -28
  8. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/AssetTaskProcessor.kt +4 -16
  9. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/ExplodeTaskProvider.kt +6 -7
  10. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/JNILibsProcessor.kt +133 -110
  11. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/ManifestTaskProcessor.kt +25 -61
  12. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/MergeProcessor.kt +7 -29
  13. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/ProguardProcessor.kt +9 -46
  14. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/ResourceTaskProcessor.kt +4 -13
  15. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantHelper.kt +52 -47
  16. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantTaskProvider.kt +31 -63
  17. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/BundleTaskProvider.kt +72 -27
  18. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/Constants.kt +0 -1
  19. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ExplodeAarTask.kt +2 -20
  20. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/Logging.kt +1 -1
  21. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/MergeClassesTask.kt +70 -0
  22. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/MergeLibraryManifestTask.kt +178 -0
  23. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/AndroidArchiveLibrary.kt +0 -4
  24. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/DirectoryManager.kt +0 -5
  25. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/Extension.kt +8 -9
  26. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/Utils.kt +2 -34
  27. package/lib/commonjs/expo-config-plugin/android/utils/constants.js +1 -1
  28. package/lib/commonjs/expo-config-plugin/android/utils/formatHelpers.js +2 -0
  29. package/lib/commonjs/expo-config-plugin/android/utils/formatHelpers.js.map +1 -0
  30. package/lib/commonjs/expo-config-plugin/android/utils/gradleHelpers.js +1 -1
  31. package/lib/commonjs/expo-config-plugin/android/utils/gradleHelpers.js.map +1 -1
  32. package/lib/commonjs/expo-config-plugin/android/withAndroidModuleFiles.js +1 -1
  33. package/lib/commonjs/expo-config-plugin/android/withAndroidModuleFiles.js.map +1 -1
  34. package/lib/commonjs/expo-config-plugin/android/withBrownfieldAndroid.js +1 -1
  35. package/lib/commonjs/expo-config-plugin/android/withBrownfieldAndroid.js.map +1 -1
  36. package/lib/commonjs/expo-config-plugin/expoUtils.js +1 -1
  37. package/lib/commonjs/expo-config-plugin/expoUtils.js.map +1 -1
  38. package/lib/commonjs/expo-config-plugin/ios/podfileHelpers.js +2 -8
  39. package/lib/commonjs/expo-config-plugin/ios/podfileHelpers.js.map +1 -1
  40. package/lib/commonjs/expo-config-plugin/ios/withBrownfieldIos.js +1 -1
  41. package/lib/commonjs/expo-config-plugin/ios/withBrownfieldIos.js.map +1 -1
  42. package/lib/commonjs/expo-config-plugin/ios/xcodeHelpers.js +2 -2
  43. package/lib/commonjs/expo-config-plugin/ios/xcodeHelpers.js.map +1 -1
  44. package/lib/commonjs/expo-config-plugin/template/android/build.gradle.kts +6 -0
  45. package/lib/commonjs/scripts/brownfield.js +0 -0
  46. package/lib/module/expo-config-plugin/android/utils/constants.js +1 -1
  47. package/lib/module/expo-config-plugin/android/utils/formatHelpers.js +2 -0
  48. package/lib/module/expo-config-plugin/android/utils/formatHelpers.js.map +1 -0
  49. package/lib/module/expo-config-plugin/android/utils/gradleHelpers.js +1 -1
  50. package/lib/module/expo-config-plugin/android/utils/gradleHelpers.js.map +1 -1
  51. package/lib/module/expo-config-plugin/android/withAndroidModuleFiles.js +1 -1
  52. package/lib/module/expo-config-plugin/android/withAndroidModuleFiles.js.map +1 -1
  53. package/lib/module/expo-config-plugin/android/withBrownfieldAndroid.js +1 -1
  54. package/lib/module/expo-config-plugin/android/withBrownfieldAndroid.js.map +1 -1
  55. package/lib/module/expo-config-plugin/expoUtils.js +1 -1
  56. package/lib/module/expo-config-plugin/expoUtils.js.map +1 -1
  57. package/lib/module/expo-config-plugin/ios/podfileHelpers.js +2 -8
  58. package/lib/module/expo-config-plugin/ios/podfileHelpers.js.map +1 -1
  59. package/lib/module/expo-config-plugin/ios/withBrownfieldIos.js +1 -1
  60. package/lib/module/expo-config-plugin/ios/withBrownfieldIos.js.map +1 -1
  61. package/lib/module/expo-config-plugin/ios/xcodeHelpers.js +2 -2
  62. package/lib/module/expo-config-plugin/ios/xcodeHelpers.js.map +1 -1
  63. package/lib/module/expo-config-plugin/template/android/build.gradle.kts +6 -0
  64. package/lib/typescript/commonjs/src/expo-config-plugin/android/utils/constants.d.ts +2 -2
  65. package/lib/typescript/commonjs/src/expo-config-plugin/android/utils/formatHelpers.d.ts +2 -0
  66. package/lib/typescript/commonjs/src/expo-config-plugin/android/utils/formatHelpers.d.ts.map +1 -0
  67. package/lib/typescript/commonjs/src/expo-config-plugin/android/utils/gradleHelpers.d.ts +7 -0
  68. package/lib/typescript/commonjs/src/expo-config-plugin/android/utils/gradleHelpers.d.ts.map +1 -1
  69. package/lib/typescript/commonjs/src/expo-config-plugin/android/withAndroidModuleFiles.d.ts +1 -5
  70. package/lib/typescript/commonjs/src/expo-config-plugin/android/withAndroidModuleFiles.d.ts.map +1 -1
  71. package/lib/typescript/commonjs/src/expo-config-plugin/android/withBrownfieldAndroid.d.ts.map +1 -1
  72. package/lib/typescript/commonjs/src/expo-config-plugin/expoUtils.d.ts +0 -1
  73. package/lib/typescript/commonjs/src/expo-config-plugin/expoUtils.d.ts.map +1 -1
  74. package/lib/typescript/commonjs/src/expo-config-plugin/ios/podfileHelpers.d.ts.map +1 -1
  75. package/lib/typescript/commonjs/src/expo-config-plugin/ios/withBrownfieldIos.d.ts.map +1 -1
  76. package/lib/typescript/commonjs/src/expo-config-plugin/ios/xcodeHelpers.d.ts +0 -16
  77. package/lib/typescript/commonjs/src/expo-config-plugin/ios/xcodeHelpers.d.ts.map +1 -1
  78. package/lib/typescript/commonjs/src/expo-config-plugin/types/android/BrownfieldPluginAndroidConfig.d.ts +5 -0
  79. package/lib/typescript/commonjs/src/expo-config-plugin/types/android/BrownfieldPluginAndroidConfig.d.ts.map +1 -1
  80. package/lib/typescript/module/src/expo-config-plugin/android/utils/constants.d.ts +2 -2
  81. package/lib/typescript/module/src/expo-config-plugin/android/utils/formatHelpers.d.ts +2 -0
  82. package/lib/typescript/module/src/expo-config-plugin/android/utils/formatHelpers.d.ts.map +1 -0
  83. package/lib/typescript/module/src/expo-config-plugin/android/utils/gradleHelpers.d.ts +7 -0
  84. package/lib/typescript/module/src/expo-config-plugin/android/utils/gradleHelpers.d.ts.map +1 -1
  85. package/lib/typescript/module/src/expo-config-plugin/android/withAndroidModuleFiles.d.ts +1 -5
  86. package/lib/typescript/module/src/expo-config-plugin/android/withAndroidModuleFiles.d.ts.map +1 -1
  87. package/lib/typescript/module/src/expo-config-plugin/android/withBrownfieldAndroid.d.ts.map +1 -1
  88. package/lib/typescript/module/src/expo-config-plugin/expoUtils.d.ts +0 -1
  89. package/lib/typescript/module/src/expo-config-plugin/expoUtils.d.ts.map +1 -1
  90. package/lib/typescript/module/src/expo-config-plugin/ios/podfileHelpers.d.ts.map +1 -1
  91. package/lib/typescript/module/src/expo-config-plugin/ios/withBrownfieldIos.d.ts.map +1 -1
  92. package/lib/typescript/module/src/expo-config-plugin/ios/xcodeHelpers.d.ts +0 -16
  93. package/lib/typescript/module/src/expo-config-plugin/ios/xcodeHelpers.d.ts.map +1 -1
  94. package/lib/typescript/module/src/expo-config-plugin/types/android/BrownfieldPluginAndroidConfig.d.ts +5 -0
  95. package/lib/typescript/module/src/expo-config-plugin/types/android/BrownfieldPluginAndroidConfig.d.ts.map +1 -1
  96. package/package.json +3 -3
  97. package/src/expo-config-plugin/android/utils/constants.ts +1 -1
  98. package/src/expo-config-plugin/android/utils/formatHelpers.ts +7 -0
  99. package/src/expo-config-plugin/android/utils/gradleHelpers.ts +41 -0
  100. package/src/expo-config-plugin/android/withAndroidModuleFiles.ts +23 -31
  101. package/src/expo-config-plugin/android/withBrownfieldAndroid.ts +16 -3
  102. package/src/expo-config-plugin/expoUtils.ts +1 -2
  103. package/src/expo-config-plugin/ios/podfileHelpers.ts +8 -52
  104. package/src/expo-config-plugin/ios/withBrownfieldIos.ts +1 -25
  105. package/src/expo-config-plugin/ios/xcodeHelpers.ts +0 -99
  106. package/src/expo-config-plugin/template/android/build.gradle.kts +6 -0
  107. package/src/expo-config-plugin/types/android/BrownfieldPluginAndroidConfig.ts +6 -0
  108. package/CHANGELOG.md +0 -287
  109. package/lib/commonjs/expo-config-plugin/template/android/ReactNativeHostManager.pre55.kt +0 -52
  110. package/lib/commonjs/expo-config-plugin/template/ios/patchExpoPre55.sh +0 -22
  111. package/lib/module/expo-config-plugin/template/android/ReactNativeHostManager.pre55.kt +0 -52
  112. package/lib/module/expo-config-plugin/template/ios/patchExpoPre55.sh +0 -22
  113. package/src/expo-config-plugin/template/android/ReactNativeHostManager.pre55.kt +0 -52
  114. package/src/expo-config-plugin/template/ios/patchExpoPre55.sh +0 -22
@@ -48,6 +48,11 @@ export interface BrownfieldPluginAndroidConfig {
48
48
  * @default false
49
49
  */
50
50
  useLocalGradlePlugin?: boolean;
51
+ /**
52
+ * Missing dimension strategies as dimension + flavor(s).
53
+ * @default []
54
+ */
55
+ missingDimensionStrategies?: string[];
51
56
  }
52
57
  /**
53
58
  * Android configuration with resolved defaults (all fields required)
@@ -1 +1 @@
1
- {"version":3,"file":"BrownfieldPluginAndroidConfig.d.ts","sourceRoot":"","sources":["../../../../../../../src/expo-config-plugin/types/android/BrownfieldPluginAndroidConfig.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,6BAA6B;IAC5C;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED;;GAEG;AACH,MAAM,MAAM,qCAAqC,GAAG,QAAQ,CAC1D,IAAI,CAAC,6BAA6B,EAAE,mBAAmB,GAAG,kBAAkB,CAAC,CAC9E,GACC,IAAI,CAAC,6BAA6B,EAAE,mBAAmB,GAAG,kBAAkB,CAAC,CAAC"}
1
+ {"version":3,"file":"BrownfieldPluginAndroidConfig.d.ts","sourceRoot":"","sources":["../../../../../../../src/expo-config-plugin/types/android/BrownfieldPluginAndroidConfig.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,6BAA6B;IAC5C;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAE/B;;;OAGG;IACH,0BAA0B,CAAC,EAAE,MAAM,EAAE,CAAC;CACvC;AAED;;GAEG;AACH,MAAM,MAAM,qCAAqC,GAAG,QAAQ,CAC1D,IAAI,CAAC,6BAA6B,EAAE,mBAAmB,GAAG,kBAAkB,CAAC,CAC9E,GACC,IAAI,CAAC,6BAA6B,EAAE,mBAAmB,GAAG,kBAAkB,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@callstack/react-native-brownfield",
3
- "version": "3.15.0",
3
+ "version": "4.1.0",
4
4
  "license": "MIT",
5
5
  "author": "Michal Chudziak <mike.chudziak@callstack.com>",
6
6
  "bin": {
@@ -89,7 +89,7 @@
89
89
  "@expo/config-plugins": ">=54 <100"
90
90
  },
91
91
  "dependencies": {
92
- "@callstack/brownfield-cli": "^3.15.0"
92
+ "@callstack/brownfield-cli": "workspace:^"
93
93
  },
94
94
  "devDependencies": {
95
95
  "@babel/core": "^7.25.2",
@@ -121,4 +121,4 @@
121
121
  "engines": {
122
122
  "node": ">=20"
123
123
  }
124
- }
124
+ }
@@ -1,2 +1,2 @@
1
- export const BROWNFIELD_PLUGIN_VERSION = '2.0.0-alpha04';
1
+ export const BROWNFIELD_PLUGIN_VERSION = '2.0.0-alpha07';
2
2
  export const brownfieldGradlePluginDependency = `classpath("com.callstack.react:brownfield-gradle-plugin:${BROWNFIELD_PLUGIN_VERSION}")`;
@@ -0,0 +1,7 @@
1
+ export function formatMissingDimensionStrategies(
2
+ missingDimensionStrategies: string[]
3
+ ): string {
4
+ return missingDimensionStrategies
5
+ .map((value) => JSON.stringify(value))
6
+ .join(', ');
7
+ }
@@ -1,5 +1,6 @@
1
1
  import { brownfieldGradlePluginDependency } from './constants';
2
2
  import { Logger } from '../../logging';
3
+ import { formatMissingDimensionStrategies } from './formatHelpers';
3
4
 
4
5
  const LOCAL_GRADLE_PLUGIN_INCLUDE_BUILD =
5
6
  'includeBuild("../node_modules/@callstack/react-native-brownfield/gradle-plugin/brownfield")';
@@ -56,6 +57,46 @@ export function modifyRootBuildGradle(
56
57
  return modifiedContents;
57
58
  }
58
59
 
60
+ /**
61
+ * Modifies the app build.gradle to add missingDimensionStrategy arguments
62
+ * @param contents The original app build.gradle content
63
+ * @param missingDimensionStrategies The arguments for missingDimensionStrategy
64
+ * @returns The modified build.gradle content
65
+ */
66
+ export function modifyAppBuildGradleMissingDimensionStrategy(
67
+ contents: string,
68
+ missingDimensionStrategies: string[]
69
+ ): string {
70
+ if (missingDimensionStrategies.length < 2) {
71
+ return contents;
72
+ }
73
+
74
+ Logger.logDebug('Modifying app build.gradle to add missingDimensionStrategy');
75
+
76
+ const defaultConfigRegex = /^([ \t]*defaultConfig\s*\{)/m;
77
+ const match = contents.match(defaultConfigRegex);
78
+
79
+ if (!match) {
80
+ throw new Error('Could not locate defaultConfig block in app build.gradle');
81
+ }
82
+
83
+ const baseIndent = match[1].match(/^[ \t]*/)?.[0] ?? '';
84
+ const indentUnit = baseIndent.includes('\t') ? '\t' : ' ';
85
+ const args = formatMissingDimensionStrategies(missingDimensionStrategies);
86
+ const missingStrategyLine = `missingDimensionStrategy(${args})`;
87
+
88
+ if (contents.includes(missingStrategyLine)) {
89
+ Logger.logDebug(
90
+ 'missingDimensionStrategy already present with same arguments, skipping'
91
+ );
92
+ return contents;
93
+ }
94
+
95
+ const insertion = `\n${baseIndent}${indentUnit}${missingStrategyLine}`;
96
+
97
+ return contents.replace(defaultConfigRegex, `$1${insertion}`);
98
+ }
99
+
59
100
  function addLocalGradlePluginIncludeBuild(contents: string): string {
60
101
  if (contents.includes('gradle-plugin/brownfield')) {
61
102
  Logger.logDebug(
@@ -9,7 +9,6 @@ import type {
9
9
  } from '../types';
10
10
  import { Logger } from '../logging';
11
11
  import { renderTemplate } from '../template/engine';
12
- import { getExpoInfo, hasExpoUpdatesInstalled } from '../expoUtils';
13
12
  import {
14
13
  type AndroidManifestMetaDataEntry,
15
14
  type AndroidStringResourceEntry,
@@ -21,6 +20,18 @@ import {
21
20
  readExpoUpdatesStringResources,
22
21
  } from './utils/expo-updates';
23
22
  import { getHermesArtifact } from './utils/hermes';
23
+ import { formatMissingDimensionStrategies } from './utils/formatHelpers';
24
+
25
+ function renderMissingDimensionStrategyBlock(
26
+ missingDimensionStrategies: string[]
27
+ ): string {
28
+ if (missingDimensionStrategies.length < 2) {
29
+ return '';
30
+ }
31
+
32
+ const args = formatMissingDimensionStrategies(missingDimensionStrategies);
33
+ return ` missingDimensionStrategy(${args})`;
34
+ }
24
35
 
25
36
  export function resolveCompileSdkVersionExpression(
26
37
  config: ResolvedBrownfieldPluginConfigWithAndroid
@@ -49,19 +60,12 @@ export function createAndroidModule({
49
60
  androidDir,
50
61
  config,
51
62
  rnVersion,
52
- isExpoPre55,
53
63
  projectRoot,
54
64
  }: {
55
65
  /**
56
66
  * Expo app root (used to detect optional dependencies such as expo-updates)
57
67
  */
58
68
  projectRoot?: string;
59
-
60
- /**
61
- * Whether the Expo project is pre-55
62
- */
63
- isExpoPre55: boolean;
64
-
65
69
  /**
66
70
  * The root Android directory path
67
71
  */
@@ -79,7 +83,6 @@ export function createAndroidModule({
79
83
  }): void {
80
84
  const { android } = config;
81
85
  const moduleDir = path.join(androidDir, android.moduleName);
82
- const hasExpoUpdates = hasExpoUpdatesInstalled(projectRoot);
83
86
 
84
87
  Logger.logDebug(`Creating Android module in: ${androidDir}`);
85
88
 
@@ -90,6 +93,12 @@ export function createAndroidModule({
90
93
  Logger.logDebug(
91
94
  `Resolved Hermes artifact: ${hermesArtifact.groupId}:${hermesArtifact.artifactId}:${hermesArtifact.version}`
92
95
  );
96
+ const missingDimensionStrategiesList = formatMissingDimensionStrategies(
97
+ android.missingDimensionStrategies
98
+ );
99
+ const missingDimensionStrategyBlock = renderMissingDimensionStrategyBlock(
100
+ android.missingDimensionStrategies
101
+ );
93
102
 
94
103
  // generate module files
95
104
  const files: RenderedTemplateFile[] = [
@@ -105,6 +114,8 @@ export function createAndroidModule({
105
114
  '{{ARTIFACT_VERSION}}': android.version,
106
115
  '{{RN_VERSION}}': rnVersion,
107
116
  '{{HERMES_ARTIFACT}}': `${hermesArtifact.groupId}:${hermesArtifact.artifactId}:${hermesArtifact.version}`,
117
+ '{{MISSING_DIMENSION_STRATEGIES}}': missingDimensionStrategiesList,
118
+ '{{MISSING_DIMENSION_STRATEGY_BLOCK}}': missingDimensionStrategyBlock,
108
119
  }),
109
120
  },
110
121
  {
@@ -113,25 +124,9 @@ export function createAndroidModule({
113
124
  },
114
125
  {
115
126
  relativePath: `src/main/java/${config.android.packageName.replace(/\./g, '/')}/ReactNativeHostManager.kt`,
116
- content: renderTemplate(
117
- 'android',
118
- isExpoPre55
119
- ? 'ReactNativeHostManager.pre55.kt'
120
- : 'ReactNativeHostManager.post55.kt',
121
- isExpoPre55
122
- ? {
123
- '{{PACKAGE_NAME}}': android.packageName,
124
- '{{EXPO_UPDATES_IMPORTS}}': hasExpoUpdates
125
- ? 'import expo.modules.updates.UpdatesController'
126
- : '',
127
- '{{EXPO_UPDATES_REACT_HOST_BLOCK}}': hasExpoUpdates
128
- ? '\n UpdatesController.setReactHost(reactHost)\n'
129
- : '\n',
130
- }
131
- : {
132
- '{{PACKAGE_NAME}}': android.packageName,
133
- }
134
- ),
127
+ content: renderTemplate('android', 'ReactNativeHostManager.post55.kt', {
128
+ '{{PACKAGE_NAME}}': android.packageName,
129
+ }),
135
130
  },
136
131
  {
137
132
  relativePath: 'consumer-rules.pro',
@@ -284,13 +279,10 @@ export const withAndroidModuleFiles: ConfigPlugin<
284
279
  );
285
280
  }
286
281
 
287
- const { isExpoPre55 } = getExpoInfo(config);
288
-
289
282
  createAndroidModule({
290
283
  androidDir,
291
284
  config: props,
292
285
  rnVersion,
293
- isExpoPre55,
294
286
  projectRoot: dangerousConfig.modRequest.projectRoot,
295
287
  });
296
288
 
@@ -1,4 +1,5 @@
1
1
  import {
2
+ withAppBuildGradle,
2
3
  withProjectBuildGradle,
3
4
  withSettingsGradle,
4
5
  withFinalizedMod,
@@ -6,6 +7,7 @@ import {
6
7
  } from '@expo/config-plugins';
7
8
 
8
9
  import {
10
+ modifyAppBuildGradleMissingDimensionStrategy,
9
11
  modifyRootBuildGradle,
10
12
  modifySettingsGradle,
11
13
  } from './utils/gradleHelpers';
@@ -39,7 +41,18 @@ export const withBrownfieldAndroid: ConfigPlugin<
39
41
  return gradleConfig;
40
42
  });
41
43
 
42
- // Step 2: modify settings.gradle to include the new module
44
+ // Step 2: modify app build.gradle to add missingDimensionStrategy
45
+ config = withAppBuildGradle(config, (gradleConfig) => {
46
+ gradleConfig.modResults.contents =
47
+ modifyAppBuildGradleMissingDimensionStrategy(
48
+ gradleConfig.modResults.contents,
49
+ androidConfig.missingDimensionStrategies
50
+ );
51
+
52
+ return gradleConfig;
53
+ });
54
+
55
+ // Step 3: modify settings.gradle to include the new module
43
56
  config = withSettingsGradle(config, (settingsConfig) => {
44
57
  settingsConfig.modResults.contents = modifySettingsGradle(
45
58
  settingsConfig.modResults.contents,
@@ -50,10 +63,10 @@ export const withBrownfieldAndroid: ConfigPlugin<
50
63
  return settingsConfig;
51
64
  });
52
65
 
53
- // Step 3: create the Android module files using dangerous mod
66
+ // Step 4: create the Android module files using dangerous mod
54
67
  config = withAndroidModuleFiles(config, props);
55
68
 
56
- // Step 4: sync module metadata after Expo writes all Android files
69
+ // Step 5: sync module metadata after Expo writes all Android files
57
70
  config = withFinalizedMod(config, [
58
71
  'android',
59
72
  async (finalizedConfig) => {
@@ -4,10 +4,9 @@ export function getExpoInfo(config: ExpoConfig) {
4
4
  const expoMajor = config.sdkVersion
5
5
  ? parseInt(config.sdkVersion.split('.')[0], 10)
6
6
  : -1;
7
- const isExpoPre55 = expoMajor < 55;
7
+
8
8
  return {
9
9
  expoMajor,
10
- isExpoPre55,
11
10
  };
12
11
  }
13
12
 
@@ -2,56 +2,10 @@ import { SourceModificationError } from '../errors/SourceModificationError';
2
2
  import { Logger } from '../logging';
3
3
  import { renderTemplate } from '../template/engine';
4
4
 
5
- const BROWNFIELD_POD_HOOK_MARKER_START =
6
- '# >>> react-native-brownfield expo phase ordering >>>';
7
- const BROWNFIELD_POD_HOOK_MARKER_END =
8
- '# <<< react-native-brownfield expo phase ordering <<<';
9
5
  const BROWNFIELD_EXPO_GTE_55_SWIFT_DEFINES_MARKER_START =
10
6
  '# >>> react-native-brownfield Expo SDK 55+ swift defines >>>';
11
7
  const BROWNFIELD_EXPO_GTE_55_SWIFT_DEFINES_MARKER_END =
12
8
  '# <<< react-native-brownfield Expo SDK 55+ swift defines <<<';
13
- const BROWNFIELD_POST_INTEGRATE_REQUIRE = `require File.join(File.dirname(\`node --print "require.resolve('@callstack/react-native-brownfield/package.json')"\`), "scripts/react_native_brownfield_post_integrate")`;
14
- const REACT_NATIVE_PODS_REQUIRE_REGEX =
15
- /^require File\.join\(File\.dirname\(`node --print "require\.resolve\('react-native\/package\.json'\)"`\), "scripts\/react_native_pods"\)\s*$/m;
16
-
17
- function ensureBrownfieldPostIntegrateRequire(podfile: string): string {
18
- if (podfile.includes('scripts/react_native_brownfield_post_integrate')) {
19
- return podfile;
20
- }
21
-
22
- const reactNativePodsRequireMatch = podfile.match(
23
- REACT_NATIVE_PODS_REQUIRE_REGEX
24
- );
25
- if (reactNativePodsRequireMatch) {
26
- const requireLine = reactNativePodsRequireMatch[0];
27
- return podfile.replace(
28
- requireLine,
29
- `${requireLine}\n${BROWNFIELD_POST_INTEGRATE_REQUIRE}\n`
30
- );
31
- }
32
-
33
- return `${BROWNFIELD_POST_INTEGRATE_REQUIRE}\n\n${podfile}`;
34
- }
35
-
36
- function ensureExpoPhaseOrderingHook(podfile: string): string {
37
- let modifiedPodfile = ensureBrownfieldPostIntegrateRequire(podfile);
38
-
39
- if (modifiedPodfile.includes(BROWNFIELD_POD_HOOK_MARKER_START)) {
40
- return modifiedPodfile;
41
- }
42
-
43
- const hook = `
44
- ${BROWNFIELD_POD_HOOK_MARKER_START}
45
- post_integrate do |installer|
46
- react_native_brownfield_post_integrate(installer)
47
- end
48
- ${BROWNFIELD_POD_HOOK_MARKER_END}
49
- `;
50
-
51
- modifiedPodfile = `${modifiedPodfile.trimEnd()}\n\n${hook}\n`;
52
-
53
- return modifiedPodfile;
54
- }
55
9
 
56
10
  function ensureExpoDefinesForSDK55AndAbove(
57
11
  podfile: string,
@@ -146,14 +100,16 @@ export function modifyPodfile(
146
100
  Logger.logDebug(`Added framework target "${frameworkName}" to Podfile`);
147
101
 
148
102
  if (expoMajor < 55) {
149
- modifiedPodfile = ensureExpoPhaseOrderingHook(modifiedPodfile);
150
- } else {
151
- // Expo SDK >= 55
152
- modifiedPodfile = ensureExpoDefinesForSDK55AndAbove(
153
- modifiedPodfile,
154
- expoMajor
103
+ const versionLabel = expoMajor < 0 ? 'unknown' : expoMajor.toString();
104
+ throw new SourceModificationError(
105
+ `Expo SDK ${versionLabel} is not supported. Please use Expo SDK 55 or newer. For older versions, please use the v3.x.x of @callstack/react-native-brownfield.`
155
106
  );
156
107
  }
157
108
 
109
+ modifiedPodfile = ensureExpoDefinesForSDK55AndAbove(
110
+ modifiedPodfile,
111
+ expoMajor
112
+ );
113
+
158
114
  return modifiedPodfile;
159
115
  }
@@ -5,7 +5,6 @@ import {
5
5
  } from '@expo/config-plugins';
6
6
 
7
7
  import {
8
- addExpoPre55ShellPatchScriptPhase,
9
8
  addFrameworkTarget,
10
9
  addSourceFilesBuildPhase,
11
10
  copyBundleReactNativePhase,
@@ -32,7 +31,7 @@ import { getExpoInfo, hasExpoUpdatesInstalled } from '../expoUtils';
32
31
  export const withBrownfieldIos: ConfigPlugin<
33
32
  ResolvedBrownfieldPluginConfigWithIos
34
33
  > = (config, props) => {
35
- const { isExpoPre55, expoMajor } = getExpoInfo(config);
34
+ const { expoMajor } = getExpoInfo(config);
36
35
 
37
36
  // Step 1: modify the Xcode project to add framework target &
38
37
  config = withXcodeProject(config, (xcodeConfig) => {
@@ -68,35 +67,12 @@ export const withBrownfieldIos: ConfigPlugin<
68
67
 
69
68
  copyBundleReactNativePhase(project, frameworkTargetUUID);
70
69
 
71
- if (isExpoPre55) {
72
- addExpoPre55ShellPatchScriptPhase(modRequest, project, {
73
- frameworkName: props.ios.frameworkName,
74
- frameworkTargetUUID: frameworkTargetUUID,
75
- });
76
- }
77
-
78
70
  return xcodeConfig;
79
71
  }
80
72
 
81
73
  // copy the "Bundle React Native code and images" build phase from the main target to the framework target
82
74
  copyBundleReactNativePhase(project, frameworkTargetUUID);
83
75
 
84
- // for Expo SDK versions < 55, add a script phase to patch ExpoModulesProvider.swift
85
- if (isExpoPre55) {
86
- Logger.logDebug(
87
- `Adding ExpoModulesProvider patch phase for Expo SDK ${config.sdkVersion}`
88
- );
89
-
90
- addExpoPre55ShellPatchScriptPhase(modRequest, project, {
91
- frameworkName: props.ios.frameworkName,
92
- frameworkTargetUUID: frameworkTargetUUID,
93
- });
94
- } else {
95
- Logger.logDebug(
96
- `Skipping ExpoModulesProvider patch phase for Expo SDK ${config.sdkVersion}`
97
- );
98
- }
99
-
100
76
  addSourceFilesBuildPhase(project, frameworkTargetUUID, iosProps);
101
77
 
102
78
  return xcodeConfig;
@@ -10,7 +10,6 @@ import { Logger } from '../logging';
10
10
  import type { ResolvedBrownfieldPluginIosConfig } from '../types';
11
11
  import { SourceModificationError } from '../errors/SourceModificationError';
12
12
  import { getFrameworkSourceFiles } from './withIosFrameworkFiles';
13
- import { renderTemplate } from '../template/engine';
14
13
 
15
14
  /**
16
15
  * Adds a new Framework target to the Xcode project for Brownfield packaging
@@ -741,101 +740,3 @@ export function resolveFrameworkDeploymentTarget(
741
740
 
742
741
  return appTargetDeploymentTarget ?? '15.0';
743
742
  }
744
-
745
- /**
746
- * Adds the "Patch ExpoModulesProvider" shell script phase to the framework target.
747
- * Safe to call on every prebuild: skips creation when the phase is already present.
748
- */
749
- export function addExpoPre55ShellPatchScriptPhase(
750
- modRequest: ModProps<XcodeProject>,
751
- project: XcodeProject,
752
- {
753
- frameworkName,
754
- frameworkTargetUUID,
755
- }: {
756
- frameworkName: string;
757
- frameworkTargetUUID: string;
758
- }
759
- ) {
760
- const resolvedAppTargetName = resolveAppTargetName(project, modRequest);
761
-
762
- Logger.logInfo(`Resolved iOS app target name: ${resolvedAppTargetName}`);
763
-
764
- if (!resolvedAppTargetName) {
765
- throw new SourceModificationError(
766
- `Could not determine the iOS app target name from the Xcode project.`
767
- );
768
- }
769
-
770
- const existingBuildPhases =
771
- project.pbxNativeTargetSection()[frameworkTargetUUID]?.buildPhases ?? [];
772
- if (
773
- existingBuildPhases.some((phase: { comment?: string }) =>
774
- hasBuildPhaseComment(phase, 'Patch ExpoModulesProvider')
775
- )
776
- ) {
777
- return;
778
- }
779
-
780
- project.addBuildPhase(
781
- [
782
- // no associated files
783
- ],
784
- 'PBXShellScriptBuildPhase',
785
- 'Patch ExpoModulesProvider',
786
- frameworkTargetUUID,
787
- {
788
- shellPath: '/bin/sh',
789
- shellScript: renderTemplate('ios', 'patchExpoPre55.sh', {
790
- '{{APP_TARGET_NAME}}': resolvedAppTargetName,
791
- '{{FRAMEWORK_NAME}}': frameworkName,
792
- }),
793
- }
794
- );
795
- }
796
-
797
- /**
798
- * Makes sure the patch expo modules provider phase is after the expo configure phase,
799
- * otherwise the patched file would be overwritten by the expo configure phase
800
- * @param project The Xcode project
801
- * @param frameworkTargetUUID The UUID of the framework target
802
- * @returns True if the build phases were modified, false otherwise
803
- */
804
- export function ensureExpoPre55ShellPatchScriptPhaseIsOrdered(
805
- project: XcodeProject,
806
- frameworkTargetUUID: string
807
- ) {
808
- let modified = false;
809
- const nativeTargetSection = project.pbxNativeTargetSection();
810
-
811
- const buildPhases: { value: string; comment?: string }[] =
812
- nativeTargetSection[frameworkTargetUUID].buildPhases;
813
-
814
- const expoConfigurePhaseIndex = buildPhases.findIndex(
815
- (phase) =>
816
- (phase as any)?.comment?.toLowerCase() ===
817
- '[Expo] Configure project'.toLowerCase()
818
- );
819
-
820
- const patchExpoModulesProviderPhaseIndex = buildPhases.findIndex(
821
- (phase) =>
822
- (phase as any)?.comment?.toLowerCase() ===
823
- 'Patch ExpoModulesProvider'.toLowerCase()
824
- );
825
-
826
- // ensure patch expo modules provider phase is after expo configure phase
827
- if (patchExpoModulesProviderPhaseIndex < expoConfigurePhaseIndex) {
828
- const element = buildPhases.splice(
829
- patchExpoModulesProviderPhaseIndex,
830
- 1
831
- )[0]; // pop the element at patchExpoModulesProviderPhaseIndex
832
- buildPhases.splice(expoConfigurePhaseIndex, 0, element); // insert the element at expoConfigurePhaseIndex ("after")
833
- modified = true;
834
- }
835
-
836
- nativeTargetSection[frameworkTargetUUID].buildPhases = buildPhases;
837
-
838
- project.writeSync();
839
-
840
- return modified;
841
- }
@@ -43,6 +43,10 @@ publishing {
43
43
  }
44
44
  }
45
45
 
46
+ reactBrownfield {
47
+ missingDimensionStrategies = listOf({{MISSING_DIMENSION_STRATEGIES}})
48
+ }
49
+
46
50
  react {
47
51
  autolinkLibrariesWithApp()
48
52
  }
@@ -69,6 +73,8 @@ android {
69
73
 
70
74
  testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
71
75
  consumerProguardFiles("consumer-rules.pro")
76
+
77
+ {{MISSING_DIMENSION_STRATEGY_BLOCK}}
72
78
  }
73
79
 
74
80
  buildFeatures {
@@ -56,6 +56,12 @@ export interface BrownfieldPluginAndroidConfig {
56
56
  * @default false
57
57
  */
58
58
  useLocalGradlePlugin?: boolean;
59
+
60
+ /**
61
+ * Missing dimension strategies as dimension + flavor(s).
62
+ * @default []
63
+ */
64
+ missingDimensionStrategies?: string[];
59
65
  }
60
66
 
61
67
  /**