Summary: Noticed some broken links while converting plugins Reviewed By: priteshrnandgaonkar Differential Revision: D27997670 fbshipit-source-id: fd2715db010a042f749e0908b44a3fb3c6aa6f18
256 lines
10 KiB
Plaintext
256 lines
10 KiB
Plaintext
---
|
|
id: desktop-plugin-structure
|
|
title: Plugin structure
|
|
---
|
|
|
|
import FbNpmDeps from '../fb/adding-npm-dependencies-0.mdx'
|
|
import FbOnlyParts from '../fb/fb-only-parts-in-os-plugins.mdx'
|
|
|
|
Flipper Desktop plugins have a rigid structure. We recommend to scaffold any new plugin using our scaffolding tooling.
|
|
|
|
## Scaffolding a new plugin
|
|
|
|
<OssOnly>
|
|
|
|
### flipper-pkg
|
|
|
|
The CLI tool `flipper-pkg` helps to initialize, validate, and package Flipper desktop plugins.
|
|
|
|
To scaffold a new plugin run `npx flipper-pkg init` in the directory where you want to store the plugin sources.
|
|
Note that this should typically _not_ be inside a Flipper checkout, but rather a fresh directory which you can put under your own source control.
|
|
|
|
</OssOnly>
|
|
|
|
<FbInternalOnly>
|
|
|
|
### scarf flipper-plugin
|
|
|
|
On a FB machine, new plugins can be scaffolded by running `scarf flipper-plugin`.
|
|
This takes care of both the Desktop and Client side setup of plugins.
|
|
Follow the instructions offered by scarf.
|
|
|
|
</FbInternalOnly>
|
|
|
|
## Desktop Plugin structure
|
|
|
|
All Flipper Desktop plugins must be self-contained in a directory. This directory must contain at a minimum package.json and entry source file, e.g.:
|
|
* package.json
|
|
* src/index.tsx
|
|
|
|
After scaffolding a new plugin has finished, you should have files `package.json` and `src/index.tsx` files in the directory. The first file is the plugin package manifest and the second is the entry point to your plugin. An example `package.json` file could look like this:
|
|
|
|
```json
|
|
{
|
|
"$schema": "https://fbflipper.com/schemas/plugin-package/v2.json",
|
|
"name": "flipper-plugin-myplugin",
|
|
"id": "myplugin",
|
|
"pluginType": "client",
|
|
"version": "1.0.0",
|
|
"main": "dist/bundle.js",
|
|
"flipperBundlerEntry": "src/index.tsx",
|
|
"license": "MIT",
|
|
"keywords": ["flipper-plugin"],
|
|
"title": "My Plugin",
|
|
"icon": "apps",
|
|
"bugs": {
|
|
"email": "you@example.com"
|
|
},
|
|
"scripts": {
|
|
"lint": "flipper-pkg lint",
|
|
"prepack": "flipper-pkg lint && flipper-pkg bundle"
|
|
},
|
|
"peerDependencies": {
|
|
"flipper": "latest",
|
|
"flipper-plugin": "latest"
|
|
},
|
|
"devDependencies": {
|
|
"flipper": "latest",
|
|
"flipper-plugin": "latest",
|
|
"flipper-pkg": "latest",
|
|
"react": "latest",
|
|
"antd": "latest
|
|
}
|
|
}
|
|
```
|
|
|
|
Important attributes of `package.json`:
|
|
|
|
- `$schema` must contain URI identifying scheme according to which the plugin is defined. Currently, Flipper supports plugins defined by the specification version 2 (https://fbflipper.com/schemas/plugin-package/v2.json), while version 1 is being deprecated.
|
|
|
|
- `name` Npm package name. Should start with `flipper-plugin-` by convention, so Flipper plugins can be easily found on npm.
|
|
|
|
- `id` Used as the plugin native identifier and **must match the mobile plugin identifier**, e.g. returned by `getId` method of your Java plugin.
|
|
|
|
- `pluginType` Specifies type of the plugin - client or device. See section [Anatomy of a Desktop plugin](#anatomy-of-a-desktop-plugin) for details.
|
|
|
|
- `main` Points to the plugin bundle which will be loaded by Flipper. The "flipper-pkg" utility uses this field to determine output location during plugin bundling.
|
|
|
|
- `flipperBundlerEntry` Points to the source entry point which will be used for plugin code bundling. "flipper-pkg" takes the path specified in `flipperBundlerEntry` as source, transpiles and bundles it, and saves the output to the path specified in `main`.
|
|
|
|
- `keywords` The field must contain the `flipper-plugin` keyword, otherwise Flipper won't discover the plugin. Additionally, the field can also contain any other keywords for better plugin discoverability.
|
|
|
|
- `title` Shown in the main sidebar as the human-readable name of the plugin.
|
|
|
|
- `icon` Determines the plugin icon which is displayed in the main sidebar. The list of available icons is static for now: https://github.com/facebook/flipper/blob/master/desktop/static/icons.json.
|
|
|
|
- `bugs` Specify an email and/or url, where plugin bugs should be reported.
|
|
|
|
In `index.tsx` you will define the plugin in JavaScript.
|
|
|
|
Example `index.tsx`:
|
|
|
|
```js
|
|
export function plugin(client) {
|
|
return {};
|
|
}
|
|
|
|
export function Component() {
|
|
return 'hello world';
|
|
}
|
|
```
|
|
|
|
Some public plugins will use a `FlipperPlugin` base class. This format is deprecated but the documentation can still be found [here](./js-plugin-api.mdx).
|
|
|
|
## Anatomy of a Desktop plugin
|
|
|
|
Flipper Desktop plugins come in three possible flavors:
|
|
|
|
1. Client plugins: A plugin that connects to a specific client plugin running in an app (recommended)
|
|
2. Device plugins: A plugin that doesn't connect to a specific client and doesn't have a native counter part, but rather shows data about the device obtained through some other means, like device logs, device temperatures, etc.
|
|
3. Table plugin: A simplified version of a client plugin, that merely displays incoming data from a client plugin in a table.
|
|
|
|
### Creating a Client Plugin
|
|
|
|
A plugin always exposes two elements from its entry module (typically `src/index.tsx`): `plugin` and `Component`:
|
|
|
|
```tsx
|
|
import {PluginClient} from 'flipper-plugin';
|
|
|
|
export function plugin(client: PluginClient) {
|
|
return {}; // API exposed from this plugin
|
|
}
|
|
|
|
export function Component() {
|
|
// Plugin UI
|
|
return <h1>Welcome to my first plugin</h1>;
|
|
}
|
|
```
|
|
|
|
A further guide on how to write custom Flipper plugins can be found here: [tutorial](../tutorial/js-custom.mdx).
|
|
|
|
### Creating a Device Plugin
|
|
|
|
Flipper also supports so-called device plugins - plugins that are available for an entire device - but don't receive a connection to a running app,
|
|
so are a bit more limited in general.
|
|
Their entry module anatomy is:
|
|
|
|
```tsx
|
|
import {DevicePluginClient} from 'flipper-plugin';
|
|
|
|
export function devicePlugin(client: DevicePluginClient) {
|
|
return {}; // API exposed from this plugin
|
|
}
|
|
|
|
export function Component() {
|
|
// Plugin UI
|
|
return <h1>Welcome to my first plugin</h1>;
|
|
}
|
|
```
|
|
|
|
Desktop plugins must have the property `pluginType` set to `device` in their package.json. They should also specify supported devices using property `supportedDevices`
|
|
in package.json. The property should contain an array of supported devices each defined as conjunction of device properties in the following format:
|
|
`{ "os": <"Android" | "iOS" | "Metro">, "type": <"physical" | "emulator">, "archived": <true | false> }`. For example: `{ "os": "Android", "type": "emulator" }` means
|
|
that device must work on Android AND must be an emulator in order to debug it using the plugin.
|
|
To specify that plugin supports all types of Android devices, and physical iOS devices, and does not support imported (archived) data, the plugin package.json should look like that:
|
|
```json
|
|
{
|
|
"$schema": "https://fbflipper.com/schemas/plugin-package/v2.json",
|
|
"name": "flipper-plugin-mydeviceplugin",
|
|
"id": "mydeviceplugin",
|
|
"pluginType": "device",
|
|
"supportedDevices": [
|
|
{"os": "Android", "archived": false},
|
|
{"os": "iOS", "type": "physical", "archived": false}
|
|
]
|
|
...
|
|
}
|
|
```
|
|
|
|
Device plugins work in general similar to normal client plugins, so aren't worked out in detail in this document.
|
|
The available APIs for device plugins are listed [here](./flipper-plugin.mdx#devicepluginclient).
|
|
|
|
### Creating a simple table plugin
|
|
|
|
Flipper provides a standard abstraction to render data received from a Client plugin in a table, see [creating a table plugin](./create-table-plugin.mdx).
|
|
|
|
|
|
## Validation
|
|
|
|
<OssOnly>
|
|
|
|
Plugin definition can be validated using command `flipper-pkg lint`. The command shows all the mismatches which should be fixed to make plugin definition valid.
|
|
|
|
</OssOnly>
|
|
|
|
<FbInternalOnly>
|
|
|
|
Make sure to address any lint errors shown in the IDE or surfaced on phabricator.
|
|
To manually run the linter run `yarn lint` in `~/fbsource/xplat/sonar/desktop`.
|
|
|
|
</FbInternalOnly>
|
|
|
|
<OssOnly>
|
|
|
|
## Transpilation and bundling
|
|
|
|
Flipper has [tooling for transpiling and bundling](#transpiling-and-bundling) which allows writing plugins in plain ES6 JavaScript or [TypeScript](https://www.typescriptlang.org/).
|
|
We recommend you use **TypeScript** for the best development experience. We also recommend you use the file extension `.tsx` when using TypeScript which adds support for inline React expressions.
|
|
|
|
As we already mentioned, the [Flipper development build](#development-build) automatically transpiles and bundles plugins on loading. It is capable of all the ES6 goodness, Flow annotations, TypeScript, as well as JSX and applies the required babel-transforms.
|
|
|
|
The Flipper release build, in contrast, does not transpile or bundle plugins on loading. For production usage, plugins should be [bundled before publishing](#packaging-and-publishing) using [flipper-pkg](https://classic.yarnpkg.com/en/package/flipper-pkg). This utility applies the same modifications as the plugin loader of the development build.
|
|
|
|
The `flipper-pkg` tool is published to npm and should be installed as a `devDependency` for the plugin package.
|
|
|
|
Then, to bundle the plugin, execute the following command in its folder:
|
|
|
|
```
|
|
yarn flipper-pkg bundle
|
|
```
|
|
|
|
This command reads the `package.json`, takes the path specified in the `flipperBundleEntry` field as entry point, transpiles and bundles all the required code, and outputs the produced bundle to the path specified in field `main`.
|
|
|
|
You can get the list of other available commands by invoking `flipper-pkg help`, and get detailed description for any command by invoking `flipper-pkg help [COMMAND]`. You can also check README on npmjs.com for usage details: https://www.npmjs.com/package/flipper-pkg.
|
|
|
|
</OssOnly>
|
|
|
|
## npm dependencies
|
|
|
|
<OssOnly>
|
|
|
|
If you need any dependencies in your plugin, you can install them using `yarn add`.
|
|
|
|
</OssOnly>
|
|
|
|
<FbNpmDeps />
|
|
|
|
<OssOnly>
|
|
|
|
## Migration to new Plugin Specification
|
|
|
|
Flipper plugins are defined according to the specification. As with any specification, it is evolving, so new versions of it can be released. Currently Flipper supports plugins defined using version 2 of specification which is described in this page. Previous version of specification is being deprecated, and we encourage all the plugins still using it to migrate.
|
|
|
|
The main difference of version 2 is that plugins are transpiled and bundled before packaging, while in version 1 this was done in run-time on plugin installation. There are no plugin API changes, so only the `package.json` changes are required to migrate.
|
|
|
|
The easiest way for migration is using of command `flipper-pkg migrate`. It will automatically migrate your plugin definition to the latest version.
|
|
|
|
</OssOnly>
|
|
|
|
<FbInternalOnly>
|
|
|
|
## Adding fb-only code to open-sourced plugins
|
|
|
|
<FbOnlyParts />
|
|
|
|
</FbInternalOnly>
|