diff --git a/android/build.gradle b/android/build.gradle index 89d84b7..3f76132 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,3 +1,5 @@ +import java.nio.file.Paths + buildscript { // The Android Gradle plugin is only required when opening the android folder stand-alone. // This avoids unnecessary downloads and potential conflicts when the library is included as a @@ -41,18 +43,47 @@ def getExtOrIntegerDefault(name) { apply plugin: 'com.android.library' +/** + * Original code: https://github.com/facebook/react-native/blob/main/packages/react-native/ReactAndroid/build.gradle#L382 + * + * Finds the path of the installed npm package with the given name using Node's + * module resolution algorithm, which searches "node_modules" directories up to + * the file system root. This handles various cases, including: + * + * - Working in the open-source RN repo: + * Gradle: /path/to/react-native/ReactAndroid + * Node module: /path/to/react-native/node_modules/[package] + * + * - Installing RN as a dependency of an app and searching for hoisted + * dependencies: + * Gradle: /path/to/app/node_modules/react-native/ReactAndroid + * Node module: /path/to/app/node_modules/[package] + * + * - Working in a larger repo (e.g., Facebook) that contains RN: + * Gradle: /path/to/repo/path/to/react-native/ReactAndroid + * Node module: /path/to/repo/node_modules/[package] + * + * The search begins at the given base directory (a File object). The returned + * path is a string. + */ +def findNodeModulePath(baseDir, packageName) { + def basePath = baseDir.toPath().normalize() + // Node's module resolution algorithm searches up to the root directory, + // after which the base path will be null + while (basePath) { + def candidatePath = Paths.get(basePath.toString(), "node_modules", packageName) + if (candidatePath.toFile().exists()) { + return candidatePath.toString() + } + basePath = basePath.getParent() + } + return null +} def resolveReactNativeDirectory() { - // monorepo workaround - // react-native can be hoisted or in project's own node_modules - def reactNativeFromProjectNodeModules = file("${rootProject.projectDir}/../node_modules/react-native") - if (reactNativeFromProjectNodeModules.exists()) { - return reactNativeFromProjectNodeModules - } - - def reactNativeFromNodeModulesWithLibrary = file("${projectDir}/../../react-native") - if (reactNativeFromNodeModulesWithLibrary.exists()) { - return reactNativeFromNodeModulesWithLibrary + def reactNative = file("${findNodeModulePath(rootProject.projectDir, "react-native")}") + if (reactNative.exists()) { + return reactNative } throw new Exception(