Make flipper messages generally available, remove self inspection infra structure
Summary: Changelog: Flipper message debugging moved from a separate device to the console tab This makes message debugging easier accessible, and in production (recently requested at GH). Also it clears up a lot of infra that was created just to make flipper a self recursive inspection device + a separate plugin. While fun, a hardcoded setup is just a bit more simpler (no exception rules and better static verification) Reviewed By: nikoant Differential Revision: D29487811 fbshipit-source-id: b412adc3ef5bd831001333443b432b6c0f934a5e
This commit is contained in:
committed by
Facebook GitHub Bot
parent
8da7495a1a
commit
328ba9513c
@@ -9,7 +9,7 @@
|
||||
|
||||
import {notification, Typography} from 'antd';
|
||||
import React from 'react';
|
||||
import {ConsoleLogs} from '../chrome/ConsoleLogs';
|
||||
import {FlipperDevTools} from '../chrome/FlipperDevTools';
|
||||
import {setStaticView} from '../reducers/connections';
|
||||
import {getStore} from '../store';
|
||||
import {Layout} from '../ui';
|
||||
@@ -29,7 +29,7 @@ export function showErrorNotification(message: string, description?: string) {
|
||||
See{' '}
|
||||
<Link
|
||||
onClick={() => {
|
||||
getStore().dispatch(setStaticView(ConsoleLogs));
|
||||
getStore().dispatch(setStaticView(FlipperDevTools));
|
||||
notification.close(key);
|
||||
}}>
|
||||
logs
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
import {FlipperConnection, FlipperPlugin} from 'flipper-client-sdk';
|
||||
|
||||
export type MessageInfo = {
|
||||
device?: string;
|
||||
app: string;
|
||||
flipperInternalMethod?: string;
|
||||
plugin?: string;
|
||||
pluginMethod?: string;
|
||||
payload?: any;
|
||||
direction:
|
||||
| 'toClient:call'
|
||||
| 'toClient:send'
|
||||
| 'toFlipper:message'
|
||||
| 'toFlipper:response';
|
||||
};
|
||||
|
||||
export class FlipperMessagesClientPlugin implements FlipperPlugin {
|
||||
protected connection: FlipperConnection | null = null;
|
||||
|
||||
onConnect(connection: FlipperConnection): void {
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
onDisconnect(): void {
|
||||
this.connection = null;
|
||||
}
|
||||
|
||||
getId(): string {
|
||||
return 'flipper-messages';
|
||||
}
|
||||
|
||||
runInBackground(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
newMessage(message: MessageInfo) {
|
||||
this.connection?.send('newMessage', message);
|
||||
}
|
||||
|
||||
isConnected() {
|
||||
return this.connection != null;
|
||||
}
|
||||
}
|
||||
|
||||
export const flipperMessagesClientPlugin = new FlipperMessagesClientPlugin();
|
||||
@@ -1,117 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
import {FlipperClientConnection} from '../../Client';
|
||||
import {Flowable, Single} from 'rsocket-flowable';
|
||||
import {Payload, ConnectionStatus, ISubscriber} from 'rsocket-types';
|
||||
|
||||
import {FlipperClient} from 'flipper-client-sdk';
|
||||
|
||||
// somehow linter isn't happy with next import so type definitions are copied
|
||||
// import {IFutureSubject} from 'rsocket-flowable/Single';
|
||||
|
||||
type CancelCallback = () => void;
|
||||
|
||||
interface IFutureSubject<T> {
|
||||
onComplete: (value: T) => void;
|
||||
onError: (error: Error) => void;
|
||||
onSubscribe: (cancel: CancelCallback | null | undefined) => void;
|
||||
}
|
||||
|
||||
export class SelfInspectionFlipperClient<M>
|
||||
extends FlipperClient
|
||||
implements FlipperClientConnection<string, M>
|
||||
{
|
||||
connStatusSubscribers: Set<ISubscriber<ConnectionStatus>> = new Set();
|
||||
connStatus: ConnectionStatus = {kind: 'CONNECTED'};
|
||||
|
||||
connectionStatus(): Flowable<ConnectionStatus> {
|
||||
return new Flowable<ConnectionStatus>((subscriber) => {
|
||||
subscriber.onSubscribe({
|
||||
cancel: () => {
|
||||
this.connStatusSubscribers.delete(subscriber);
|
||||
},
|
||||
request: (_) => {
|
||||
this.connStatusSubscribers.add(subscriber);
|
||||
subscriber.onNext(this.connStatus);
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
close(): void {
|
||||
this.connStatus = {kind: 'CLOSED'};
|
||||
this.connStatusSubscribers.forEach((subscriber) => {
|
||||
subscriber.onNext(this.connStatus);
|
||||
});
|
||||
}
|
||||
|
||||
fireAndForget(payload: Payload<string, M>): void {
|
||||
if (payload.data == null) {
|
||||
return;
|
||||
}
|
||||
const message = JSON.parse(payload.data) as {
|
||||
method: string;
|
||||
id: number;
|
||||
params: any;
|
||||
};
|
||||
this.onMessageReceived(message);
|
||||
}
|
||||
|
||||
activeRequests = new Map<number, IFutureSubject<Payload<string, M>>>();
|
||||
|
||||
requestResponse(payload: Payload<string, M>): Single<Payload<string, M>> {
|
||||
return new Single((subscriber) => {
|
||||
subscriber.onSubscribe(() => {});
|
||||
if (payload.data == null) {
|
||||
subscriber.onError(new Error('empty payload'));
|
||||
return;
|
||||
}
|
||||
const message = JSON.parse(payload.data) as {
|
||||
method: string;
|
||||
id: number;
|
||||
params: any;
|
||||
};
|
||||
this.activeRequests.set(message.id, subscriber);
|
||||
this.onMessageReceived(message);
|
||||
});
|
||||
}
|
||||
|
||||
// Client methods
|
||||
|
||||
messagesHandler: ((message: any) => void) | undefined;
|
||||
|
||||
start(_appName: string): void {
|
||||
this.onConnect();
|
||||
}
|
||||
|
||||
stop(): void {}
|
||||
|
||||
sendData(payload: any): void {
|
||||
if (payload['success'] != null) {
|
||||
const message = payload as {id: number; success: unknown};
|
||||
const sub = this.activeRequests.get(message.id);
|
||||
sub?.onComplete({data: JSON.stringify(message)});
|
||||
this.activeRequests.delete(message.id);
|
||||
return;
|
||||
}
|
||||
|
||||
this.messagesHandler && this.messagesHandler(payload);
|
||||
}
|
||||
|
||||
isAvailable(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
subscibeForClientMessages(handler: (message: any) => void) {
|
||||
this.messagesHandler = handler;
|
||||
}
|
||||
}
|
||||
|
||||
export const selfInspectionClient = new SelfInspectionFlipperClient();
|
||||
@@ -1,94 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
import Client, {ClientQuery} from '../../Client';
|
||||
import {FlipperClientConnection} from '../../Client';
|
||||
import {Store} from '../../reducers';
|
||||
import {Logger} from '../../fb-interfaces/Logger';
|
||||
|
||||
import Server from '../../server';
|
||||
import {buildClientId} from '../clientUtils';
|
||||
import {selfInspectionClient} from './selfInspectionClient';
|
||||
import {flipperMessagesClientPlugin} from './plugins/FlipperMessagesClientPlugin';
|
||||
import {destroyDevice} from '../../reducers/connections';
|
||||
|
||||
export function initSelfInpector(
|
||||
store: Store,
|
||||
logger: Logger,
|
||||
flipperServer: Server,
|
||||
flipperConnections: Map<
|
||||
string,
|
||||
{
|
||||
connection: FlipperClientConnection<any, any> | null | undefined;
|
||||
client: Client;
|
||||
}
|
||||
>,
|
||||
) {
|
||||
const appName = 'Flipper';
|
||||
|
||||
selfInspectionClient.addPlugin(flipperMessagesClientPlugin);
|
||||
const hostDevice = store
|
||||
.getState()
|
||||
.connections.devices.find((d) => d.serial === '');
|
||||
if (!hostDevice) {
|
||||
console.error('Failed to find host device for self inspector');
|
||||
return;
|
||||
}
|
||||
|
||||
const query: ClientQuery = {
|
||||
app: appName,
|
||||
os: 'MacOS',
|
||||
device: 'emulator',
|
||||
device_id: '',
|
||||
sdk_version: 4,
|
||||
};
|
||||
const clientId = buildClientId(query);
|
||||
|
||||
const client = new Client(
|
||||
clientId,
|
||||
query,
|
||||
selfInspectionClient,
|
||||
logger,
|
||||
store,
|
||||
undefined,
|
||||
hostDevice,
|
||||
);
|
||||
|
||||
flipperConnections.set(clientId, {
|
||||
connection: selfInspectionClient,
|
||||
client: client,
|
||||
});
|
||||
|
||||
selfInspectionClient.connectionStatus().subscribe({
|
||||
onNext(payload) {
|
||||
if (payload.kind == 'ERROR' || payload.kind == 'CLOSED') {
|
||||
console.debug(`Device disconnected ${client.id}`, 'server');
|
||||
flipperServer.removeConnection(client.id);
|
||||
destroyDevice(store, logger, client.id);
|
||||
}
|
||||
},
|
||||
onSubscribe(subscription) {
|
||||
subscription.request(Number.MAX_SAFE_INTEGER);
|
||||
},
|
||||
});
|
||||
|
||||
client.init().then(() => {
|
||||
flipperServer.emit('new-client', client);
|
||||
flipperServer.emit('clients-change');
|
||||
client.emit('plugins-change');
|
||||
|
||||
selfInspectionClient.subscibeForClientMessages((payload: any) => {
|
||||
// let's break the possible recursion problems here
|
||||
// for example we want to send init plugin message, but store state is being updated when we enable plugins
|
||||
setImmediate(() => {
|
||||
client.onMessage(JSON.stringify(payload));
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user