Export data for the universal export as a single zip archive
Summary: Design doc: https://docs.google.com/document/d/1HLCFl46RfqG0o1mSt8SWrwf_HMfOCRg_oENioc1rkvQ/edit# It is better UX not to prompt a user multiple times to save various pieces of the debug export Reviewed By: passy Differential Revision: D40550084 fbshipit-source-id: 51ea3acee7daf5074682219020e1e1eed2182b7d
This commit is contained in:
committed by
Facebook GitHub Bot
parent
821bf2b5b7
commit
6af6652ab2
@@ -162,10 +162,18 @@ export interface FSStatsLike {
|
||||
birthtimeMs: number;
|
||||
}
|
||||
|
||||
export interface DeviceDebugFile {
|
||||
path: string;
|
||||
data: string;
|
||||
}
|
||||
export interface DeviceDebugCommand {
|
||||
command: string;
|
||||
result: string;
|
||||
}
|
||||
export interface DeviceDebugData {
|
||||
serial: string;
|
||||
appId: string;
|
||||
data: ({path: string; data: string} | {command: string; result: string})[];
|
||||
data: (DeviceDebugFile | DeviceDebugCommand)[];
|
||||
}
|
||||
|
||||
export type FlipperServerCommands = {
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
"hotkeys-js": "^3.9.3",
|
||||
"immer": "^9.0.12",
|
||||
"js-base64": "^3.7.2",
|
||||
"jszip": "^3.10.1",
|
||||
"lodash": "^4.17.21",
|
||||
"lodash.memoize": "^4.1.2",
|
||||
"p-map": "^4.0.0",
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and 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 {safeFilename} from '../safeFilename';
|
||||
|
||||
describe('safeFilename', () => {
|
||||
test('replaces special chars in a string to make it a safe file name', async () => {
|
||||
expect(safeFilename('/data/data/0/files/sonar/spec!al file name%')).toBe(
|
||||
'-data-data-0-files-sonar-spec-al-file-name-',
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -8,7 +8,7 @@
|
||||
*/
|
||||
|
||||
import * as React from 'react';
|
||||
import {getLogger} from 'flipper-common';
|
||||
import {getLogger, DeviceDebugFile, DeviceDebugCommand} from 'flipper-common';
|
||||
import {Store, MiddlewareAPI} from '../reducers';
|
||||
import {DeviceExport} from 'flipper-frontend-core';
|
||||
import {selectedPlugins, State as PluginsState} from '../reducers/plugins';
|
||||
@@ -33,6 +33,8 @@ import ExportDataPluginSheet from '../chrome/ExportDataPluginSheet';
|
||||
import {getRenderHostInstance} from 'flipper-frontend-core';
|
||||
import {uploadFlipperMedia} from '../fb-stubs/user';
|
||||
import {exportLogs} from '../chrome/ConsoleLogs';
|
||||
import JSZip from 'jszip';
|
||||
import {safeFilename} from './safeFilename';
|
||||
|
||||
export const IMPORT_FLIPPER_TRACE_EVENT = 'import-flipper-trace';
|
||||
export const EXPORT_FLIPPER_TRACE_EVENT = 'export-flipper-trace';
|
||||
@@ -612,25 +614,50 @@ export async function startFlipperLogsExport() {
|
||||
await getRenderHostInstance().exportFile?.(serializedLogs);
|
||||
}
|
||||
|
||||
export async function startClientLogsExport() {
|
||||
const _clientLogs = await getRenderHostInstance().flipperServer.exec(
|
||||
'fetch-debug-data',
|
||||
);
|
||||
|
||||
// TODO: Save all log files
|
||||
async function startDeviceFlipperFolderExport() {
|
||||
return await getRenderHostInstance().flipperServer.exec('fetch-debug-data');
|
||||
}
|
||||
|
||||
export async function exportEverythingEverywhereAllAtOnce(
|
||||
store: MiddlewareAPI,
|
||||
) {
|
||||
// TODO: Show a progress dialog
|
||||
// TODO: Pack all files in a single archive
|
||||
const zip = new JSZip();
|
||||
|
||||
// Step 1: Export Flipper logs
|
||||
await startFlipperLogsExport();
|
||||
const serializedLogs = exportLogs
|
||||
.map((item) => JSON.stringify(item))
|
||||
.join('\n');
|
||||
|
||||
zip.file('flipper_logs.txt', serializedLogs);
|
||||
|
||||
// Step 2: Export device logs
|
||||
await startClientLogsExport();
|
||||
const flipperFolderContent = await startDeviceFlipperFolderExport();
|
||||
|
||||
const deviceFlipperFolder = zip.folder('device_flipper_folder')!;
|
||||
flipperFolderContent.forEach((deviceDebugItem) => {
|
||||
const deviceAppFolder = deviceFlipperFolder.folder(
|
||||
safeFilename(`${deviceDebugItem.serial}__${deviceDebugItem.appId}`),
|
||||
)!;
|
||||
|
||||
deviceDebugItem.data.forEach((appDebugItem) => {
|
||||
const appDebugItemIsFile = (
|
||||
item: DeviceDebugFile | DeviceDebugCommand,
|
||||
): item is DeviceDebugFile => !!(appDebugItem as DeviceDebugFile).path;
|
||||
|
||||
if (appDebugItemIsFile(appDebugItem)) {
|
||||
deviceAppFolder.file(
|
||||
safeFilename(appDebugItem.path),
|
||||
appDebugItem.data,
|
||||
);
|
||||
} else {
|
||||
deviceAppFolder.file(
|
||||
safeFilename(appDebugItem.command),
|
||||
appDebugItem.result,
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Step 3: Export Flipper State
|
||||
// TODO: Export all plugins automatically
|
||||
@@ -642,7 +669,12 @@ export async function exportEverythingEverywhereAllAtOnce(
|
||||
// need to be cleaned up later in combination with SupportForm
|
||||
store.dispatch(selectedPlugins(plugins));
|
||||
const {serializedString} = await exportStore(store);
|
||||
await getRenderHostInstance().exportFile?.(serializedString);
|
||||
|
||||
zip.file('flipper_export', serializedString);
|
||||
|
||||
const archiveData = await zip.generateAsync({type: 'uint8array'});
|
||||
|
||||
await getRenderHostInstance().exportFileBinary?.(archiveData);
|
||||
}
|
||||
|
||||
export async function startFileExport(dispatch: Store['dispatch']) {
|
||||
|
||||
11
desktop/flipper-ui-core/src/utils/safeFilename.tsx
Normal file
11
desktop/flipper-ui-core/src/utils/safeFilename.tsx
Normal file
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
export const safeFilename = (rawFilename: string) =>
|
||||
rawFilename.replace(/(\W+)/gi, '-');
|
||||
@@ -9965,6 +9965,16 @@ jszip@^3.1.0:
|
||||
readable-stream "~2.3.6"
|
||||
set-immediate-shim "~1.0.1"
|
||||
|
||||
jszip@^3.10.1:
|
||||
version "3.10.1"
|
||||
resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.10.1.tgz#34aee70eb18ea1faec2f589208a157d1feb091c2"
|
||||
integrity sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==
|
||||
dependencies:
|
||||
lie "~3.3.0"
|
||||
pako "~1.0.2"
|
||||
readable-stream "~2.3.6"
|
||||
setimmediate "^1.0.5"
|
||||
|
||||
keyv@^3.0.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9"
|
||||
|
||||
Reference in New Issue
Block a user