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:
Andrey Goncharov
2022-06-01 02:49:25 -07:00
committed by Facebook GitHub Bot
parent ee64216725
commit 055b14c6dd
5 changed files with 40 additions and 6 deletions

View File

@@ -11,7 +11,12 @@ import {FlipperConnection} from './connection';
import {FlipperRequest, FlipperResponse} from './message';
import {FlipperPlugin} from './plugin';
import {FlipperResponder} from './responder';
import {assert, detectDevice, detectOS} from './util';
import {
assert,
detectDevice,
detectOS,
getDeviceId as getDeviceIdDefault,
} from './util';
import {RECONNECT_TIMEOUT} from './consts';
// TODO: Share with flipper-server-core
@@ -133,13 +138,15 @@ interface FlipperClientOptions {
onError?: (e: unknown) => void;
// Timeout after which client tries to reconnect to Flipper
reconnectTimeout?: number;
// Set device ID. Default: random ID persisted to local storage.
getDeviceId?: () => Promise<string> | string;
}
export class FlipperClient {
private readonly plugins: Map<string, FlipperPlugin> = new Map();
private readonly connections: Map<string, FlipperConnection> = new Map();
private ws?: FlipperWebSocket;
private readonly devicePseudoId = `${Date.now()}.${Math.random()}`;
private deviceId!: string;
private readonly os = detectOS();
private readonly device = detectDevice();
private reconnectionTimer?: NodeJS.Timeout;
@@ -171,12 +178,14 @@ export class FlipperClient {
websocketFactory = (url) => new WebSocket(url) as FlipperWebSocket,
onError = (e) => console.error('WebSocket error', e),
reconnectTimeout = RECONNECT_TIMEOUT,
getDeviceId = getDeviceIdDefault,
}: FlipperClientOptions = {},
): Promise<void> {
if (this.ws) {
return;
}
this.deviceId = await getDeviceId();
this.appName = appName;
this.onError = onError;
this.urlBase = urlBase;
@@ -218,7 +227,7 @@ export class FlipperClient {
}
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);
this.ws = this.websocketFactory(encodedUrl);

View File

@@ -8,3 +8,4 @@
*/
export const RECONNECT_TIMEOUT = 1000;
export const DEVICE_ID_STORAGE_KEY = 'js-flipper-device-id';

View File

@@ -9,6 +9,7 @@
import {FlipperClient} from './client';
export * from './consts';
export * from './client';
export * from './plugin';

View File

@@ -7,6 +7,8 @@
* @format
*/
import {DEVICE_ID_STORAGE_KEY} from './consts';
// https://github.com/microsoft/TypeScript/issues/36931#issuecomment-846131999
type Assert = (condition: unknown) => asserts condition;
export const assert: Assert = (condition) => {
@@ -66,3 +68,22 @@ export const detectDevice = (): string => {
}
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;
};