Skip to content
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

feat: autolinking for Android with Gradle #258

Merged
merged 51 commits into from
Apr 19, 2019

Conversation

Salakar
Copy link
Member

@Salakar Salakar commented Mar 21, 2019

Provides the Android/Gradle functionality to go with #256 & #254

CLI Changes

  • Updated react-native config to include the android sourceDir for react native module packages

Usage

These are the one-off changes required to enable this in the React Native init template (or for existing user projects).

Modify android/settings.gradle

Include the following line in your Android projects settings.gradle file:

apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)

Modify android/app/build.gradle

Add the following line at the bottom of your Android projects android/app/build.gradle file:

apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)

Modify MainApplication.java

Import the PackageList class;

import com.facebook.react.PackageList;

Replace the protected List<ReactPackage> getPackages() method with the following:

    @Override
    protected List<ReactPackage> getPackages() {
      @SuppressWarnings("UnnecessaryLocalVariable")
      List<ReactPackage> packages = new PackageList(this).getPackages();
      // additional non auto detected packages can still be added here:
      // packages.add(new SomeReactNativePackage());
      return packages;
    }

Testing

I've tested the following scenarios locally:

  • User has no React Native global CLI installed
    • Will warn but continue without issue
  • User has no React Native packages installed yet
    • Continues as normal with no warning
  • User has more than one React Native package installed
    • Correctly adds multiple packages without issue
  • User has a package installed that does not support autodetection (config == null)
    • Prints a warning but continues gracefully
  • User has custom/non-linked React Native packages
    • Can be sucessfully manually added via packages.add(new SomeReactNativePackage()); as documented above in MainApplication.java

To test this in a new react-native init project locally:

  • Clone the CLI project
  • Run yarn in the CLI project
  • Run cd packages/cli && yarn && yarn link in the CLI project
    • (a little hacky as it's a mono-repo)
  • Run yarn link "@react-native-community/cli" on your React Native project
  • Make the required changes as above to your React Native project

Codegen Output Example

An example of the generated PackageList.java class:

package com.facebook.react;

import android.app.Application;
import android.content.Context;
import android.content.res.Resources;

import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;
import java.util.Arrays;
import java.util.List;

import com.test.BuildConfig;

// react-native-webview
import com.reactnativecommunity.webview.RNCWebViewPackage;

public class PackageList {
  private ReactNativeHost reactNativeHost;
  public PackageList(ReactNativeHost reactNativeHost) {
    this.reactNativeHost = reactNativeHost;
  }

  private ReactNativeHost getReactNativeHost() {
    return this.reactNativeHost;
  }

  private Resources getResources() {
    return this.getApplication().getResources();
  }

  private Application getApplication() {
    return this.reactNativeHost.getApplication();
  }

  private Context getApplicationContext() {
    return this.getApplication().getApplicationContext();
  }

  public List<ReactPackage> getPackages() {
    return Arrays.<ReactPackage>asList(
      new MainReactPackage(),
      new RNCWebViewPackage()
    );
  }
}

@Salakar Salakar requested review from grabbou and removed request for grabbou March 21, 2019 23:27
@Salakar
Copy link
Member Author

Salakar commented Mar 21, 2019

cc @dulmandakh & @bartolkaruza for review

@Salakar Salakar changed the title [WIP] Feat/config Android additions Feat/config Android additions Mar 21, 2019
@grabbou
Copy link
Member

grabbou commented Mar 22, 2019

Before reviewing, I'll implement JS changes you did here over in my PR, so you can rebase the branch. That way, it will merge cleanly.

Going to attempt a review next week, on Monday.

@grabbou
Copy link
Member

grabbou commented Mar 22, 2019

Regarding:

I've tested the following scenarios locally:

Shall we also make sure that we print similar messages on iOS, e.g. when the package is not supported or global CLI wasn't recognised?

@Salakar
Copy link
Member Author

Salakar commented Mar 22, 2019

Shall we also make sure that we print similar messages on iOS, e.g. when the package is not supported or global CLI wasn't recognised?

I think so - cc @alloy @orta - what are your thoughts on this?

@alloy
Copy link
Member

alloy commented Mar 22, 2019

I definitely think we should try to be helpful, but I think we should do this when the user uses react-native install [pkg] by running the spec validation (react-native validate [pkg]?), as that’s the time we know their intent. Afterwards, during eg pod install I personally prefer only relevant output (unless perhaps —verbose is passed), i.e. not list all packages that are not included. I’ll need to read the PR more to make sure I fully understand the other warnings.

@punksta
Copy link

punksta commented Mar 22, 2019

This looks much better than javascript linking!
There are react-native packages with constructor accepts parameters. For example new FBSDKPackage(mCallbackManager) from https://github.com/facebook/react-native-fbsdk#31-android.

Will there be a way of excluding package from auto-linking? annotations may be used.

@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
public @interface NoAutoLink {
   String message();
}

@NoAutoLink(message = "Link module manually, providing ReactApplication class instance")
class LibraryPackage {
    public LibraryPackage(ReactApplication application) {
     
    }
}

@Salakar
Copy link
Member Author

Salakar commented Mar 22, 2019

Hey @punksta, I was just discussing args support with @grabbou - for now, we'd look at only supporting arguments where they are set up already to be linked, for example https://github.com/Microsoft/react-native-code-push/blob/master/package.json#L45 is one I'm looking at supporting as it works as is currently on the old way of linking.

Whereas the FBSDK one you linked doesn't link the package with args by default - you have to manually link it, so probably not a scenario we'd support yet.


For excluding packages from auto-linking, this can be configured in the CLI config (not sure where yet 😅), when it tells us in the config that the Android config is null we skip linking.

@grabbou
Copy link
Member

grabbou commented Mar 22, 2019

Ideally, fbsdk would provide a custom packageInstance property in their package.json so that we know it needs extra parameters.

Alternatively, maybe we can guess it and provide some stubs?

Will there be a way of excluding package from auto-linking? annotations may be used.

We are keeping JavaScript as a source of truth, so you will be able to modify settings for each package (in case it has broken settings or doesn't link properly, e.g. providing that custom packageInstance yourself to tell us to use it to link fbsdk or just disable linking on Android/iOS/both entirely). Details to follow in my PR #254

@Salakar Salakar changed the base branch from feat/config to master April 18, 2019 08:38
…act-native-cli into feat/config

# Conflicts:
#	packages/cli/package.json
#	packages/cli/src/cliEntry.js
#	packages/cli/src/commands/config/config.js
#	packages/cli/src/commands/index.js
#	packages/cli/src/commands/info/__tests__/info.test.js
#	packages/cli/src/commands/link/getDependencyConfig.js
#	packages/cli/src/commands/link/getProjectConfig.js
#	packages/cli/src/commands/link/linkAll.js
#	packages/cli/src/commands/upgrade/__tests__/upgrade.test.js
#	packages/cli/src/tools/config/findDependencies.js
#	packages/cli/src/tools/config/index.js
#	packages/cli/src/tools/config/readConfigFromDisk.js
#	packages/cli/src/tools/config/resolveReactNativePath.js
#	packages/cli/src/tools/config/schema.js
#	packages/cli/src/tools/errors.js
#	packages/cli/src/tools/loadMetroConfig.js
#	packages/cli/src/tools/types.flow.js
#	yarn.lock
@Salakar
Copy link
Member Author

Salakar commented Apr 18, 2019

Updated to work with latest config changes + new platform-android package

cc @grabbou @thymikee

@thymikee thymikee changed the title Feat/config Android additions feat: autolinking for Android Apr 18, 2019
@thymikee thymikee changed the title feat: autolinking for Android feat: autolinking for Android with Gradle Apr 18, 2019
Copy link
Member

@thymikee thymikee left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left small comments to address, but this looks good! Is there a chance we could add a smoke test for that, similar to CocoaPods version?

"test:ci:cocoapods": "ruby packages/platform-ios/native_modules.rb",

@Salakar
Copy link
Member Author

Salakar commented Apr 18, 2019

@thymikee changes requested have been made, thanks for the review 🎉

For testing: the only way I can see testing being added is if we set up an Android project and run a build and validate that it:

  1. builds the apk without error
  2. the generated output at generated/rncli/src/main/java/com/facebook/react/PackageList.java contains the RN modules that should be available as part of the test (e.g. yarn add react-native-webview)

I think this should be based off the RN template though, init a fresh project as part of the test, add a couple of RN modules via npm/yarn, build android and validate output.

Current problem is the template is not yet live with the new changes so not sure how best to do this until then? Thoughts? Or shall we add test suites once the template is live on RN master? This will also need Windows testing for CI - have tested locally though for Mac + Windows.

@@ -54,7 +54,8 @@ class ReactNativeModules {
private ArrayList<HashMap<String, String>> reactNativeModules

private static String LOG_PREFIX = ":ReactNative:"
private static String REACT_NATIVE_CONFIG_CMD = "react-native config"
private static String REACT_NATIVE_CLI_BIN = "node_modules${File.separator}@react-native-community${File.separator}cli${File.separator}build${File.separator}index.js"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RN can technically be in monorepo so we can't make assumptions about where node_modules with cli are. That's why in iOS implementation we spawn a Node process and use its require.resolve to output the resolved path to stdout

Copy link
Member Author

@Salakar Salakar Apr 18, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is handled by the final arg here:

cmdProcess = Runtime.getRuntime().exec(REACT_NATIVE_CONFIG_CMD, null, getReactNativeProjectRoot())
- the process is spawned relative to the project root, which can also be overridden here:
if (this.extension.has("reactNativeProjectRoot")) {

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, so it won't be seamless but at least that's supported. We need to add documentation on how the autolinking is working on how to configure it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Salakar, we already have config.root in our config outputted from react-native config. You could use that one.

Also, you can just do console.log(require.resolve('react-native')) script and exec node to get the exact location. I think this is what we use on iOS.

@thymikee
Copy link
Member

I'm cool with waiting for RN to publish the new template and using that as a source. Or you could publish a custom template (based on the PR you made to RN) and create a custom test in e2e/ directory. See how the new template looks like: https://github.com/Esemesek/react-native-new-template/ (basically a template.config.js with a path to the template that will be straight copied over to your project)

@thymikee thymikee requested a review from grabbou April 18, 2019 12:46

String generatedFileContents = generatedFileContentsTemplate
.replace("{{ packageImports }}", packageImports)
.replace("{{ packageClassInstances }}", packageClassInstances)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am wondering if there's any way we can wrap an instance of ReactPackage here to LazyReactPackage. By default, packageClassInstance is e.g. new CodePushPackage() and in order to convert it to a LazyPackage, we would have to update that package itself.

Is there a way to wrap it or create our custom lazy package for each ReactPackage, that will lazily create it and return everything what's needed?

Copy link
Member Author

@Salakar Salakar Apr 18, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the CodePushPackage class itself would need to extend LazyReactPackage instead of ReactPackage for this to work? Not something we can do? 🤷‍♂️

Would forcing every package to be lazy also cause issues for packages that are not inherently meant to be lazy, e.g. modules that have app initialization logic that must always be run?

Not 100% sure

@thymikee thymikee merged commit f1105bc into react-native-community:master Apr 19, 2019
@thymikee
Copy link
Member

let's give it a shot!

facebook-github-bot pushed a commit to facebook/react-native that referenced this pull request Apr 24, 2019
Summary:
Replaces #24099 (original PR became detached for some reason)

Implements the template changes required to enable native modules auto-linking for both Android & iOS.

Requires the following to be merged first and an updated CLI to be published:

- [x] react-native-community/cli#254
- [x] react-native-community/cli#256
- [x] react-native-community/cli#258

cc grabbou thymikee orta for review

- [ ] #24517 update CLI version)

[TEMPLATE] [FEATURE] - Enable auto-initialization/linking of react native modules for new projects
Pull Request resolved: #24506

Differential Revision: D15062701

Pulled By: cpojer

fbshipit-source-id: 65296cbec2925405fe8033de71910325e0c719bc
kelset pushed a commit to facebook/react-native that referenced this pull request Jun 19, 2019
Summary:
Replaces #24099 (original PR became detached for some reason)

Implements the template changes required to enable native modules auto-linking for both Android & iOS.

Requires the following to be merged first and an updated CLI to be published:

- [x] react-native-community/cli#254
- [x] react-native-community/cli#256
- [x] react-native-community/cli#258

cc grabbou thymikee orta for review

- [ ] #24517 update CLI version)

[TEMPLATE] [FEATURE] - Enable auto-initialization/linking of react native modules for new projects
Pull Request resolved: #24506

Differential Revision: D15062701

Pulled By: cpojer

fbshipit-source-id: 65296cbec2925405fe8033de71910325e0c719bc

# Conflicts:
#	template/ios/Podfile
dratwas added a commit to dratwas/react-native-cli that referenced this pull request Jul 12, 2019
* chore: use @react-native-community/eslint-config (#205)

Summary:
---------

I changed @callstack/eslint-config to @react-native-community/eslint-config and fixed all lint issues.


Test Plan:
----------

Green CI

* fix: change diff links for upgrade command (#206)

* fix: change diff links for upgrade command

* use prettier without @format pragma

* fix: correct paths for eject command (#208)

Summary:
---------

`eject` had wrong paths (pointing to old RN directories), so this PR fixes that.

Fixes #207 	

Test Plan:
----------

1. Init new project RN 0.59+
2. Remove `android` and/or `ios`
3. Use the `eject` command to generate ios/android projects

* chore: simplify commander/minimist usage (#209)

* chore: simplify commander/minimist usage

* feedback

* remove extra parse

* add options back

* rephrase comment

* remove excess whitespace

* chore: remove unnecessary noHelp option for a command (#215)

`noHelp` doesn't work because we override `printHelpInformation` and we need to handle `description` (that can be undefined) manually

* chore: remove unnecessary checks for react peer dep (#216)

* docs: fix cli path in contributing doc (#218)

Summary:
---------

Fix incorrect path to cli index.js in Contributing documentation.

* fix: path to InitializeCore module in default metro config (#220)

Summary:
---------

Fix path to React Native `InitializeCore` module in default metro config.
For some reason, this path was modified when moving the `loadMetroConfig.js` file in new `tools` directory.
In current released version (v1.3.2) of the cli, the path is the correct one, as seen in the [loadMetroConfig.js](https://github.com/react-native-community/react-native-cli/blob/%40react-native-community/cli%401.3.2/packages/cli/src/util/loadMetroConfig.js#L52) of v1.3.2.

Test Plan:
----------

Was trying out `react-native run-ios` / `run-android` commands, after a fresh `react-native init` with current master branch of the cli, and was facing following metro bundler error:

```
error: bundling failed: Error: Cannot find module '/Users/blemair/Code/foo/node_modules/react-native/Libraries/tools/InitializeCore'
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:580:15)
    at Function.resolve (internal/modules/cjs/helpers.js:30:19)
    at Object.getModulesRunBeforeMainModule (/Users/blemair/Code/foo/node_modules/@react-native-community/cli/build/tools/loadMetroConfig.js:80:53)
[...]
```

After fixing the path, bundling error was gone.

* chore: remove some unused files (#217)

* fix: android unlink regression (#221)

* Fix Android unlink regression

* Update regex to accept extra whitespaces

* Extract dependency regex string to own function

With this approach we have one source of truth for both the regex and
the dependency types.

* Rename dependency types to dependency configs

The Gradle documentation calls "configurations" what we have been
referring to as "types".

* docs: fix verdaccio command in contributing doc (#219)

* fix: re-export findPlugins under cli/core for backcompat with RN 0.59 (#224)

* v1.4.0

* fix: set proper peer dependencies (#227)

* fix: debugger-ui incorrect path (#226)

Summary:
---------

Missed this one while moving files around in https://github.com/react-native-community/react-native-cli/pull/201.
Fixes https://github.com/react-native-community/react-native-cli/issues/225


Test Plan:
----------

Verified locally on a clean project.

* v1.4.1

* fix: refine upgrade error handling; improve the output (#232)

* fix: refine upgrade error handling

* moar refinements to the output

* fix: linking assets on Android (#231)

* v1.4.2

* fix: correct export of findPlugins

* Publish

 - @react-native-community/cli@1.4.3

* Revert "fix: correct export of findPlugins"

This reverts commit df17527c6819d3f707fa9ebf3bbfd4df1f0e1998.

* chore: export findPlugins for ReactNative

* Publish

 - @react-native-community/cli@1.4.4

* fix: reactNativePath and projectRoot not being parsed by commander (#234)

* fix: reactNativePath and projectRoot not being parsed by commander

* add minimist

* v1.4.5

* build: remove dependepcies command

* chore: bump metro to 0.53

* chore: remove legacy core/findPlugins (#235)

Summary:
---------

Now that we prepare 2.0 release, we can remove it. Also added `build-clean` to `postinstall` hook to avoid publishing extras when not using lerna.


Test Plan:
----------

@grabbou

* v2.0.0

* Bring back lost customDebugger function (#237)

* fix: throw an error if an invalid platform is passed to the bundle (#240)

Summary:
---------

This pull request adds a new error message to the `react-native bundle` command that will throw an error if an invalid platform is passed to the `--platform` command, instead of failing with cryptic Haste errors.

The error message looks like this:

```
> react-native bundle --entry-file index.js --platform foo --bundle-output test.jsbundle
Invalid platform (foo) selected.
Available platforms are:
ios, android, native
If you are trying to bundle for an out-of-tree platform, it may not be installed.
error Invalid platform selected.
```


Test Plan:
----------

If you provide a platform that is not installed to `react-native bundle`, it will throw this error. If you provide a valid platform, it will continue bundling without issue.

* Add verbose logging flag, debug logging for (un)link commands (#239)

Summary:
---------
This PR addresses #96 and:

* Adds the `--verbose` flag to enable `DEBUG` logs
* Adds `setVerbose(boolean)` to `tools/logger.js` so that it can enable/disable `DEBUG` logs
* Adds debug logs for the (un)link commands
* Adds Flow typings to `commands/link/android/unlinkAssets.js`

I haven't added `DEBUG` logs to other parts of the CLI because:
* I'm not that familiar with the other CLI commands
* I'd like some feedback on what I've done so far before going on

Also, would it be better to add debug logs in chunks, say one PR per command? I suspect this PR would become too big otherwise.

Test Plan:
----------
These additions do not change any implementations but I ran the tests anyway, all green.
I also ran it against two existing projects and a freshly created one: no changes in behavior.

Screenshots:
----------
How the new flag is presented when using `--help`:
<img width="500" alt="Screenshot 2019-03-15 at 22 07 26" src="https://user-images.githubusercontent.com/1713151/54462920-a2d11a00-4771-11e9-812a-00972da67f1a.png">

How `link packageName --verbose` looks like:
<img width="816" alt="Screenshot 2019-03-15 at 22 09 08" src="https://user-images.githubusercontent.com/1713151/54463021-f2afe100-4771-11e9-9213-d1f783c1f0d5.png">

How `link packageName --verbose` looks like (module with assets):
<img width="789" alt="Screenshot 2019-03-15 at 22 33 28" src="https://user-images.githubusercontent.com/1713151/54463179-7b2e8180-4772-11e9-9547-1e8907d6151d.png">

How `unlink packageName --verbose` looks like:
<img width="803" alt="Screenshot 2019-03-15 at 22 09 34" src="https://user-images.githubusercontent.com/1713151/54463217-a022f480-4772-11e9-8130-9824bb0bb0f9.png">
<img width="805" alt="Screenshot 2019-03-15 at 22 13 58" src="https://user-images.githubusercontent.com/1713151/54463227-a618d580-4772-11e9-9420-315e35d3d55c.png">

* Refactor: Rework PackageManager implementation (#243)

Summary:
---------

Removed nasty `class`, and replaced it with grouped methods.

`projectDir` is always the same in `cli` lifecycle, so we set it once on the start. Based on the presence of `yarn.lock` we decide either to use yarn or not to use it. `preferYarn` is overriding this behavior, and can later be used in `init` command which lacks correct `projectDir`.

Test Plan:
----------

- [x] - Unit tests passing
- [x] - Manual testing

* refactor: don't add purge as remote when upgrading (#245)

* feat: Add hint for browser extensions that may break debug (#253)

* Add hint for browser extensions that may break debug

* Update getSecurityHeadersMiddleware.js

* Fix lint error

* feat: Add `eslint` to react native project template. (#229)

* chore: add eslint to RN template

* Change .eslintrc to .eslintrc.js

* fix: pass `--projectRoot` argument to Metro (#259)

* fix: set project directory to install packages in init command (#262)

Fixes https://github.com/react-native-community/react-native-cli/issues/260 and https://github.com/facebook/react-native/issues/24103 by setting project directory on PackageManager which is needed to check for yarn.lock file.

Summary:
---------

I'm not sure how to test this but creating new projects fail with the exception 
```
info Adding required dependencies
internal/validators.js:125
    throw new ERR_INVALID_ARG_TYPE(name, 'string', value);
    ^

TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received type undefined
    at validateString (internal/validators.js:125:11)
    at Object.join (path.js:1147:7)
    at isProjectUsingYarn (/path/to/app/node_modules/@react-native-community/cli/build/tools/yarn.js:101:51)
    at shouldUseYarn (/path/to/app/node_modules/@react-native-community/cli/build/tools/PackageManager.js:36:39)
    at Object.install (/path/to/app/node_modules/@react-native-community/cli/build/tools/PackageManager.js:44:10)
    at generateProject (/path/to/app/node_modules/@react-native-community/cli/build/commands/init/init.js:111:18)
    at Object.init (/path/to/app/node_modules/@react-native-community/cli/build/commands/init/init.js:94:3)
    at run (/Users/xxx/.config/yarn/global/node_modules/react-native-cli/index.js:302:7)
    at createProject (/Users/xxx/.config/yarn/global/node_modules/react-native-cli/index.js:249:3)
    at init (/Users/xxx/.config/yarn/global/node_modules/react-native-cli/index.js:200:5)
```

The error seems to be stemming from passing `undefined` for `projectDir` to `path.join`. Added a line to fix this.

Test Plan:
----------

`react-native init TestProject` should not fail.

* chore: setup e2e tests (#264)

* chore: setup e2e tests

* add flowfixmes

* use test.each

* add docs to install/uninstall

* remove dead code

* [General] [Fixed] - Fixes Xcode 10.2 simulator not found issue (#274)

* feat: upgrade envinfo for better output of info command (#265)

* feat: upgrade envinfo for better output

* remove --packages options

* chore: update deps to avoid security warnings (#270)

Summary:
---------

Upgrading deps.


Test Plan:
----------

Green CI

* Refactor: Remove eject (#275)

Summary:
---------

Since `create-react-native-app` is deprecated this functionality is no longer needed.

* Standardise configuration mechanism (#254)

Summary:
---------

This pull requests brings a new way of configuring the CLI and drops never properly standardised and documented "rnpm" configuration.

This is done in order to support new "auto-linking" feature and consolidate the configuration into a single place, that is easy to customise by developers.

### Highlights

Given the scope of this PR, it's hard to write down every tiny detail. I've tried to leave as many comments as possible throughout the code to make it easier for you to navigate and understand some of the code patterns.

Please see the highlighted changes below:

- We now use `cosmiconfig` to load user preferences. We do that by taking "react-native" out of "package.json" and reading "react-native.config.js". We still read "rnpm" for legacy purposes and print appropriate deprecation messages along the instructions on what to do in order to upgrade. Jest validation library makes this kind of things super easy.

- We validate the provided configuration by user using Jest validation library. This gives instant feedback whether the configuration is correct or not.

- We now read configuration in a single place (happens in main CLI file) and pass it down to commands. Previously, we used to call `findPlugins` multiple times w/o cache, causing expensive globs to be performed.

- Project configuration is lazy. We won't glob node_modules and/or look for native files unless you explicitly read for that package configuration.

- Better support for out-of-tree-platforms - no need to define "haste" yourself, we are able to infer it from other properties. The files are also better organised now, causing less of maintenance pain with "linkConfig" 

- We consider our automatically generated configuration a set of defaults. Users can override settings for the project and each of the dependencies. Useful, especially with auto-linking feature to disable certain packages from it or when you don't want to link particular platform automatically. This has been historically really hard to implement

- Global flags (e.g. "reactNativePath") can now be defined in configuration, instead of passing every time around. This fixes issues with "packager.sh" script (starting automatically Metro when running from Xcode) when run from RNTester.xcodeproj

### Next steps

Once this PR is merged, we can concurrently start working/merging other "auto-linking" PRs. In the meantime, I'll submit a PR to move regular "link" (soon to be considered a legacy) to use the new configuration format as well.

The new configuration has been designed in the way to still include previous configuration keys to support "link" and other community packages. 

For now, we print handy deprecation messages to help migrate the community from "rnpm" to "react-native" configuration. 

When "link" gets deprecated/removed forever in favour of "auto-linking", we should revisit the configuration and eventually, remove extraneous keys out of it. With "auto-linking", we don't need majority of it.

Test Plan:
----------

Run `react-native config` to output the configuration.

* fix: set correct peer dep of RN 0.60 for CLI@2.x (#280)

* fix: sort modules in debugger delta patcher to match source map order (#279)

Summary:
---------

Context: https://github.com/facebook/metro/issues/380, https://github.com/facebook/react-native/issues/23955

Fixes a discrepancy between the order of modules in the source map and in the actual bundle, caused by a change in Metro (see details in https://github.com/facebook/metro/issues/380#issuecomment-478633831). Consequently fixes React Native remote JS debugging.

Test Plan:
----------

1. Made the same change in my checkout of the repro code from https://github.com/facebook/metro/issues/380 and verified debugging works.
2. Added unit tests.

* fix: flaky tests; upgrade Jest to 24.6 (#282)

Summary:
---------

While working on #241 we discovered some flaky tests. This diff aims to fix those. It also updates Jest to 24.6 which comes with pretty nice perf improvements.

Test Plan:
----------

Green CI

* feat: new `init` command, leave legacy (#241)

Summary:
---------

New `init` command will exist in `@react-native-community/cli` and will deprecate current initialization flow.

### What has been done:
- [x] - Added `init` command to `cli` (the previous implementation was partially existing in `global cli`)
- [x] - Created a more friendly interface to create custom templates for initialization
- [x] - Redesigned template to match custom template interface (https://github.com/Esemesek/react-native-new-template)
- [x] - Added support to pass local repositories to `--version` and `--template` options through `file:`

### New template
Structure:
```
.
├── package.json
├── template
│   ├── App.js
│   ├── __tests__
│   ├── android
│   ├── babel.config.js
│   ├── index.js
│   ├── ios
│   ├── metro.config.js
│   ├── package.json
│   └── yarn.lock
└── template.config.js
```

* Root level `package.json` defines package
* `template.config.js` is a configuration file. Not a lot of properties we can configure for now, but can be extended in the future. (https://github.com/Esemesek/react-native-new-template/blob/master/template.config.js - supported properties)
* Directory with `template` which will be copied and processed during initialization process. In this structure it is called `template`, but it can be configured.

### Initalization

You can try out this PR, by cloning repository, checkouting to `Esemesek/init` branch, building `cli` and then running command:
```sh
node react-native-cli/packages/cli/buld init {projectName} --template react-native-new-template
```

To test intialization process without using custom template, `react-native` package you are using should contain update template. You can either create new version of `react-native` and publish it to local npm repository or use `--version file:{/absolute/path/to/update/react-native}`

### Example usage

Init with custom version:
```
npx react-native init ProjectName --version 0.60.0
```

Init with custom local version:
```
npx react-native init ProjectName --version file:///Users/username/local/version/of/react-native
```

Init with custom template:
```
npx react-native init ProjectName --template custom-template
```

Inite with custom local template:
```
npx react-native init ProjectName --template file:///Users/username/local/custom/template
```

> Note that `--template` needs to be valid absolute URL to react native or custom template 

Initialization could also be done by first installing `react-native` and then running init.
```sh
mkdir SomeDir && cd SomeDir
yarn add react-native
react-native init ProjectName
```

Hopefully we will be able to support yarn flows in the future: https://github.com/yarnpkg/rfcs/pull/113

### TODO:
- [x] - Add better logging
- [x] - Add more unit tests
- [x] - Update template in `react-native` repository (https://github.com/facebook/react-native/pull/24138)
- [ ] - Update documentation

Test Plan:
----------

- [x] - Tested manually
- [x] - Unit tests
- [x] - E2E tests - probably most important one

* feat: point to --verbose when command fails (#283)

* v2.0.0-alpha.1

* fix: properly copy template binary files (#285)

Summary:
---------
`fs.copySync` does not properly copy binary files. I am using the copy method that we already have in the repo.

Test Plan:
----------
Without this change `react-native run-android` breaks with the following error:
<img width="962" alt="Screen Shot 2019-04-02 at 16 58 14" src="https://user-images.githubusercontent.com/13352/55443764-b8638380-5568-11e9-94ba-0d33322d24da.png">

* chore: make legacyInit test less flaky (#286)

Summary:
---------

Get rid of moving parts in legacy init test


Test Plan:
----------

Test runs fine

* feat: make legacy `link` use new configuration (#281)

Summary:
---------

This PR switches `link` to rely on the new configuration (from "ctx") that is also used by "react-native config" and soon, "auto linking".

Test Plan:
----------

You should be able to run link w/o any issues

* chore: add better error handling for failing e2e tests (#289)

* feat: add React logo and spinners to make `init` UI nicer (#292)

* Implement spinners for initializing flow

* Use execa module

* Change banner

* Ignore silent flag when in verbose mode

* Refactor packageManager test

* Change loader exports

* Fix e2e test

* Rename packageManager

* Add e2e test

* smaller paddings for React logo

* Cleanup tests

* fix flowfixme

* add space for post install script

* rename packageManager.test as well

* feat: extract iOS and Android specific linking files out of the core (#290)

Summary:
---------

Historically, Android and iOS platform were hardcoded inside CLI and provided by default. Then, other packages could export additional platforms on top of it.

React Native as a platform was hardcoded in Metro configuration (default platforms, default extensions) and inside link. That means all new features were always developed with these platforms in mind, leaving others behind. We often used private APIs, which made things more complicated for 3rd party platform developers.

From this PR on, there's no longer concept of an out-of-tree platform inside of the CLI. In a follow up PR to React Native, I am going to configure iOS and Android platforms inside React Native, just like React Native Windows exposes Windows platform.

This will open room for improvements and should make it even easier for the CLI to welcome other platforms.

* remove clean on postinstall

* v2.0.0-alpha.4

* feat: apply upgrade patch in subdirectory if necessary (#272)

* bug: apply update patch in subdirectory if necessary

* add tests instead of changing existing ones

* fix: copy `.keystore` files as binary extensions. (#300)

* v2.0.0-alpha.5

* feat: use `logkitty` to format android logs (#294)

feat: use `logkitty` to format android logs

* feat: commands should be defined as object, unless defined via legacy config (#295)

Summary:
---------

This PR moves the logic for loading commands from CLI to the dependency authors. They should define a JavaScript configuration and return an array of commands (an object with required properties)  they want to load.

Previously, we would require them to define paths (relative to root) to a JavaScript file to require.

This is necessary to send a follow-up PR, which removes built-in platform commands to be bundled with React Native.

WIP: Need to check tests and update one or two snapshots to make sure we output Objects, instead of strings in a configuration.

* fix: resolve relative paths for reactNativePath (#297)

* Fix for relative paths

* Update snapshots

* chore: bump Jest and Flow to latest (#304)

* feat: infer package and project name for upgrade from config (#299)

* feat: infer packageName and projectName for upgrade from config

* extract merge to tools and use it in tests

* warn if unsupported platform is being upgraded

* feat: extract commands out to platform packages (#302)

* wip

* Finish it up

* Clean up packages

* Move files around

* Simplify regex

* Remove unused type

* Move packages around

* Fix type

* Update snapshot

* Make snapshot even smaller

* Throw unlink error

* fix: pass maxWorkers arg to server (#305)

Summary:
---------

I've noticed that the `max-workers` CLI flag is not behaving as expected for the bundle command.

We need it in one of our CI builds where the container is a bit memory-starved and the default of `numberOfWorkers = numberOfCores` isn't always accurate in a virtualized environment.

This fix ensures the flag makes it to the server config and that the number of node processes reflect the number provided + 1.


Test Plan:
----------

I made a reproduction repo: https://github.com/sterlingwes/rn-cli-repro

The values in the "expected output" reflect the fact:

* i already have a node process running for an unrelated task
* the number of node processes should be `maxWorkersValue + 1`, since there's a parent node process that spawns the child workers

So in the success case, `maxWorkers: 2` would lead to 3 node processes for the RN cli

* chore: don't apply RN config automatically (#306)

Summary:
---------

Thanks to this change, CLI will not add default React Native configuration when one is present. I can now go to React Native, add the configuration and release it and CLI will pick that one.

The below temporary workaround allows us to run on 0.59, where config is not yet present.

* v2.0.0-alpha.6

* feat: skip packages that have invalid config instead of throwing an error (#309)

* Do not throw on invalid packages

* Fix type error

* Update test

* add dot

* Update snapshots

* feat: skip successful Metro server requests if --verbose not set (#291)

Summary:
---------
Metro server can become too verbose if there are a lot of assets due to morgan verbosely logging every request. Trying to make use of `verbose` flag to allow users skipping successful requests if 'verbose' is set to false (default)

<!-- Thank you for sending the PR! We appreciate you spending the time to work on these changes.
Help us understand your motivation by explaining why you decided to make this change: -->


Test Plan:
----------
1. run `react-native start`
Expected Result: no console output on a successful request
2. run `react-native start --verbose`
Expected Result: console output for every request


<!-- Write your test plan here (**REQUIRED**). If you changed any code, please provide us with clear instructions on how you verified your changes work. Bonus points for screenshots and videos! Increase test coverage whenever possible. -->

* chore: fix typo in link debug message (#311)

Typo

* chore: use files instead of npmignore for publishing (#314)

* fix: add new line to the help message (#319)

Summary:
---------
There is a problem with the line break of command help as below.

<img width="561" src="https://user-images.githubusercontent.com/3139234/56199103-3484bd80-6077-11e9-9c00-9aa4f45bc185.png">

Test Plan:
----------

Not required.

* chore: add documentation on link, unlink, start, upgrade (#316)

* chore: move shared types to root; moar link styles; bye promiseWaterfall (#312)

* chore: move shared types to root; moar link styles; bye promiseWaterfall

* fix test

* add alias for global types

* bump Flow to 0.97

* add lint annotation to bin

* enable babel module resolver plugin

* import inquirer prompt type

* Add support for assetPlugins argument to start command (#318)

* Add support for assetPlugins argument to start command

* Add assetPlugins arg type

* feat: autolink on iOS

* chore: fix CI

* fix: give a better error message when CocoaPods linking fails (#321)

* initial commit

* Remove log

* fix: failing cocoa-pods tests

* Improve accessibility

* fix: prevent run-android failure when updating APK (#323)

Summary:
---------

If we run `react-native run-android` while it's already installed, it will fail with the following error.

```bash
info Installing the app on the device (cd android && adb -s emulator-5554 install app/build/outputs/apk/debug/app-x86-debug.apk
adb: failed to install app/build/outputs/apk/debug/app-x86-debug.apk: Failure [INSTALL_FAILED_ALREADY_EXISTS: Attempt to re-install me.mycake without first uninstalling.]
```

In the development phase, I think using adb's install options below is much more efficient.

```
-r : Reinstall an existing app, keeping its data.
-d : Allow version code downgrade.
```


Test Plan:
----------

Not required.

* fix: open Metro in the correct terminal (#310)

* Put `isPackagerRunning` function on `cli-tools` to share between iOS & Android

* Fix `terminal` argument not working when not being provided

* Fallback to the default terminal of the machine when starting the packager on `run-android`

* Delete `isPackagerRunning` as it was moved to `tools`

* Add `terminal` argument to `run-ios`

* Launch Metro from within the `runIOS` command

* Remove code & add `—terminal` argument

* Try using `REACT_TERMINAL` before the default terminal

* Put `isPackagerRunning` function on `cli-tools` to share between iOS & Android

* Fix `terminal` argument not working when not being provided

* Fallback to the default terminal of the machine when starting the packager on `run-android`

* Delete `isPackagerRunning` as it was moved to `tools`

* Add `terminal` argument to `run-ios`

* Launch Metro from within the `runIOS` command

* Remove code & add `—terminal` argument

* Try using `REACT_TERMINAL` before the default terminal

* Add tool function to get the default user terminal

* Fix `terminal` arg type

* Remove spread and specify entry twice instead

* Improve `args` being passed through functions

* Reduce code duplication

* Put `device` and `udid` variable up in the scope

* v2.0.0-alpha.7

* fix: prevent unnecessary actions if android build failed (#325)

* feat: refactor `run-ios` for readability and better error messages (#328)

Summary:
---------

Refactor `run-ios` for readability and better error messages:

<img width="737" alt="Screenshot 2019-04-17 at 22 04 38" src="https://user-images.githubusercontent.com/5106466/56317371-e0540900-615c-11e9-82e2-e8ef4e706721.png">
<img width="535" alt="Screenshot 2019-04-17 at 22 05 04" src="https://user-images.githubusercontent.com/5106466/56317372-e0540900-615c-11e9-9c82-774889ee2b05.png">
<img width="621" alt="Screenshot 2019-04-17 at 22 08 00" src="https://user-images.githubusercontent.com/5106466/56317551-4e003500-615d-11e9-92dc-c06f0e092e90.png">

Followup to #310 cc @lucasbento 

Test Plan:
----------

Verified that following commands work properly:
- `run-ios`
- `run-ios --device`
- `run-ios --device phone-name`
- `run-ios --uuid asd123`

* fix: publish native_modules.rb file (#331)

* v2.0.0-alpha.8

* Support functions in default (#333)

* v2.0.0-alpha.9

* fix: allow empty strings to be used as defaults

* v2.0.0-alpha.10

* feat: support platforms that ship with project  (#335)

* Project can also have platforms

* strip unknown

* Remove stripUnknown and prefer allowUnknown on one level only

* fix: update haste config with platforms too

* v2.0.0-alpha.11

* handle haste (#336)

* v2.0.0-alpha.12

* chore: top-level unknown keys are now allowed, update test case

* fix: modify wrong install arguments (#337)

* feat: check `ios-deploy` installation before proceeding to build on device (#332)

Summary:
---------

This PR fixes #330, it checks if `ios-deploy` is installed or not before it actually starts building.

Test Plan:
----------

- Run `npm uninstall -g ios-deploy`;
- Run the CLI with `--device` argument and wait for it to fail;
- Run `npm i -g ios-deploy`;
- Run the CLI again and see it working.

cc @thymikee

---

### Error about `ios-deploy` not installed
![image](https://user-images.githubusercontent.com/6207220/56423345-e7d5f800-62ab-11e9-9acf-e5336685904a.png)

### Random error when executing `ios-deploy`
![image](https://user-images.githubusercontent.com/6207220/56423377-12c04c00-62ac-11e9-863a-82c12800893a.png)

* feat: support init inside monorepos (#320)

* feat: autolinking for Android with Gradle (#258)

Provides the Android/Gradle functionality to go with https://github.com/react-native-community/react-native-cli/pull/256 & https://github.com/react-native-community/react-native-cli/pull/254

## CLI Changes

- Updated `react-native config` to include the android `sourceDir` for react native module packages

----

## Usage

These are the one-off changes required to enable this in the React Native init template (or for existing user projects).

### Modify `android/settings.gradle`

Include the following line in your Android projects `settings.gradle` file:

```groovy
apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
```

### Modify `android/app/build.gradle`

Add the following line at the bottom of your Android projects `android/app/build.gradle` file:

```groovy
apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
```

### Modify `MainApplication.java`

Import the PackageList class;

```java
import com.facebook.react.PackageList;
```

Replace the `protected List<ReactPackage> getPackages()` method with the following:

```java
    @Override
    protected List<ReactPackage> getPackages() {
      @SuppressWarnings("UnnecessaryLocalVariable")
      List<ReactPackage> packages = new PackageList(this).getPackages();
      // additional non auto detected packages can still be added here:
      // packages.add(new SomeReactNativePackage());
      return packages;
    }
```


### Testing

I've tested the following scenarios locally:

- User has no React Native global CLI installed
  - Will warn but continue without issue
- User has no React Native packages installed yet
  - Continues as normal with no warning
- User has more than one React Native package installed
  - Correctly adds multiple packages without issue
- User has a package installed that does not support autodetection (config == null)
  - Prints a warning but continues gracefully
- User has custom/non-linked React Native packages
  - Can be sucessfully manually added via `packages.add(new SomeReactNativePackage());` as documented above in `MainApplication.java`

To test this in a new `react-native init` project locally:

- Clone the CLI project
- Run `yarn` in the CLI project
- Run `cd packages/cli && yarn && yarn link`  in the CLI project
  - (a little hacky as it's a mono-repo)
- Run `yarn link "@react-native-community/cli"` on your React Native project
- Make the required changes as above to your React Native project

----

### Codegen Output Example

An example of the generated `PackageList.java` class:

```java
package com.facebook.react;

import android.app.Application;
import android.content.Context;
import android.content.res.Resources;

import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;
import java.util.Arrays;
import java.util.List;

import com.test.BuildConfig;

// react-native-webview
import com.reactnativecommunity.webview.RNCWebViewPackage;

public class PackageList {
  private ReactNativeHost reactNativeHost;
  public PackageList(ReactNativeHost reactNativeHost) {
    this.reactNativeHost = reactNativeHost;
  }

  private ReactNativeHost getReactNativeHost() {
    return this.reactNativeHost;
  }

  private Resources getResources() {
    return this.getApplication().getResources();
  }

  private Application getApplication() {
    return this.reactNativeHost.getApplication();
  }

  private Context getApplicationContext() {
    return this.getApplication().getApplicationContext();
  }

  public List<ReactPackage> getPackages() {
    return Arrays.<ReactPackage>asList(
      new MainReactPackage(),
      new RNCWebViewPackage()
    );
  }
}
```

* v2.0.0-alpha.13

* fix(autolinking): remove deprecated Gradle task syntax (#339)

Summary:
---------

Gradle 5 no longer supports the `<<` syntax - swapped to the non-shorthand syntax of `doLast {}`

Test Plan:
----------

Builds successfully with the updated syntax and `PackageList.java` file generated

![image](https://user-images.githubusercontent.com/5347038/56444115-57b9a200-62ef-11e9-94bc-16818c33e65e.png)

![image](https://user-images.githubusercontent.com/5347038/56444122-5f794680-62ef-11e9-962a-5beb06e90667.png)

* v2.0.0-alpha.14

* fix: [android] remove forward slashes from package name (#340)

Summary:
---------

The previous CLI config use to return names with `/`'s replaced with `_`'s - it no longer does this so I've moved the replacing logic into the auto-linking build script so as to avoid breaking on Gradle 5+:
![image](https://user-images.githubusercontent.com/5347038/56455870-2b883a80-635c-11e9-90ef-53f00282391f.png)


Test Plan:
----------

After change build no longer fails:

![image](https://user-images.githubusercontent.com/5347038/56455888-8883f080-635c-11e9-9bda-905baf83d3bd.png)

![image](https://user-images.githubusercontent.com/5347038/56455892-98033980-635c-11e9-9cc6-8005e866bc2b.png)

* fix: stop resolving "react-native" from package.json as a config  (#341)

* fix: stop resolving "react-native" as a valid package.json config property

* add missing editTemplate file

* docs: update and rearrange documentation (#338)

* docs: update and rearrange documentation

* add autolinking base docs

* add init docs

* chore: remove unsupported CocoaPods options from a documentation

This is currently not supported. Let's have it as a "todo" for the future releases, ideally, upon request from someone.

* docs: initial documentation of plugins (#345)

* fix: typos in Autolinking & use same repo for both examples

* structure new files

* Add documentation for plugins and update naming in one place

* Update index.js

* Fix flow and update docs

* Update

* Prefix

* Updates

* Take advantage of Joi

* Update docs/plugins.md

Co-Authored-By: grabbou <grabbou@gmail.com>

* Update docs/plugins.md

Co-Authored-By: grabbou <grabbou@gmail.com>

* Some other tweaks

* Placeholder for dependency

* Updates

* Delete linking.md

* fix tests

* docs: add init documentation (#347)

* docs: add init documentation

* docs: add mentions in other files

* docs: revert

* Update docs/init.md

Co-Authored-By: Esemesek <kacperwiszczuk@gmail.com>

* feat: add `platforms` doc (#349)

* Add platforms doc

* Migration guide

* Update docs/platforms.md

Co-Authored-By: grabbou <grabbou@gmail.com>

* feat: add dependency and project documentation (#350)

* Add dependency documentation and links

* Update

* Update

* Add project desc

* Move notice above

* add catch-all doc

* Typo

* Rename the type

* Update docs/configuration.md

Co-Authored-By: grabbou <grabbou@gmail.com>

* Update docs/configuration.md

Co-Authored-By: grabbou <grabbou@gmail.com>

* Do where not when

* Plural

* v2.0.0-alpha.15

* fix: ignore undefined when renaming

* chore: update wording in docs

* chore: change `upgrade` to use new diff files approach (#348)

* use diff files and dont rely on gh

* lint

* update snapshots

* update link to diff table

* feat: improve copying binary files in `init` (#353)

* Update autolinking.md (#355)

* [ios] Ensure that the right cwd is set up for auto-linking dependencies (#354)

* [ios] Ensure that the right cwd is set up for auto-linking dependencies

* [autolink] Switch to DIing in the root path as a param in to use_native_modules

* [autolink] Docs for autolink root changes

* v2.0.0-alpha.17

* feat(breaking): remove legacy `library` command (#358)

feat(breaking): remove legacy `library` command

* fix: init from url (#361)

* feat: init from tarball (#362)

* feat: init from tarball

* adjust error message

* skip flaky config test

* update docs

* update snapshots

* feat: copy all files in `init` through streams (#363)

* feat: copy all files in init through streams

* fix asynchrony

* only replace file if necessary

* docs: add `maintainers` section (#369)

* Add `maintainers` section

* Update README.md

* Polacy nie gęsi, swój język mają xd

* fix: refactor init for less duplication; fix handling versioned templates (#364)

* chore: refactor init for less duplication

* fix handling versioned packages

* polish error messages a bit

* support npm tags

* fix: reporter config option (#370)

The `loadConfig` function in `metro-config` reads the `reporter` option
from the second argument (`defaultConfigOverrides`) instead of the
first argument (`argv`), so we need to pass it in that object to
make the `customLogReporterPath` CLI option work.

* chore: Update prettier config (#379)

* Use `require.resolve` to resolve package path (#378)

* Use `require.resolve` to resolve package path

* resolveNodeModule -> resolveNodeModuleDir

* feat: improve `run-android` error messages; rename "installDebug" -> "task" (#372)

* chore: cleanup run-android implementation

* feat: overhaul gradle install errors

* fix copying executables by bringing back chmod

* rename 'installDebug' -> 'task'

* cleanup unused args from refactor

* use inherit and don't show null error

* simplify creating gradle args

* adjust descriptions

* use logger

* Add support for multiple tasks

* Change function name to match current functionality

* Change task to tasks

* v2.0.0-alpha.18

* feat: automatically run `pod install` when running `init` command (#373)

* Specify `.xcworkspace` on run instructions instead of `.xcodeproj`

* Add `command-exists` package

* Remove unneeded space after log message

* Run `pod install` and check for cocoa pods when running `init` command

* Put pods installation directly on `init` file and verify if `Podfile` exists before running

* Revert change to space

* Remove unneeded `console.log`

* `cd` back to the directory after pod installation

* Throw with `CLIError` instead of `Error`

* Remove unneeded `try…catch`

* Fix wrong uppercased word

* Try to install `cocoapods` without sudo before trying with it

* Run pods installation only on macOS

* Check which extension for the project to print out on the run instructions for iOS

* Use `fs` instead of `fs-extra`

* Move `installPods` to separate file

* Add missing `logger` import

* Fix warnings on duplicated variable declaration

* fixups

* Add openURLMiddleware (#383)

* Add openURLMiddleware

This allow’s react-native to open Chrome windows arbitrarily.

* Upgrade open, add launchBrowser command.

* v2.0.0-alpha.19

* fix: run "config" from react-native binary in autolinking scripts (#384)

* fix: run "config" from react-native binary

* use yarn run when necessary and fallback to accessing binary with Node

* filter out non-json stuff in gradle implementation

* use yarn --silent

* Improve CocoaPods prompt question when running  `init` (#389)

* chore: upgrade joi to @hapi/joi to remove npm warnings (#388)

* fix: config.reporter undefined bug (#376)

* fix: config.reporter undefined bug

* refactor

* Update loadMetroConfig.js

* feat: automatically install pods in legacy init (#386)

* feat: Show message if CocoaPods installation takes long (#390)

* Add message that shows only if `cocoapods` installation take more than 30 seconds

* adjustments

* chore: bump lerna to latest

* v2.0.0-alpha.20

* chore: Update npm version badge link (#391)

* feat: support `init` with custom project directory (#365)

* Change `packageName` to `projectName` & add `projectPath` argument

* Add a way to specify a custom project path to init the app on

* Force the `init` command to create the project path recursively

* Add test for providing the project path on init

* Throw error if custom project path doesn’t exist and can’t be created

* Fix type error on `customProjectPath`

* Create directory before running the test with custom project path

* Use `mkdirp` to create project folder & Use `inquirer` to prompt for a directory replace

* Specify `directory` as an option

* Handle custom directory path after react logo

* Check if `ios` folder exists before trying to open it

* Update `init` tests

* Add `directory` type

* Remove unused `inquirer` from `init` test

* Only remove the project folder if it didn’t exist before running `init`

* Remove correct directory if it didn’t exist before `init`

* simplify

* make directory an argument instead of a flag

* update descriptions

* fix test

* use --directory after all

* address feedback; remove version handling from createFromTemplate

* flip the default

* chore: migrate `tools` to TypeScript (#296)

* Migrate tools package to Typescript

* Prebuild ts

* Improve yarn build-clean

* Remove unnecessary statements

* Fix linting

* Fix eslint

* Update packages/tools/src/isPackagerRunning.ts

Co-Authored-By: Michał Pierzchała <thymikee@gmail.com>

* adjust package.json

* add vscode helper settings

* remove dead node-fetch references

* chore: improve RNPM warnings (#395)

* Improve RNPM warnings

* Update packages/cli/src/tools/config/readConfigFromDisk.js

Co-Authored-By: Michał Pierzchała <thymikee@gmail.com>

* Fix lint error

* v2.0.0-alpha.21

* feat: allow `dependencyConfig` to override `podspec` name (#393)

* [ios][docs] document podspec param

* [ios] add podspec to dependencyConfig schema

* [types] add podspec to config

* [config] add podspec param override to config

* feat: remove manifest from config output (#398)

* feat: remove manifest from config output

* fix typo in the docs

* v2.0.0-alpha.22

* feat: log error stacktrace by default (#396)

* [CI] Migrate to Circle 2.1, add Node LTS tests (#402)

* fix: Ensure that bundle URL origin matches debugger page origin (#403)

This structurally sets up the Chrome debugger not to have CORS issues if the bundle URL domain differs from the Chrome debugger page domain. This bug was initially fixed in https://github.com/facebook/react-native/pull/17720 and regressed in https://github.com/react-native-community/cli/pull/194. This commit fixes the original bug without changing the behavior introduced in #194.

This commit makes the debugger page use its own URL origin when loading the bundle URL. This addresses the case where the native client may have a bundle URL with a domain like xip.io. Fundamentally, unless the development server allows cross-origin requests, the bundle URL's domain must match the domain used by the Chrome debugger page, which is what this commit achieves.

* [android] Fixed a crash when adding non-autolinked custom `ReactPackages` (#407)

* v2.0.0-alpha.23

* chore: add CODEOWNERS file (#404)

* chore(docs): update CONTRIBUTING.md (#409)

* fix: no active iOS device case in `logIOS` (#410)

* fix: Add a simulator.isAvailable check for true value (#414)

* Add a simulator.isAvailable check for true

Installing the Xcode 11 beta changes the result of isAvailable to `true` and `false`.

* Fix lint error

* feat: Only pass `hasteImplModulePath` if the `hasteImpl` file is available in RN (#417)

* chore: remove deprecated entries in DevTools middleware (#415)

* feat(breaking): link only assets by default; add `--all` flag (#416)

Change the default behavior of `link` to only link assets.

Since autolinking, manual linking of packages is quickly becoming obsolete, however there's no easy way to autolink assets (can be automated with CocoaPods podspecs, but not sure about Gradle cc @Salakar. EDIT: should be doable, @Salakar is on it). That's why I think it makes sense to default `link` to process assets only, unless the `--all` flag is passed explicitly.

Additional changes that accumulated while testing: 

- fix linking hooks failing to execute
- fix handling assets from legacy "rnpm" config
- overhaul linking logs and error messages
- disable flaky e2e tests in lts-tests phase

* feat: notify of new major RN version at most once a week (#268)

Summary:
---------

This PR addresses the first part of #189: notifying the user when a newer version of React Native is available to upgrade to when using the CLI.

**Behaviour**
* The remote release check mechanism uses the [GitHub API](https://developer.github.com/v3/repos/releases/#get-the-latest-release).
* The mechanism is triggered for any CLI command.
* Nothing will be displayed if the project is already up-to-date.
* The release data returned from the API call is cached per-project. Caching is necessary to not hit the GitHub API rate limit.
* For the time being, there is no way to "mute" this behaviour if a project is intentionally using an older RN version because we have not discussed yet how the UX for that will be.

**Caveats**
The GitHub API we are using is specific to [Releases](https://help.github.com/en/articles/creating-releases), so we need to make sure that each new version of React Native has one. For example, 0.59.1 has been cut and published on NPM on March 14th but the release has been made only on the 25th. During that interval, the CLI would have not notified users of the newer version.

Test Plan:
----------

* Clone this branch
* Install dependencies with `yarn install`
* Test the behaviour in newer and older projects by calling `cli.js` directly from the cloned repository as described in `CONTRIBUTING.md`.

Screenshots:
---------
Linking a module in an older project:
![Screenshot from 2019-03-25 19-22-14](https://user-images.githubusercontent.com/1713151/54944577-1a523680-4f34-11e9-8d28-5c4b3e00b8f9.png)

Output when a project is up-to-date (showing debug messages as normally there would be no output):
![Screenshot from 2019-03-25 19-35-42](https://user-images.githubusercontent.com/1713151/54945093-55a13500-4f35-11e9-879e-69780ae7a59c.png)

* v2.0.0-rc.0

* chore: bump Metro to 0.54.1 (#420)

* chore: bump Metro to 0.54.1

* fix hasteImpl path resolving

* v2.0.0-rc.1

* feat: Pass along CLI port configuration for Android (#421)

This commit operates in conjunction with a change to React Native
Android to allow the overriding of the development server port.

* fix: make sure the port passed to Metro is a number (#424)

* v2.0.0-rc.2

* Log `console` invocations to the terminal. (#426)

* fix: Add fallback path check when not found app file for iOS (#428)

* chore: update init docs to be more descriptive (#427)

* updated docs to match the current implementation

* added note about the shebang

* re-added the .js extension as it works with it as well

* fix: allow upgrading with binary files in the diff (#432)

* feat: allow upgrading with binary files in the diff

* fix tests

* chore: bump Flow to 0.101 (#431)

* fix: Add import for `applicationId.R` class in generated `PackageList.java` (#435)

* Add import for `applicationId.R` class

* Remove redundant semicolon

* chore: refactor packageManager.js for less redundancy (#433)

* feat: filter out non-native deps from config output; fix missing hooks (#436)

* fix: use `packageName` instead of `applicationId` in gradle script (#439)

* Use `packageName` instead of `applicationId`

* Use pre-parsed config for `packageName`

* Remove param `packageName`

Co-Authored-By: Michał Pierzchała <thymikee@gmail.com>

* feat(breaking): use 'podspecPath' instead of 'podspec', make it smarter (#442)

* docs: document how to disable autolinking for unsupported packag… (#444)

* v2.0.0-rc.3

* fix: don't use yarn for spawning 'config' command (#449)

* feat: add warnings for `run-ios` and `run-android` when manually… (#447)

* wip

* add warnings for run-ios and run-android

* memoize in place

* cleanup

* chore: group deprecated rnpm warnings, add migration guide (#450)

* chore: group deprecated rnpm warnings, add migration guide

* Update packages/cli/src/tools/config/index.js

Co-Authored-By: Satyajit Sahoo <satyajit.happy@gmail.com>

* remove parens from links

* chore: fix grammar in warning (#453)

* chore: fix grammar in warning

* adjust wording

* fix: incorrect condition for upgrade newer version check (#455)

* chore(docs): simplify autolinking (#454)

* chore(docs): simplify autolinking

* address feedback

* feat: simplify passing root to gradle autolinking (#457)

* feat: simplify passing root to gradle autolinking

* improve docs

* v2.0.0-rc.4

* feat: support local RN libraries in autolinking (#451)

* feat: support local RN libraries in autolinking

* simplify local deps config

* address feedback

* v2.0.0-rc.5

* feat: improve `upgrade` when patches fail to apply (#461)

* v2.0.1

* fix: config on Windows & warnings breaking config JSON output on… (#464)

* fix: warnings breaking config JSON output

* fix legacy test

* v2.0.2

* fix: Changed the URL to be valid for configuration.md (#466)

* Changed the URL to be valid for configuration.md

* Update packages/cli/src/tools/config/index.js

Co-Authored-By: Kacper Wiszczuk <kacperwiszczuk@gmail.com>

* fix: log-android not working. update logkitty. (#469)

* fix: log-android not working. update logkitty.

* fix registry

* fix: run release checker only after `start` and `info` command (#479)

* fix: run release checker only after `start` command

* fix test

* fix: autolinking bug on Windows when reading config (#480)

* fix: duplicate entires in rnpm warning (#481)

* feat: make run-ios output leaner (#472)

* feat: make run-ios output leaner

* --ammend

* chore: use StringBuffer when getting config (#482)

* v2.1.0

* chore: revamp README for readability, about and updating info (#490)

* chore: add updating guide & improve about

* update readme

* fix typo

* docs: add table of contents (#491)

* fix: support an Application instance in PackageList for Android (#493)

* fix: Metro Bundler crashing on `run-android` on Windows (#489)

* fix: passing iOS simulator name with brackets in latest Xcode (#460)

* Fixed cli --simulator not working with latest Xcode simulator name with brackets

* Updated test case

* Fixed findMatchingSimulator unit test

* v2.1.1

* fix: `init` command with scoped templates without version (#497)

* fix: don't set `projetRoot` for Metro (#496)

* chore: fix typo in contribution guide (#501)

* v2.1.2

* chore: add more information to autolinking guide (#505)

* feat: use relative paths for Podfile.lock (#502)

* fix: use_native_modules! warns and skips dependencies without a podspec (#507)

* fix: correct project directory in run instructions after `init` (#504)

* fix: fix project directory name in run instructions

* fix: pass the right project directory to printRunInstructions

* v2.2.0

* chore: remove unstable `init --template` shorthand support (#495)

* feat: support `unlink --platforms` (#511)

* v2.3.0

* docs: add docs for `unlink --platforms`

* feat: add `xed -b ios` for opening Xcode to init instructions (#514)

* fix: run `pod repo update` after installing CocoaPods (#513)

* fix: run `pod repo update` after installing CocoaPods (#487)

Added `pod repo update` command call after CocoaPods installation to
avoid issues with pod command being unable to find specification for
dependency.
Added loader to CocoaPods installation step for consistency with other
steps of init and better DX, removed logger info after 30s timeout
because of redundancy with loader.
Changed loader method before prompt for CocoaPods installation from
`stop` to `info` for better prompt visibility.

* always show installing pods step

* add notice back

* minor loader refactor

* fix false positive for pod command being available

* use pod --version for smaller output

* v2.4.0

* fix: add chalk as dependency of cli-platform-android (#517)

* v2.4.1

* fix: don't copy node_modules in templates (#519)

* v2.4.2

* fix: cache lazy project getter for perf when accessed repeatedly (#520)

* adjust build-clean and publish scirpts

* v2.4.3
dratwas pushed a commit to dratwas/react-native-cli that referenced this pull request Jul 12, 2019
Provides the Android/Gradle functionality to go with react-native-community#256 & react-native-community#254

## CLI Changes

- Updated `react-native config` to include the android `sourceDir` for react native module packages

----

## Usage

These are the one-off changes required to enable this in the React Native init template (or for existing user projects).

### Modify `android/settings.gradle`

Include the following line in your Android projects `settings.gradle` file:

```groovy
apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
```

### Modify `android/app/build.gradle`

Add the following line at the bottom of your Android projects `android/app/build.gradle` file:

```groovy
apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
```

### Modify `MainApplication.java`

Import the PackageList class;

```java
import com.facebook.react.PackageList;
```

Replace the `protected List<ReactPackage> getPackages()` method with the following:

```java
    @OverRide
    protected List<ReactPackage> getPackages() {
      @SuppressWarnings("UnnecessaryLocalVariable")
      List<ReactPackage> packages = new PackageList(this).getPackages();
      // additional non auto detected packages can still be added here:
      // packages.add(new SomeReactNativePackage());
      return packages;
    }
```


### Testing

I've tested the following scenarios locally:

- User has no React Native global CLI installed
  - Will warn but continue without issue
- User has no React Native packages installed yet
  - Continues as normal with no warning
- User has more than one React Native package installed
  - Correctly adds multiple packages without issue
- User has a package installed that does not support autodetection (config == null)
  - Prints a warning but continues gracefully
- User has custom/non-linked React Native packages
  - Can be sucessfully manually added via `packages.add(new SomeReactNativePackage());` as documented above in `MainApplication.java`

To test this in a new `react-native init` project locally:

- Clone the CLI project
- Run `yarn` in the CLI project
- Run `cd packages/cli && yarn && yarn link`  in the CLI project
  - (a little hacky as it's a mono-repo)
- Run `yarn link "@react-native-community/cli"` on your React Native project
- Make the required changes as above to your React Native project

----

### Codegen Output Example

An example of the generated `PackageList.java` class:

```java
package com.facebook.react;

import android.app.Application;
import android.content.Context;
import android.content.res.Resources;

import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;
import java.util.Arrays;
import java.util.List;

import com.test.BuildConfig;

// react-native-webview
import com.reactnativecommunity.webview.RNCWebViewPackage;

public class PackageList {
  private ReactNativeHost reactNativeHost;
  public PackageList(ReactNativeHost reactNativeHost) {
    this.reactNativeHost = reactNativeHost;
  }

  private ReactNativeHost getReactNativeHost() {
    return this.reactNativeHost;
  }

  private Resources getResources() {
    return this.getApplication().getResources();
  }

  private Application getApplication() {
    return this.reactNativeHost.getApplication();
  }

  private Context getApplicationContext() {
    return this.getApplication().getApplicationContext();
  }

  public List<ReactPackage> getPackages() {
    return Arrays.<ReactPackage>asList(
      new MainReactPackage(),
      new RNCWebViewPackage()
    );
  }
}
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants