-
Notifications
You must be signed in to change notification settings - Fork 935
feat: support autolinking in monorepos
#768
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 11 commits
b3b09ef
440f166
1ffc0c2
391505d
e0722c3
f85186f
435d314
78065e0
80be9d2
3495fe5
7e46d77
68639b7
f8de995
5041be8
53f59d1
9dd0ce1
3be7ea4
4091c4c
27fac31
0cbe32d
e362dc6
19fd10e
366b7c4
553df50
858ac79
883068f
7733cb2
c4c1745
a13e47f
bdcc9fa
07bd62e
858ea5e
94d8bba
81e7b10
beca41b
cc8c80c
6661421
781c0e6
46b0cd3
5033e50
cc4b5bf
7402931
90bacbc
d0bd034
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| import path from 'path'; | ||
| import findProjectRoot from '../findProjectRoot'; | ||
| import { | ||
| cleanup, | ||
| writeFiles, | ||
| getTempDirectory, | ||
| } from '../../../../../../jest/helpers'; | ||
|
|
||
| beforeEach(() => { | ||
| cleanup(DIR); | ||
| jest.resetModules(); | ||
| }); | ||
|
|
||
| afterEach(() => cleanup(DIR)); | ||
|
|
||
| const DIR = getTempDirectory('find_project_root_test'); | ||
|
|
||
| test('resolves to correct project root', () => { | ||
| writeFiles(DIR, { | ||
| 'package.json': '{}', | ||
| 'ios/Podfile': '', | ||
| }); | ||
| const cwd = path.join(DIR, 'ios'); | ||
| expect(findProjectRoot(cwd)).toBe(DIR); | ||
| expect(findProjectRoot(DIR)).toBe(DIR); | ||
| }); | ||
|
|
||
| test('resolves to correct project root in a monorepo', () => { | ||
| writeFiles(DIR, { | ||
| 'package.json': '{}', | ||
| 'packages/mobile/package.json': '{}', | ||
| 'packages/mobile/ios/Podfile': '', | ||
| }); | ||
| const cwd = path.join(DIR, 'packages/mobile/ios'); | ||
| expect(findProjectRoot(cwd)).toBe(path.join(DIR, 'packages/mobile')); | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| import findUp from 'find-up'; | ||
| import path from 'path'; | ||
| import {CLIError} from '@react-native-community/cli-tools'; | ||
|
|
||
| /** | ||
| * Finds project root by looking for a closest `package.json`. | ||
| */ | ||
| export default function findProjectRoot(cwd = process.cwd()): string { | ||
| const packageLocation = findUp.sync('package.json', {cwd}); | ||
|
|
||
| /** | ||
| * It is possible that `package.json` doesn't exist | ||
| * in the tree. In that case, we want to throw an error. | ||
| * | ||
| * When executing via `npx`, this will never happen as `npm` | ||
| * requires that file to be present in order to run. | ||
| */ | ||
| if (!packageLocation) { | ||
| throw new CLIError(` | ||
| We couldn't find a package.json in your project. | ||
| Are you sure you are running it inside a React Native project? | ||
| `); | ||
| } | ||
|
|
||
| return path.dirname(packageLocation); | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -5,24 +5,22 @@ | |||||
| # | ||||||
| require 'pathname' | ||||||
|
|
||||||
| def use_native_modules!(root = "..", config = nil) | ||||||
|
grabbou marked this conversation as resolved.
grabbou marked this conversation as resolved.
|
||||||
| def use_native_modules!(config = nil) | ||||||
| if (!config) | ||||||
| json = [] | ||||||
|
|
||||||
| # Make sure `react-native config` is ran from your project root | ||||||
| Dir.chdir(root) do | ||||||
| IO.popen("./node_modules/.bin/react-native config") do |data| | ||||||
| while line = data.gets | ||||||
| json << line | ||||||
| end | ||||||
| IO.popen("npx react-native config") do |data| | ||||||
| while line = data.gets | ||||||
| json << line | ||||||
| end | ||||||
| end | ||||||
|
|
||||||
| config = JSON.parse(json.join("\n")) | ||||||
| end | ||||||
|
|
||||||
| project_root = Pathname.new(config["project"]["ios"]["sourceDir"]) | ||||||
|
grabbou marked this conversation as resolved.
|
||||||
|
|
||||||
| packages = config["dependencies"] | ||||||
| config_root = config["root"] | ||||||
|
grabbou marked this conversation as resolved.
|
||||||
| found_pods = [] | ||||||
|
|
||||||
| packages.each do |package_name, package| | ||||||
|
|
@@ -57,10 +55,10 @@ def use_native_modules!(root = "..", config = nil) | |||||
| end | ||||||
|
|
||||||
| podspec_dir_path = Pathname.new(File.dirname(podspec_path)) | ||||||
| project_root = Pathname.new(config_root) | ||||||
|
|
||||||
| relative_path = podspec_dir_path.relative_path_from project_root | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Now that we don't have custom root, I think instead of using
Suggested change
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
PWD might be not a good idea, see: #657 when running from root folder with |
||||||
|
|
||||||
| pod spec.name, :path => File.join(root, relative_path) | ||||||
| pod spec.name, :path => relative_path.to_path | ||||||
|
|
||||||
| if package_config["scriptPhases"] | ||||||
| # Can be either an object, or an array of objects | ||||||
|
|
@@ -129,7 +127,6 @@ def pluralize(count) | |||||
| "execution_position" => "before_compile", | ||||||
| "input" => "string" | ||||||
| } | ||||||
|
|
||||||
| @ios_package = ios_package = { | ||||||
| "root" => "/root/app/node_modules/react", | ||||||
| "platforms" => { | ||||||
|
|
@@ -148,8 +145,13 @@ def pluralize(count) | |||||
| }, | ||||||
| } | ||||||
| } | ||||||
| @project = { | ||||||
| "ios" => { | ||||||
| "sourceDir" => "/root/app/ios" | ||||||
| } | ||||||
| } | ||||||
| @config = { | ||||||
| "root" => "/root/app", | ||||||
| "project" => @project, | ||||||
| "dependencies" => { | ||||||
| "ios-dep" => @ios_package, | ||||||
| "android-dep" => @android_package | ||||||
|
|
@@ -166,8 +168,8 @@ def pluralize(count) | |||||
|
|
||||||
| spec.singleton_class.send(:define_method, :name) { "ios-dep" } | ||||||
|
|
||||||
| podfile.singleton_class.send(:define_method, :use_native_modules) do |path, config| | ||||||
| use_native_modules!('..', config) | ||||||
| podfile.singleton_class.send(:define_method, :use_native_modules) do |config| | ||||||
| use_native_modules!(config) | ||||||
| end | ||||||
|
|
||||||
| Pod::Specification.singleton_class.send(:define_method, :from_file) do |podspec_path| | ||||||
|
|
@@ -197,7 +199,7 @@ def pluralize(count) | |||||
| end | ||||||
|
|
||||||
| it "activates iOS pods" do | ||||||
| @podfile.use_native_modules('..', @config) | ||||||
| @podfile.use_native_modules(@config) | ||||||
| @activated_pods.must_equal [{ | ||||||
| name: "ios-dep", | ||||||
| options: { path: "../node_modules/react" } | ||||||
|
|
@@ -208,23 +210,23 @@ def pluralize(count) | |||||
| activated_pod = Object.new | ||||||
| activated_pod.singleton_class.send(:define_method, :name) { "ios-dep" } | ||||||
| @current_target_definition_dependencies << activated_pod | ||||||
| @podfile.use_native_modules('..', @config) | ||||||
| @podfile.use_native_modules(@config) | ||||||
| @activated_pods.must_equal [] | ||||||
| end | ||||||
|
|
||||||
| it "does not activate pods whose root spec were already activated previously (by the user in their Podfile)" do | ||||||
| activated_pod = Object.new | ||||||
| activated_pod.singleton_class.send(:define_method, :name) { "ios-dep/foo/bar" } | ||||||
| @current_target_definition_dependencies << activated_pod | ||||||
| @podfile.use_native_modules('..', @config) | ||||||
| @podfile.use_native_modules(@config) | ||||||
| @activated_pods.must_equal [] | ||||||
| end | ||||||
|
|
||||||
| it "prints out the native module pods that were found" do | ||||||
| @podfile.use_native_modules('..', { "root" => "/root/app", "dependencies" => {} }) | ||||||
| @podfile.use_native_modules('..', { "root" => "/root/app", "dependencies" => { "pkg-1" => @ios_package }}) | ||||||
| @podfile.use_native_modules('..', { | ||||||
| "root" => "/root/app", "dependencies" => { "pkg-1" => @ios_package, "pkg-2" => @ios_package } | ||||||
| @podfile.use_native_modules({ "project" => @project, "dependencies" => {} }) | ||||||
| @podfile.use_native_modules({ "project" => @project, "dependencies" => { "pkg-1" => @ios_package }}) | ||||||
| @podfile.use_native_modules({ | ||||||
| "project" => @project, "dependencies" => { "pkg-1" => @ios_package, "pkg-2" => @ios_package } | ||||||
| }) | ||||||
| @printed_messages.must_equal [ | ||||||
| "Detected React Native module pod for ios-dep", | ||||||
|
|
@@ -235,7 +237,7 @@ def pluralize(count) | |||||
| describe "concerning script_phases" do | ||||||
| it "uses the options directly" do | ||||||
| @config["dependencies"]["ios-dep"]["platforms"]["ios"]["scriptPhases"] = [@script_phase] | ||||||
| @podfile.use_native_modules('..', @config) | ||||||
| @podfile.use_native_modules(@config) | ||||||
| @added_scripts.must_equal [{ | ||||||
| :script => "123", | ||||||
| :name => "My Name", | ||||||
|
|
@@ -253,7 +255,7 @@ def pluralize(count) | |||||
| file_read_mock.expect(:call, "contents from file", [File.join(@ios_package["root"], "some_shell_script.sh")]) | ||||||
|
|
||||||
| File.stub(:read, file_read_mock) do | ||||||
| @podfile.use_native_modules('..', @config) | ||||||
| @podfile.use_native_modules(@config) | ||||||
| end | ||||||
|
|
||||||
| @added_scripts.must_equal [{ | ||||||
|
|
||||||
Uh oh!
There was an error while loading. Please reload this page.