diff --git a/docsite/docs/cli-commands.md b/docsite/docs/cli-commands.md index d20af05cab31..7c57b9155d58 100644 --- a/docsite/docs/cli-commands.md +++ b/docsite/docs/cli-commands.md @@ -49,3 +49,11 @@ npx react-native build-macos [options] | `--scheme [string]` | Explicitly set the Xcode scheme to use | `{ProjectName}-macOS` | | `--project-path [string]` | Path relative to project root where the Xcode project lives | `macos` | | `--verbose` | Show detailed build output (disable xcpretty) | `false` | + +### `config-macos` + +Print CLI configuration of react-native-macos + +```bash +npx react-native config-macos +``` diff --git a/packages/react-native/local-cli/config-macos/config-macos.js b/packages/react-native/local-cli/config-macos/config-macos.js new file mode 100644 index 000000000000..aa919c85355c --- /dev/null +++ b/packages/react-native/local-cli/config-macos/config-macos.js @@ -0,0 +1,42 @@ +// @flow + +const + nodePath = + require("node:path"), + + readConfigFromDisk = + require("./read-config-from-disk") + +/** + * This is an extension of `npx react-native config` cli result, but with some modifications. + * + * Modifications: + * - Override the `reactNativePath` with `react-native-macos` package path instead of `react-native` + * only if users do not have their own `reactNativePath` property in their react-native.config.js file + * + * @param {import("@react-native-community/cli-types").Config} ctx + * @returns {import("@react-native-community/cli-types").Config} + */ +function configMacos(ctx) { + /** + * Actually, the `ctx.reactNativePath` is already using + * `reactNativePath` from user config, but we actually do not know + * if the output is from a user or a default result from \@react-native-community/cli-config, + * hence, we need to read the user config again. + */ + const userConfig = readConfigFromDisk(ctx.root) + + let reactNativePath = ctx.reactNativePath + + if(!userConfig?.reactNativePath) { + const reactNativeMacosPackageJsonPath = require.resolve("react-native-macos/package.json", { paths: [ctx.root] }) + reactNativePath = nodePath.dirname(reactNativeMacosPackageJsonPath) + } + + return { + ...ctx, + reactNativePath, + } +} + +module.exports = configMacos diff --git a/packages/react-native/local-cli/config-macos/index.js b/packages/react-native/local-cli/config-macos/index.js new file mode 100644 index 000000000000..24a1b1d33d08 --- /dev/null +++ b/packages/react-native/local-cli/config-macos/index.js @@ -0,0 +1,3 @@ +// @flow + +module.exports = require("./config-macos") diff --git a/packages/react-native/local-cli/config-macos/read-config-from-disk.js b/packages/react-native/local-cli/config-macos/read-config-from-disk.js new file mode 100644 index 000000000000..8373219be6d3 --- /dev/null +++ b/packages/react-native/local-cli/config-macos/read-config-from-disk.js @@ -0,0 +1,67 @@ +// @flow + +const + nodeFs = + require("node:fs"), + + nodePath = + require("node:path") + +const searchFiles = [ + "react-native.config.js", + "react-native.config.cjs", + "react-native.config.mjs", +] + +/** + * @param {string} root + * @returns {string | null} Returns the config file path e.g. "/Users/rn-project/react-native.config.js". Returns `null` if the config file cannot be found. + */ +function findConfigFile( + root, +) { + /** + * @type {ReturnType} + */ + let configFilePath = null + + for(const place of searchFiles) { + const __configFilePath = nodePath.join(root, place) + + if(nodeFs.existsSync(__configFilePath)) { + configFilePath = __configFilePath + break + } + } + + return configFilePath || null +} + +/** + * Find and read user `react-native.config.js` file. + * + * This is a similar function from + * {@link https://github.com/react-native-community/cli/blob/main/packages/cli-config/src/readConfigFromDisk.ts|@react-native-community/cli-config}. + * We have to re-invent how to read the user config, because the original function is not exported publicly. + * It is better if we can use the original function from \@react-native-community/cli-config. + * + * @param {string} root + * @returns {import("@react-native-community/cli-types").Config | null} + */ +function readConfigFromDisk( + root, +) { + const configFilePath = findConfigFile(root) + + if(configFilePath) { + try { + return require(configFilePath) + } catch { + return null + } + } + + return null +} + +module.exports = readConfigFromDisk diff --git a/packages/react-native/local-cli/generator-macos/templates/macos/Podfile b/packages/react-native/local-cli/generator-macos/templates/macos/Podfile index f2e9f7532431..6f62ff8880c0 100644 --- a/packages/react-native/local-cli/generator-macos/templates/macos/Podfile +++ b/packages/react-native/local-cli/generator-macos/templates/macos/Podfile @@ -1,10 +1,9 @@ -require 'pathname' - -ws_dir = Pathname.new(__dir__) -ws_dir = ws_dir.parent until - File.exist?("#{ws_dir}/node_modules/react-native-macos/scripts/react_native_pods.rb") || - ws_dir.expand_path.to_s == '/' -require "#{ws_dir}/node_modules/react-native-macos/scripts/react_native_pods.rb" +# Resolve react_native_pods.rb with node to allow for hoisting +require Pod::Executable.execute_command('node', ['-p', + 'require.resolve( + "react-native-macos/scripts/react_native_pods.rb", + {paths: [process.argv[1]]}, + )', __dir__]).strip prepare_react_native_project! @@ -16,13 +15,16 @@ target 'HelloWorld-macOS' do flags = get_default_flags() use_react_native!( - :path => '../node_modules/react-native-macos', + :path => config[:reactNativePath], :fabric_enabled => ENV['RCT_NEW_ARCH_ENABLED'] == '1', # An absolute path to your application root. :app_path => "#{Pod::Config.instance.installation_root}/.." ) post_install do |installer| - react_native_post_install(installer) + react_native_post_install( + installer, + config[:reactNativePath] + ) end end diff --git a/packages/react-native/react-native.config.js b/packages/react-native/react-native.config.js index 21219d91c49a..68bf1906f563 100644 --- a/packages/react-native/react-native.config.js +++ b/packages/react-native/react-native.config.js @@ -215,6 +215,18 @@ if (apple) { dependencyConfig: apple.getDependencyConfig(visionos), }; } + +const configMacosCommand = { + name: "config-macos", + description: "Print CLI configuration of React Native macOS", + func: (_argv, ctx, _args) => { + const configMacos = require("./local-cli/config-macos")(ctx) + console.log( + JSON.stringify(configMacos, null, 2), + ) + }, +} +config.commands.push(configMacosCommand) // macOS] module.exports = config; diff --git a/packages/react-native/scripts/cocoapods/autolinking.rb b/packages/react-native/scripts/cocoapods/autolinking.rb index a09280c2ea56..e9033232da3c 100644 --- a/packages/react-native/scripts/cocoapods/autolinking.rb +++ b/packages/react-native/scripts/cocoapods/autolinking.rb @@ -201,7 +201,7 @@ def link_native_modules!(config) } end -$default_command = ['node', '-e', "process.argv=['', '', 'config'];require('@react-native-community/cli').run()"]; +$default_command = ['node', '-e', "process.argv=['', '', 'config-macos'];require('@react-native-community/cli').run()"]; # [macOS] # Autolink your native modules #