Show status updates while exporting
Summary: Adds a feature to display status update, while exporting Flipper trace. This will make user aware of the steps which are being executed to export flipper trace. This diff also logs the status update, to better support the issue posted by the user regarding the Flipper trace. Reviewed By: jknoxville Differential Revision: D16203810 fbshipit-source-id: 8f0bdc3836fec6dd79f2ca9827822d13f6cfd8bd
This commit is contained in:
committed by
Facebook Github Bot
parent
7f2709e1a5
commit
ba95e73a8d
@@ -80,6 +80,7 @@ type State = {
|
|||||||
| {
|
| {
|
||||||
flipperUrl: string,
|
flipperUrl: string,
|
||||||
},
|
},
|
||||||
|
statusUpdate: ?string,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default class ShareSheet extends Component<Props, State> {
|
export default class ShareSheet extends Component<Props, State> {
|
||||||
@@ -90,6 +91,7 @@ export default class ShareSheet extends Component<Props, State> {
|
|||||||
state = {
|
state = {
|
||||||
errorArray: [],
|
errorArray: [],
|
||||||
result: null,
|
result: null,
|
||||||
|
statusUpdate: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
idler = new Idler();
|
idler = new Idler();
|
||||||
@@ -99,7 +101,9 @@ export default class ShareSheet extends Component<Props, State> {
|
|||||||
performance.mark(mark);
|
performance.mark(mark);
|
||||||
try {
|
try {
|
||||||
const {serializedString, errorArray} = await reportPlatformFailures(
|
const {serializedString, errorArray} = await reportPlatformFailures(
|
||||||
exportStore(this.context.store, this.idler),
|
exportStore(this.context.store, this.idler, (msg: string) => {
|
||||||
|
this.setState({statusUpdate: msg});
|
||||||
|
}),
|
||||||
`${EXPORT_FLIPPER_TRACE_EVENT}:UI_LINK`,
|
`${EXPORT_FLIPPER_TRACE_EVENT}:UI_LINK`,
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -129,66 +133,80 @@ export default class ShareSheet extends Component<Props, State> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderTheProgessState(onHide: () => void, statusUpdate: ?string) {
|
||||||
|
return (
|
||||||
|
<Container>
|
||||||
|
<FlexColumn>
|
||||||
|
<Center>
|
||||||
|
<LoadingIndicator size={30} />
|
||||||
|
{statusUpdate && statusUpdate.length > 0 ? (
|
||||||
|
<Uploading bold color={colors.macOSTitleBarIcon}>
|
||||||
|
{statusUpdate}
|
||||||
|
</Uploading>
|
||||||
|
) : (
|
||||||
|
<Uploading bold color={colors.macOSTitleBarIcon}>
|
||||||
|
Uploading Flipper trace...
|
||||||
|
</Uploading>
|
||||||
|
)}
|
||||||
|
</Center>
|
||||||
|
<FlexRow>
|
||||||
|
<Spacer />
|
||||||
|
<Button compact padded onClick={onHide}>
|
||||||
|
Close
|
||||||
|
</Button>
|
||||||
|
</FlexRow>
|
||||||
|
</FlexColumn>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const onHide = () => {
|
const onHide = () => {
|
||||||
this.props.onHide();
|
this.props.onHide();
|
||||||
this.idler.cancel();
|
this.idler.cancel();
|
||||||
};
|
};
|
||||||
|
const {result, statusUpdate, errorArray} = this.state;
|
||||||
|
if (!result || !result.flipperUrl) {
|
||||||
|
return this.renderTheProgessState(onHide, statusUpdate);
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
{this.state.result ? (
|
<>
|
||||||
<>
|
|
||||||
<FlexColumn>
|
|
||||||
{this.state.result.flipperUrl ? (
|
|
||||||
<>
|
|
||||||
<Title bold>Data Upload Successful</Title>
|
|
||||||
<InfoText>
|
|
||||||
Flipper's data was successfully uploaded. This URL can be
|
|
||||||
used to share with other Flipper users. Opening it will
|
|
||||||
import the data from your trace.
|
|
||||||
</InfoText>
|
|
||||||
<Copy value={this.state.result.flipperUrl} />
|
|
||||||
<InfoText>
|
|
||||||
When sharing your Flipper link, consider that the captured
|
|
||||||
data might contain sensitve information like access tokens
|
|
||||||
used in network requests.
|
|
||||||
</InfoText>
|
|
||||||
<ShareSheetErrorList errors={this.state.errorArray} />
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
<Title bold>{this.state.result.error_class || 'Error'}</Title>
|
|
||||||
<ErrorMessage code>
|
|
||||||
{this.state.result.error ||
|
|
||||||
'The data could not be uploaded'}
|
|
||||||
</ErrorMessage>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</FlexColumn>
|
|
||||||
<FlexRow>
|
|
||||||
<Spacer />
|
|
||||||
<Button compact padded onClick={onHide}>
|
|
||||||
Close
|
|
||||||
</Button>
|
|
||||||
</FlexRow>
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<FlexColumn>
|
<FlexColumn>
|
||||||
<Center>
|
{result.flipperUrl ? (
|
||||||
<LoadingIndicator size={30} />
|
<>
|
||||||
<Uploading bold color={colors.macOSTitleBarIcon}>
|
<Title bold>Data Upload Successful</Title>
|
||||||
Uploading Flipper trace...
|
<InfoText>
|
||||||
</Uploading>
|
Flipper's data was successfully uploaded. This URL can be used
|
||||||
</Center>
|
to share with other Flipper users. Opening it will import the
|
||||||
<FlexRow>
|
data from your trace.
|
||||||
<Spacer />
|
</InfoText>
|
||||||
<Button compact padded onClick={onHide}>
|
<Copy value={result.flipperUrl} />
|
||||||
Cancel
|
<InfoText>
|
||||||
</Button>
|
When sharing your Flipper link, consider that the captured
|
||||||
</FlexRow>
|
data might contain sensitve information like access tokens
|
||||||
|
used in network requests.
|
||||||
|
</InfoText>
|
||||||
|
<ShareSheetErrorList errors={errorArray} />
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<Title bold>{result.error_class || 'Error'}</Title>
|
||||||
|
<ErrorMessage code>
|
||||||
|
{result.error || 'The data could not be uploaded'}
|
||||||
|
</ErrorMessage>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</FlexColumn>
|
</FlexColumn>
|
||||||
)}
|
<FlexRow>
|
||||||
|
<Spacer />
|
||||||
|
<Button compact padded onClick={onHide}>
|
||||||
|
Close
|
||||||
|
</Button>
|
||||||
|
</FlexRow>
|
||||||
|
</>
|
||||||
|
)
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ type State = {
|
|||||||
success: boolean,
|
success: boolean,
|
||||||
error: ?Error,
|
error: ?Error,
|
||||||
},
|
},
|
||||||
|
statusUpdate: ?string,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default class ShareSheetExportFile extends Component<Props, State> {
|
export default class ShareSheetExportFile extends Component<Props, State> {
|
||||||
@@ -81,6 +82,7 @@ export default class ShareSheetExportFile extends Component<Props, State> {
|
|||||||
state = {
|
state = {
|
||||||
errorArray: [],
|
errorArray: [],
|
||||||
result: null,
|
result: null,
|
||||||
|
statusUpdate: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
idler = new Idler();
|
idler = new Idler();
|
||||||
@@ -95,7 +97,14 @@ export default class ShareSheetExportFile extends Component<Props, State> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const {errorArray} = await reportPlatformFailures(
|
const {errorArray} = await reportPlatformFailures(
|
||||||
exportStoreToFile(this.props.file, this.context.store, this.idler),
|
exportStoreToFile(
|
||||||
|
this.props.file,
|
||||||
|
this.context.store,
|
||||||
|
this.idler,
|
||||||
|
(msg: string) => {
|
||||||
|
this.setState({statusUpdate: msg});
|
||||||
|
},
|
||||||
|
),
|
||||||
`${EXPORT_FLIPPER_TRACE_EVENT}:UI_FILE`,
|
`${EXPORT_FLIPPER_TRACE_EVENT}:UI_FILE`,
|
||||||
);
|
);
|
||||||
this.setState({errorArray, result: {success: true, error: null}});
|
this.setState({errorArray, result: {success: true, error: null}});
|
||||||
@@ -115,7 +124,7 @@ export default class ShareSheetExportFile extends Component<Props, State> {
|
|||||||
if (!this.props.file) {
|
if (!this.props.file) {
|
||||||
return this.renderNoFileError(onHide);
|
return this.renderNoFileError(onHide);
|
||||||
}
|
}
|
||||||
const {result} = this.state;
|
const {result, statusUpdate} = this.state;
|
||||||
if (result) {
|
if (result) {
|
||||||
const {success, error} = result;
|
const {success, error} = result;
|
||||||
if (success) {
|
if (success) {
|
||||||
@@ -161,9 +170,15 @@ export default class ShareSheetExportFile extends Component<Props, State> {
|
|||||||
<Container>
|
<Container>
|
||||||
<Center>
|
<Center>
|
||||||
<LoadingIndicator size={30} />
|
<LoadingIndicator size={30} />
|
||||||
<Uploading bold color={colors.macOSTitleBarIcon}>
|
{statusUpdate && statusUpdate.length > 0 ? (
|
||||||
Exporting Flipper trace...
|
<Uploading bold color={colors.macOSTitleBarIcon}>
|
||||||
</Uploading>
|
{statusUpdate}
|
||||||
|
</Uploading>
|
||||||
|
) : (
|
||||||
|
<Uploading bold color={colors.macOSTitleBarIcon}>
|
||||||
|
Exporting Flipper trace...
|
||||||
|
</Uploading>
|
||||||
|
)}
|
||||||
</Center>
|
</Center>
|
||||||
<FlexRow>
|
<FlexRow>
|
||||||
<Spacer />
|
<Spacer />
|
||||||
|
|||||||
@@ -43,8 +43,14 @@ export type ExportType = {|
|
|||||||
export function processClients(
|
export function processClients(
|
||||||
clients: Array<ClientExport>,
|
clients: Array<ClientExport>,
|
||||||
serial: string,
|
serial: string,
|
||||||
|
statusUpdate?: (msg: string) => void,
|
||||||
): Array<ClientExport> {
|
): Array<ClientExport> {
|
||||||
return clients.filter(client => client.query.device_id === serial);
|
statusUpdate &&
|
||||||
|
statusUpdate(`Filtering Clients for the device id ${serial}...`);
|
||||||
|
const filteredClients = clients.filter(
|
||||||
|
client => client.query.device_id === serial,
|
||||||
|
);
|
||||||
|
return filteredClients;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function pluginsClassMap(
|
export function pluginsClassMap(
|
||||||
@@ -68,8 +74,11 @@ export function processPluginStates(
|
|||||||
serial: string,
|
serial: string,
|
||||||
allPluginStates: PluginStatesState,
|
allPluginStates: PluginStatesState,
|
||||||
devicePlugins: Map<string, Class<FlipperDevicePlugin<>>>,
|
devicePlugins: Map<string, Class<FlipperDevicePlugin<>>>,
|
||||||
|
statusUpdate?: (msg: string) => void,
|
||||||
): PluginStatesState {
|
): PluginStatesState {
|
||||||
let pluginStates = {};
|
let pluginStates = {};
|
||||||
|
statusUpdate &&
|
||||||
|
statusUpdate('Filtering the plugin states for the filtered Clients...');
|
||||||
for (const key in allPluginStates) {
|
for (const key in allPluginStates) {
|
||||||
const keyArray = key.split('#');
|
const keyArray = key.split('#');
|
||||||
const pluginName = keyArray.pop();
|
const pluginName = keyArray.pop();
|
||||||
@@ -93,7 +102,10 @@ export function processNotificationStates(
|
|||||||
serial: string,
|
serial: string,
|
||||||
allActiveNotifications: Array<PluginNotification>,
|
allActiveNotifications: Array<PluginNotification>,
|
||||||
devicePlugins: Map<string, Class<FlipperDevicePlugin<>>>,
|
devicePlugins: Map<string, Class<FlipperDevicePlugin<>>>,
|
||||||
|
statusUpdate?: (msg: string) => void,
|
||||||
): Array<PluginNotification> {
|
): Array<PluginNotification> {
|
||||||
|
statusUpdate &&
|
||||||
|
statusUpdate('Filtering the notifications for the filtered Clients...');
|
||||||
const activeNotifications = allActiveNotifications.filter(notif => {
|
const activeNotifications = allActiveNotifications.filter(notif => {
|
||||||
const filteredClients = clients.filter(client =>
|
const filteredClients = clients.filter(client =>
|
||||||
notif.client ? client.id.includes(notif.client) : false,
|
notif.client ? client.id.includes(notif.client) : false,
|
||||||
@@ -112,6 +124,7 @@ const addSaltToDeviceSerial = async (
|
|||||||
clients: Array<ClientExport>,
|
clients: Array<ClientExport>,
|
||||||
pluginStates: PluginStatesState,
|
pluginStates: PluginStatesState,
|
||||||
pluginNotification: Array<PluginNotification>,
|
pluginNotification: Array<PluginNotification>,
|
||||||
|
statusUpdate?: (msg: string) => void,
|
||||||
): Promise<ExportType> => {
|
): Promise<ExportType> => {
|
||||||
const {serial} = device;
|
const {serial} = device;
|
||||||
const newSerial = salt + '-' + serial;
|
const newSerial = salt + '-' + serial;
|
||||||
@@ -122,6 +135,8 @@ const addSaltToDeviceSerial = async (
|
|||||||
device.os,
|
device.os,
|
||||||
device.getLogs(),
|
device.getLogs(),
|
||||||
);
|
);
|
||||||
|
statusUpdate &&
|
||||||
|
statusUpdate('Adding salt to the selected device id in the client data...');
|
||||||
const updatedClients = clients.map((client: ClientExport) => {
|
const updatedClients = clients.map((client: ClientExport) => {
|
||||||
return {
|
return {
|
||||||
...client,
|
...client,
|
||||||
@@ -130,6 +145,10 @@ const addSaltToDeviceSerial = async (
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
statusUpdate &&
|
||||||
|
statusUpdate(
|
||||||
|
'Adding salt to the selected device id in the plugin states...',
|
||||||
|
);
|
||||||
const updatedPluginStates: PluginStatesState = {};
|
const updatedPluginStates: PluginStatesState = {};
|
||||||
for (let key in pluginStates) {
|
for (let key in pluginStates) {
|
||||||
if (!key.includes(serial)) {
|
if (!key.includes(serial)) {
|
||||||
@@ -142,6 +161,10 @@ const addSaltToDeviceSerial = async (
|
|||||||
updatedPluginStates[key] = pluginData;
|
updatedPluginStates[key] = pluginData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
statusUpdate &&
|
||||||
|
statusUpdate(
|
||||||
|
'Adding salt to the selected device id in the notification data...',
|
||||||
|
);
|
||||||
const updatedPluginNotifications = pluginNotification.map(notif => {
|
const updatedPluginNotifications = pluginNotification.map(notif => {
|
||||||
if (!notif.client || !notif.client.includes(serial)) {
|
if (!notif.client || !notif.client.includes(serial)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
@@ -172,21 +195,24 @@ export const processStore = async (
|
|||||||
clients: Array<ClientExport>,
|
clients: Array<ClientExport>,
|
||||||
devicePlugins: Map<string, Class<FlipperDevicePlugin<>>>,
|
devicePlugins: Map<string, Class<FlipperDevicePlugin<>>>,
|
||||||
salt: string,
|
salt: string,
|
||||||
|
statusUpdate?: (msg: string) => void,
|
||||||
): Promise<?ExportType> => {
|
): Promise<?ExportType> => {
|
||||||
if (device) {
|
if (device) {
|
||||||
const {serial} = device;
|
const {serial} = device;
|
||||||
const processedClients = processClients(clients, serial);
|
const processedClients = processClients(clients, serial, statusUpdate);
|
||||||
const processedPluginStates = processPluginStates(
|
const processedPluginStates = processPluginStates(
|
||||||
processedClients,
|
processedClients,
|
||||||
serial,
|
serial,
|
||||||
pluginStates,
|
pluginStates,
|
||||||
devicePlugins,
|
devicePlugins,
|
||||||
|
statusUpdate,
|
||||||
);
|
);
|
||||||
const processedActiveNotifications = processNotificationStates(
|
const processedActiveNotifications = processNotificationStates(
|
||||||
processedClients,
|
processedClients,
|
||||||
serial,
|
serial,
|
||||||
activeNotifications,
|
activeNotifications,
|
||||||
devicePlugins,
|
devicePlugins,
|
||||||
|
statusUpdate,
|
||||||
);
|
);
|
||||||
// Adding salt to the device id, so that the device_id in the device list is unique.
|
// Adding salt to the device id, so that the device_id in the device list is unique.
|
||||||
const exportFlipperData = await addSaltToDeviceSerial(
|
const exportFlipperData = await addSaltToDeviceSerial(
|
||||||
@@ -195,6 +221,7 @@ export const processStore = async (
|
|||||||
processedClients,
|
processedClients,
|
||||||
processedPluginStates,
|
processedPluginStates,
|
||||||
processedActiveNotifications,
|
processedActiveNotifications,
|
||||||
|
statusUpdate,
|
||||||
);
|
);
|
||||||
return exportFlipperData;
|
return exportFlipperData;
|
||||||
}
|
}
|
||||||
@@ -205,6 +232,7 @@ export async function fetchMetadata(
|
|||||||
pluginStates: PluginStatesState,
|
pluginStates: PluginStatesState,
|
||||||
pluginsMap: Map<string, Class<FlipperDevicePlugin<> | FlipperPlugin<>>>,
|
pluginsMap: Map<string, Class<FlipperDevicePlugin<> | FlipperPlugin<>>>,
|
||||||
store: MiddlewareAPI,
|
store: MiddlewareAPI,
|
||||||
|
statusUpdate?: (msg: string) => void,
|
||||||
): Promise<{pluginStates: PluginStatesState, errorArray: Array<Error>}> {
|
): Promise<{pluginStates: PluginStatesState, errorArray: Array<Error>}> {
|
||||||
const newPluginState = {...pluginStates};
|
const newPluginState = {...pluginStates};
|
||||||
const errorArray: Array<Error> = [];
|
const errorArray: Array<Error> = [];
|
||||||
@@ -226,6 +254,8 @@ export async function fetchMetadata(
|
|||||||
if (exportState) {
|
if (exportState) {
|
||||||
const key = pluginKey(client.id, plugin);
|
const key = pluginKey(client.id, plugin);
|
||||||
try {
|
try {
|
||||||
|
statusUpdate &&
|
||||||
|
statusUpdate(`Fetching metadata for plugin ${plugin}...`);
|
||||||
const data = await promiseTimeout(
|
const data = await promiseTimeout(
|
||||||
120000, // Timeout in 2 mins
|
120000, // Timeout in 2 mins
|
||||||
exportState(callClient(client, plugin), newPluginState[key], store),
|
exportState(callClient(client, plugin), newPluginState[key], store),
|
||||||
@@ -244,6 +274,7 @@ export async function fetchMetadata(
|
|||||||
|
|
||||||
export async function getStoreExport(
|
export async function getStoreExport(
|
||||||
store: MiddlewareAPI,
|
store: MiddlewareAPI,
|
||||||
|
statusUpdate?: (msg: string) => void,
|
||||||
): Promise<{exportData: ?ExportType, errorArray: Array<Error>}> {
|
): Promise<{exportData: ?ExportType, errorArray: Array<Error>}> {
|
||||||
const state = store.getState();
|
const state = store.getState();
|
||||||
const {clients} = state.connections;
|
const {clients} = state.connections;
|
||||||
@@ -266,7 +297,13 @@ export async function getStoreExport(
|
|||||||
plugins.devicePlugins.forEach((val, key) => {
|
plugins.devicePlugins.forEach((val, key) => {
|
||||||
pluginsMap.set(key, val);
|
pluginsMap.set(key, val);
|
||||||
});
|
});
|
||||||
const metadata = await fetchMetadata(pluginStates, pluginsMap, store);
|
statusUpdate && statusUpdate('Preparing to fetch metadata from client...');
|
||||||
|
const metadata = await fetchMetadata(
|
||||||
|
pluginStates,
|
||||||
|
pluginsMap,
|
||||||
|
store,
|
||||||
|
statusUpdate,
|
||||||
|
);
|
||||||
const {errorArray} = metadata;
|
const {errorArray} = metadata;
|
||||||
const newPluginState = metadata.pluginStates;
|
const newPluginState = metadata.pluginStates;
|
||||||
|
|
||||||
@@ -279,6 +316,7 @@ export async function getStoreExport(
|
|||||||
clients.map(client => client.toJSON()),
|
clients.map(client => client.toJSON()),
|
||||||
devicePlugins,
|
devicePlugins,
|
||||||
uuid.v4(),
|
uuid.v4(),
|
||||||
|
statusUpdate,
|
||||||
);
|
);
|
||||||
return {exportData, errorArray};
|
return {exportData, errorArray};
|
||||||
}
|
}
|
||||||
@@ -286,16 +324,22 @@ export async function getStoreExport(
|
|||||||
export function exportStore(
|
export function exportStore(
|
||||||
store: MiddlewareAPI,
|
store: MiddlewareAPI,
|
||||||
idler?: Idler,
|
idler?: Idler,
|
||||||
|
statusUpdate?: (msg: string) => void,
|
||||||
): Promise<{serializedString: string, errorArray: Array<Error>}> {
|
): Promise<{serializedString: string, errorArray: Array<Error>}> {
|
||||||
getLogger().track('usage', EXPORT_FLIPPER_TRACE_EVENT);
|
getLogger().track('usage', EXPORT_FLIPPER_TRACE_EVENT);
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
const {exportData, errorArray} = await getStoreExport(store);
|
statusUpdate && statusUpdate('Preparing to export Flipper data...');
|
||||||
|
const {exportData, errorArray} = await getStoreExport(
|
||||||
|
store,
|
||||||
|
statusUpdate,
|
||||||
|
);
|
||||||
if (!exportData) {
|
if (!exportData) {
|
||||||
console.error('Make sure a device is connected');
|
console.error('Make sure a device is connected');
|
||||||
reject(new Error('No device is selected'));
|
reject(new Error('No device is selected'));
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
statusUpdate && statusUpdate('Serializing Flipper data...');
|
||||||
const serializedString = await serialize(exportData, idler);
|
const serializedString = await serialize(exportData, idler);
|
||||||
if (serializedString.length <= 0) {
|
if (serializedString.length <= 0) {
|
||||||
reject(new Error('Serialize function returned empty string'));
|
reject(new Error('Serialize function returned empty string'));
|
||||||
@@ -314,14 +358,17 @@ export const exportStoreToFile = (
|
|||||||
exportFilePath: string,
|
exportFilePath: string,
|
||||||
store: Store,
|
store: Store,
|
||||||
idler?: Idler,
|
idler?: Idler,
|
||||||
|
statusUpdate?: (msg: string) => void,
|
||||||
): Promise<{errorArray: Array<Error>}> => {
|
): Promise<{errorArray: Array<Error>}> => {
|
||||||
return exportStore(store, idler).then(({serializedString, errorArray}) => {
|
return exportStore(store, idler, statusUpdate).then(
|
||||||
return promisify(fs.writeFile)(exportFilePath, serializedString).then(
|
({serializedString, errorArray}) => {
|
||||||
() => {
|
return promisify(fs.writeFile)(exportFilePath, serializedString).then(
|
||||||
return {errorArray};
|
() => {
|
||||||
},
|
return {errorArray};
|
||||||
);
|
},
|
||||||
});
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export function importDataToStore(data: string, store: Store) {
|
export function importDataToStore(data: string, store: Store) {
|
||||||
|
|||||||
Reference in New Issue
Block a user