From ae78ed36efdeaa7c440b104de164ee55860303b8 Mon Sep 17 00:00:00 2001 From: Sebastien Dionne Date: Fri, 6 Oct 2023 22:17:10 -0400 Subject: [PATCH 01/29] Building electron script in js to support different OS --- package.json | 5 +- packages/bruno-electron/package.json | 3 + scripts/build-electron.js | 98 ++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+), 2 deletions(-) create mode 100644 scripts/build-electron.js diff --git a/package.json b/package.json index 9aaaf23f2..bba854916 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,8 @@ "jest": "^29.2.0", "pretty-quick": "^3.1.3", "randomstring": "^1.2.2", - "ts-jest": "^29.0.5" + "ts-jest": "^29.0.5", + "fs-extra": "^11.1.1" }, "scripts": { "dev:web": "npm run dev --workspace=packages/bruno-app", @@ -31,7 +32,7 @@ "dev:electron": "npm run dev --workspace=packages/bruno-electron", "build:bruno-query": "npm run build --workspace=packages/bruno-query", "build:graphql-docs": "npm run build --workspace=packages/bruno-graphql-docs", - "build:electron": "./scripts/build-electron.sh", + "build:electron": "node ./scripts/build-electron.js", "test:e2e": "npx playwright test", "test:report": "npx playwright show-report", "prepare": "husky install" diff --git a/packages/bruno-electron/package.json b/packages/bruno-electron/package.json index 6cdd6914d..12883d8ff 100644 --- a/packages/bruno-electron/package.json +++ b/packages/bruno-electron/package.json @@ -10,6 +10,9 @@ "clean": "rimraf dist", "dev": "electron .", "dist": "electron-builder --mac --config electron-builder-config.js", + "dist-mac": "electron-builder --mac --config electron-builder-config.js", + "dist-win": "electron-builder --win --config electron-builder-config.js", + "dist-linux": "electron-builder --linux --config electron-builder-config.js", "pack": "electron-builder --dir", "test": "jest" }, diff --git a/scripts/build-electron.js b/scripts/build-electron.js new file mode 100644 index 000000000..363fdf4d2 --- /dev/null +++ b/scripts/build-electron.js @@ -0,0 +1,98 @@ +const os = require('os'); +const fs = require('fs-extra'); +const util = require('util'); +const exec = util.promisify(require('child_process').exec); + + +async function deleteFileIfExists(filePath) { + try { + const exists = await fs.pathExists(filePath); + if (exists) { + await fs.remove(filePath); + console.log(`${filePath} has been successfully deleted.`); + } else { + console.log(`${filePath} does not exist.`); + } + } catch (err) { + console.error(`Error while checking the existence of ${filePath}: ${err}`); + } +} + +async function copyFolderIfExists(srcPath, destPath) { + try { + const exists = await fs.pathExists(srcPath); + if (exists) { + await fs.copy(srcPath, destPath); + console.log(`${srcPath} has been successfully copied.`); + } else { + console.log(`${srcPath} was not copied as it does not exist.`); + } + } catch (err) { + console.error(`Error while checking the existence of ${srcPath}: ${err}`); + } +} + +async function removeSourceMapFiles(directory) { + try { + const files = await fs.readdir(directory); + for (const file of files) { + if (file.endsWith('.map')) { + const filePath = path.join(directory, file); + await fs.remove(filePath); + console.log(`${filePath} has been successfully deleted.`); + } + } + } catch (error) { + console.error(`Error while deleting .map files: ${error}`); + } +} + +async function main() { + try { + // Remove out directory + await deleteFileIfExists('packages/bruno-electron/out'); + + // Remove web directory + await deleteFileIfExists('packages/bruno-electron/web'); + + // Create a new web directory + await fs.ensureDir('packages/bruno-electron/web'); + console.log('The directory has been created successfully!'); + + // Copy build + await copyFolderIfExists('packages/bruno-app/out', 'packages/bruno-electron/web'); + + // Change paths in next + const files = await fs.readdir('packages/bruno-electron/web'); + for (const file of files) { + if (file.endsWith('.html')) { + let content = await fs.readFile(`packages/bruno-electron/web/${file}`, 'utf8'); + content = content.replace(/\/_next\//g, '/_next/'); + await fs.writeFile(`packages/bruno-electron/web/${file}`, content); + } + } + + // Remove sourcemaps + await removeSourceMapFiles('packages/bruno-electron/web') + + // Run npm dist command + console.log('Building the Electron distribution'); + + // Determine the OS and set the appropriate argument + let osArg; + if (os.platform() === 'win32') { + osArg = 'win'; + } else if (os.platform() === 'darwin') { + osArg = 'mac'; + } else { + osArg = 'linux'; + } + + await exec(`npm run dist-${osArg} --workspace=packages/bruno-electron`); + + } catch (error) { + console.error('An error occurred:', error); + } +} + +main(); From 21536f9a27666a35e151e0579f7c35ec7ff88c17 Mon Sep 17 00:00:00 2001 From: Sebastien Dionne Date: Sat, 7 Oct 2023 15:28:17 -0400 Subject: [PATCH 02/29] Support request name with "index" in the name if index is not separated --- .../bruno-app/src/components/Sidebar/NewRequest/index.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/bruno-app/src/components/Sidebar/NewRequest/index.js b/packages/bruno-app/src/components/Sidebar/NewRequest/index.js index f5753aced..55be133b8 100644 --- a/packages/bruno-app/src/components/Sidebar/NewRequest/index.js +++ b/packages/bruno-app/src/components/Sidebar/NewRequest/index.js @@ -30,7 +30,10 @@ const NewRequest = ({ collection, item, isEphemeral, onClose }) => { .test({ name: 'requestName', message: 'The request name "index" is reserved in bruno', - test: (value) => value && !value.trim().toLowerCase().includes('index') + test: (value) => { + const regex = /(\s|^)\W*index\W*(\s|$)/i; + return value && !regex.test(value); + } }) }), onSubmit: (values) => { From 5ef0de2e4d2e8f4e42e667ae5b7af0e3bebb2754 Mon Sep 17 00:00:00 2001 From: Sebastien Dionne Date: Sat, 7 Oct 2023 15:33:38 -0400 Subject: [PATCH 03/29] Revert "Building electron script in js to support different OS" This reverts commit ae78ed36efdeaa7c440b104de164ee55860303b8. --- package.json | 5 +- packages/bruno-electron/package.json | 3 - scripts/build-electron.js | 98 ---------------------------- 3 files changed, 2 insertions(+), 104 deletions(-) delete mode 100644 scripts/build-electron.js diff --git a/package.json b/package.json index bba854916..9aaaf23f2 100644 --- a/package.json +++ b/package.json @@ -22,8 +22,7 @@ "jest": "^29.2.0", "pretty-quick": "^3.1.3", "randomstring": "^1.2.2", - "ts-jest": "^29.0.5", - "fs-extra": "^11.1.1" + "ts-jest": "^29.0.5" }, "scripts": { "dev:web": "npm run dev --workspace=packages/bruno-app", @@ -32,7 +31,7 @@ "dev:electron": "npm run dev --workspace=packages/bruno-electron", "build:bruno-query": "npm run build --workspace=packages/bruno-query", "build:graphql-docs": "npm run build --workspace=packages/bruno-graphql-docs", - "build:electron": "node ./scripts/build-electron.js", + "build:electron": "./scripts/build-electron.sh", "test:e2e": "npx playwright test", "test:report": "npx playwright show-report", "prepare": "husky install" diff --git a/packages/bruno-electron/package.json b/packages/bruno-electron/package.json index 12883d8ff..6cdd6914d 100644 --- a/packages/bruno-electron/package.json +++ b/packages/bruno-electron/package.json @@ -10,9 +10,6 @@ "clean": "rimraf dist", "dev": "electron .", "dist": "electron-builder --mac --config electron-builder-config.js", - "dist-mac": "electron-builder --mac --config electron-builder-config.js", - "dist-win": "electron-builder --win --config electron-builder-config.js", - "dist-linux": "electron-builder --linux --config electron-builder-config.js", "pack": "electron-builder --dir", "test": "jest" }, diff --git a/scripts/build-electron.js b/scripts/build-electron.js deleted file mode 100644 index 363fdf4d2..000000000 --- a/scripts/build-electron.js +++ /dev/null @@ -1,98 +0,0 @@ -const os = require('os'); -const fs = require('fs-extra'); -const util = require('util'); -const exec = util.promisify(require('child_process').exec); - - -async function deleteFileIfExists(filePath) { - try { - const exists = await fs.pathExists(filePath); - if (exists) { - await fs.remove(filePath); - console.log(`${filePath} has been successfully deleted.`); - } else { - console.log(`${filePath} does not exist.`); - } - } catch (err) { - console.error(`Error while checking the existence of ${filePath}: ${err}`); - } -} - -async function copyFolderIfExists(srcPath, destPath) { - try { - const exists = await fs.pathExists(srcPath); - if (exists) { - await fs.copy(srcPath, destPath); - console.log(`${srcPath} has been successfully copied.`); - } else { - console.log(`${srcPath} was not copied as it does not exist.`); - } - } catch (err) { - console.error(`Error while checking the existence of ${srcPath}: ${err}`); - } -} - -async function removeSourceMapFiles(directory) { - try { - const files = await fs.readdir(directory); - for (const file of files) { - if (file.endsWith('.map')) { - const filePath = path.join(directory, file); - await fs.remove(filePath); - console.log(`${filePath} has been successfully deleted.`); - } - } - } catch (error) { - console.error(`Error while deleting .map files: ${error}`); - } -} - -async function main() { - try { - // Remove out directory - await deleteFileIfExists('packages/bruno-electron/out'); - - // Remove web directory - await deleteFileIfExists('packages/bruno-electron/web'); - - // Create a new web directory - await fs.ensureDir('packages/bruno-electron/web'); - console.log('The directory has been created successfully!'); - - // Copy build - await copyFolderIfExists('packages/bruno-app/out', 'packages/bruno-electron/web'); - - // Change paths in next - const files = await fs.readdir('packages/bruno-electron/web'); - for (const file of files) { - if (file.endsWith('.html')) { - let content = await fs.readFile(`packages/bruno-electron/web/${file}`, 'utf8'); - content = content.replace(/\/_next\//g, '/_next/'); - await fs.writeFile(`packages/bruno-electron/web/${file}`, content); - } - } - - // Remove sourcemaps - await removeSourceMapFiles('packages/bruno-electron/web') - - // Run npm dist command - console.log('Building the Electron distribution'); - - // Determine the OS and set the appropriate argument - let osArg; - if (os.platform() === 'win32') { - osArg = 'win'; - } else if (os.platform() === 'darwin') { - osArg = 'mac'; - } else { - osArg = 'linux'; - } - - await exec(`npm run dist-${osArg} --workspace=packages/bruno-electron`); - - } catch (error) { - console.error('An error occurred:', error); - } -} - -main(); From 905e993a13d2855d1be2dbfc3dcd56f895db814f Mon Sep 17 00:00:00 2001 From: game5413 Date: Sun, 8 Oct 2023 21:46:13 +0700 Subject: [PATCH 04/29] better experience for open dropdown collection --- .../Collection/CollectionItem/index.js | 60 ++++++++++++------- .../Sidebar/Collections/Collection/index.js | 18 +++++- 2 files changed, 53 insertions(+), 25 deletions(-) diff --git a/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/index.js b/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/index.js index f0cc8d360..0b33941f7 100644 --- a/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/index.js +++ b/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/index.js @@ -88,30 +88,44 @@ const CollectionItem = ({ item, collection, searchText }) => { }); const handleClick = (event) => { - if (isItemARequest(item)) { - if (itemIsOpenedInTabs(item, tabs)) { + switch (event.button) { + case 0: // left click + if (isItemARequest(item)) { + dispatch(hideHomePage()); + if (itemIsOpenedInTabs(item, tabs)) { + dispatch( + focusTab({ + uid: item.uid + }) + ); + return; + } + dispatch( + addTab({ + uid: item.uid, + collectionUid: collection.uid, + requestPaneTab: getDefaultRequestPaneTab(item) + }) + ); + return; + } dispatch( - focusTab({ - uid: item.uid + collectionFolderClicked({ + itemUid: item.uid, + collectionUid: collection.uid }) ); - } else { - dispatch( - addTab({ - uid: item.uid, - collectionUid: collection.uid, - requestPaneTab: getDefaultRequestPaneTab(item) - }) - ); - } - dispatch(hideHomePage()); - } else { - dispatch( - collectionFolderClicked({ - itemUid: item.uid, - collectionUid: collection.uid - }) - ); + return; + case 2: // right click + const _menuDropdown = dropdownTippyRef.current; + if (_menuDropdown) { + let menuDropdownBehavior = 'show'; + if (_menuDropdown.state.isShown) { + menuDropdownBehavior = 'hide'; + } + _menuDropdown[menuDropdownBehavior](); + } + return; } }; @@ -189,7 +203,7 @@ const CollectionItem = ({ item, collection, searchText }) => { ? indents.map((i) => { return (
{ }) : null}
{ }); const handleClick = (event) => { - dispatch(collectionClicked(collection.uid)); + const _menuDropdown = menuDropdownTippyRef.current; + switch (event.button) { + case 0: // left click + dispatch(collectionClicked(collection.uid)); + return; + case 2: // right click + if (_menuDropdown) { + let menuDropdownBehavior = 'show'; + if (_menuDropdown.state.isShown) { + menuDropdownBehavior = 'hide'; + } + _menuDropdown[menuDropdownBehavior](); + } + return; + } }; const handleExportClick = () => { @@ -119,7 +133,7 @@ const Collection = ({ collection, searchText }) => { setCollectionPropertiesModal(false)} /> )}
-
+
Date: Sun, 8 Oct 2023 10:04:16 -0500 Subject: [PATCH 05/29] feat: add support for socks5 proxy --- package-lock.json | 164 ++++++++++++++---- .../CollectionSettings/ProxySettings/index.js | 17 +- packages/bruno-electron/package.json | 1 + .../bruno-electron/src/ipc/network/index.js | 49 ++++-- 4 files changed, 180 insertions(+), 51 deletions(-) diff --git a/package-lock.json b/package-lock.json index 332917b37..7699a2239 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9356,6 +9356,11 @@ "node": ">=0.10.0" } }, + "node_modules/ip": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" + }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -13507,8 +13512,7 @@ "node_modules/react-is": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" }, "node_modules/react-redux": { "version": "7.2.9", @@ -14603,12 +14607,48 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "optional": true, "engines": { "node": ">= 6.0.0", "npm": ">= 3.0.0" } }, + "node_modules/socks": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", + "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "dependencies": { + "ip": "^2.0.0", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.2.tgz", + "integrity": "sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g==", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "socks": "^2.7.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/socks-proxy-agent/node_modules/agent-base": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", + "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -16647,7 +16687,7 @@ }, "packages/bruno-cli": { "name": "@usebruno/cli", - "version": "0.12.0", + "version": "0.13.0", "license": "MIT", "dependencies": { "@usebruno/js": "0.8.0", @@ -16730,7 +16770,7 @@ }, "packages/bruno-electron": { "name": "bruno", - "version": "v0.20.0", + "version": "v0.21.1", "dependencies": { "@usebruno/js": "0.8.0", "@usebruno/lang": "0.5.0", @@ -16757,6 +16797,7 @@ "nanoid": "3.3.4", "node-machine-id": "^1.1.12", "qs": "^6.11.0", + "socks-proxy-agent": "^8.0.2", "uuid": "^9.0.0", "vm2": "^3.9.13", "yup": "^0.32.11" @@ -19496,7 +19537,8 @@ "@tabler/icons": { "version": "1.119.0", "resolved": "https://registry.npmjs.org/@tabler/icons/-/icons-1.119.0.tgz", - "integrity": "sha512-Fk3Qq4w2SXcTjc/n1cuL5bccPkylrOMo7cYpQIf/yw6zP76LQV9dtLcHQUjFiUnaYuswR645CnURIhlafyAh9g==" + "integrity": "sha512-Fk3Qq4w2SXcTjc/n1cuL5bccPkylrOMo7cYpQIf/yw6zP76LQV9dtLcHQUjFiUnaYuswR645CnURIhlafyAh9g==", + "requires": {} }, "@tauri-apps/cli": { "version": "1.2.2", @@ -20117,7 +20159,8 @@ } }, "@usebruno/schema": { - "version": "file:packages/bruno-schema" + "version": "file:packages/bruno-schema", + "requires": {} }, "@usebruno/testbench": { "version": "file:packages/bruno-testbench", @@ -20293,7 +20336,8 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.2.0.tgz", "integrity": "sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg==", - "dev": true + "dev": true, + "requires": {} }, "@webpack-cli/info": { "version": "1.5.0", @@ -20308,7 +20352,8 @@ "version": "1.7.0", "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.7.0.tgz", "integrity": "sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q==", - "dev": true + "dev": true, + "requires": {} }, "@xtuc/ieee754": { "version": "1.2.0", @@ -20413,7 +20458,8 @@ "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true + "dev": true, + "requires": {} }, "amdefine": { "version": "0.0.8", @@ -21115,6 +21161,7 @@ "nanoid": "3.3.4", "node-machine-id": "^1.1.12", "qs": "^6.11.0", + "socks-proxy-agent": "*", "uuid": "^9.0.0", "vm2": "^3.9.13", "yup": "^0.32.11" @@ -22011,7 +22058,8 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.3.1.tgz", "integrity": "sha512-fBffmak0bPAnyqc/HO8C3n2sHrp9wcqQz6ES9koRF2/mLOVAx9zIQ3Y7R29sYCteTPqMCwns4WYQoCX91Xl3+w==", - "dev": true + "dev": true, + "requires": {} }, "css-loader": { "version": "6.7.3", @@ -22156,7 +22204,8 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.1.0.tgz", "integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==", - "dev": true + "dev": true, + "requires": {} }, "csso": { "version": "4.2.0", @@ -23617,7 +23666,8 @@ "goober": { "version": "2.1.11", "resolved": "https://registry.npmjs.org/goober/-/goober-2.1.11.tgz", - "integrity": "sha512-5SS2lmxbhqH0u9ABEWq7WPU69a4i2pYcHeCxqaNq6Cw3mnrF0ghWNM4tEGid4dKy8XNIAUbuThuozDHHKJVh3A==" + "integrity": "sha512-5SS2lmxbhqH0u9ABEWq7WPU69a4i2pYcHeCxqaNq6Cw3mnrF0ghWNM4tEGid4dKy8XNIAUbuThuozDHHKJVh3A==", + "requires": {} }, "got": { "version": "9.6.0", @@ -24090,7 +24140,8 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", - "dev": true + "dev": true, + "requires": {} }, "idb": { "version": "7.1.1", @@ -24308,6 +24359,11 @@ "integrity": "sha512-xgs2NH9AE66ucSq4cNG1nhSFghr5l6tdL15Pk+jl46bmmBapgoaY/AacXyaDznAqmGL99TiLSQgO/XazFSKYeQ==", "dev": true }, + "ip": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" + }, "ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -24869,7 +24925,8 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", - "dev": true + "dev": true, + "requires": {} }, "jest-regex-util": { "version": "29.2.0", @@ -25631,7 +25688,8 @@ "meros": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/meros/-/meros-1.2.1.tgz", - "integrity": "sha512-R2f/jxYqCAGI19KhAvaxSOxALBMkaXWH2a7rOyqQw+ZmizX5bKkEYWLzdhC+U82ZVVPVp6MCXe3EkVligh+12g==" + "integrity": "sha512-R2f/jxYqCAGI19KhAvaxSOxALBMkaXWH2a7rOyqQw+ZmizX5bKkEYWLzdhC+U82ZVVPVp6MCXe3EkVligh+12g==", + "requires": {} }, "methods": { "version": "1.1.2", @@ -26661,25 +26719,29 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz", "integrity": "sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==", - "dev": true + "dev": true, + "requires": {} }, "postcss-discard-duplicates": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz", "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==", - "dev": true + "dev": true, + "requires": {} }, "postcss-discard-empty": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz", "integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==", - "dev": true + "dev": true, + "requires": {} }, "postcss-discard-overridden": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz", "integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==", - "dev": true + "dev": true, + "requires": {} }, "postcss-js": { "version": "3.0.3", @@ -26781,7 +26843,8 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", - "dev": true + "dev": true, + "requires": {} }, "postcss-modules-local-by-default": { "version": "4.0.0", @@ -26824,7 +26887,8 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz", "integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==", - "dev": true + "dev": true, + "requires": {} }, "postcss-normalize-display-values": { "version": "5.1.0", @@ -27345,13 +27409,13 @@ "react-inspector": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/react-inspector/-/react-inspector-6.0.2.tgz", - "integrity": "sha512-x+b7LxhmHXjHoU/VrFAzw5iutsILRoYyDq97EDYdFpPLcvqtEzk4ZSZSQjnFPbr5T57tLXnHcqFYoN1pI6u8uQ==" + "integrity": "sha512-x+b7LxhmHXjHoU/VrFAzw5iutsILRoYyDq97EDYdFpPLcvqtEzk4ZSZSQjnFPbr5T57tLXnHcqFYoN1pI6u8uQ==", + "requires": {} }, "react-is": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" }, "react-redux": { "version": "7.2.9", @@ -27538,7 +27602,8 @@ "redux-thunk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.2.tgz", - "integrity": "sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==" + "integrity": "sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==", + "requires": {} }, "regenerate": { "version": "1.4.2", @@ -27840,7 +27905,8 @@ "version": "2.2.4", "resolved": "https://registry.npmjs.org/rollup-plugin-peer-deps-external/-/rollup-plugin-peer-deps-external-2.2.4.tgz", "integrity": "sha512-AWdukIM1+k5JDdAqV/Cxd+nejvno2FVLVeZ74NKggm3Q5s9cbbcOgUPGdbxPi4BXu7xGaZ8HG12F+thImYu/0g==", - "dev": true + "dev": true, + "requires": {} }, "rollup-plugin-postcss": { "version": "4.0.2", @@ -28224,8 +28290,36 @@ "smart-buffer": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "optional": true + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==" + }, + "socks": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", + "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "requires": { + "ip": "^2.0.0", + "smart-buffer": "^4.2.0" + } + }, + "socks-proxy-agent": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.2.tgz", + "integrity": "sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g==", + "requires": { + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "socks": "^2.7.1" + }, + "dependencies": { + "agent-base": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", + "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", + "requires": { + "debug": "^4.3.4" + } + } + } }, "source-map": { "version": "0.6.1", @@ -28453,7 +28547,8 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.1.tgz", "integrity": "sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ==", - "dev": true + "dev": true, + "requires": {} }, "styled-components": { "version": "5.3.6", @@ -28490,7 +28585,8 @@ "styled-jsx": { "version": "5.0.7", "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.0.7.tgz", - "integrity": "sha512-b3sUzamS086YLRuvnaDigdAewz1/EFYlHpYBP5mZovKEdQQOIIYq8lApylub3HHZ6xFjV051kkGU7cudJmrXEA==" + "integrity": "sha512-b3sUzamS086YLRuvnaDigdAewz1/EFYlHpYBP5mZovKEdQQOIIYq8lApylub3HHZ6xFjV051kkGU7cudJmrXEA==", + "requires": {} }, "stylehacks": { "version": "5.1.1", @@ -29228,7 +29324,8 @@ "use-sync-external-store": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", - "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==" + "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", + "requires": {} }, "utf8-byte-length": { "version": "1.0.4", @@ -29441,7 +29538,8 @@ "version": "1.8.0", "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", - "dev": true + "dev": true, + "requires": {} }, "schema-utils": { "version": "3.1.1", diff --git a/packages/bruno-app/src/components/CollectionSettings/ProxySettings/index.js b/packages/bruno-app/src/components/CollectionSettings/ProxySettings/index.js index c3746f566..62e686708 100644 --- a/packages/bruno-app/src/components/CollectionSettings/ProxySettings/index.js +++ b/packages/bruno-app/src/components/CollectionSettings/ProxySettings/index.js @@ -19,7 +19,7 @@ const ProxySettings = ({ proxyConfig, onUpdate }) => { }, validationSchema: Yup.object({ enabled: Yup.boolean(), - protocol: Yup.string().oneOf(['http', 'https']), + protocol: Yup.string().oneOf(['http', 'https', 'socks5']), hostname: Yup.string().max(1024), port: Yup.number().min(0).max(65535), auth: Yup.object({ @@ -62,7 +62,7 @@ const ProxySettings = ({ proxyConfig, onUpdate }) => { Protocol
-
diff --git a/packages/bruno-electron/package.json b/packages/bruno-electron/package.json index 033d4b696..d614bf58f 100644 --- a/packages/bruno-electron/package.json +++ b/packages/bruno-electron/package.json @@ -39,6 +39,7 @@ "nanoid": "3.3.4", "node-machine-id": "^1.1.12", "qs": "^6.11.0", + "socks-proxy-agent": "^8.0.2", "uuid": "^9.0.0", "vm2": "^3.9.13", "yup": "^0.32.11" diff --git a/packages/bruno-electron/src/ipc/network/index.js b/packages/bruno-electron/src/ipc/network/index.js index a0b66099c..103ea967e 100644 --- a/packages/bruno-electron/src/ipc/network/index.js +++ b/packages/bruno-electron/src/ipc/network/index.js @@ -19,6 +19,7 @@ const { getProcessEnvVars } = require('../../store/process-env'); const { getBrunoConfig } = require('../../store/bruno-config'); const { HttpsProxyAgent } = require('https-proxy-agent'); const { HttpProxyAgent } = require('http-proxy-agent'); +const { SocksProxyAgent } = require('socks-proxy-agent'); const { makeAxiosInstance } = require('./axios-instance'); // override the default escape function to prevent escaping @@ -220,7 +221,7 @@ const registerNetworkIpc = (mainWindow) => { const brunoConfig = getBrunoConfig(collectionUid); const proxyEnabled = get(brunoConfig, 'proxy.enabled', false); if (proxyEnabled) { - let proxy; + let proxyUri; const interpolationOptions = { envVars, @@ -232,22 +233,31 @@ const registerNetworkIpc = (mainWindow) => { const proxyHostname = interpolateString(get(brunoConfig, 'proxy.hostname'), interpolationOptions); const proxyPort = interpolateString(get(brunoConfig, 'proxy.port'), interpolationOptions); const proxyAuthEnabled = get(brunoConfig, 'proxy.auth.enabled', false); + const socksEnabled = proxyProtocol.includes('socks'); if (proxyAuthEnabled) { const proxyAuthUsername = interpolateString(get(brunoConfig, 'proxy.auth.username'), interpolationOptions); const proxyAuthPassword = interpolateString(get(brunoConfig, 'proxy.auth.password'), interpolationOptions); - proxy = `${proxyProtocol}://${proxyAuthUsername}:${proxyAuthPassword}@${proxyHostname}:${proxyPort}`; + proxyUri = `${proxyProtocol}://${proxyAuthUsername}:${proxyAuthPassword}@${proxyHostname}:${proxyPort}`; } else { - proxy = `${proxyProtocol}://${proxyHostname}:${proxyPort}`; + proxyUri = `${proxyProtocol}://${proxyHostname}:${proxyPort}`; } - request.httpsAgent = new HttpsProxyAgent( - proxy, - Object.keys(httpsAgentRequestFields).length > 0 ? { ...httpsAgentRequestFields } : undefined - ); + if (socksEnabled) { + const socksProxyAgent = new SocksProxyAgent(proxyUri); - request.httpAgent = new HttpProxyAgent(proxy); + request.httpsAgent = socksProxyAgent; + + request.httpAgent = socksProxyAgent; + } else { + request.httpsAgent = new HttpsProxyAgent( + proxyUri, + Object.keys(httpsAgentRequestFields).length > 0 ? { ...httpsAgentRequestFields } : undefined + ); + + request.httpAgent = new HttpProxyAgent(proxyUri); + } } else if (Object.keys(httpsAgentRequestFields).length > 0) { request.httpsAgent = new https.Agent({ ...httpsAgentRequestFields @@ -656,7 +666,7 @@ const registerNetworkIpc = (mainWindow) => { const brunoConfig = getBrunoConfig(collectionUid); const proxyEnabled = get(brunoConfig, 'proxy.enabled', false); if (proxyEnabled) { - let proxy; + let proxyUri; const interpolationOptions = { envVars, collectionVariables, @@ -667,6 +677,7 @@ const registerNetworkIpc = (mainWindow) => { const proxyHostname = interpolateString(get(brunoConfig, 'proxy.hostname'), interpolationOptions); const proxyPort = interpolateString(get(brunoConfig, 'proxy.port'), interpolationOptions); const proxyAuthEnabled = get(brunoConfig, 'proxy.auth.enabled', false); + const socksEnabled = proxyProtocol.includes('socks'); if (proxyAuthEnabled) { const proxyAuthUsername = interpolateString( @@ -679,16 +690,24 @@ const registerNetworkIpc = (mainWindow) => { interpolationOptions ); - proxy = `${proxyProtocol}://${proxyAuthUsername}:${proxyAuthPassword}@${proxyHostname}:${proxyPort}`; + proxyUri = `${proxyProtocol}://${proxyAuthUsername}:${proxyAuthPassword}@${proxyHostname}:${proxyPort}`; } else { - proxy = `${proxyProtocol}://${proxyHostname}:${proxyPort}`; + proxyUri = `${proxyProtocol}://${proxyHostname}:${proxyPort}`; } - request.httpsAgent = new HttpsProxyAgent(proxy, { - rejectUnauthorized: sslVerification - }); + if (socksEnabled) { + const socksProxyAgent = new SocksProxyAgent(proxyUri); - request.httpAgent = new HttpProxyAgent(proxy); + request.httpsAgent = socksProxyAgent; + + request.httpAgent = socksProxyAgent; + } else { + request.httpsAgent = new HttpsProxyAgent(proxyUri, { + rejectUnauthorized: sslVerification + }); + + request.httpAgent = new HttpProxyAgent(proxyUri); + } } else if (!sslVerification) { request.httpsAgent = new https.Agent({ rejectUnauthorized: false From bf90ee96e518484368027743fe31406fd415d930 Mon Sep 17 00:00:00 2001 From: "Ricardo Q. Bazan" Date: Sun, 8 Oct 2023 12:09:33 -0500 Subject: [PATCH 06/29] chore: add support for cli --- package-lock.json | 4 ++- packages/bruno-cli/package.json | 1 + .../src/runner/run-single-request.js | 26 +++++++++++++------ 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7699a2239..bd7f4911c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16705,6 +16705,7 @@ "lodash": "^4.17.21", "mustache": "^4.2.0", "qs": "^6.11.0", + "socks-proxy-agent": "^8.0.2", "yargs": "^17.6.2" }, "bin": { @@ -20024,6 +20025,7 @@ "lodash": "^4.17.21", "mustache": "^4.2.0", "qs": "^6.11.0", + "socks-proxy-agent": "*", "yargs": "^17.6.2" }, "dependencies": { @@ -21161,7 +21163,7 @@ "nanoid": "3.3.4", "node-machine-id": "^1.1.12", "qs": "^6.11.0", - "socks-proxy-agent": "*", + "socks-proxy-agent": "^8.0.2", "uuid": "^9.0.0", "vm2": "^3.9.13", "yup": "^0.32.11" diff --git a/packages/bruno-cli/package.json b/packages/bruno-cli/package.json index dca3a8231..77d7bc596 100644 --- a/packages/bruno-cli/package.json +++ b/packages/bruno-cli/package.json @@ -39,6 +39,7 @@ "lodash": "^4.17.21", "mustache": "^4.2.0", "qs": "^6.11.0", + "socks-proxy-agent": "^8.0.2", "yargs": "^17.6.2" } } diff --git a/packages/bruno-cli/src/runner/run-single-request.js b/packages/bruno-cli/src/runner/run-single-request.js index f86e1b028..3e56bf0a5 100644 --- a/packages/bruno-cli/src/runner/run-single-request.js +++ b/packages/bruno-cli/src/runner/run-single-request.js @@ -13,6 +13,7 @@ const { getOptions } = require('../utils/bru'); const https = require('https'); const { HttpsProxyAgent } = require('https-proxy-agent'); const { HttpProxyAgent } = require('http-proxy-agent'); +const { SocksProxyAgent } = require('socks-proxy-agent'); const { makeAxiosInstance } = require('../utils/axios-instance'); const runSingleRequest = async function ( @@ -96,7 +97,7 @@ const runSingleRequest = async function ( // set proxy if enabled const proxyEnabled = get(brunoConfig, 'proxy.enabled', false); if (proxyEnabled) { - let proxy; + let proxyUri; const interpolationOptions = { envVars: envVariables, collectionVariables, @@ -107,6 +108,7 @@ const runSingleRequest = async function ( const proxyHostname = interpolateString(get(brunoConfig, 'proxy.hostname'), interpolationOptions); const proxyPort = interpolateString(get(brunoConfig, 'proxy.port'), interpolationOptions); const proxyAuthEnabled = get(brunoConfig, 'proxy.auth.enabled', false); + const socksEnabled = proxyProtocol.includes('socks'); interpolateString; @@ -114,17 +116,25 @@ const runSingleRequest = async function ( const proxyAuthUsername = interpolateString(get(brunoConfig, 'proxy.auth.username'), interpolationOptions); const proxyAuthPassword = interpolateString(get(brunoConfig, 'proxy.auth.password'), interpolationOptions); - proxy = `${proxyProtocol}://${proxyAuthUsername}:${proxyAuthPassword}@${proxyHostname}:${proxyPort}`; + proxyUri = `${proxyProtocol}://${proxyAuthUsername}:${proxyAuthPassword}@${proxyHostname}:${proxyPort}`; } else { - proxy = `${proxyProtocol}://${proxyHostname}:${proxyPort}`; + proxyUri = `${proxyProtocol}://${proxyHostname}:${proxyPort}`; } - request.httpsAgent = new HttpsProxyAgent( - proxy, - Object.keys(httpsAgentRequestFields).length > 0 ? { ...httpsAgentRequestFields } : undefined - ); + if (socksEnabled) { + const socksProxyAgent = new SocksProxyAgent(proxyUri); - request.httpAgent = new HttpProxyAgent(proxy); + request.httpsAgent = socksProxyAgent; + + request.httpAgent = socksProxyAgent; + } else { + request.httpsAgent = new HttpsProxyAgent( + proxyUri, + Object.keys(httpsAgentRequestFields).length > 0 ? { ...httpsAgentRequestFields } : undefined + ); + + request.httpAgent = new HttpProxyAgent(proxyUri); + } } else if (Object.keys(httpsAgentRequestFields).length > 0) { request.httpsAgent = new https.Agent({ ...httpsAgentRequestFields From 1ce8d707f1b4cc461235333174b3bdcb290c9c40 Mon Sep 17 00:00:00 2001 From: Anoop M D Date: Mon, 9 Oct 2023 06:18:05 +0530 Subject: [PATCH 07/29] feat(#334): collection level headers, auth, scripts and tests --- .../Auth/AuthMode/StyledWrapper.js | 28 + .../CollectionSettings/Auth/AuthMode/index.js | 69 ++ .../Auth/BasicAuth/StyledWrapper.js | 16 + .../Auth/BasicAuth/index.js | 71 ++ .../Auth/BearerAuth/StyledWrapper.js | 16 + .../Auth/BearerAuth/index.js | 46 ++ .../CollectionSettings/Auth/StyledWrapper.js | 5 + .../CollectionSettings/Auth/index.js | 42 ++ .../Headers/StyledWrapper.js | 56 ++ .../CollectionSettings/Headers/index.js | 151 +++++ .../CollectionSettings/ProxySettings/index.js | 17 +- .../Script/StyledWrapper.js | 13 + .../CollectionSettings/Script/index.js | 73 +++ .../CollectionSettings/StyledWrapper.js | 26 + .../CollectionSettings/Tests/StyledWrapper.js | 5 + .../CollectionSettings/Tests/index.js | 47 ++ .../components/CollectionSettings/index.js | 64 +- .../RequestTabs/RequestTab/SpecialTab.js | 2 +- .../bruno-app/src/providers/Hotkeys/index.js | 3 +- .../ReduxStore/slices/collections/actions.js | 23 + .../ReduxStore/slices/collections/index.js | 118 ++++ packages/bruno-app/src/styles/globals.css | 13 +- packages/bruno-app/src/utils/network/index.js | 2 +- packages/bruno-electron/src/app/watcher.js | 72 ++- packages/bruno-electron/src/bru/index.js | 57 +- packages/bruno-electron/src/ipc/collection.js | 13 +- .../bruno-electron/src/ipc/network/index.js | 609 +++++++++--------- .../src/ipc/network/prepare-request.js | 30 +- packages/bruno-lang/src/index.js | 16 +- .../bruno-lang/v2/src/jsonToCollectionBru.js | 4 +- readme.md | 1 + 31 files changed, 1380 insertions(+), 328 deletions(-) create mode 100644 packages/bruno-app/src/components/CollectionSettings/Auth/AuthMode/StyledWrapper.js create mode 100644 packages/bruno-app/src/components/CollectionSettings/Auth/AuthMode/index.js create mode 100644 packages/bruno-app/src/components/CollectionSettings/Auth/BasicAuth/StyledWrapper.js create mode 100644 packages/bruno-app/src/components/CollectionSettings/Auth/BasicAuth/index.js create mode 100644 packages/bruno-app/src/components/CollectionSettings/Auth/BearerAuth/StyledWrapper.js create mode 100644 packages/bruno-app/src/components/CollectionSettings/Auth/BearerAuth/index.js create mode 100644 packages/bruno-app/src/components/CollectionSettings/Auth/StyledWrapper.js create mode 100644 packages/bruno-app/src/components/CollectionSettings/Auth/index.js create mode 100644 packages/bruno-app/src/components/CollectionSettings/Headers/StyledWrapper.js create mode 100644 packages/bruno-app/src/components/CollectionSettings/Headers/index.js create mode 100644 packages/bruno-app/src/components/CollectionSettings/Script/StyledWrapper.js create mode 100644 packages/bruno-app/src/components/CollectionSettings/Script/index.js create mode 100644 packages/bruno-app/src/components/CollectionSettings/Tests/StyledWrapper.js create mode 100644 packages/bruno-app/src/components/CollectionSettings/Tests/index.js diff --git a/packages/bruno-app/src/components/CollectionSettings/Auth/AuthMode/StyledWrapper.js b/packages/bruno-app/src/components/CollectionSettings/Auth/AuthMode/StyledWrapper.js new file mode 100644 index 000000000..cdbdf8424 --- /dev/null +++ b/packages/bruno-app/src/components/CollectionSettings/Auth/AuthMode/StyledWrapper.js @@ -0,0 +1,28 @@ +import styled from 'styled-components'; + +const Wrapper = styled.div` + font-size: 0.8125rem; + + .auth-mode-selector { + background: transparent; + + .auth-mode-label { + color: ${(props) => props.theme.colors.text.yellow}; + } + + .dropdown-item { + padding: 0.2rem 0.6rem !important; + } + + .label-item { + padding: 0.2rem 0.6rem !important; + } + } + + .caret { + color: rgb(140, 140, 140); + fill: rgb(140 140 140); + } +`; + +export default Wrapper; diff --git a/packages/bruno-app/src/components/CollectionSettings/Auth/AuthMode/index.js b/packages/bruno-app/src/components/CollectionSettings/Auth/AuthMode/index.js new file mode 100644 index 000000000..2e0abe572 --- /dev/null +++ b/packages/bruno-app/src/components/CollectionSettings/Auth/AuthMode/index.js @@ -0,0 +1,69 @@ +import React, { useRef, forwardRef } from 'react'; +import get from 'lodash/get'; +import { IconCaretDown } from '@tabler/icons'; +import Dropdown from 'components/Dropdown'; +import { useDispatch } from 'react-redux'; +import { updateCollectionAuthMode } from 'providers/ReduxStore/slices/collections'; +import { humanizeRequestAuthMode } from 'utils/collections'; +import StyledWrapper from './StyledWrapper'; + +const AuthMode = ({ collection }) => { + const dispatch = useDispatch(); + const dropdownTippyRef = useRef(); + const onDropdownCreate = (ref) => (dropdownTippyRef.current = ref); + const authMode = get(collection, 'root.request.auth.mode'); + + const Icon = forwardRef((props, ref) => { + return ( +
+ {humanizeRequestAuthMode(authMode)} +
+ ); + }); + + const onModeChange = (value) => { + dispatch( + updateCollectionAuthMode({ + collectionUid: collection.uid, + mode: value + }) + ); + }; + + return ( + +
+ } placement="bottom-end"> +
{ + dropdownTippyRef.current.hide(); + onModeChange('basic'); + }} + > + Basic Auth +
+
{ + dropdownTippyRef.current.hide(); + onModeChange('bearer'); + }} + > + Bearer Token +
+
{ + dropdownTippyRef.current.hide(); + onModeChange('none'); + }} + > + No Auth +
+
+
+
+ ); +}; +export default AuthMode; diff --git a/packages/bruno-app/src/components/CollectionSettings/Auth/BasicAuth/StyledWrapper.js b/packages/bruno-app/src/components/CollectionSettings/Auth/BasicAuth/StyledWrapper.js new file mode 100644 index 000000000..c2bb5d207 --- /dev/null +++ b/packages/bruno-app/src/components/CollectionSettings/Auth/BasicAuth/StyledWrapper.js @@ -0,0 +1,16 @@ +import styled from 'styled-components'; + +const Wrapper = styled.div` + label { + font-size: 0.8125rem; + } + + .single-line-editor-wrapper { + padding: 0.15rem 0.4rem; + border-radius: 3px; + border: solid 1px ${(props) => props.theme.input.border}; + background-color: ${(props) => props.theme.input.bg}; + } +`; + +export default Wrapper; diff --git a/packages/bruno-app/src/components/CollectionSettings/Auth/BasicAuth/index.js b/packages/bruno-app/src/components/CollectionSettings/Auth/BasicAuth/index.js new file mode 100644 index 000000000..b09cf1175 --- /dev/null +++ b/packages/bruno-app/src/components/CollectionSettings/Auth/BasicAuth/index.js @@ -0,0 +1,71 @@ +import React from 'react'; +import get from 'lodash/get'; +import { useTheme } from 'providers/Theme'; +import { useDispatch } from 'react-redux'; +import SingleLineEditor from 'components/SingleLineEditor'; +import { updateCollectionAuth } from 'providers/ReduxStore/slices/collections'; +import { saveCollectionRoot } from 'providers/ReduxStore/slices/collections/actions'; +import StyledWrapper from './StyledWrapper'; + +const BasicAuth = ({ collection }) => { + const dispatch = useDispatch(); + const { storedTheme } = useTheme(); + + const basicAuth = get(collection, 'root.request.auth.basic', {}); + + const handleSave = () => dispatch(saveCollectionRoot(collection.uid)); + + const handleUsernameChange = (username) => { + dispatch( + updateCollectionAuth({ + mode: 'basic', + collectionUid: collection.uid, + content: { + username: username, + password: basicAuth.password + } + }) + ); + }; + + const handlePasswordChange = (password) => { + dispatch( + updateCollectionAuth({ + mode: 'basic', + collectionUid: collection.uid, + content: { + username: basicAuth.username, + password: password + } + }) + ); + }; + + return ( + + +
+ handleUsernameChange(val)} + collection={collection} + /> +
+ + +
+ handlePasswordChange(val)} + collection={collection} + /> +
+
+ ); +}; + +export default BasicAuth; diff --git a/packages/bruno-app/src/components/CollectionSettings/Auth/BearerAuth/StyledWrapper.js b/packages/bruno-app/src/components/CollectionSettings/Auth/BearerAuth/StyledWrapper.js new file mode 100644 index 000000000..c2bb5d207 --- /dev/null +++ b/packages/bruno-app/src/components/CollectionSettings/Auth/BearerAuth/StyledWrapper.js @@ -0,0 +1,16 @@ +import styled from 'styled-components'; + +const Wrapper = styled.div` + label { + font-size: 0.8125rem; + } + + .single-line-editor-wrapper { + padding: 0.15rem 0.4rem; + border-radius: 3px; + border: solid 1px ${(props) => props.theme.input.border}; + background-color: ${(props) => props.theme.input.bg}; + } +`; + +export default Wrapper; diff --git a/packages/bruno-app/src/components/CollectionSettings/Auth/BearerAuth/index.js b/packages/bruno-app/src/components/CollectionSettings/Auth/BearerAuth/index.js new file mode 100644 index 000000000..701a4d7fa --- /dev/null +++ b/packages/bruno-app/src/components/CollectionSettings/Auth/BearerAuth/index.js @@ -0,0 +1,46 @@ +import React from 'react'; +import get from 'lodash/get'; +import { useTheme } from 'providers/Theme'; +import { useDispatch } from 'react-redux'; +import SingleLineEditor from 'components/SingleLineEditor'; +import { updateCollectionAuth } from 'providers/ReduxStore/slices/collections'; +import { saveCollectionRoot } from 'providers/ReduxStore/slices/collections/actions'; +import StyledWrapper from './StyledWrapper'; + +const BearerAuth = ({ collection }) => { + const dispatch = useDispatch(); + const { storedTheme } = useTheme(); + + const bearerToken = get(collection, 'root.request.auth.bearer.token'); + + const handleSave = () => dispatch(saveCollectionRoot(collection.uid)); + + const handleTokenChange = (token) => { + dispatch( + updateCollectionAuth({ + mode: 'bearer', + collectionUid: collection.uid, + content: { + token: token + } + }) + ); + }; + + return ( + + +
+ handleTokenChange(val)} + collection={collection} + /> +
+
+ ); +}; + +export default BearerAuth; diff --git a/packages/bruno-app/src/components/CollectionSettings/Auth/StyledWrapper.js b/packages/bruno-app/src/components/CollectionSettings/Auth/StyledWrapper.js new file mode 100644 index 000000000..e49220854 --- /dev/null +++ b/packages/bruno-app/src/components/CollectionSettings/Auth/StyledWrapper.js @@ -0,0 +1,5 @@ +import styled from 'styled-components'; + +const Wrapper = styled.div``; + +export default Wrapper; diff --git a/packages/bruno-app/src/components/CollectionSettings/Auth/index.js b/packages/bruno-app/src/components/CollectionSettings/Auth/index.js new file mode 100644 index 000000000..fe2fd5b33 --- /dev/null +++ b/packages/bruno-app/src/components/CollectionSettings/Auth/index.js @@ -0,0 +1,42 @@ +import React from 'react'; +import get from 'lodash/get'; +import { useDispatch } from 'react-redux'; +import AuthMode from './AuthMode'; +import BearerAuth from './BearerAuth'; +import BasicAuth from './BasicAuth'; +import { saveCollectionRoot } from 'providers/ReduxStore/slices/collections/actions'; +import StyledWrapper from './StyledWrapper'; + +const Auth = ({ collection }) => { + const authMode = get(collection, 'root.request.auth.mode'); + const dispatch = useDispatch(); + + const handleSave = () => dispatch(saveCollectionRoot(collection.uid)); + + const getAuthView = () => { + switch (authMode) { + case 'basic': { + return ; + } + case 'bearer': { + return ; + } + } + }; + + return ( + +
+ +
+ {getAuthView()} + +
+ +
+
+ ); +}; +export default Auth; diff --git a/packages/bruno-app/src/components/CollectionSettings/Headers/StyledWrapper.js b/packages/bruno-app/src/components/CollectionSettings/Headers/StyledWrapper.js new file mode 100644 index 000000000..9f723cb81 --- /dev/null +++ b/packages/bruno-app/src/components/CollectionSettings/Headers/StyledWrapper.js @@ -0,0 +1,56 @@ +import styled from 'styled-components'; + +const Wrapper = styled.div` + table { + width: 100%; + border-collapse: collapse; + font-weight: 600; + table-layout: fixed; + + thead, + td { + border: 1px solid ${(props) => props.theme.table.border}; + } + + thead { + color: ${(props) => props.theme.table.thead.color}; + font-size: 0.8125rem; + user-select: none; + } + td { + padding: 6px 10px; + + &:nth-child(1) { + width: 30%; + } + + &:nth-child(3) { + width: 70px; + } + } + } + + .btn-add-header { + font-size: 0.8125rem; + } + + input[type='text'] { + width: 100%; + border: solid 1px transparent; + outline: none !important; + background-color: inherit; + + &:focus { + outline: none !important; + border: solid 1px transparent; + } + } + + input[type='checkbox'] { + cursor: pointer; + position: relative; + top: 1px; + } +`; + +export default Wrapper; diff --git a/packages/bruno-app/src/components/CollectionSettings/Headers/index.js b/packages/bruno-app/src/components/CollectionSettings/Headers/index.js new file mode 100644 index 000000000..9ce78bc1c --- /dev/null +++ b/packages/bruno-app/src/components/CollectionSettings/Headers/index.js @@ -0,0 +1,151 @@ +import React from 'react'; +import get from 'lodash/get'; +import cloneDeep from 'lodash/cloneDeep'; +import { IconTrash } from '@tabler/icons'; +import { useDispatch } from 'react-redux'; +import { useTheme } from 'providers/Theme'; +import { + addCollectionHeader, + updateCollectionHeader, + deleteCollectionHeader +} from 'providers/ReduxStore/slices/collections'; +import { saveCollectionRoot } from 'providers/ReduxStore/slices/collections/actions'; +import SingleLineEditor from 'components/SingleLineEditor'; +import StyledWrapper from './StyledWrapper'; +import { headers as StandardHTTPHeaders } from 'know-your-http-well'; +const headerAutoCompleteList = StandardHTTPHeaders.map((e) => e.header); + +const Headers = ({ collection }) => { + const dispatch = useDispatch(); + const { storedTheme } = useTheme(); + const headers = get(collection, 'root.request.headers', []); + + const addHeader = () => { + dispatch( + addCollectionHeader({ + collectionUid: collection.uid + }) + ); + }; + + const handleSave = () => dispatch(saveCollectionRoot(collection.uid)); + const handleHeaderValueChange = (e, _header, type) => { + const header = cloneDeep(_header); + switch (type) { + case 'name': { + header.name = e.target.value; + break; + } + case 'value': { + header.value = e.target.value; + break; + } + case 'enabled': { + header.enabled = e.target.checked; + break; + } + } + dispatch( + updateCollectionHeader({ + header: header, + collectionUid: collection.uid + }) + ); + }; + + const handleRemoveHeader = (header) => { + dispatch( + deleteCollectionHeader({ + headerUid: header.uid, + collectionUid: collection.uid + }) + ); + }; + + return ( + + + + + + + + + + + {headers && headers.length + ? headers.map((header) => { + return ( + + + + + + ); + }) + : null} + +
NameValue
+ + handleHeaderValueChange( + { + target: { + value: newValue + } + }, + header, + 'name' + ) + } + autocomplete={headerAutoCompleteList} + collection={collection} + /> + + + handleHeaderValueChange( + { + target: { + value: newValue + } + }, + header, + 'value' + ) + } + collection={collection} + /> + +
+ handleHeaderValueChange(e, header, 'enabled')} + /> + +
+
+ + +
+ +
+
+ ); +}; +export default Headers; diff --git a/packages/bruno-app/src/components/CollectionSettings/ProxySettings/index.js b/packages/bruno-app/src/components/CollectionSettings/ProxySettings/index.js index c3746f566..618c3fa84 100644 --- a/packages/bruno-app/src/components/CollectionSettings/ProxySettings/index.js +++ b/packages/bruno-app/src/components/CollectionSettings/ProxySettings/index.js @@ -49,15 +49,14 @@ const ProxySettings = ({ proxyConfig, onUpdate }) => { return ( -

Proxy Settings

-
+
-
+
@@ -86,7 +85,7 @@ const ProxySettings = ({ proxyConfig, onUpdate }) => {
-
+
@@ -106,7 +105,7 @@ const ProxySettings = ({ proxyConfig, onUpdate }) => {
{formik.errors.hostname}
) : null}
-
+
@@ -124,7 +123,7 @@ const ProxySettings = ({ proxyConfig, onUpdate }) => { /> {formik.touched.port && formik.errors.port ?
{formik.errors.port}
: null}
-
+
@@ -136,7 +135,7 @@ const ProxySettings = ({ proxyConfig, onUpdate }) => { />
-
+
@@ -156,7 +155,7 @@ const ProxySettings = ({ proxyConfig, onUpdate }) => {
{formik.errors.auth.username}
) : null}
-
+
@@ -178,7 +177,7 @@ const ProxySettings = ({ proxyConfig, onUpdate }) => {
-
diff --git a/packages/bruno-app/src/components/CollectionSettings/Script/StyledWrapper.js b/packages/bruno-app/src/components/CollectionSettings/Script/StyledWrapper.js new file mode 100644 index 000000000..66ba1ed3d --- /dev/null +++ b/packages/bruno-app/src/components/CollectionSettings/Script/StyledWrapper.js @@ -0,0 +1,13 @@ +import styled from 'styled-components'; + +const StyledWrapper = styled.div` + div.CodeMirror { + height: inherit; + } + + div.title { + color: var(--color-tab-inactive); + } +`; + +export default StyledWrapper; diff --git a/packages/bruno-app/src/components/CollectionSettings/Script/index.js b/packages/bruno-app/src/components/CollectionSettings/Script/index.js new file mode 100644 index 000000000..7cfff272e --- /dev/null +++ b/packages/bruno-app/src/components/CollectionSettings/Script/index.js @@ -0,0 +1,73 @@ +import React from 'react'; +import get from 'lodash/get'; +import { useDispatch } from 'react-redux'; +import CodeEditor from 'components/CodeEditor'; +import { updateCollectionRequestScript, updateCollectionResponseScript } from 'providers/ReduxStore/slices/collections'; +import { saveCollectionRoot } from 'providers/ReduxStore/slices/collections/actions'; +import { useTheme } from 'providers/Theme'; +import StyledWrapper from './StyledWrapper'; + +const Script = ({ collection }) => { + const dispatch = useDispatch(); + const requestScript = get(collection, 'root.request.script.req', ''); + const responseScript = get(collection, 'root.request.script.res', ''); + + const { storedTheme } = useTheme(); + + const onRequestScriptEdit = (value) => { + dispatch( + updateCollectionRequestScript({ + script: value, + collectionUid: collection.uid + }) + ); + }; + + const onResponseScriptEdit = (value) => { + dispatch( + updateCollectionResponseScript({ + script: value, + collectionUid: collection.uid + }) + ); + }; + + const handleSave = () => { + dispatch(saveCollectionRoot(collection.uid)); + }; + + return ( + +
+
Pre Request
+ +
+
+
Post Response
+ +
+ +
+ +
+
+ ); +}; + +export default Script; diff --git a/packages/bruno-app/src/components/CollectionSettings/StyledWrapper.js b/packages/bruno-app/src/components/CollectionSettings/StyledWrapper.js index e4d976b0d..b88a31e0d 100644 --- a/packages/bruno-app/src/components/CollectionSettings/StyledWrapper.js +++ b/packages/bruno-app/src/components/CollectionSettings/StyledWrapper.js @@ -1,6 +1,32 @@ import styled from 'styled-components'; const StyledWrapper = styled.div` + max-width: 800px; + + div.tabs { + div.tab { + padding: 6px 0px; + border: none; + border-bottom: solid 2px transparent; + margin-right: 1.25rem; + color: var(--color-tab-inactive); + cursor: pointer; + + &:focus, + &:active, + &:focus-within, + &:focus-visible, + &:target { + outline: none !important; + box-shadow: none !important; + } + + &.active { + color: ${(props) => props.theme.tabs.active.color} !important; + border-bottom: solid 2px ${(props) => props.theme.tabs.active.border} !important; + } + } + } table { thead, td { diff --git a/packages/bruno-app/src/components/CollectionSettings/Tests/StyledWrapper.js b/packages/bruno-app/src/components/CollectionSettings/Tests/StyledWrapper.js new file mode 100644 index 000000000..ec278887d --- /dev/null +++ b/packages/bruno-app/src/components/CollectionSettings/Tests/StyledWrapper.js @@ -0,0 +1,5 @@ +import styled from 'styled-components'; + +const StyledWrapper = styled.div``; + +export default StyledWrapper; diff --git a/packages/bruno-app/src/components/CollectionSettings/Tests/index.js b/packages/bruno-app/src/components/CollectionSettings/Tests/index.js new file mode 100644 index 000000000..469d2b409 --- /dev/null +++ b/packages/bruno-app/src/components/CollectionSettings/Tests/index.js @@ -0,0 +1,47 @@ +import React from 'react'; +import get from 'lodash/get'; +import { useDispatch } from 'react-redux'; +import CodeEditor from 'components/CodeEditor'; +import { updateCollectionTests } from 'providers/ReduxStore/slices/collections'; +import { saveCollectionRoot } from 'providers/ReduxStore/slices/collections/actions'; +import { useTheme } from 'providers/Theme'; +import StyledWrapper from './StyledWrapper'; + +const Tests = ({ collection }) => { + const dispatch = useDispatch(); + const tests = get(collection, 'root.request.tests', ''); + + const { storedTheme } = useTheme(); + + const onEdit = (value) => { + dispatch( + updateCollectionTests({ + tests: value, + collectionUid: collection.uid + }) + ); + }; + + const handleSave = () => dispatch(saveCollectionRoot(collection.uid)); + + return ( + + + +
+ +
+
+ ); +}; + +export default Tests; diff --git a/packages/bruno-app/src/components/CollectionSettings/index.js b/packages/bruno-app/src/components/CollectionSettings/index.js index 98d8aed48..eaf44e758 100644 --- a/packages/bruno-app/src/components/CollectionSettings/index.js +++ b/packages/bruno-app/src/components/CollectionSettings/index.js @@ -1,14 +1,29 @@ import React from 'react'; +import classnames from 'classnames'; import get from 'lodash/get'; import cloneDeep from 'lodash/cloneDeep'; import toast from 'react-hot-toast'; import { updateBrunoConfig } from 'providers/ReduxStore/slices/collections/actions'; +import { updateSettingsSelectedTab } from 'providers/ReduxStore/slices/collections'; import { useDispatch } from 'react-redux'; import ProxySettings from './ProxySettings'; +import Headers from './Headers'; +import Auth from './Auth'; +import Script from './Script'; +import Test from './Tests'; import StyledWrapper from './StyledWrapper'; const CollectionSettings = ({ collection }) => { const dispatch = useDispatch(); + const tab = collection.settingsSelectedTab; + const setTab = (tab) => { + dispatch( + updateSettingsSelectedTab({ + collectionUid: collection.uid, + tab + }) + ); + }; const proxyConfig = get(collection, 'brunoConfig.proxy', {}); @@ -22,11 +37,52 @@ const CollectionSettings = ({ collection }) => { .catch((err) => console.log(err) && toast.error('Failed to update collection settings')); }; - return ( - -

Collection Settings

+ const getTabPanel = (tab) => { + switch (tab) { + case 'headers': { + return ; + } + case 'auth': { + return ; + } + case 'script': { + return