Summary:
This diff adds the capability to export the flipper data to a file. With this diff you can click on the "Export Flipper" option from the "Edit" menu in menubar. It will export it in the file at this location
`~/.flipper/MessageLogs.json`
We do not exactly export the store, but just the important part of it. We export in the following format
```
{
fileVersion: '1.0',
device: {
os: 'iOS',
title: 'iPhone 7',
serial: '',
deviceType: 'physical',
},
clients: [
{
query: {
app: 'Facebook',
},
d: '12345678'
},
{
query: {
app: 'Instagram',
},
id: '12345678'
}
],
store: {
pluginState: {},
notifications: {}
}
}
```
In next diff I will add the capability to select the folder to export the file too.
Reviewed By: danielbuechele
Differential Revision: D13751963
fbshipit-source-id: 7d3d49c6adf8145b2181d2332c7dbd589155cec3
177 lines
5.0 KiB
JavaScript
177 lines
5.0 KiB
JavaScript
/**
|
|
* Copyright 2018-present Facebook.
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
* @format
|
|
*/
|
|
|
|
import type {Store} from '../reducers/index.js';
|
|
import type Logger from '../fb-stubs/Logger.js';
|
|
import type {FlipperPlugin, FlipperDevicePlugin} from '../plugin.js';
|
|
import type {State} from '../reducers/plugins';
|
|
|
|
import React from 'react';
|
|
import ReactDOM from 'react-dom';
|
|
import * as Flipper from '../index.js';
|
|
import {
|
|
registerPlugins,
|
|
addGatekeepedPlugins,
|
|
addDisabledPlugins,
|
|
addFailedPlugins,
|
|
} from '../reducers/plugins';
|
|
import {remote} from 'electron';
|
|
import GK from '../fb-stubs/GK';
|
|
import {FlipperBasePlugin} from '../plugin.js';
|
|
import {setupMenuBar} from '../MenuBar.js';
|
|
|
|
export type PluginDefinition = {
|
|
name: string,
|
|
out: string,
|
|
gatekeeper?: string,
|
|
entry?: string,
|
|
};
|
|
|
|
export default (store: Store, logger: Logger) => {
|
|
// expose Flipper and exact globally for dynamically loaded plugins
|
|
const globalObject = typeof window === 'undefined' ? global : window;
|
|
globalObject.React = React;
|
|
globalObject.ReactDOM = ReactDOM;
|
|
globalObject.Flipper = Flipper;
|
|
|
|
const gatekeepedPlugins: Array<PluginDefinition> = [];
|
|
const disabledPlugins: Array<PluginDefinition> = [];
|
|
const failedPlugins: Array<[PluginDefinition, string]> = [];
|
|
|
|
const initialPlugins: Array<
|
|
Class<FlipperPlugin<> | FlipperDevicePlugin<>>,
|
|
> = [...getBundledPlugins(), ...getDynamicPlugins()]
|
|
.filter(checkDisabled(disabledPlugins))
|
|
.filter(checkGK(gatekeepedPlugins))
|
|
.map(requirePlugin(failedPlugins))
|
|
.filter(Boolean);
|
|
|
|
store.dispatch(addGatekeepedPlugins(gatekeepedPlugins));
|
|
store.dispatch(addDisabledPlugins(disabledPlugins));
|
|
store.dispatch(addFailedPlugins(failedPlugins));
|
|
store.dispatch(registerPlugins(initialPlugins));
|
|
|
|
let state: ?State = null;
|
|
store.subscribe(() => {
|
|
const newState = store.getState().plugins;
|
|
if (state !== newState) {
|
|
setupMenuBar(
|
|
[
|
|
...newState.devicePlugins.values(),
|
|
...newState.clientPlugins.values(),
|
|
],
|
|
store,
|
|
);
|
|
}
|
|
state = newState;
|
|
});
|
|
};
|
|
|
|
function getBundledPlugins(): Array<PluginDefinition> {
|
|
// DefaultPlugins that are included in the bundle.
|
|
// List of defaultPlugins is written at build time
|
|
let bundledPlugins: Array<PluginDefinition> = [];
|
|
try {
|
|
bundledPlugins = global.electronRequire('./defaultPlugins/index.json');
|
|
} catch (e) {}
|
|
|
|
return bundledPlugins.map(plugin => ({
|
|
...plugin,
|
|
out: './' + plugin.out,
|
|
}));
|
|
}
|
|
|
|
export function getDynamicPlugins() {
|
|
let dynamicPlugins: Array<PluginDefinition> = [];
|
|
try {
|
|
dynamicPlugins = JSON.parse(
|
|
// $FlowFixMe process.env not defined in electron API spec
|
|
remote?.process.env.PLUGINS || process.env.PLUGINS || '[]',
|
|
);
|
|
} catch (e) {
|
|
console.error(e);
|
|
}
|
|
return dynamicPlugins;
|
|
}
|
|
|
|
export const checkGK = (gatekeepedPlugins: Array<PluginDefinition>) => (
|
|
plugin: PluginDefinition,
|
|
): boolean => {
|
|
if (!plugin.gatekeeper) {
|
|
return true;
|
|
}
|
|
const result = GK.get(plugin.gatekeeper);
|
|
if (!result) {
|
|
gatekeepedPlugins.push(plugin);
|
|
console.warn(
|
|
'Plugin %s will be ignored as user is not part of the gatekeeper "%s".',
|
|
plugin.name,
|
|
plugin.gatekeeper,
|
|
);
|
|
}
|
|
return result;
|
|
};
|
|
|
|
export const checkDisabled = (disabledPlugins: Array<PluginDefinition>) => (
|
|
plugin: PluginDefinition,
|
|
): boolean => {
|
|
let disabledList: Set<string> = new Set();
|
|
try {
|
|
disabledList = new Set(
|
|
// $FlowFixMe process.env not defined in electron API spec
|
|
JSON.parse(remote?.process.env.CONFIG || process.env.CONFIG || '{}')
|
|
.disabledPlugins || [],
|
|
);
|
|
} catch (e) {
|
|
console.error(e);
|
|
}
|
|
|
|
if (disabledList.has(plugin.name)) {
|
|
disabledPlugins.push(plugin);
|
|
}
|
|
|
|
return !disabledList.has(plugin.name);
|
|
};
|
|
|
|
export const requirePlugin = (
|
|
failedPlugins: Array<[PluginDefinition, string]>,
|
|
reqFn: Function = global.electronRequire,
|
|
) => {
|
|
return (
|
|
pluginDefinition: PluginDefinition,
|
|
): ?Class<FlipperPlugin<> | FlipperDevicePlugin<>> => {
|
|
try {
|
|
let plugin = reqFn(pluginDefinition.out);
|
|
if (plugin.default) {
|
|
plugin = plugin.default;
|
|
}
|
|
if (!plugin.prototype instanceof FlipperBasePlugin) {
|
|
throw new Error(`Plugin ${plugin.name} is not a FlipperBasePlugin`);
|
|
}
|
|
|
|
// set values from package.json as static variables on class
|
|
Object.keys(pluginDefinition).forEach(key => {
|
|
if (key === 'name') {
|
|
plugin.id = plugin.id || pluginDefinition.name;
|
|
} else if (key === 'id') {
|
|
throw new Error(
|
|
'Field "id" not allowed in package.json. The plugin\'s name will be used as ID"',
|
|
);
|
|
} else {
|
|
plugin[key] = plugin[key] || pluginDefinition[key];
|
|
}
|
|
});
|
|
|
|
return plugin;
|
|
} catch (e) {
|
|
failedPlugins.push([pluginDefinition, e.message]);
|
|
console.error(pluginDefinition, e);
|
|
return null;
|
|
}
|
|
};
|
|
};
|