Persist device ID
Summary: Linked to https://github.com/facebook/flipper/issues/3319 Reviewed By: passy Differential Revision: D36786952 fbshipit-source-id: f3214f35039845a8e35fa14e63f509a6fbdddb1f
This commit is contained in:
committed by
Facebook GitHub Bot
parent
ee64216725
commit
055b14c6dd
@@ -24,8 +24,8 @@ if the corresponding desktop plugin is selected in the Flipper Desktop. The full
|
|||||||
plugin API is documented
|
plugin API is documented
|
||||||
[here](https://fbflipper.com/docs/extending/create-plugin).
|
[here](https://fbflipper.com/docs/extending/create-plugin).
|
||||||
- `start` method. It starts the client. It has two arguments:
|
- `start` method. It starts the client. It has two arguments:
|
||||||
- `appName` - (required) the name dsplayed in Flipper
|
- `appName` - (required) the name displayed in Flipper
|
||||||
- `options` which conforms to the infterface
|
- `options` which conforms to the interface
|
||||||
```ts
|
```ts
|
||||||
interface FlipperClientOptions {
|
interface FlipperClientOptions {
|
||||||
// Make the client connect to a different URL
|
// Make the client connect to a different URL
|
||||||
@@ -36,6 +36,8 @@ plugin API is documented
|
|||||||
onError?: (e: unknown) => void;
|
onError?: (e: unknown) => void;
|
||||||
// Timeout after which client tries to reconnect to Flipper
|
// Timeout after which client tries to reconnect to Flipper
|
||||||
reconnectTimeout?: number;
|
reconnectTimeout?: number;
|
||||||
|
// Set device ID. Default: random ID persisted to local storage.
|
||||||
|
getDeviceId?: () => Promise<string> | string
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -54,7 +56,7 @@ The sources of the corresponding Desktop plugin can be found
|
|||||||
## Node.js
|
## Node.js
|
||||||
|
|
||||||
Node.js does not have a built-in WebSocket implementation. You need to install
|
Node.js does not have a built-in WebSocket implementation. You need to install
|
||||||
any implmentation of WebSockets for Node.js that is compatible with the
|
any implementation of WebSockets for Node.js that is compatible with the
|
||||||
interface of the
|
interface of the
|
||||||
[web version](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket).
|
[web version](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket).
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,12 @@ import {FlipperConnection} from './connection';
|
|||||||
import {FlipperRequest, FlipperResponse} from './message';
|
import {FlipperRequest, FlipperResponse} from './message';
|
||||||
import {FlipperPlugin} from './plugin';
|
import {FlipperPlugin} from './plugin';
|
||||||
import {FlipperResponder} from './responder';
|
import {FlipperResponder} from './responder';
|
||||||
import {assert, detectDevice, detectOS} from './util';
|
import {
|
||||||
|
assert,
|
||||||
|
detectDevice,
|
||||||
|
detectOS,
|
||||||
|
getDeviceId as getDeviceIdDefault,
|
||||||
|
} from './util';
|
||||||
import {RECONNECT_TIMEOUT} from './consts';
|
import {RECONNECT_TIMEOUT} from './consts';
|
||||||
|
|
||||||
// TODO: Share with flipper-server-core
|
// TODO: Share with flipper-server-core
|
||||||
@@ -133,13 +138,15 @@ interface FlipperClientOptions {
|
|||||||
onError?: (e: unknown) => void;
|
onError?: (e: unknown) => void;
|
||||||
// Timeout after which client tries to reconnect to Flipper
|
// Timeout after which client tries to reconnect to Flipper
|
||||||
reconnectTimeout?: number;
|
reconnectTimeout?: number;
|
||||||
|
// Set device ID. Default: random ID persisted to local storage.
|
||||||
|
getDeviceId?: () => Promise<string> | string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class FlipperClient {
|
export class FlipperClient {
|
||||||
private readonly plugins: Map<string, FlipperPlugin> = new Map();
|
private readonly plugins: Map<string, FlipperPlugin> = new Map();
|
||||||
private readonly connections: Map<string, FlipperConnection> = new Map();
|
private readonly connections: Map<string, FlipperConnection> = new Map();
|
||||||
private ws?: FlipperWebSocket;
|
private ws?: FlipperWebSocket;
|
||||||
private readonly devicePseudoId = `${Date.now()}.${Math.random()}`;
|
private deviceId!: string;
|
||||||
private readonly os = detectOS();
|
private readonly os = detectOS();
|
||||||
private readonly device = detectDevice();
|
private readonly device = detectDevice();
|
||||||
private reconnectionTimer?: NodeJS.Timeout;
|
private reconnectionTimer?: NodeJS.Timeout;
|
||||||
@@ -171,12 +178,14 @@ export class FlipperClient {
|
|||||||
websocketFactory = (url) => new WebSocket(url) as FlipperWebSocket,
|
websocketFactory = (url) => new WebSocket(url) as FlipperWebSocket,
|
||||||
onError = (e) => console.error('WebSocket error', e),
|
onError = (e) => console.error('WebSocket error', e),
|
||||||
reconnectTimeout = RECONNECT_TIMEOUT,
|
reconnectTimeout = RECONNECT_TIMEOUT,
|
||||||
|
getDeviceId = getDeviceIdDefault,
|
||||||
}: FlipperClientOptions = {},
|
}: FlipperClientOptions = {},
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
if (this.ws) {
|
if (this.ws) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.deviceId = await getDeviceId();
|
||||||
this.appName = appName;
|
this.appName = appName;
|
||||||
this.onError = onError;
|
this.onError = onError;
|
||||||
this.urlBase = urlBase;
|
this.urlBase = urlBase;
|
||||||
@@ -218,7 +227,7 @@ export class FlipperClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private connectToFlipper() {
|
private connectToFlipper() {
|
||||||
const url = `ws://${this.urlBase}?device_id=${this.device}${this.devicePseudoId}&device=${this.device}&app=${this.appName}&os=${this.os}`;
|
const url = `ws://${this.urlBase}?device_id=${this.device}${this.deviceId}&device=${this.device}&app=${this.appName}&os=${this.os}`;
|
||||||
const encodedUrl = encodeURI(url);
|
const encodedUrl = encodeURI(url);
|
||||||
|
|
||||||
this.ws = this.websocketFactory(encodedUrl);
|
this.ws = this.websocketFactory(encodedUrl);
|
||||||
|
|||||||
@@ -8,3 +8,4 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
export const RECONNECT_TIMEOUT = 1000;
|
export const RECONNECT_TIMEOUT = 1000;
|
||||||
|
export const DEVICE_ID_STORAGE_KEY = 'js-flipper-device-id';
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
import {FlipperClient} from './client';
|
import {FlipperClient} from './client';
|
||||||
|
|
||||||
|
export * from './consts';
|
||||||
export * from './client';
|
export * from './client';
|
||||||
export * from './plugin';
|
export * from './plugin';
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,8 @@
|
|||||||
* @format
|
* @format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import {DEVICE_ID_STORAGE_KEY} from './consts';
|
||||||
|
|
||||||
// https://github.com/microsoft/TypeScript/issues/36931#issuecomment-846131999
|
// https://github.com/microsoft/TypeScript/issues/36931#issuecomment-846131999
|
||||||
type Assert = (condition: unknown) => asserts condition;
|
type Assert = (condition: unknown) => asserts condition;
|
||||||
export const assert: Assert = (condition) => {
|
export const assert: Assert = (condition) => {
|
||||||
@@ -66,3 +68,22 @@ export const detectDevice = (): string => {
|
|||||||
}
|
}
|
||||||
return require('os').release();
|
return require('os').release();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getDeviceId = () => {
|
||||||
|
// localStorage is not defined in Node.js env
|
||||||
|
const persistedId =
|
||||||
|
typeof localStorage === 'object'
|
||||||
|
? localStorage?.getItem(DEVICE_ID_STORAGE_KEY)
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
if (persistedId) {
|
||||||
|
return persistedId;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newId = `${Date.now()}.${Math.random()}`;
|
||||||
|
if (typeof localStorage === 'object') {
|
||||||
|
localStorage?.setItem(DEVICE_ID_STORAGE_KEY, newId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return newId;
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user