From 9ac3926afc2e73cde61498332127b92d487a9f95 Mon Sep 17 00:00:00 2001 From: James Gatz Date: Wed, 3 Jul 2024 11:24:51 +0200 Subject: [PATCH] fix(Export): Allow exporting workspaces without requests (#7643) * allow exporting without requests * seaparate export for envs * add export to workspace dropdown --- packages/insomnia/src/common/export.tsx | 62 ++++++++++++++++++- .../dropdowns/workspace-card-dropdown.tsx | 14 +++-- .../dropdowns/workspace-dropdown.tsx | 30 ++++++--- 3 files changed, 94 insertions(+), 12 deletions(-) diff --git a/packages/insomnia/src/common/export.tsx b/packages/insomnia/src/common/export.tsx index ad5d1b896..53d8185e6 100644 --- a/packages/insomnia/src/common/export.tsx +++ b/packages/insomnia/src/common/export.tsx @@ -455,6 +455,7 @@ const exportMockServer = async (workspace: Workspace, selectedFormat: 'json' | ' } return JSON.stringify(data); }; + export const exportMockServerToFile = async (workspace: Workspace) => { const options = [{ name: 'Insomnia v4 (JSON)', value: VALUE_JSON }, { name: 'Insomnia v4 (YAML)', value: VALUE_YAML }]; const lastFormat = window.localStorage.getItem('insomnia.lastExportFormat'); @@ -490,8 +491,67 @@ export const exportMockServerToFile = async (workspace: Workspace) => { } }, }); - }; + +const exportGlobalEnvironment = async (workspace: Workspace, selectedFormat: 'json' | 'yaml') => { + const data: Insomnia4Data = { + _type: 'export', + __export_format: EXPORT_FORMAT, + __export_date: new Date(), + __export_source: `insomnia.desktop.app:v${getAppVersion()}`, + resources: [], + }; + + const baseEnvironment = await models.environment.getOrCreateForParentId(workspace._id); + const subEnvironments = await models.environment.findByParentId(baseEnvironment._id); + + data.resources.push({ ...workspace, _type: 'workspace' }); + data.resources.push({ ...baseEnvironment, _type: 'environment' }); + subEnvironments.map(environment => data.resources.push({ ...environment, _type: 'environment' })); + + if (selectedFormat === 'yaml') { + return YAML.stringify(data); + } + return JSON.stringify(data); +}; + +export const exportGlobalEnvironmentToFile = async (workspace: Workspace) => { + const options = [{ name: 'Insomnia v4 (JSON)', value: VALUE_JSON }, { name: 'Insomnia v4 (YAML)', value: VALUE_YAML }]; + const lastFormat = window.localStorage.getItem('insomnia.lastExportFormat'); + const defaultValue = options.find(({ value }) => value === lastFormat) ? lastFormat : VALUE_JSON; + + showModal(SelectModal, { + title: 'Select Export Type', + value: defaultValue, + options, + message: 'Which format would you like to export as?', + onDone: async selectedFormat => { + invariant(selectedFormat, 'expected selected format to be defined'); + invariant(selectedFormat === 'json' || selectedFormat === 'yaml', 'unexpected selected format'); + window.localStorage.setItem('insomnia.lastExportFormat', selectedFormat); + const fileName = await showSaveExportedFileDialog({ + exportedFileNamePrefix: workspace.name, + selectedFormat, + }); + if (!fileName) { + return; + } + try { + const stringifiedExport = await exportGlobalEnvironment(workspace, selectedFormat); + writeExportedFileToFileSystem(fileName, stringifiedExport, err => err && console.warn('Export failed', err)); + window.main.trackSegmentEvent({ event: SegmentEvent.dataExport, properties: { type: selectedFormat, scope: 'environment' } }); + } catch (err) { + showError({ + title: 'Export Failed', + error: err, + message: 'Export failed due to an unexpected error', + }); + return; + } + }, + }); +}; + export const exportRequestsToFile = (workspaceId: string, requestIds: string[]) => { showSelectExportTypeModal({ onDone: async selectedFormat => { diff --git a/packages/insomnia/src/ui/components/dropdowns/workspace-card-dropdown.tsx b/packages/insomnia/src/ui/components/dropdowns/workspace-card-dropdown.tsx index 4da7d379b..2423cd596 100644 --- a/packages/insomnia/src/ui/components/dropdowns/workspace-card-dropdown.tsx +++ b/packages/insomnia/src/ui/components/dropdowns/workspace-card-dropdown.tsx @@ -4,7 +4,7 @@ import { useFetcher, useParams } from 'react-router-dom'; import { parseApiSpec } from '../../../common/api-specs'; import { getProductName } from '../../../common/constants'; -import { exportMockServerToFile } from '../../../common/export'; +import { exportGlobalEnvironmentToFile, exportMockServerToFile } from '../../../common/export'; import { getWorkspaceLabel } from '../../../common/get-workspace-label'; import { RENDER_PURPOSE_NO_RENDER } from '../../../common/render'; import type { ApiSpec } from '../../../models/api-spec'; @@ -153,9 +153,15 @@ export const WorkspaceCardDropdown: FC = props => { workspace.scope !== 'mock-server' - ? setIsExportModalOpen(true) - : exportMockServerToFile(workspace)} + onClick={() => { + if (workspace.scope === 'mock-server') { + return exportMockServerToFile(workspace); + } + if (workspace.scope === 'environment') { + return exportGlobalEnvironmentToFile(workspace); + } + return setIsExportModalOpen(true); + }} /> diff --git a/packages/insomnia/src/ui/components/dropdowns/workspace-dropdown.tsx b/packages/insomnia/src/ui/components/dropdowns/workspace-dropdown.tsx index ad5bc4880..be29e2523 100644 --- a/packages/insomnia/src/ui/components/dropdowns/workspace-dropdown.tsx +++ b/packages/insomnia/src/ui/components/dropdowns/workspace-dropdown.tsx @@ -5,7 +5,7 @@ import { useFetcher, useParams, useRouteLoaderData } from 'react-router-dom'; import { getProductName } from '../../../common/constants'; import { database as db } from '../../../common/database'; -import { exportMockServerToFile } from '../../../common/export'; +import { exportGlobalEnvironmentToFile, exportMockServerToFile } from '../../../common/export'; import { getWorkspaceLabel } from '../../../common/get-workspace-label'; import { RENDER_PURPOSE_NO_RENDER } from '../../../common/render'; import { PlatformKeyCombinations } from '../../../common/settings'; @@ -122,9 +122,17 @@ export const WorkspaceDropdown: FC = () => { id: 'Export', name: 'Export', icon: , - action: () => activeWorkspace.scope !== 'mock-server' - ? setIsExportModalOpen(true) - : exportMockServerToFile(activeWorkspace), + action: () => { + if (activeWorkspace.scope === 'mock-server') { + return exportMockServerToFile(activeWorkspace); + } + + if (activeWorkspace.scope === 'environment') { + return exportGlobalEnvironmentToFile(activeWorkspace); + } + + return setIsExportModalOpen(true); + }, }], }]; @@ -187,9 +195,17 @@ export const WorkspaceDropdown: FC = () => { id: 'export', name: 'Export', icon: , - action: () => activeWorkspace.scope !== 'mock-server' - ? setIsExportModalOpen(true) - : exportMockServerToFile(activeWorkspace), + action: () => { + if (activeWorkspace.scope === 'mock-server') { + return exportMockServerToFile(activeWorkspace); + } + + if (activeWorkspace.scope === 'environment') { + return exportGlobalEnvironmentToFile(activeWorkspace); + } + + return setIsExportModalOpen(true); + }, }, { id: 'settings',