Add documentation
Summary: Document Flipper integration with JavaScript clients. Reviewed By: passy Differential Revision: D31827187 fbshipit-source-id: c40d8820241c0f85bd2366a0c087d4270d316c71
This commit is contained in:
committed by
Facebook GitHub Bot
parent
02115722b3
commit
9b16d0c29a
@@ -15,7 +15,7 @@ To build a client plugin, implement the `FlipperPlugin` interface.
|
||||
The ID that is returned from your implementation needs to match the `name` defined in your JavaScript counterpart's `package.json`.
|
||||
|
||||
|
||||
<Tabs defaultValue="android" values={[{label: 'Android', value: 'android'}, { label: 'iOS', value: 'ios'}, { label: 'C++', value: 'cpp'}, { label: 'React Native (JS)', value: 'rn' }]}>
|
||||
<Tabs defaultValue="android" values={[{label: 'Android', value: 'android'}, { label: 'iOS', value: 'ios'}, { label: 'C++', value: 'cpp'}, { label: 'React Native (JS)', value: 'rn' }, { label: 'React (JS)', value: 'js' }]}>
|
||||
<TabItem value="android">
|
||||
|
||||
```java
|
||||
@@ -91,15 +91,54 @@ addPlugin({
|
||||
return 'MyFlipperPlugin';
|
||||
},
|
||||
onConnect(connection) {
|
||||
console.log("connected");
|
||||
console.log('connected');
|
||||
},
|
||||
onDisconnect() {
|
||||
console.log("disconnected");
|
||||
console.log('disconnected');
|
||||
},
|
||||
runInBackground() {
|
||||
return false;
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="js">
|
||||
|
||||
<div class="warning">
|
||||
|
||||
Please note that using Flipper from JavaScript in your browser requires the package [`js-flipper`](https://www.npmjs.com/package/js-flipper) to be installed in the hosting application.
|
||||
|
||||
</div>
|
||||
|
||||
```javascript
|
||||
import {flipperClient} from 'js-flipper';
|
||||
|
||||
// We want to import and start flipper client only in development and test modes
|
||||
// We want to exclude it from our production build
|
||||
let flipperClientPromise;
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
flipperClientPromise = import('js-flipper').then(({flipperClient}) => {
|
||||
flipperClient.start('React Tic-Tac-Toe');
|
||||
return flipperClient;
|
||||
});
|
||||
}
|
||||
|
||||
flipperClientPromise?.then((flipperClient) => {
|
||||
flipperClient.addPlugin({
|
||||
getId() {
|
||||
return 'MyFlipperPlugin';
|
||||
},
|
||||
onConnect(connection) {
|
||||
console.log('connected');
|
||||
},
|
||||
onDisconnect() {
|
||||
console.log('disconnected');
|
||||
},
|
||||
runInBackground() {
|
||||
return false;
|
||||
},
|
||||
});
|
||||
});
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
@@ -109,7 +148,7 @@ addPlugin({
|
||||
|
||||
`onConnect` will be called when your plugin becomes active. This will provide a `FlipperConnection` allowing you to register receivers for desktop method calls and respond with data.
|
||||
|
||||
<Tabs defaultValue="android" values={[{label: 'Android', value: 'android'}, { label: 'iOS', value: 'ios'}, { label: 'C++', value: 'cpp'}, { label: 'React Native (JS)', value: 'rn' }]}>
|
||||
<Tabs defaultValue="android" values={[{label: 'Android', value: 'android'}, { label: 'iOS', value: 'ios'}, { label: 'C++', value: 'cpp'}, { label: 'React Native (JS)', value: 'rn' }, { label: 'React (JS)', value: 'js' }]}>
|
||||
<TabItem value="android">
|
||||
|
||||
```java
|
||||
@@ -171,17 +210,61 @@ addPlugin({
|
||||
return 'MyFlipperPlugin';
|
||||
},
|
||||
onConnect(connection) {
|
||||
console.log("connected");
|
||||
connection.receive("getData", (data, responder) => {
|
||||
console.log("incoming data", data);
|
||||
console.log('connected');
|
||||
connection.receive('getData', (data, responder) => {
|
||||
console.log('incoming data', data);
|
||||
// respond with some data
|
||||
responder.success({
|
||||
ack: true
|
||||
ack: true,
|
||||
});
|
||||
});
|
||||
},
|
||||
// ...as-is
|
||||
})
|
||||
});
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="js">
|
||||
|
||||
```javascript
|
||||
flipperClient.addPlugin({
|
||||
getId() {
|
||||
return 'MyFlipperPlugin';
|
||||
},
|
||||
onConnect(connection) {
|
||||
console.log('connected');
|
||||
connection.receive('getData', (data) => {
|
||||
console.log('incoming data', data);
|
||||
// return data to send it as a response
|
||||
return {
|
||||
ack: true,
|
||||
};
|
||||
});
|
||||
// Flipper client can also send the data you return from your async functions
|
||||
connection.receive('getDataAsync', async (data) => {
|
||||
console.log('incoming data', data);
|
||||
const myAsyncData = await doAsyncStuff();
|
||||
// return data to send it as a response
|
||||
return {
|
||||
data: myAsyncData,
|
||||
};
|
||||
});
|
||||
// Flipper client catches your exceptions and sends them as an error response to the desktop
|
||||
connection.receive('getErrorData', (data) => {
|
||||
console.log('incoming data', data);
|
||||
throw new Error('Ooops');
|
||||
});
|
||||
// It catches the execptions in your async functions as well
|
||||
connection.receive('getErrorDataAsync', async (data) => {
|
||||
console.log('incoming data', data);
|
||||
const myAsyncData = await doAsyncStuff();
|
||||
if (!myAsyncData) {
|
||||
throw new Error('Ooops! Async data is not there!!!');
|
||||
}
|
||||
});
|
||||
},
|
||||
// ...as-is
|
||||
});
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
@@ -191,7 +274,7 @@ addPlugin({
|
||||
|
||||
You don't have to wait for the desktop to request data though, you can also push data directly to the desktop. If the JS plugin subscribes to the same method, it will receive the data.
|
||||
|
||||
<Tabs defaultValue="android" values={[{label: 'Android', value: 'android'}, { label: 'iOS', value: 'ios'}, { label: 'C++', value: 'cpp'}, { label: 'React Native (JS)', value: 'rn' }]}>
|
||||
<Tabs defaultValue="android" values={[{label: 'Android', value: 'android'}, { label: 'iOS', value: 'ios'}, { label: 'C++', value: 'cpp'}, { label: 'React Native (JS)', value: 'rn' }, { label: 'React (JS)', value: 'js' }]}>
|
||||
<TabItem value="android">
|
||||
|
||||
```java
|
||||
@@ -227,11 +310,27 @@ addPlugin({
|
||||
return 'MyFlipperPlugin';
|
||||
},
|
||||
onConnect(connection) {
|
||||
console.log("connected");
|
||||
connection.send("newRow", { message: "Hello" });
|
||||
console.log('connected');
|
||||
connection.send('newRow', {message: 'Hello'});
|
||||
},
|
||||
// ...as-is
|
||||
})
|
||||
});
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="js">
|
||||
|
||||
```javascript
|
||||
flipperClient.addPlugin({
|
||||
getId() {
|
||||
return 'MyFlipperPlugin';
|
||||
},
|
||||
onConnect(connection) {
|
||||
console.log('connected');
|
||||
connection.send('newRow', {message: 'Hello'});
|
||||
},
|
||||
// ...as-is
|
||||
});
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
@@ -299,10 +398,16 @@ Here, `sendData` is an example of a method that might be implemented by the Flip
|
||||
|
||||
### Bi-directional communication demo
|
||||
|
||||
An minimal communication demo can be found in our [Sample project]:
|
||||
An minimal communication demo for Android and iOS can be found in our Sample project:
|
||||
|
||||
* [Desktop implementation](https://github.com/facebook/flipper/blob/main/desktop/plugins/public/example/index.tsx)
|
||||
* [Android implementation](https://github.com/facebook/flipper/blob/main/android/sample/src/debug/java/com/facebook/flipper/plugins/example/ExampleFlipperPlugin.java) / [iOS implementation](https://github.com/facebook/flipper/tree/7bd4f80c2570bebb52af3cf49e45fc6130d6a473/iOS/Plugins/FlipperKitExamplePlugin/FlipperKitExamplePlugin)
|
||||
* [Android](https://github.com/facebook/flipper/blob/main/android/sample/src/debug/java/com/facebook/flipper/plugins/example/ExampleFlipperPlugin.java) / [iOS](https://github.com/facebook/flipper/tree/7bd4f80c2570bebb52af3cf49e45fc6130d6a473/iOS/Plugins/FlipperKitExamplePlugin/FlipperKitExamplePlugin)
|
||||
|
||||
For React Native and JavaScript we have a simple game of Tic Tac Toe:
|
||||
|
||||
* [Desktop implementation](https://github.com/facebook/flipper/blob/main/desktop/plugins/public/rn-tic-tac-toe/index.tsx)
|
||||
* [React Native implementation](https://github.com/facebook/flipper/tree/main/react-native/ReactNativeFlipperExample) / [JavaScript (React) implementation](https://github.com/facebook/flipper/tree/main/js/react-flipper-example)
|
||||
|
||||
|
||||
## Background Plugins
|
||||
|
||||
|
||||
@@ -6,12 +6,13 @@ import useBaseUrl from '@docusaurus/useBaseUrl';
|
||||
|
||||
import FbInstallation from './fb/installation.mdx';
|
||||
|
||||
Flipper helps you debug Android and iOS apps running in an emulator/simulator or connected physical development devices. Flipper consists of two parts:
|
||||
Flipper helps you debug Android, iOS, and even web apps running in an emulator/simulator, connected physical development devices, or in your browser. Flipper consists of two parts:
|
||||
|
||||
- The desktop app
|
||||
- The native mobile SDKs for Android and iOS
|
||||
- The native mobile SDKs for Android and iOS, the client for JavaScript, or even a third-party client you could implement yourself or find on the web
|
||||
|
||||
Once you start Flipper and launch an emulator/simulator or connect a device, you'll start to see the device logs (and any other device-level plugins that work with your device).
|
||||
For web apps, we do not ship any built in plugins yet.
|
||||
|
||||
To see app specific data, you need to integrate the Flipper SDK into your app. See the relevant section in the sidebar for how to do that.
|
||||
|
||||
@@ -21,9 +22,10 @@ To see app specific data, you need to integrate the Flipper SDK into your app. S
|
||||
|
||||
The desktop part of Flipper doesn't need any particular setup. Simply download the latest build for [Mac](https://www.facebook.com/fbflipper/public/mac), [Linux](https://www.facebook.com/fbflipper/public/linux) or [Windows](https://www.facebook.com/fbflipper/public/windows) and launch it. If you're on macOS, you can run `brew install --cask flipper` to let `homebrew` manage installation and upgrades (simply run `brew upgrade` to upgrade when a new version is released, although it might take a few hours up to a day for the package to be upgraded on `homebrew`).
|
||||
|
||||
In order to work properly, Flipper requires a working installation of the Android and (if where applicable) iOS development tools on your system, as well as the [OpenSSL](https://www.openssl.org) binary on your `$PATH`.
|
||||
To work properly with mobile apps, Flipper requires a working installation of the Android and (if where applicable) iOS development tools on your system, as well as the [OpenSSL](https://www.openssl.org) binary on your `$PATH`. A compatible OpenSSL for Windows can be downloaded [here](https://slproweb.com/products/Win32OpenSSL.html) or from Chocolatey with `choco install openssl`.
|
||||
|
||||
If you are hacking a JS app, you should be good to go without any extra dependencies installed.
|
||||
|
||||
A compatible OpenSSL for Windows can be downloaded [here](https://slproweb.com/products/Win32OpenSSL.html) or from Chocolatey with `choco install openssl`.
|
||||
|
||||
</OssOnly>
|
||||
<FbInternalOnly>
|
||||
|
||||
83
docs/getting-started/javascript.mdx
Normal file
83
docs/getting-started/javascript.mdx
Normal file
@@ -0,0 +1,83 @@
|
||||
---
|
||||
id: javascript
|
||||
title: Set up your JavaScript App
|
||||
sidebar_label: JavaScript (browser / Node.js)
|
||||
---
|
||||
import useBaseUrl from '@docusaurus/useBaseUrl';
|
||||
import Link from '@docusaurus/Link';
|
||||
|
||||
To set up Flipper in your JavaScript app, you need to add the neccessary dependencies to your
|
||||
app, initialize the Flipper client and enable the plugins you want to use.
|
||||
|
||||
Currently, we do not ship any plugins for JavaScript environments you can use right away, but we encourage you to <Link to={useBaseUrl("/docs/extending/create-plugin")}>write your own</Link>!
|
||||
|
||||
## Dependencies
|
||||
|
||||
Flipper JavaScript SDK is distiributed via NPM. To add it to your app run:
|
||||
|
||||
```sh
|
||||
npm install js-flipper
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```sh
|
||||
yarn add js-flipper
|
||||
```
|
||||
|
||||
## Application Setup
|
||||
|
||||
Flipper SDK works in browser and Node.js environments. For browsers, it works out-of-the-box as long as your browser supports [WebSockets](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket). For node.js, it requires a compatible WebSocket implementation (e.g. [ws](https://github.com/websockets/ws)).
|
||||
|
||||
You MUST NOT start Flipper client in production. In browser environments, you should think about not including it in the final production build at all.
|
||||
|
||||
Here is how you setup Flipper in your browser:
|
||||
|
||||
```ts
|
||||
import flipperClient from 'js-flipper';
|
||||
|
||||
// Start the client and pass your app name
|
||||
flipperClient.start('My cool browser app');
|
||||
```
|
||||
|
||||
Here is how you can do it in your Node.js app:
|
||||
|
||||
```ts
|
||||
import flipperClient from 'js-flipper';
|
||||
// Say, you decided to go with 'ws' as your WebSocket implementation
|
||||
// https://github.com/websockets/ws
|
||||
import WebSocket from 'ws';
|
||||
|
||||
// Start the client and pass your app name
|
||||
// You might ask yourself why there is the second argument `{ origin: 'localhost:' }`
|
||||
// Flipper Desktop verifies the `Origin` header for every WS connection. You need to set it to one of the whitelisted values (see `VALID_WEB_SOCKET_REQUEST_ORIGIN_PREFIXES`).
|
||||
flipperClient.start('My cool nodejs app', { websocketFactory: url => new WebSocket(url, {origin: 'localhost:'}) });
|
||||
```
|
||||
|
||||
As you can see, `flipperClient` accepts an options object as a second parameter to its `start` method. Here is what you can pass there:
|
||||
|
||||
```ts
|
||||
interface FlipperClientOptions {
|
||||
// Make the client connect to a different URL
|
||||
urlBase?: string;
|
||||
// Override WebSocket implementation (Node.js folks, it is for you!)
|
||||
websocketFactory?: (url: string) => FlipperWebSocket;
|
||||
// Override how errors are handled (it is simple `console.error` by default)
|
||||
onError?: (e: unknown) => void;
|
||||
// Timeout after which client tries to reconnect to Flipper
|
||||
reconnectTimeout?: number;
|
||||
}
|
||||
```
|
||||
|
||||
## Enabling plugins
|
||||
|
||||
Flipper is just a communication channel between the desktop app and your application. Its true power comes from its plugins.
|
||||
|
||||
All plugins must be added to the client. Client communicates the list of available plugins to the desktop upon connection.
|
||||
You can add a plugin by calling:
|
||||
|
||||
```ts
|
||||
flipperClient.addPlugin(/* your plugin */)
|
||||
```
|
||||
|
||||
Chekc out <Link to={useBaseUrl("/docs/extending/create-plugin")}>documentation on creating plugins</Link> to write your own!
|
||||
49
docs/tutorial/javascript.mdx
Normal file
49
docs/tutorial/javascript.mdx
Normal file
@@ -0,0 +1,49 @@
|
||||
---
|
||||
id: javascript
|
||||
title: Building a JavaScript (browser) Plugin
|
||||
---
|
||||
import useBaseUrl from '@docusaurus/useBaseUrl';
|
||||
import Link from '@docusaurus/Link';
|
||||
|
||||
This tutorial requires a browser that supports [WebSockets](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket).
|
||||
|
||||
## Step 1. Install Flipper JavaScript SDK
|
||||
|
||||
Add Flipper client to your web application. Run `npm install js-flipper` (`yarn add js-flipper`)
|
||||
|
||||
## Step 2. Start Flipper client
|
||||
|
||||
<div class="warning">
|
||||
|
||||
Do not start Flipper client in production! Preferably, do not even include Flipper in your production builds!
|
||||
|
||||
</div>
|
||||
|
||||
```tsx file=js/react-flipper-example/src/FlipperTicTacToe.tsx start=DOCS_START_CLIENT_START end=DOCS_START_CLIENT_END
|
||||
```
|
||||
|
||||
## Step 3. Call `addPlugin` to add your plugin
|
||||
|
||||
To register a new plugin with Flipper call `flipperClient.addPlugin` and pass your plugin as an object. Your plugin must conform to the following interface:
|
||||
|
||||
```ts file=js/js-flipper/src/plugin.ts start=DOCS_FLIPPER_PLUGIN_START end=DOCS_FLIPPER_PLUGIN_END
|
||||
```
|
||||
|
||||
These `onConnect` and `onDisconnect` events are triggered every time the plugin becomes (in)active in the Flipper desktop application.
|
||||
If the plugin is a <Link to={useBaseUrl("/docs/extending/create-plugin#background-plugins")}>background plugin</Link>, these events are triggered typically only once (they might be triggered never, if the Desktop user didn't enable the plugin, or multiple times if they enabled or disabled the plugin a few times).
|
||||
|
||||
The `onConnect` callback receive a `connection` which can be used to communicate with the backend:
|
||||
|
||||
```tsx file=js/react-flipper-example/src/FlipperTicTacToe.tsx start=DOCS_ADD_PLUGIN_START end=DOCS_ADD_PLUGIN_END
|
||||
```
|
||||
|
||||
You might want to store the connection somewhere to be able to send more events as long as `onDisconnect` event hasn't been fired.
|
||||
|
||||
The `connection` object can also be used to listen to messages coming from the Desktop plugin. See <Link to={useBaseUrl("/docs/extending/create-plugin")}>Client Plugin API</Link> for details.
|
||||
|
||||
## Live demo
|
||||
|
||||
An example plugin to play a little Tic-Tac-Toe between the Flipper Desktop and a React app can be found inside this repository as well (run `yarn && yarn start` in `js/react-flipper-example` to start the test project):
|
||||
|
||||
* The React plugin implementation: [FlipperTicTacToe.tsx](https://github.com/facebook/flipper/tree/main/js/react-flipper-example/src/FlipperTicTacToe.tsx)
|
||||
* The Flipper Desktop plugin implementation: [rn-tic-tac-toe/index.tsx](https://github.com/facebook/flipper/blob/main/desktop/plugins/public/rn-tic-tac-toe/index.tsx)
|
||||
Reference in New Issue
Block a user