diff --git a/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/index.js b/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/index.js
index b80cd92a..e310eb0c 100644
--- a/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/index.js
+++ b/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/index.js
@@ -4,6 +4,7 @@ import usePrevious from 'hooks/usePrevious';
import EnvironmentDetails from './EnvironmentDetails';
import CreateEnvironment from '../CreateEnvironment/index';
import StyledWrapper from './StyledWrapper';
+import ImportEnvironment from "components/Environments/EnvironmentSettings/ImportEnvironment";
const EnvironmentList = ({ collection }) => {
const { environments } = collection;
@@ -65,6 +66,7 @@ const EnvironmentList = ({ collection }) => {
setOpenCreateModal(true)}>
+ Create
+
diff --git a/packages/bruno-app/src/components/Environments/EnvironmentSettings/ImportEnvironment/index.js b/packages/bruno-app/src/components/Environments/EnvironmentSettings/ImportEnvironment/index.js
new file mode 100644
index 00000000..1b0fd9dd
--- /dev/null
+++ b/packages/bruno-app/src/components/Environments/EnvironmentSettings/ImportEnvironment/index.js
@@ -0,0 +1,33 @@
+import toast from "react-hot-toast";
+import {toastError} from "utils/common/error";
+import {useDispatch} from "react-redux";
+import {importEnvironment} from "providers/ReduxStore/slices/collections/actions";
+import importPostmanEnvironment from "utils/importers/postman-environment";
+import React from "react";
+
+const ImportEnvironment = ({title, collectionUid}) => {
+ const dispatch = useDispatch();
+
+ const handleImportPostmanEnvironment = () => {
+ importPostmanEnvironment()
+ .then((environment) => {
+ dispatch(importEnvironment(environment.name, environment.variables, collectionUid))
+ .then(() => {
+ toast.success('Environment imported successfully');
+ })
+ .catch(() => toast.error('An error occurred while importing the environment'));
+ })
+ .catch((err) => toastError(err, 'Postman Import environment failed'));
+ };
+
+ return(
+
+ );
+};
+
+export default ImportEnvironment;
\ No newline at end of file
diff --git a/packages/bruno-app/src/components/Environments/EnvironmentSettings/index.js b/packages/bruno-app/src/components/Environments/EnvironmentSettings/index.js
index 855e0fb3..39c410ee 100644
--- a/packages/bruno-app/src/components/Environments/EnvironmentSettings/index.js
+++ b/packages/bruno-app/src/components/Environments/EnvironmentSettings/index.js
@@ -3,6 +3,7 @@ import React, { useState } from 'react';
import CreateEnvironment from './CreateEnvironment';
import EnvironmentList from './EnvironmentList';
import StyledWrapper from './StyledWrapper';
+import ImportEnvironment from "components/Environments/EnvironmentSettings/ImportEnvironment";
const EnvironmentSettings = ({ collection, onClose }) => {
const { environments } = collection;
@@ -28,6 +29,7 @@ const EnvironmentSettings = ({ collection, onClose }) => {
>
+ Create Environment
+
diff --git a/packages/bruno-app/src/providers/ReduxStore/slices/collections/actions.js b/packages/bruno-app/src/providers/ReduxStore/slices/collections/actions.js
index 80c82345..1b36ed65 100644
--- a/packages/bruno-app/src/providers/ReduxStore/slices/collections/actions.js
+++ b/packages/bruno-app/src/providers/ReduxStore/slices/collections/actions.js
@@ -722,6 +722,32 @@ export const addEnvironment = (name, collectionUid) => (dispatch, getState) => {
});
};
+export const importEnvironment = (name, variables, collectionUid) => (dispatch, getState) => {
+ return new Promise((resolve, reject) => {
+ const state = getState();
+ const collection = findCollectionByUid(state.collections.collections, collectionUid);
+ if (!collection) {
+ return reject(new Error('Collection not found'));
+ }
+
+ ipcRenderer
+ .invoke('renderer:import-environment', collection.pathname, name, variables)
+ .then(
+ dispatch(
+ updateLastAction({
+ collectionUid,
+ lastAction: {
+ type: 'ADD_ENVIRONMENT',
+ payload: name
+ }
+ })
+ )
+ )
+ .then(resolve)
+ .catch(reject);
+ });
+};
+
export const copyEnvironment = (name, baseEnvUid, collectionUid) => (dispatch, getState) => {
return new Promise((resolve, reject) => {
const state = getState();
diff --git a/packages/bruno-app/src/utils/importers/postman-environment.js b/packages/bruno-app/src/utils/importers/postman-environment.js
new file mode 100644
index 00000000..61c62311
--- /dev/null
+++ b/packages/bruno-app/src/utils/importers/postman-environment.js
@@ -0,0 +1,71 @@
+import each from 'lodash/each';
+import fileDialog from 'file-dialog';
+import { BrunoError } from 'utils/common/error';
+
+const readFile = (files) => {
+ return new Promise((resolve, reject) => {
+ const fileReader = new FileReader();
+ fileReader.onload = (e) => resolve(e.target.result);
+ fileReader.onerror = (err) => reject(err);
+ fileReader.readAsText(files[0]);
+ });
+};
+
+const isSecret = (type) => {
+ return type === 'secret';
+};
+
+const importPostmanEnvironmentVariables = (brunoEnvironment, values) => {
+ brunoEnvironment.variables = brunoEnvironment.variables || [];
+
+ each(values, (i) => {
+ const brunoEnvironmentVariable = {
+ name: i.key,
+ value: i.value,
+ enabled: i.enabled,
+ secret: isSecret(i.type)
+ };
+
+ brunoEnvironment.variables.push(brunoEnvironmentVariable);
+ });
+};
+
+const importPostmanEnvironment = (environment) => {
+ const brunoEnvironment = {
+ name: environment.name,
+ variables: []
+ };
+
+ importPostmanEnvironmentVariables(brunoEnvironment, environment.values);
+ return brunoEnvironment;
+};
+
+const parsePostmanEnvironment = (str) => {
+ return new Promise((resolve, reject) => {
+ try {
+ let environment = JSON.parse(str);
+ return resolve(importPostmanEnvironment(environment));
+ } catch (err) {
+ console.log(err);
+ if (err instanceof BrunoError) {
+ return reject(err);
+ }
+ return reject(new BrunoError('Unable to parse the postman environment json file'));
+ }
+ });
+};
+
+const importEnvironment = () => {
+ return new Promise((resolve, reject) => {
+ fileDialog({ accept: 'application/json' })
+ .then(readFile)
+ .then(parsePostmanEnvironment)
+ .then((environment) => resolve(environment))
+ .catch((err) => {
+ console.log(err);
+ reject(new BrunoError('Import Environment failed'));
+ });
+ });
+};
+
+export default importEnvironment;
diff --git a/packages/bruno-electron/src/ipc/collection.js b/packages/bruno-electron/src/ipc/collection.js
index 3b121200..a78294b1 100644
--- a/packages/bruno-electron/src/ipc/collection.js
+++ b/packages/bruno-electron/src/ipc/collection.js
@@ -183,6 +183,28 @@ const registerRendererEventHandlers = (mainWindow, watcher, lastOpenedCollection
}
});
+ // copy environment
+ ipcMain.handle('renderer:import-environment', async (event, collectionPathname, name, variables) => {
+ try {
+ const envDirPath = path.join(collectionPathname, 'environments');
+ if (!fs.existsSync(envDirPath)) {
+ await createDirectory(envDirPath);
+ }
+
+ const envFilePath = path.join(envDirPath, `${name}.bru`);
+ if (fs.existsSync(envFilePath)) {
+ throw new Error(`environment: ${envFilePath} already exists`);
+ }
+
+ const content = envJsonToBru({
+ variables: variables
+ });
+ await writeFile(envFilePath, content);
+ } catch (error) {
+ return Promise.reject(error);
+ }
+ });
+
// save environment
ipcMain.handle('renderer:save-environment', async (event, collectionPathname, environment) => {
try {