Add support for async / custom plugin export
Summary: Sandy plugins can now set up an `onExport` handler to enable customizing the export format of a plugin: `client.onExport(callback: (idler, onStatusMessage) => Promise<state>)` Import will be done in next diff Reviewed By: nikoant Differential Revision: D26124440 fbshipit-source-id: c787c79d929aa8fb484f15a9340d7c87545793cb
This commit is contained in:
committed by
Facebook GitHub Bot
parent
32bde8cace
commit
34c915a739
@@ -14,6 +14,12 @@ import {MenuEntry, NormalizedMenuEntry, normalizeMenuEntry} from './MenuEntry';
|
||||
import {FlipperLib} from './FlipperLib';
|
||||
import {Device, RealFlipperDevice} from './DevicePlugin';
|
||||
import {batched} from '../state/batch';
|
||||
import {Idler} from '../utils/Idler';
|
||||
|
||||
type StateExportHandler = (
|
||||
idler: Idler,
|
||||
onStatusMessage: (msg: string) => void,
|
||||
) => Promise<Record<string, any>>;
|
||||
|
||||
export interface BasePluginClient {
|
||||
readonly device: Device;
|
||||
@@ -38,6 +44,12 @@ export interface BasePluginClient {
|
||||
*/
|
||||
onDeepLink(cb: (deepLink: unknown) => void): void;
|
||||
|
||||
/**
|
||||
* Triggered when the current plugin is being exported and should create a snapshot of the state exported.
|
||||
* Overrides the default export behavior and ignores any 'persist' flags of state.
|
||||
*/
|
||||
onExport(exporter: StateExportHandler): void;
|
||||
|
||||
/**
|
||||
* Register menu entries in the Flipper toolbar
|
||||
*/
|
||||
@@ -88,6 +100,8 @@ export abstract class BasePluginInstance {
|
||||
rootStates: Record<string, Atom<any>> = {};
|
||||
// last seen deeplink
|
||||
lastDeeplink?: any;
|
||||
// export handler
|
||||
exportHandler?: StateExportHandler;
|
||||
|
||||
menuEntries: NormalizedMenuEntry[] = [];
|
||||
|
||||
@@ -145,6 +159,12 @@ export abstract class BasePluginInstance {
|
||||
onDestroy: (cb) => {
|
||||
this.events.on('destroy', batched(cb));
|
||||
},
|
||||
onExport: (cb) => {
|
||||
if (this.exportHandler) {
|
||||
throw new Error('onExport handler already set');
|
||||
}
|
||||
this.exportHandler = cb;
|
||||
},
|
||||
addMenuEntry: (...entries) => {
|
||||
for (const entry of entries) {
|
||||
const normalized = normalizeMenuEntry(entry);
|
||||
@@ -204,14 +224,30 @@ export abstract class BasePluginInstance {
|
||||
}
|
||||
}
|
||||
|
||||
exportState() {
|
||||
exportStateSync() {
|
||||
// This method is mainly intended for unit testing
|
||||
if (this.exportHandler) {
|
||||
throw new Error(
|
||||
'Cannot export sync a plugin that does have an export handler',
|
||||
);
|
||||
}
|
||||
return Object.fromEntries(
|
||||
Object.entries(this.rootStates).map(([key, atom]) => [key, atom.get()]),
|
||||
);
|
||||
}
|
||||
|
||||
async exportState(
|
||||
idler: Idler,
|
||||
onStatusMessage: (msg: string) => void,
|
||||
): Promise<Record<string, any>> {
|
||||
if (this.exportHandler) {
|
||||
return await this.exportHandler(idler, onStatusMessage);
|
||||
}
|
||||
return this.exportStateSync();
|
||||
}
|
||||
|
||||
isPersistable(): boolean {
|
||||
return Object.keys(this.rootStates).length > 0;
|
||||
return !!this.exportHandler || Object.keys(this.rootStates).length > 0;
|
||||
}
|
||||
|
||||
protected assertNotDestroyed() {
|
||||
|
||||
Reference in New Issue
Block a user