diff --git a/packages/bruno-app/src/components/Sidebar/Collections/Collection/ExportCollection/index.js b/packages/bruno-app/src/components/Sidebar/Collections/Collection/ExportCollection/index.js
new file mode 100644
index 00000000..0a1c7cd8
--- /dev/null
+++ b/packages/bruno-app/src/components/Sidebar/Collections/Collection/ExportCollection/index.js
@@ -0,0 +1,37 @@
+import React from 'react';
+import exportBrunoCollection from 'utils/collections/export';
+import exportPostmanCollection from 'utils/exporters/postman-collection';
+import { toastError } from 'utils/common/error';
+import cloneDeep from 'lodash/cloneDeep';
+import Modal from 'components/Modal';
+import { transformCollectionToSaveToExportAsFile } from 'utils/collections/index';
+
+const ExportCollection = ({ onClose, collection }) => {
+ const handleExportBrunoCollection = () => {
+ const collectionCopy = cloneDeep(collection);
+ exportBrunoCollection(transformCollectionToSaveToExportAsFile(collectionCopy));
+ onClose();
+ };
+
+ const handleExportPostmanCollection = () => {
+ const collectionCopy = cloneDeep(collection);
+ exportPostmanCollection(collectionCopy);
+ // exportPostmanCollection(transformCollectionToSaveToExportAsFile(collectionCopy));
+ onClose();
+ };
+
+ return (
+
+
+
+ Bruno Collection
+
+
+ Postman Collection
+
+
+
+ );
+};
+
+export default ExportCollection;
diff --git a/packages/bruno-app/src/components/Sidebar/Collections/Collection/index.js b/packages/bruno-app/src/components/Sidebar/Collections/Collection/index.js
index b150ade8..2f7b876a 100644
--- a/packages/bruno-app/src/components/Sidebar/Collections/Collection/index.js
+++ b/packages/bruno-app/src/components/Sidebar/Collections/Collection/index.js
@@ -14,6 +14,7 @@ import NewRequest from 'components/Sidebar/NewRequest';
import NewFolder from 'components/Sidebar/NewFolder';
import CollectionItem from './CollectionItem';
import RemoveCollection from './RemoveCollection';
+import ExportCollection from './ExportCollection';
import CollectionProperties from './CollectionProperties';
import { doesCollectionHaveItemsMatchingSearchText } from 'utils/collections/search';
import { isItemAFolder, isItemARequest, transformCollectionToSaveToExportAsFile } from 'utils/collections';
@@ -26,6 +27,7 @@ const Collection = ({ collection, searchText }) => {
const [showNewFolderModal, setShowNewFolderModal] = useState(false);
const [showNewRequestModal, setShowNewRequestModal] = useState(false);
const [showRenameCollectionModal, setShowRenameCollectionModal] = useState(false);
+ const [showExportCollectionModal, setShowExportCollectionModal] = useState(false);
const [showRemoveCollectionModal, setShowRemoveCollectionModal] = useState(false);
const [collectionPropertiesModal, setCollectionPropertiesModal] = useState(false);
const [collectionIsCollapsed, setCollectionIsCollapsed] = useState(collection.collapsed);
@@ -68,6 +70,7 @@ const Collection = ({ collection, searchText }) => {
};
const handleExportClick = () => {
+ //EXPORT KOLEKCIE
const collectionCopy = cloneDeep(collection);
exportCollection(transformCollectionToSaveToExportAsFile(collectionCopy));
};
@@ -115,6 +118,9 @@ const Collection = ({ collection, searchText }) => {
{showRemoveCollectionModal && (
setShowRemoveCollectionModal(false)} />
)}
+ {showExportCollectionModal && (
+ setShowExportCollectionModal(false)} />
+ )}
{collectionPropertiesModal && (
setCollectionPropertiesModal(false)} />
)}
@@ -172,7 +178,7 @@ const Collection = ({ collection, searchText }) => {
className="dropdown-item"
onClick={(e) => {
menuDropdownTippyRef.current.hide();
- handleExportClick(true);
+ setShowExportCollectionModal(true);
}}
>
Export
diff --git a/packages/bruno-app/src/utils/collections/export.js b/packages/bruno-app/src/utils/collections/export.js
index 64fc0da9..e5a68bc6 100644
--- a/packages/bruno-app/src/utils/collections/export.js
+++ b/packages/bruno-app/src/utils/collections/export.js
@@ -2,7 +2,7 @@ import * as FileSaver from 'file-saver';
import get from 'lodash/get';
import each from 'lodash/each';
-const deleteUidsInItems = (items) => {
+export const deleteUidsInItems = (items) => {
each(items, (item) => {
delete item.uid;
@@ -26,7 +26,7 @@ const deleteUidsInItems = (items) => {
* Some of the models in the app are not consistent with the Collection Json format
* This function is used to transform the models to the Collection Json format
*/
-const transformItem = (items = []) => {
+export const transformItem = (items = []) => {
each(items, (item) => {
if (['http-request', 'graphql-request'].includes(item.type)) {
item.request.query = item.request.params;
@@ -47,14 +47,14 @@ const transformItem = (items = []) => {
});
};
-const deleteUidsInEnvs = (envs) => {
+export const deleteUidsInEnvs = (envs) => {
each(envs, (env) => {
delete env.uid;
each(env.variables, (variable) => delete variable.uid);
});
};
-const deleteSecretsInEnvs = (envs) => {
+export const deleteSecretsInEnvs = (envs) => {
each(envs, (env) => {
each(env.variables, (variable) => {
if (variable.secret) {
@@ -64,7 +64,7 @@ const deleteSecretsInEnvs = (envs) => {
});
};
-const exportCollection = (collection) => {
+export const exportCollection = (collection) => {
// delete uids
delete collection.uid;
deleteUidsInItems(collection.items);
diff --git a/packages/bruno-app/src/utils/exporters/postman-collection.js b/packages/bruno-app/src/utils/exporters/postman-collection.js
new file mode 100644
index 00000000..38fc6fbf
--- /dev/null
+++ b/packages/bruno-app/src/utils/exporters/postman-collection.js
@@ -0,0 +1,151 @@
+import { BrunoError } from 'utils/common/error';
+import map from 'lodash/map';
+import { deleteSecretsInEnvs, deleteUidsInEnvs, deleteUidsInItems } from 'utils/collections/export';
+
+export const exportCollection = (collection) => {
+ delete collection.uid;
+ deleteUidsInItems(collection.items);
+ deleteUidsInEnvs(collection.environments);
+ deleteSecretsInEnvs(collection.environments);
+
+ const generateInfoSection = () => {
+ return {
+ name: collection.name,
+ schema: 'https://schema.getpostman.com/json/collection/v2.1.0/collection.json'
+ };
+ };
+
+ const generateEventSection = (item) => {
+ const eventArray = [];
+ if (item.request.tests.length) {
+ eventArray.push({
+ listen: 'test',
+ script: {
+ exec: item.request.tests.split('\n')
+ // type: 'text/javascript'
+ }
+ });
+ }
+ if (item.request.script.req) {
+ eventArray.push({
+ listen: 'prerequest',
+ script: {
+ exec: item.request.script.req.split('\n')
+ // type: 'text/javascript'
+ }
+ });
+ }
+ return eventArray;
+ };
+
+ const generateHeaders = (headersArray) => {
+ return map(headersArray, (item) => {
+ return {
+ key: item.name,
+ value: item.value,
+ disabled: !item.enabled,
+ type: 'default'
+ };
+ });
+ };
+
+ const generateBody = (body) => {
+ switch (body.mode) {
+ case 'formUrlEncoded':
+ return {
+ mode: 'urlencoded',
+ urlencoded: map(body.formUrlEncoded, (bodyItem) => {
+ return {
+ key: bodyItem.name,
+ value: bodyItem.value,
+ disabled: !bodyItem.enabled,
+ type: 'default'
+ };
+ })
+ };
+ case 'multipartForm':
+ return {
+ mode: 'formdata',
+ formdata: map(body.multipartForm, (bodyItem) => {
+ return {
+ key: bodyItem.name,
+ value: bodyItem.value,
+ disabled: !bodyItem.enabled,
+ type: 'default'
+ };
+ })
+ };
+ case 'json':
+ return {
+ mode: 'raw',
+ raw: body.json,
+ options: {
+ raw: {
+ language: 'json'
+ }
+ }
+ };
+ case 'xml':
+ return {
+ mode: 'raw',
+ raw: body.xml,
+ options: {
+ raw: {
+ language: 'xml'
+ }
+ }
+ };
+ case 'text':
+ return {
+ mode: 'raw',
+ raw: body.text,
+ options: {
+ raw: {
+ language: 'text'
+ }
+ }
+ };
+ }
+ };
+
+ const generateRequestSection = (itemRequest) => {
+ const requestObject = {
+ method: itemRequest.method,
+ header: generateHeaders(itemRequest.headers),
+ url: {
+ raw: itemRequest.url,
+ protocol: itemRequest.url.split('://')[0]
+ }
+ // host: TODO
+ // path: TODO
+ };
+
+ if (itemRequest.body.mode != 'none') {
+ requestObject.body = generateBody(itemRequest.body);
+ }
+ return requestObject;
+ };
+
+ const generateItemSection = (itemsArray) => {
+ return map(itemsArray, (item) => {
+ if (item.type === 'folder') {
+ return {
+ name: item.name,
+ item: item.items.length ? generateItemSection(item.items) : []
+ };
+ } else {
+ return {
+ name: item.name,
+ event: generateEventSection(item),
+ request: generateRequestSection(item.request)
+ };
+ }
+ });
+ };
+ const collectionToExport = {};
+ collectionToExport.info = generateInfoSection();
+ collectionToExport.item = generateItemSection(collection.items);
+ console.log(collectionToExport);
+};
+
+export default exportCollection;