Skip to content

Commit

Permalink
docs: initial documentation of plugins (react-native-community#345)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>

* Update docs/plugins.md

Co-Authored-By: grabbou <[email protected]>

* Some other tweaks

* Placeholder for dependency

* Updates

* Delete linking.md

* fix tests
  • Loading branch information
grabbou authored Apr 23, 2019
1 parent 29ae253 commit bca56c9
Show file tree
Hide file tree
Showing 18 changed files with 237 additions and 77 deletions.
6 changes: 4 additions & 2 deletions docs/autolinking.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
Autolinking is a mechanism built into CLI that allows adding a dependency with native components for React Native to be as simple as:

```sh
yarn add react-native-firebase
yarn add react-native-webview
```

> Autolinking is a replacement for [`react-native link`](./linking.md) that brings new features (such as ability to easily integrate native dependencies on iOS) and fixes some of the long-standing issues.
## How does it work

React Native CLI provides a [`config`](./commands.md#config) command which grabs all of the configuration for React Native packages installed in the project (by scanning dependenecies in `package.json`) and outputs it in JSON format.
React Native CLI provides a [`config`](./commands.md#config) command which grabs all of the configuration for React Native packages installed in the project (by scanning dependencies in `package.json`) and outputs it in JSON format.

This information is then used by the projects advertised as platforms (with `react-native` being a default project supporting both iOS and Android platforms) that implement their autolinking behavior.

Expand Down
3 changes: 3 additions & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Configuration

TBD
3 changes: 3 additions & 0 deletions docs/dependency.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Dependency

TBD
3 changes: 3 additions & 0 deletions docs/platforms.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Platforms

TBD
150 changes: 149 additions & 1 deletion docs/plugins.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,151 @@
# Plugins

TBD
Plugin is a JavaScript package that extends built-in React Native CLI features. It can provide an array of additional commands to run or platforms to target.

For example, `react-native-windows` package is a plugin that provides `react-native run-windows` command and `windows` platform.

Details of this particular integration as well as how to provide an additional platform for React Native were described in a [`dedicated section`](./platforms.md) about platforms.

## How does it work?

Except for React Native dependencies, where configuration is implicit, each package needs to have a `react-native.config.js` at the root folder in order to be discovered by the CLI as a plugin.

```js
module.exports = {
commands: [
{
name: 'foo-command',
func: () => console.log('It worked')
}
]
};
```

> Above is an example of a plugin that exports a command named `foo-command` that can be executed with `react-native foo-command` and logs "It worked" and exits.

At the startup, React Native CLI reads configuration from all dependencies listed in `package.json` and reduces them into a single configuration.

At the end, an array of commands concatenated from all plugins is passed on to the CLI to be loaded after built-in commands.

## Command interface

```ts
type Command = {
name: string,
description?: string,
func: (argv: Array<string>, config: ConfigT, args: Object) => ?Promise<void>,
options?: Array<{
name: string,
description?: string,
parse?: (val: string) => any,
default?:
| string
| boolean
| number
| ((config: ConfigT) => string | boolean | number),
}>,
examples?: Array<{
desc: string,
cmd: string,
}>,
};
```

> Note: `ConfigT` is described in [`configuration`](./configuration.md) section
#### `name`

A name that will be used in order to run the command.

Note: If you want your command to accept additional arguments, make sure to include them in the name.

For example, `my-command <argument>` will require an argument to be provided and will throw a validation error otherwise. Alternatively, `my-command [argument]` will accept an argument, but will not throw when run without it. In that case, make sure to check for its presence.

#### `func`

Function that will be run when this command is executed. Receives an array of arguments, in order they were provided, a config object (see [`configuration` section](./configuration.md)) and options, that were passed to your command.

You can return a Promise if your command is async.

All errors are handled by the built-in logger. Prefer throwing instead of implementing your own logging mechanism.

#### `options`

An array of options that your command accepts.

##### `options.name`

Name of the option.

For example, a `--reset-cache` option will result in a `resetCache: true` or `resetCache: false` present in the `options` object - passed to a command function as a last argument.

Just like with a [command name](#name), your option can require a value (e.g. `--port <port>`) or accept an optional one (e.g. `--host [host]`). In this case, you may find [`default`](#optionsdefault) value useful.

##### `options.description`

Optional description of your option. When provided, will be used to output a better help information.

##### `options.parse`

Parsing function that can be used to transform a raw (string) option as passed by the user into a format expected by your function.

##### `options.default`

Default value for the option when not provided. Can be either a primitive value or a function, that receives a configuration and returns a primitive.

Useful when you want to use project settings as default value for your option.

#### `examples`

An array of example usage of the command to be printed to the user.

##### `examples.desc`

String that describes this particular usage.

##### `examples.cmd`

A command with arguments and options (if applicable) that can be run in order to achieve the desired goal.

## Migrating from `rnpm` configuration

The changes are mostly cosmetic so the migration should be pretty straight-forward.

### Changing the configuration

A `plugin` property should be renamed to `commands`.

For example, the following `rnpm` configuration inside `package.json`:
```json
{
"rnpm": {
"plugin": "./path-to-commands.js",
}
}
```
should be moved to a `react-native.config.js`:
```js
module.exports = {
commands: require('./path-to-commands.js')
};
```
provided that `./path-to-commands.js` returns an array of commands.

### Renaming command options

If your command accepts options, rename `command` property of each of them to `name`.

```diff
module.exports = {
name: 'foo',
func: () => console.log('My work'),
options: [
{
- command: '--reset-cache, --resetCache',
+ name: '--reset-cache, --resetCache',
description: 'Removes cached files',
}
]
}
```
4 changes: 2 additions & 2 deletions packages/cli/src/cliEntry.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ function printHelpInformation(examples, pkg) {
: [];

let output = [
chalk.bold(`react-native ${cmdName} ${this.usage()}`),
chalk.bold(`react-native ${cmdName}`),
this._description ? `\n${this._description}\n` : '',
...sourceInformation,
`${chalk.bold('Options:')}`,
Expand Down Expand Up @@ -122,7 +122,7 @@ const addCommand = (command: CommandT, ctx: ConfigT) => {

options.forEach(opt =>
cmd.option(
opt.command,
opt.name,
opt.description,
opt.parse || defaultOptParser,
typeof opt.default === 'function' ? opt.default(ctx) : opt.default,
Expand Down
30 changes: 15 additions & 15 deletions packages/cli/src/commands/bundle/bundleCommandLineArgs.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,85 +30,85 @@ export type CommandLineArgs = {

export default [
{
command: '--entry-file <path>',
name: '--entry-file <path>',
description:
'Path to the root JS file, either absolute or relative to JS root',
},
{
command: '--platform [string]',
name: '--platform [string]',
description: 'Either "ios" or "android"',
default: 'ios',
},
{
command: '--transformer [string]',
name: '--transformer [string]',
description: 'Specify a custom transformer to be used',
},
{
command: '--dev [boolean]',
name: '--dev [boolean]',
description: 'If false, warnings are disabled and the bundle is minified',
parse: (val: string) => val !== 'false',
default: true,
},
{
command: '--minify [boolean]',
name: '--minify [boolean]',
description:
'Allows overriding whether bundle is minified. This defaults to ' +
'false if dev is true, and true if dev is false. Disabling minification ' +
'can be useful for speeding up production builds for testing purposes.',
parse: (val: string) => val !== 'false',
},
{
command: '--bundle-output <string>',
name: '--bundle-output <string>',
description:
'File name where to store the resulting bundle, ex. /tmp/groups.bundle',
},
{
command: '--bundle-encoding [string]',
name: '--bundle-encoding [string]',
description:
'Encoding the bundle should be written in (https://nodejs.org/api/buffer.html#buffer_buffer).',
default: 'utf8',
},
{
command: '--max-workers [number]',
name: '--max-workers [number]',
description:
'Specifies the maximum number of workers the worker-pool ' +
'will spawn for transforming files. This defaults to the number of the ' +
'cores available on your machine.',
parse: (workers: string) => Number(workers),
},
{
command: '--sourcemap-output [string]',
name: '--sourcemap-output [string]',
description:
'File name where to store the sourcemap file for resulting bundle, ex. /tmp/groups.map',
},
{
command: '--sourcemap-sources-root [string]',
name: '--sourcemap-sources-root [string]',
description:
"Path to make sourcemap's sources entries relative to, ex. /root/dir",
},
{
command: '--sourcemap-use-absolute-path',
name: '--sourcemap-use-absolute-path',
description: 'Report SourceMapURL using its full path',
default: false,
},
{
command: '--assets-dest [string]',
name: '--assets-dest [string]',
description:
'Directory name where to store assets referenced in the bundle',
},
{
command: '--reset-cache',
name: '--reset-cache',
description: 'Removes cached files',
default: false,
},
{
command: '--read-global-cache',
name: '--read-global-cache',
description:
'Try to fetch transformed JS code from the global cache, if configured.',
default: false,
},
{
command: '--config [string]',
name: '--config [string]',
description: 'Path to the CLI configuration file',
parse: (val: string) => path.resolve(val),
},
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/commands/bundle/ramBundle.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export default {
'builds javascript as a "Random Access Module" bundle for offline use',
func: ramBundle,
options: bundleCommandLineArgs.concat({
command: '--indexed-ram-bundle',
name: '--indexed-ram-bundle',
description:
'Force the "Indexed RAM" bundle file format, even when building for android',
default: false,
Expand Down
6 changes: 3 additions & 3 deletions packages/cli/src/commands/init/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ export default {
description: 'initialize new React Native project',
options: [
{
command: '--version [string]',
name: '--version [string]',
description: 'Version of RN',
},
{
command: '--template [string]',
name: '--template [string]',
description: 'Custom template',
},
{
command: '--npm',
name: '--npm',
description: 'Force use of npm during initialization',
},
],
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/commands/library/library.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export default {
description: 'generates a native library bridge',
options: [
{
command: '--name <string>',
name: '--name <string>',
description: 'name of the library to generate',
default: null,
},
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/commands/link/link.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ export default {
name: 'link [packageName]',
options: [
{
command: '--platforms [list]',
name: '--platforms [list]',
description:
'If you want to link dependencies only for specific platforms',
parse: (val: string) => val.toLowerCase().split(','),
Expand Down
Loading

0 comments on commit bca56c9

Please sign in to comment.