From be72d24ecbb912cbb34d2fd178961d0f8278efc4 Mon Sep 17 00:00:00 2001 From: therealrinku Date: Fri, 6 Oct 2023 14:57:20 +0545 Subject: [PATCH 01/71] request colors made consistent on the sidebar and tabs --- .../RequestTabs/RequestTab/index.js | 21 ++++++++++++------- .../RequestMethod/StyledWrapper.js | 6 +++--- .../CollectionItem/RequestMethod/index.js | 3 ++- packages/bruno-app/src/themes/dark.js | 6 +++++- packages/bruno-app/src/themes/light.js | 6 +++++- 5 files changed, 29 insertions(+), 13 deletions(-) diff --git a/packages/bruno-app/src/components/RequestTabs/RequestTab/index.js b/packages/bruno-app/src/components/RequestTabs/RequestTab/index.js index 429100fee..9b7b59a30 100644 --- a/packages/bruno-app/src/components/RequestTabs/RequestTab/index.js +++ b/packages/bruno-app/src/components/RequestTabs/RequestTab/index.js @@ -6,9 +6,13 @@ import { findItemInCollection } from 'utils/collections'; import StyledWrapper from './StyledWrapper'; import RequestTabNotFound from './RequestTabNotFound'; import SpecialTab from './SpecialTab'; +import { useTheme } from 'providers/Theme'; +import darkTheme from 'themes/dark'; +import lightTheme from 'themes/light'; const RequestTab = ({ tab, collection }) => { const dispatch = useDispatch(); + const { storedTheme } = useTheme(); const handleCloseClick = (event) => { event.stopPropagation(); @@ -21,35 +25,38 @@ const RequestTab = ({ tab, collection }) => { }; const getMethodColor = (method = '') => { + const theme = storedTheme === 'dark' ? darkTheme : lightTheme; + let color = ''; method = method.toLocaleLowerCase(); + switch (method) { case 'get': { - color = 'var(--color-method-get)'; + color = theme.request.methods.get; break; } case 'post': { - color = 'var(--color-method-post)'; + color = theme.request.methods.post; break; } case 'put': { - color = 'var(--color-method-put)'; + color = theme.request.methods.put; break; } case 'delete': { - color = 'var(--color-method-delete)'; + color = theme.request.methods.delete; break; } case 'patch': { - color = 'var(--color-method-patch)'; + color = theme.request.methods.patch; break; } case 'options': { - color = 'var(--color-method-options)'; + color = theme.request.methods.options; break; } case 'head': { - color = 'var(--color-method-head)'; + color = theme.request.methods.head; break; } } diff --git a/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/RequestMethod/StyledWrapper.js b/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/RequestMethod/StyledWrapper.js index 7b3058a6a..d9dfe622f 100644 --- a/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/RequestMethod/StyledWrapper.js +++ b/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/RequestMethod/StyledWrapper.js @@ -25,13 +25,13 @@ const Wrapper = styled.div` color: ${(props) => props.theme.request.methods.delete}; } .method-patch { - color: ${(props) => props.theme.request.methods.put}; + color: ${(props) => props.theme.request.methods.patch}; } .method-options { - color: ${(props) => props.theme.request.methods.put}; + color: ${(props) => props.theme.request.methods.options}; } .method-head { - color: ${(props) => props.theme.request.methods.put}; + color: ${(props) => props.theme.request.methods.head}; } `; diff --git a/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/RequestMethod/index.js b/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/RequestMethod/index.js index a408fc81e..87315dfea 100644 --- a/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/RequestMethod/index.js +++ b/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/RequestMethod/index.js @@ -15,7 +15,8 @@ const RequestMethod = ({ item }) => { 'method-put': method === 'put', 'method-delete': method === 'delete', 'method-patch': method === 'patch', - 'method-head': method === 'head' + 'method-head': method === 'head', + 'method-options': method == 'options' }); }; diff --git a/packages/bruno-app/src/themes/dark.js b/packages/bruno-app/src/themes/dark.js index 7a4ad64de..f93fc646a 100644 --- a/packages/bruno-app/src/themes/dark.js +++ b/packages/bruno-app/src/themes/dark.js @@ -86,7 +86,11 @@ const darkTheme = { get: '#8cd656', post: '#cd56d6', put: '#d69956', - delete: '#f06f57' + delete: '#f06f57', + // customize these colors if needed + patch: '#d69956', + options: '#d69956', + head: '#d69956' } }, diff --git a/packages/bruno-app/src/themes/light.js b/packages/bruno-app/src/themes/light.js index b014c2f38..b461f44de 100644 --- a/packages/bruno-app/src/themes/light.js +++ b/packages/bruno-app/src/themes/light.js @@ -86,7 +86,11 @@ const lightTheme = { get: 'rgb(5, 150, 105)', post: '#8e44ad', put: '#ca7811', - delete: 'rgb(185, 28, 28)' + delete: 'rgb(185, 28, 28)', + // customize these colors if needed + patch: '#ca7811', + options: '#ca7811', + head: '#ca7811' } }, From 1f5aa25d5ea56ee87a6ab41a2dd4939dceca2d88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Szymborski?= Date: Fri, 6 Oct 2023 16:39:13 +0200 Subject: [PATCH 02/71] fix(#428): moving requests into directories or into root of collection broke ordering --- packages/bruno-app/src/utils/collections/index.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/bruno-app/src/utils/collections/index.js b/packages/bruno-app/src/utils/collections/index.js index bf0fe6879..9eb6c0d1f 100644 --- a/packages/bruno-app/src/utils/collections/index.js +++ b/packages/bruno-app/src/utils/collections/index.js @@ -138,7 +138,7 @@ export const moveCollectionItem = (collection, draggedItem, targetItem) => { } if (targetItem.type === 'folder') { - targetItem.items = targetItem.items || []; + targetItem.items = sortBy(targetItem.items || [], (item) => item.seq); targetItem.items.push(draggedItem); draggedItem.pathname = path.join(targetItem.pathname, draggedItem.filename); } else { @@ -166,7 +166,9 @@ export const moveCollectionItemToRootOfCollection = (collection, draggedItem) => return; } + draggedItemParent.items = sortBy(draggedItemParent.items, (item) => item.seq); draggedItemParent.items = filter(draggedItemParent.items, (i) => i.uid !== draggedItem.uid); + collection.items = sortBy(collection.items, (item) => item.seq); collection.items.push(draggedItem); if (draggedItem.type == 'folder') { draggedItem.pathname = path.join(collection.pathname, draggedItem.name); From de74edb50f198b010517ac52e4b0fa18395c2075 Mon Sep 17 00:00:00 2001 From: Anoop M D Date: Fri, 6 Oct 2023 22:49:48 +0530 Subject: [PATCH 03/71] feat: interpolation of proxy vars --- .../ResponsePane/QueryResult/index.js | 2 +- .../src/runner/interpolate-string.js | 55 +++++++++++++++++++ .../src/runner/run-single-request.js | 20 +++++-- .../bruno-cli/src/utils/axios-instance.js | 4 +- .../src/ipc/network/axios-instance.js | 4 +- .../bruno-electron/src/ipc/network/index.js | 47 +++++++++++----- .../src/ipc/network/interpolate-string.js | 55 +++++++++++++++++++ 7 files changed, 164 insertions(+), 23 deletions(-) create mode 100644 packages/bruno-cli/src/runner/interpolate-string.js create mode 100644 packages/bruno-electron/src/ipc/network/interpolate-string.js diff --git a/packages/bruno-app/src/components/ResponsePane/QueryResult/index.js b/packages/bruno-app/src/components/ResponsePane/QueryResult/index.js index 5729e0b2d..999eb16fc 100644 --- a/packages/bruno-app/src/components/ResponsePane/QueryResult/index.js +++ b/packages/bruno-app/src/components/ResponsePane/QueryResult/index.js @@ -87,7 +87,7 @@ const QueryResult = ({ item, collection, data, width, disableRunEventListener, h }; const activeResult = useMemo(() => { - if (tab === 'preview' && mode.includes('html')) { + if (tab === 'preview' && mode.includes('html') && item.requestSent && item.requestSent.url) { // Add the Base tag to the head so content loads properly. This also needs the correct CSP settings const webViewSrc = data.replace('', ``); return ( diff --git a/packages/bruno-cli/src/runner/interpolate-string.js b/packages/bruno-cli/src/runner/interpolate-string.js new file mode 100644 index 000000000..33701dd0b --- /dev/null +++ b/packages/bruno-cli/src/runner/interpolate-string.js @@ -0,0 +1,55 @@ +const Handlebars = require('handlebars'); +const { forOwn, cloneDeep } = require('lodash'); + +const interpolateEnvVars = (str, processEnvVars) => { + if (!str || !str.length || typeof str !== 'string') { + return str; + } + + const template = Handlebars.compile(str, { noEscape: true }); + + return template({ + process: { + env: { + ...processEnvVars + } + } + }); +}; + +const interpolateString = (str, { envVars, collectionVariables, processEnvVars }) => { + if (!str || !str.length || typeof str !== 'string') { + return str; + } + + processEnvVars = processEnvVars || {}; + collectionVariables = collectionVariables || {}; + + // we clone envVars because we don't want to modify the original object + envVars = envVars ? cloneDeep(envVars) : {}; + + // envVars can inturn have values as {{process.env.VAR_NAME}} + // so we need to interpolate envVars first with processEnvVars + forOwn(envVars, (value, key) => { + envVars[key] = interpolateEnvVars(value, processEnvVars); + }); + + const template = Handlebars.compile(str, { noEscape: true }); + + // collectionVariables take precedence over envVars + const combinedVars = { + ...envVars, + ...collectionVariables, + process: { + env: { + ...processEnvVars + } + } + }; + + return template(combinedVars); +}; + +module.exports = { + interpolateString +}; diff --git a/packages/bruno-cli/src/runner/run-single-request.js b/packages/bruno-cli/src/runner/run-single-request.js index 7497a53c4..1bdc77999 100644 --- a/packages/bruno-cli/src/runner/run-single-request.js +++ b/packages/bruno-cli/src/runner/run-single-request.js @@ -6,6 +6,7 @@ const { forOwn, each, extend, get } = require('lodash'); const FormData = require('form-data'); const prepareRequest = require('./prepare-request'); const interpolateVars = require('./interpolate-vars'); +const { interpolateString } = require('./interpolate-string'); const { ScriptRuntime, TestRuntime, VarsRuntime, AssertRuntime } = require('@usebruno/js'); const { stripExtension } = require('../utils/filesystem'); const { getOptions } = require('../utils/bru'); @@ -92,16 +93,23 @@ const runSingleRequest = async function ( // set proxy if enabled const proxyEnabled = get(brunoConfig, 'proxy.enabled', false); if (proxyEnabled) { - const proxyProtocol = get(brunoConfig, 'proxy.protocol'); - const proxyHostname = get(brunoConfig, 'proxy.hostname'); - const proxyPort = get(brunoConfig, 'proxy.port'); + let proxy; + const interpolationOptions = { + envVars: envVariables, + collectionVariables, + processEnvVars + }; + + const proxyProtocol = interpolateString(get(brunoConfig, 'proxy.protocol'), interpolationOptions); + const proxyHostname = interpolateString(get(brunoConfig, 'proxy.hostname'), interpolationOptions); + const proxyPort = interpolateString(get(brunoConfig, 'proxy.port'), interpolationOptions); const proxyAuthEnabled = get(brunoConfig, 'proxy.auth.enabled', false); - let proxy; + interpolateString; if (proxyAuthEnabled) { - const proxyAuthUsername = get(brunoConfig, 'proxy.auth.username'); - const proxyAuthPassword = get(brunoConfig, 'proxy.auth.password'); + const proxyAuthUsername = interpolateString(get(brunoConfig, 'proxy.auth.username'), interpolationOptions); + const proxyAuthPassword = interpolateString(get(brunoConfig, 'proxy.auth.password'), interpolationOptions); proxy = `${proxyProtocol}://${proxyAuthUsername}:${proxyAuthPassword}@${proxyHostname}:${proxyPort}`; } else { diff --git a/packages/bruno-cli/src/utils/axios-instance.js b/packages/bruno-cli/src/utils/axios-instance.js index f4810becd..286ffc0f5 100644 --- a/packages/bruno-cli/src/utils/axios-instance.js +++ b/packages/bruno-cli/src/utils/axios-instance.js @@ -26,7 +26,9 @@ function makeAxiosInstance() { if (error.response) { const end = Date.now(); const start = error.config.headers['request-start-time']; - error.response.headers['request-duration'] = end - start; + if (error.response) { + error.response.headers['request-duration'] = end - start; + } } return Promise.reject(error); } diff --git a/packages/bruno-electron/src/ipc/network/axios-instance.js b/packages/bruno-electron/src/ipc/network/axios-instance.js index f4abd839a..90ca1afea 100644 --- a/packages/bruno-electron/src/ipc/network/axios-instance.js +++ b/packages/bruno-electron/src/ipc/network/axios-instance.js @@ -25,7 +25,9 @@ function makeAxiosInstance() { (error) => { const end = Date.now(); const start = error.config.headers['request-start-time']; - error.response.headers['request-duration'] = end - start; + if (error.response) { + error.response.headers['request-duration'] = end - start; + } return Promise.reject(error); } ); diff --git a/packages/bruno-electron/src/ipc/network/index.js b/packages/bruno-electron/src/ipc/network/index.js index 9ba07b5e2..43d06d6c4 100644 --- a/packages/bruno-electron/src/ipc/network/index.js +++ b/packages/bruno-electron/src/ipc/network/index.js @@ -12,6 +12,7 @@ const prepareGqlIntrospectionRequest = require('./prepare-gql-introspection-requ const { cancelTokens, saveCancelToken, deleteCancelToken } = require('../../utils/cancel-token'); const { uuid } = require('../../utils/common'); const interpolateVars = require('./interpolate-vars'); +const { interpolateString } = require('./interpolate-string'); const { sortFolder, getAllRequestsInFolderRecursively } = require('./helper'); const { getPreferences } = require('../../store/preferences'); const { getProcessEnvVars } = require('../../store/process-env'); @@ -219,16 +220,22 @@ const registerNetworkIpc = (mainWindow) => { const brunoConfig = getBrunoConfig(collectionUid); const proxyEnabled = get(brunoConfig, 'proxy.enabled', false); if (proxyEnabled) { - const proxyProtocol = get(brunoConfig, 'proxy.protocol'); - const proxyHostname = get(brunoConfig, 'proxy.hostname'); - const proxyPort = get(brunoConfig, 'proxy.port'); - const proxyAuthEnabled = get(brunoConfig, 'proxy.auth.enabled', false); - let proxy; + const interpolationOptions = { + envVars, + collectionVariables, + processEnvVars + }; + + const proxyProtocol = interpolateString(get(brunoConfig, 'proxy.protocol'), interpolationOptions); + const proxyHostname = interpolateString(get(brunoConfig, 'proxy.hostname'), interpolationOptions); + const proxyPort = interpolateString(get(brunoConfig, 'proxy.port'), interpolationOptions); + const proxyAuthEnabled = get(brunoConfig, 'proxy.auth.enabled', false); + if (proxyAuthEnabled) { - const proxyAuthUsername = get(brunoConfig, 'proxy.auth.username'); - const proxyAuthPassword = get(brunoConfig, 'proxy.auth.password'); + const proxyAuthUsername = interpolateString(get(brunoConfig, 'proxy.auth.username'), interpolationOptions); + const proxyAuthPassword = interpolateString(get(brunoConfig, 'proxy.auth.password'), interpolationOptions); proxy = `${proxyProtocol}://${proxyAuthUsername}:${proxyAuthPassword}@${proxyHostname}:${proxyPort}`; } else { @@ -648,16 +655,28 @@ const registerNetworkIpc = (mainWindow) => { const brunoConfig = getBrunoConfig(collectionUid); const proxyEnabled = get(brunoConfig, 'proxy.enabled', false); if (proxyEnabled) { - const proxyProtocol = get(brunoConfig, 'proxy.protocol'); - const proxyHostname = get(brunoConfig, 'proxy.hostname'); - const proxyPort = get(brunoConfig, 'proxy.port'); + let proxy; + const interpolationOptions = { + envVars, + collectionVariables, + processEnvVars + }; + + const proxyProtocol = interpolateString(get(brunoConfig, 'proxy.protocol'), interpolationOptions); + const proxyHostname = interpolateString(get(brunoConfig, 'proxy.hostname'), interpolationOptions); + const proxyPort = interpolateString(get(brunoConfig, 'proxy.port'), interpolationOptions); const proxyAuthEnabled = get(brunoConfig, 'proxy.auth.enabled', false); - let proxy; - if (proxyAuthEnabled) { - const proxyAuthUsername = get(brunoConfig, 'proxy.auth.username'); - const proxyAuthPassword = get(brunoConfig, 'proxy.auth.password'); + const proxyAuthUsername = interpolateString( + get(brunoConfig, 'proxy.auth.username'), + interpolationOptions + ); + + const proxyAuthPassword = interpolateString( + get(brunoConfig, 'proxy.auth.password'), + interpolationOptions + ); proxy = `${proxyProtocol}://${proxyAuthUsername}:${proxyAuthPassword}@${proxyHostname}:${proxyPort}`; } else { diff --git a/packages/bruno-electron/src/ipc/network/interpolate-string.js b/packages/bruno-electron/src/ipc/network/interpolate-string.js new file mode 100644 index 000000000..33701dd0b --- /dev/null +++ b/packages/bruno-electron/src/ipc/network/interpolate-string.js @@ -0,0 +1,55 @@ +const Handlebars = require('handlebars'); +const { forOwn, cloneDeep } = require('lodash'); + +const interpolateEnvVars = (str, processEnvVars) => { + if (!str || !str.length || typeof str !== 'string') { + return str; + } + + const template = Handlebars.compile(str, { noEscape: true }); + + return template({ + process: { + env: { + ...processEnvVars + } + } + }); +}; + +const interpolateString = (str, { envVars, collectionVariables, processEnvVars }) => { + if (!str || !str.length || typeof str !== 'string') { + return str; + } + + processEnvVars = processEnvVars || {}; + collectionVariables = collectionVariables || {}; + + // we clone envVars because we don't want to modify the original object + envVars = envVars ? cloneDeep(envVars) : {}; + + // envVars can inturn have values as {{process.env.VAR_NAME}} + // so we need to interpolate envVars first with processEnvVars + forOwn(envVars, (value, key) => { + envVars[key] = interpolateEnvVars(value, processEnvVars); + }); + + const template = Handlebars.compile(str, { noEscape: true }); + + // collectionVariables take precedence over envVars + const combinedVars = { + ...envVars, + ...collectionVariables, + process: { + env: { + ...processEnvVars + } + } + }; + + return template(combinedVars); +}; + +module.exports = { + interpolateString +}; From 945f1eb74ae14a2cb5073a5a4a309f79837f7279 Mon Sep 17 00:00:00 2001 From: not-known-person Date: Fri, 6 Oct 2023 22:00:20 -0400 Subject: [PATCH 04/71] fix-/#419 --- package-lock.json | 6 +++--- .../CollectionItem/GenerateCodeItem/index.js | 20 +++++++++++-------- .../Collection/CollectionItem/index.js | 16 ++++++++++----- 3 files changed, 26 insertions(+), 16 deletions(-) diff --git a/package-lock.json b/package-lock.json index c22296288..a7f0faa74 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16776,7 +16776,7 @@ }, "packages/bruno-cli": { "name": "@usebruno/cli", - "version": "0.11.0", + "version": "0.12.0", "license": "MIT", "dependencies": { "@usebruno/js": "0.6.0", @@ -16822,7 +16822,7 @@ }, "packages/bruno-electron": { "name": "bruno", - "version": "v0.19.0", + "version": "v0.20.0", "dependencies": { "@usebruno/js": "0.6.0", "@usebruno/lang": "0.5.0", @@ -20107,7 +20107,7 @@ "axios": "^1.5.1", "chai": "^4.3.7", "chalk": "^3.0.0", - "decomment": "*", + "decomment": "^0.9.5", "form-data": "^4.0.0", "fs-extra": "^10.1.0", "handlebars": "^4.7.8", diff --git a/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/GenerateCodeItem/index.js b/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/GenerateCodeItem/index.js index 509a529bd..3b16d99cf 100644 --- a/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/GenerateCodeItem/index.js +++ b/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/GenerateCodeItem/index.js @@ -9,7 +9,7 @@ import { findEnvironmentInCollection } from 'utils/collections'; const interpolateUrl = ({ url, envVars, collectionVariables, processEnvVars }) => { if (!url || !url.length || typeof url !== 'string') { - return str; + return; } const template = handlebars.compile(url, { noEscape: true }); @@ -74,9 +74,8 @@ const languages = [ ]; const GenerateCodeItem = ({ collection, item, onClose }) => { - const url = get(item, 'request.url') || ''; + const url = get(item, 'draft.request.url') !== undefined ? get(item, 'draft.request.url') : get(item, 'request.url'); const environment = findEnvironmentInCollection(collection, collection.activeEnvironmentUid); - let envVars = {}; if (environment) { const vars = get(environment, 'variables', []); @@ -92,7 +91,6 @@ const GenerateCodeItem = ({ collection, item, onClose }) => { collectionVariables: collection.collectionVariables, processEnvVars: collection.processEnvVariables }); - const [selectedLanguage, setSelectedLanguage] = useState(languages[0]); return ( @@ -121,10 +119,16 @@ const GenerateCodeItem = ({ collection, item, onClose }) => { language={selectedLanguage} item={{ ...item, - request: { - ...item.request, - url: interpolatedUrl - } + request: + item.request.url !== '' + ? { + ...item.request, + url: interpolatedUrl + } + : { + ...item.draft.request, + url: interpolatedUrl + } }} /> ) : ( 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 a08b4fe1f..f0cc8d360 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 @@ -21,7 +21,7 @@ import { isItemARequest, isItemAFolder, itemIsOpenedInTabs } from 'utils/tabs'; import { doesRequestMatchSearchText, doesFolderHaveItemsMatchSearchText } from 'utils/collections/search'; import { getDefaultRequestPaneTab } from 'utils/collections'; import { hideHomePage } from 'providers/ReduxStore/slices/app'; - +import toast from 'react-hot-toast'; import StyledWrapper from './StyledWrapper'; const CollectionItem = ({ item, collection, searchText }) => { @@ -148,7 +148,15 @@ const CollectionItem = ({ item, collection, searchText }) => { const sortFolderItems = (items = []) => { return items.sort((a, b) => a.name.localeCompare(b.name)); }; - + const handleGenerateCode = (e) => { + e.stopPropagation(); + dropdownTippyRef.current.hide(); + if (item.request.url !== '' || (item.draft?.request.url !== undefined && item.draft?.request.url !== '')) { + setGenerateCodeItemModalOpen(true); + } else { + toast.error('URL is required'); + } + }; const requestItems = sortRequestItems(filter(item.items, (i) => isItemARequest(i))); const folderItems = sortFolderItems(filter(item.items, (i) => isItemAFolder(i))); @@ -279,9 +287,7 @@ const CollectionItem = ({ item, collection, searchText }) => {
{ - e.stopPropagation(); - dropdownTippyRef.current.hide(); - setGenerateCodeItemModalOpen(true); + handleGenerateCode(e); }} > Generate Code From 5a89d1271647b70c76e3987d19ae6416d9c33777 Mon Sep 17 00:00:00 2001 From: Anoop M D Date: Sat, 7 Oct 2023 00:25:26 +0530 Subject: [PATCH 05/71] feat: removed legacy v1 bru lang auto migrate functionality --- packages/bruno-electron/src/app/watcher.js | 40 +-------- packages/bruno-electron/src/bru/migrate.js | 99 ---------------------- 2 files changed, 1 insertion(+), 138 deletions(-) delete mode 100644 packages/bruno-electron/src/bru/migrate.js diff --git a/packages/bruno-electron/src/app/watcher.js b/packages/bruno-electron/src/app/watcher.js index b4162db90..96822ec64 100644 --- a/packages/bruno-electron/src/app/watcher.js +++ b/packages/bruno-electron/src/app/watcher.js @@ -2,12 +2,10 @@ const _ = require('lodash'); const fs = require('fs'); const path = require('path'); const chokidar = require('chokidar'); -const { hasJsonExtension, hasBruExtension, writeFile } = require('../utils/filesystem'); +const { hasBruExtension, writeFile } = require('../utils/filesystem'); const { bruToEnvJson, envJsonToBru, bruToJson, jsonToBru } = require('../bru'); const { dotenvToJson } = require('@usebruno/lang'); -const { isLegacyEnvFile, migrateLegacyEnvFile, isLegacyBruFile, migrateLegacyBruFile } = require('../bru/migrate'); -const { itemSchema } = require('@usebruno/schema'); const { uuid } = require('../utils/common'); const { getRequestUid } = require('../cache/requestUids'); const { decryptString } = require('../utils/encryption'); @@ -87,11 +85,6 @@ const addEnvironmentFile = async (win, pathname, collectionUid, collectionPath) let bruContent = fs.readFileSync(pathname, 'utf8'); - // migrate old env json to bru file - if (isLegacyEnvFile(bruContent)) { - bruContent = await migrateLegacyEnvFile(bruContent, pathname); - } - file.data = bruToEnvJson(bruContent); file.data.name = basename.substring(0, basename.length - 4); file.data.uid = getRequestUid(pathname); @@ -235,27 +228,6 @@ const add = async (win, pathname, collectionUid, collectionPath) => { return addEnvironmentFile(win, pathname, collectionUid, collectionPath); } - // migrate old json files to bru - if (hasJsonExtension(pathname)) { - try { - const json = fs.readFileSync(pathname, 'utf8'); - const jsonData = JSON.parse(json); - - await itemSchema.validate(jsonData); - - const content = jsonToBru(jsonData); - - const re = /(.*)\.json$/; - const subst = `$1.bru`; - const bruFilename = pathname.replace(re, subst); - - await writeFile(bruFilename, content); - await fs.unlinkSync(pathname); - } catch (err) { - // do nothing - } - } - if (hasBruExtension(pathname)) { const file = { meta: { @@ -268,11 +240,6 @@ const add = async (win, pathname, collectionUid, collectionPath) => { try { let bruContent = fs.readFileSync(pathname, 'utf8'); - // migrate old bru format to new bru format - if (isLegacyBruFile(bruContent)) { - bruContent = await migrateLegacyBruFile(bruContent, pathname); - } - file.data = bruToJson(bruContent); hydrateRequestWithUuid(file.data, pathname); win.webContents.send('main:collection-tree-updated', 'addFile', file); @@ -404,11 +371,6 @@ class Watcher { this.watchers[watchPath].close(); } - // todo - // enable this in a future release - // once we can confirm all older json based files have been auto migrated to .bru format - // watchPath = path.join(watchPath, '**/*.bru'); - const self = this; setTimeout(() => { const watcher = chokidar.watch(watchPath, { diff --git a/packages/bruno-electron/src/bru/migrate.js b/packages/bruno-electron/src/bru/migrate.js deleted file mode 100644 index a74dc2fd0..000000000 --- a/packages/bruno-electron/src/bru/migrate.js +++ /dev/null @@ -1,99 +0,0 @@ -const { - bruToEnvJson: bruToEnvJsonV1, - bruToJson: bruToJsonV1, - - jsonToBruV2, - envJsonToBruV2 -} = require('@usebruno/lang'); -const _ = require('lodash'); - -const { writeFile } = require('../utils/filesystem'); - -const isLegacyEnvFile = (bruContent = '') => { - bruContent = bruContent.trim(); - let regex = /^vars[\s\S]*\/vars$/; - - return regex.test(bruContent); -}; - -const migrateLegacyEnvFile = async (bruContent, pathname) => { - const envJson = bruToEnvJsonV1(bruContent); - const newBruContent = envJsonToBruV2(envJson); - - await writeFile(pathname, newBruContent); - - return newBruContent; -}; - -const isLegacyBruFile = (bruContent = '') => { - bruContent = bruContent.trim(); - let lines = bruContent.split(/\r?\n/); - let hasName = false; - let hasMethod = false; - let hasUrl = false; - - for (let line of lines) { - line = line.trim(); - if (line.startsWith('name')) { - hasName = true; - } else if (line.startsWith('method')) { - hasMethod = true; - } else if (line.startsWith('url')) { - hasUrl = true; - } - } - - return hasName && hasMethod && hasUrl; -}; - -const migrateLegacyBruFile = async (bruContent, pathname) => { - const json = bruToJsonV1(bruContent); - - let type = _.get(json, 'type'); - if (type === 'http-request') { - type = 'http'; - } else if (type === 'graphql-request') { - type = 'graphql'; - } else { - type = 'http'; - } - - let script = {}; - let legacyScript = _.get(json, 'request.script'); - if (legacyScript && legacyScript.trim().length > 0) { - script = { - res: legacyScript - }; - } - - const bruJson = { - meta: { - name: _.get(json, 'name'), - type: type, - seq: _.get(json, 'seq') - }, - http: { - method: _.lowerCase(_.get(json, 'request.method')), - url: _.get(json, 'request.url'), - body: _.get(json, 'request.body.mode', 'none') - }, - query: _.get(json, 'request.params', []), - headers: _.get(json, 'request.headers', []), - body: _.get(json, 'request.body', {}), - script: script, - tests: _.get(json, 'request.tests', '') - }; - - const newBruContent = jsonToBruV2(bruJson); - - await writeFile(pathname, newBruContent); - - return newBruContent; -}; - -module.exports = { - isLegacyEnvFile, - migrateLegacyEnvFile, - isLegacyBruFile, - migrateLegacyBruFile -}; From 3c0770b7928406b8003ead2abaea3cc1f7f79721 Mon Sep 17 00:00:00 2001 From: Jonathan Gruber Date: Fri, 6 Oct 2023 23:10:53 +0200 Subject: [PATCH 06/71] fix(#354): also interpolate env vars in introspection request --- .../src/components/RequestPane/GraphQLRequestPane/index.js | 2 +- .../RequestPane/GraphQLRequestPane/useGraphqlSchema.js | 4 ++-- packages/bruno-app/src/utils/network/index.js | 7 ++----- packages/bruno-electron/src/ipc/network/index.js | 5 +++-- 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/packages/bruno-app/src/components/RequestPane/GraphQLRequestPane/index.js b/packages/bruno-app/src/components/RequestPane/GraphQLRequestPane/index.js index 45a345a6a..6d4eba2a6 100644 --- a/packages/bruno-app/src/components/RequestPane/GraphQLRequestPane/index.js +++ b/packages/bruno-app/src/components/RequestPane/GraphQLRequestPane/index.js @@ -40,7 +40,7 @@ const GraphQLRequestPane = ({ item, collection, leftPaneWidth, onSchemaLoad, tog loadSchema, isLoading: isSchemaLoading, error: schemaError - } = useGraphqlSchema(url, environment, request, collection.collectionVariables); + } = useGraphqlSchema(url, environment, request, collection); const loadGqlSchema = () => { if (!isSchemaLoading) { diff --git a/packages/bruno-app/src/components/RequestPane/GraphQLRequestPane/useGraphqlSchema.js b/packages/bruno-app/src/components/RequestPane/GraphQLRequestPane/useGraphqlSchema.js index e59127717..e28ea5bc4 100644 --- a/packages/bruno-app/src/components/RequestPane/GraphQLRequestPane/useGraphqlSchema.js +++ b/packages/bruno-app/src/components/RequestPane/GraphQLRequestPane/useGraphqlSchema.js @@ -6,7 +6,7 @@ import { simpleHash } from 'utils/common'; const schemaHashPrefix = 'bruno.graphqlSchema'; -const useGraphqlSchema = (endpoint, environment, request, collectionVariables) => { +const useGraphqlSchema = (endpoint, environment, request, collection) => { const localStorageKey = `${schemaHashPrefix}.${simpleHash(endpoint)}`; const [error, setError] = useState(null); const [isLoading, setIsLoading] = useState(false); @@ -25,7 +25,7 @@ const useGraphqlSchema = (endpoint, environment, request, collectionVariables) = const loadSchema = () => { setIsLoading(true); - fetchGqlSchema(endpoint, environment, request, collectionVariables) + fetchGqlSchema(endpoint, environment, request, collection) .then((res) => res.data) .then((s) => { if (s && s.data) { diff --git a/packages/bruno-app/src/utils/network/index.js b/packages/bruno-app/src/utils/network/index.js index 2c5c3a1d3..042546854 100644 --- a/packages/bruno-app/src/utils/network/index.js +++ b/packages/bruno-app/src/utils/network/index.js @@ -29,14 +29,11 @@ const sendHttpRequest = async (item, collection, environment, collectionVariable }); }; -export const fetchGqlSchema = async (endpoint, environment, request, collectionVariables) => { +export const fetchGqlSchema = async (endpoint, environment, request, collection) => { return new Promise((resolve, reject) => { const { ipcRenderer } = window; - ipcRenderer - .invoke('fetch-gql-schema', endpoint, environment, request, collectionVariables) - .then(resolve) - .catch(reject); + ipcRenderer.invoke('fetch-gql-schema', endpoint, environment, request, collection).then(resolve).catch(reject); }); }; diff --git a/packages/bruno-electron/src/ipc/network/index.js b/packages/bruno-electron/src/ipc/network/index.js index 43d06d6c4..9110abb14 100644 --- a/packages/bruno-electron/src/ipc/network/index.js +++ b/packages/bruno-electron/src/ipc/network/index.js @@ -469,7 +469,7 @@ const registerNetworkIpc = (mainWindow) => { }); }); - ipcMain.handle('fetch-gql-schema', async (event, endpoint, environment, request, collectionVariables) => { + ipcMain.handle('fetch-gql-schema', async (event, endpoint, environment, request, collection) => { try { const envVars = getEnvVars(environment); const preparedRequest = prepareGqlIntrospectionRequest(endpoint, envVars, request); @@ -483,7 +483,8 @@ const registerNetworkIpc = (mainWindow) => { }); } - interpolateVars(preparedRequest, envVars, collectionVariables); + const processEnvVars = getProcessEnvVars(collection.uid); + interpolateVars(preparedRequest, envVars, collection.collectionVariables, processEnvVars); const response = await axios(preparedRequest); From 0f3a8a87bbd2a80b24d491bfa6317b2c4329821f Mon Sep 17 00:00:00 2001 From: Anoop M D Date: Sat, 7 Oct 2023 02:41:56 +0530 Subject: [PATCH 07/71] feat(#306): bru cli support for allowScriptFilesystemAccess --- packages/bruno-cli/src/runner/run-single-request.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/bruno-cli/src/runner/run-single-request.js b/packages/bruno-cli/src/runner/run-single-request.js index 1bdc77999..c658d76ca 100644 --- a/packages/bruno-cli/src/runner/run-single-request.js +++ b/packages/bruno-cli/src/runner/run-single-request.js @@ -29,6 +29,8 @@ const runSingleRequest = async function ( request = prepareRequest(bruJson.request); + const allowScriptFilesystemAccess = get(brunoConfig, 'filesystemAccess.allow', false); + // make axios work in node using form data // reference: https://github.com/axios/axios/issues/1006#issuecomment-320165427 if (request.headers && request.headers['content-type'] === 'multipart/form-data') { @@ -65,7 +67,8 @@ const runSingleRequest = async function ( collectionVariables, collectionPath, null, - processEnvVars + processEnvVars, + allowScriptFilesystemAccess ); } @@ -206,7 +209,8 @@ const runSingleRequest = async function ( collectionVariables, collectionPath, null, - processEnvVars + processEnvVars, + allowScriptFilesystemAccess ); } @@ -247,7 +251,8 @@ const runSingleRequest = async function ( collectionVariables, collectionPath, null, - processEnvVars + processEnvVars, + allowScriptFilesystemAccess ); testResults = get(result, 'results', []); } From d2b35beb6fca13d308c82db38ebcbdab7cf410ed Mon Sep 17 00:00:00 2001 From: Jonathan Gruber Date: Fri, 6 Oct 2023 23:23:57 +0200 Subject: [PATCH 08/71] fix(#354): use Handlebars instead of deprecated Mustache --- .../ipc/network/prepare-gql-introspection-request.js | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/packages/bruno-electron/src/ipc/network/prepare-gql-introspection-request.js b/packages/bruno-electron/src/ipc/network/prepare-gql-introspection-request.js index d41be8f4c..8329941f7 100644 --- a/packages/bruno-electron/src/ipc/network/prepare-gql-introspection-request.js +++ b/packages/bruno-electron/src/ipc/network/prepare-gql-introspection-request.js @@ -1,16 +1,12 @@ -const Mustache = require('mustache'); +const Handlebars = require('handlebars'); const { getIntrospectionQuery } = require('graphql'); const { get } = require('lodash'); -// override the default escape function to prevent escaping -Mustache.escape = function (value) { - return value; -}; - const prepareGqlIntrospectionRequest = (endpoint, envVars, request) => { if (endpoint && endpoint.length) { - endpoint = Mustache.render(endpoint, envVars); + endpoint = Handlebars.compile(endpoint, { noEscape: true })(envVars); } + const introspectionQuery = getIntrospectionQuery(); const queryParams = { query: introspectionQuery From 7f17999486053dbfddbdddd761ac0b262b716ee1 Mon Sep 17 00:00:00 2001 From: Jonathan Gruber Date: Fri, 6 Oct 2023 23:48:40 +0200 Subject: [PATCH 09/71] fix(#354): add set headers to introspection request --- .../src/ipc/network/prepare-gql-introspection-request.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packages/bruno-electron/src/ipc/network/prepare-gql-introspection-request.js b/packages/bruno-electron/src/ipc/network/prepare-gql-introspection-request.js index 8329941f7..4a1e41c88 100644 --- a/packages/bruno-electron/src/ipc/network/prepare-gql-introspection-request.js +++ b/packages/bruno-electron/src/ipc/network/prepare-gql-introspection-request.js @@ -16,6 +16,7 @@ const prepareGqlIntrospectionRequest = (endpoint, envVars, request) => { method: 'POST', url: endpoint, headers: { + ...mapHeaders(request.headers), Accept: 'application/json', 'Content-Type': 'application/json' }, @@ -38,4 +39,10 @@ const prepareGqlIntrospectionRequest = (endpoint, envVars, request) => { return axiosRequest; }; +const mapHeaders = (headers) => { + const entries = headers.filter((header) => header.enabled).map(({ name, value }) => [name, value]); + + return Object.fromEntries(entries); +}; + module.exports = prepareGqlIntrospectionRequest; From e3679c9ee9a8281efe1376dc98c72392ae9dd805 Mon Sep 17 00:00:00 2001 From: Anoop M D Date: Sat, 7 Oct 2023 03:19:02 +0530 Subject: [PATCH 10/71] feat(#306): module whitelisting support --- packages/bruno-js/package.json | 2 +- .../bruno-js/src/runtime/script-runtime.js | 33 +++++++++++++++++-- packages/bruno-js/src/runtime/test-runtime.js | 17 +++++++++- 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/packages/bruno-js/package.json b/packages/bruno-js/package.json index 00c66c254..00ccdcb15 100644 --- a/packages/bruno-js/package.json +++ b/packages/bruno-js/package.json @@ -1,6 +1,6 @@ { "name": "@usebruno/js", - "version": "0.6.0", + "version": "0.8.0", "license": "MIT", "main": "src/index.js", "files": [ diff --git a/packages/bruno-js/src/runtime/script-runtime.js b/packages/bruno-js/src/runtime/script-runtime.js index 46c88b0c1..0d9d246f5 100644 --- a/packages/bruno-js/src/runtime/script-runtime.js +++ b/packages/bruno-js/src/runtime/script-runtime.js @@ -8,6 +8,7 @@ const zlib = require('zlib'); const url = require('url'); const punycode = require('punycode'); const fs = require('fs'); +const { get } = require('lodash'); const Bru = require('../bru'); const BrunoRequest = require('../bruno-request'); const BrunoResponse = require('../bruno-response'); @@ -38,10 +39,23 @@ class ScriptRuntime { collectionPath, onConsoleLog, processEnvVars, - allowScriptFilesystemAccess + scriptingConfig ) { const bru = new Bru(envVariables, collectionVariables, processEnvVars, collectionPath); const req = new BrunoRequest(request); + const allowScriptFilesystemAccess = get(scriptingConfig, 'filesystemAccess.allow', false); + const moduleWhitelist = get(scriptingConfig, 'moduleWhitelist', []); + + const whitelistedModules = {}; + + for (let module of moduleWhitelist) { + try { + whitelistedModules[module] = require(module); + } catch (e) { + // Ignore + console.warn(e); + } + } const context = { bru, @@ -89,6 +103,7 @@ class ScriptRuntime { chai, 'node-fetch': fetch, 'crypto-js': CryptoJS, + ...whitelistedModules, fs: allowScriptFilesystemAccess ? fs : undefined } } @@ -111,11 +126,24 @@ class ScriptRuntime { collectionPath, onConsoleLog, processEnvVars, - allowScriptFilesystemAccess + scriptingConfig ) { const bru = new Bru(envVariables, collectionVariables, processEnvVars, collectionPath); const req = new BrunoRequest(request); const res = new BrunoResponse(response); + const allowScriptFilesystemAccess = get(scriptingConfig, 'filesystemAccess.allow', false); + const moduleWhitelist = get(scriptingConfig, 'moduleWhitelist', []); + + const whitelistedModules = {}; + + for (let module of moduleWhitelist) { + try { + whitelistedModules[module] = require(module); + } catch (e) { + // Ignore + console.warn(e); + } + } const context = { bru, @@ -163,6 +191,7 @@ class ScriptRuntime { axios, 'node-fetch': fetch, 'crypto-js': CryptoJS, + ...whitelistedModules, fs: allowScriptFilesystemAccess ? fs : undefined } } diff --git a/packages/bruno-js/src/runtime/test-runtime.js b/packages/bruno-js/src/runtime/test-runtime.js index efefb451f..b4ad3f04c 100644 --- a/packages/bruno-js/src/runtime/test-runtime.js +++ b/packages/bruno-js/src/runtime/test-runtime.js @@ -9,6 +9,7 @@ const zlib = require('zlib'); const url = require('url'); const punycode = require('punycode'); const fs = require('fs'); +const { get } = require('lodash'); const Bru = require('../bru'); const BrunoRequest = require('../bruno-request'); const BrunoResponse = require('../bruno-response'); @@ -38,11 +39,24 @@ class TestRuntime { collectionPath, onConsoleLog, processEnvVars, - allowScriptFilesystemAccess + scriptingConfig ) { const bru = new Bru(envVariables, collectionVariables, processEnvVars, collectionPath); const req = new BrunoRequest(request); const res = new BrunoResponse(response); + const allowScriptFilesystemAccess = get(scriptingConfig, 'filesystemAccess.allow', false); + const moduleWhitelist = get(scriptingConfig, 'moduleWhitelist', []); + + const whitelistedModules = {}; + + for (let module of moduleWhitelist) { + try { + whitelistedModules[module] = require(module); + } catch (e) { + // Ignore + console.warn(e); + } + } const __brunoTestResults = new TestResults(); const test = Test(__brunoTestResults, chai); @@ -106,6 +120,7 @@ class TestRuntime { nanoid, chai, 'crypto-js': CryptoJS, + ...whitelistedModules, fs: allowScriptFilesystemAccess ? fs : undefined } } From 8f1f41374c24d435d92013550d55873554d19ece Mon Sep 17 00:00:00 2001 From: Anoop M D Date: Sat, 7 Oct 2023 03:20:44 +0530 Subject: [PATCH 11/71] feat(#306): module whitelisting support --- package-lock.json | 98 ++++++++++++++++++- packages/bruno-cli/package.json | 2 +- .../src/runner/run-single-request.js | 8 +- packages/bruno-electron/package.json | 2 +- .../bruno-electron/src/ipc/network/index.js | 20 ++-- 5 files changed, 109 insertions(+), 21 deletions(-) diff --git a/package-lock.json b/package-lock.json index a7f0faa74..095bdc2ea 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16779,7 +16779,7 @@ "version": "0.12.0", "license": "MIT", "dependencies": { - "@usebruno/js": "0.6.0", + "@usebruno/js": "0.8.0", "@usebruno/lang": "0.5.0", "axios": "^1.5.1", "chai": "^4.3.7", @@ -16788,6 +16788,8 @@ "form-data": "^4.0.0", "fs-extra": "^10.1.0", "handlebars": "^4.7.8", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.2", "inquirer": "^9.1.4", "lodash": "^4.17.21", "mustache": "^4.2.0", @@ -16798,6 +16800,17 @@ "bru": "bin/bru.js" } }, + "packages/bruno-cli/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" + } + }, "packages/bruno-cli/node_modules/axios": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/axios/-/axios-1.5.1.tgz", @@ -16820,11 +16833,35 @@ "node": ">=8" } }, + "packages/bruno-cli/node_modules/http-proxy-agent": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz", + "integrity": "sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "packages/bruno-cli/node_modules/https-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz", + "integrity": "sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, "packages/bruno-electron": { "name": "bruno", "version": "v0.20.0", "dependencies": { - "@usebruno/js": "0.6.0", + "@usebruno/js": "0.8.0", "@usebruno/lang": "0.5.0", "@usebruno/schema": "0.5.0", "about-window": "^1.15.2", @@ -16841,6 +16878,7 @@ "fs-extra": "^10.1.0", "graphql": "^16.6.0", "handlebars": "^4.7.8", + "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.2", "is-valid-path": "^0.1.1", "lodash": "^4.17.21", @@ -16950,6 +16988,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "packages/bruno-electron/node_modules/http-proxy-agent": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz", + "integrity": "sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, "packages/bruno-electron/node_modules/https-proxy-agent": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz", @@ -17006,7 +17056,7 @@ }, "packages/bruno-js": { "name": "@usebruno/js", - "version": "0.6.0", + "version": "0.8.0", "license": "MIT", "dependencies": { "@usebruno/query": "0.1.0", @@ -20102,7 +20152,7 @@ "@usebruno/cli": { "version": "file:packages/bruno-cli", "requires": { - "@usebruno/js": "0.6.0", + "@usebruno/js": "0.8.0", "@usebruno/lang": "0.5.0", "axios": "^1.5.1", "chai": "^4.3.7", @@ -20111,6 +20161,8 @@ "form-data": "^4.0.0", "fs-extra": "^10.1.0", "handlebars": "^4.7.8", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.2", "inquirer": "^9.1.4", "lodash": "^4.17.21", "mustache": "^4.2.0", @@ -20118,6 +20170,14 @@ "yargs": "^17.6.2" }, "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" + } + }, "axios": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/axios/-/axios-1.5.1.tgz", @@ -20136,6 +20196,24 @@ "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } + }, + "http-proxy-agent": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz", + "integrity": "sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==", + "requires": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + } + }, + "https-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz", + "integrity": "sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==", + "requires": { + "agent-base": "^7.0.2", + "debug": "4" + } } } }, @@ -21210,7 +21288,7 @@ "bruno": { "version": "file:packages/bruno-electron", "requires": { - "@usebruno/js": "0.6.0", + "@usebruno/js": "0.8.0", "@usebruno/lang": "0.5.0", "@usebruno/schema": "0.5.0", "about-window": "^1.15.2", @@ -21231,6 +21309,7 @@ "fs-extra": "^10.1.0", "graphql": "^16.6.0", "handlebars": "^4.7.8", + "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.2", "is-valid-path": "^0.1.1", "lodash": "^4.17.21", @@ -21300,6 +21379,15 @@ "pump": "^3.0.0" } }, + "http-proxy-agent": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz", + "integrity": "sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==", + "requires": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + } + }, "https-proxy-agent": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz", diff --git a/packages/bruno-cli/package.json b/packages/bruno-cli/package.json index c5e213509..fd5a74faf 100644 --- a/packages/bruno-cli/package.json +++ b/packages/bruno-cli/package.json @@ -24,7 +24,7 @@ "package.json" ], "dependencies": { - "@usebruno/js": "0.6.0", + "@usebruno/js": "0.8.0", "@usebruno/lang": "0.5.0", "axios": "^1.5.1", "chai": "^4.3.7", diff --git a/packages/bruno-cli/src/runner/run-single-request.js b/packages/bruno-cli/src/runner/run-single-request.js index c658d76ca..f86e1b028 100644 --- a/packages/bruno-cli/src/runner/run-single-request.js +++ b/packages/bruno-cli/src/runner/run-single-request.js @@ -29,7 +29,7 @@ const runSingleRequest = async function ( request = prepareRequest(bruJson.request); - const allowScriptFilesystemAccess = get(brunoConfig, 'filesystemAccess.allow', false); + const scriptingConfig = get(brunoConfig, 'scripts', {}); // make axios work in node using form data // reference: https://github.com/axios/axios/issues/1006#issuecomment-320165427 @@ -68,7 +68,7 @@ const runSingleRequest = async function ( collectionPath, null, processEnvVars, - allowScriptFilesystemAccess + scriptingConfig ); } @@ -210,7 +210,7 @@ const runSingleRequest = async function ( collectionPath, null, processEnvVars, - allowScriptFilesystemAccess + scriptingConfig ); } @@ -252,7 +252,7 @@ const runSingleRequest = async function ( collectionPath, null, processEnvVars, - allowScriptFilesystemAccess + scriptingConfig ); testResults = get(result, 'results', []); } diff --git a/packages/bruno-electron/package.json b/packages/bruno-electron/package.json index 8b1fce2af..b66dd0434 100644 --- a/packages/bruno-electron/package.json +++ b/packages/bruno-electron/package.json @@ -14,7 +14,7 @@ "test": "jest" }, "dependencies": { - "@usebruno/js": "0.6.0", + "@usebruno/js": "0.8.0", "@usebruno/lang": "0.5.0", "@usebruno/schema": "0.5.0", "about-window": "^1.15.2", diff --git a/packages/bruno-electron/src/ipc/network/index.js b/packages/bruno-electron/src/ipc/network/index.js index 43d06d6c4..0586054d1 100644 --- a/packages/bruno-electron/src/ipc/network/index.js +++ b/packages/bruno-electron/src/ipc/network/index.js @@ -109,7 +109,7 @@ const registerNetworkIpc = (mainWindow) => { const envVars = getEnvVars(environment); const processEnvVars = getProcessEnvVars(collectionUid); const brunoConfig = getBrunoConfig(collectionUid); - const allowScriptFilesystemAccess = get(brunoConfig, 'filesystemAccess.allow', false); + const scriptingConfig = get(brunoConfig, 'scripts', {}); try { // make axios work in node using form data @@ -162,7 +162,7 @@ const registerNetworkIpc = (mainWindow) => { collectionPath, onConsoleLog, processEnvVars, - allowScriptFilesystemAccess + scriptingConfig ); mainWindow.webContents.send('main:script-environment-update', { @@ -296,7 +296,7 @@ const registerNetworkIpc = (mainWindow) => { collectionPath, onConsoleLog, processEnvVars, - allowScriptFilesystemAccess + scriptingConfig ); mainWindow.webContents.send('main:script-environment-update', { @@ -342,7 +342,7 @@ const registerNetworkIpc = (mainWindow) => { collectionPath, onConsoleLog, processEnvVars, - allowScriptFilesystemAccess + scriptingConfig ); mainWindow.webContents.send('main:run-request-event', { @@ -421,7 +421,7 @@ const registerNetworkIpc = (mainWindow) => { collectionPath, onConsoleLog, processEnvVars, - allowScriptFilesystemAccess + scriptingConfig ); mainWindow.webContents.send('main:run-request-event', { @@ -514,7 +514,7 @@ const registerNetworkIpc = (mainWindow) => { const collectionPath = collection.pathname; const folderUid = folder ? folder.uid : null; const brunoConfig = getBrunoConfig(collectionUid); - const allowScriptFilesystemAccess = get(brunoConfig, 'filesystemAccess.allow', false); + const scriptingConfig = get(brunoConfig, 'scripts', {}); const onConsoleLog = (type, args) => { console[type](...args); @@ -621,7 +621,7 @@ const registerNetworkIpc = (mainWindow) => { collectionPath, onConsoleLog, processEnvVars, - allowScriptFilesystemAccess + scriptingConfig ); mainWindow.webContents.send('main:script-environment-update', { @@ -735,7 +735,7 @@ const registerNetworkIpc = (mainWindow) => { collectionPath, onConsoleLog, processEnvVars, - allowScriptFilesystemAccess + scriptingConfig ); mainWindow.webContents.send('main:script-environment-update', { @@ -779,7 +779,7 @@ const registerNetworkIpc = (mainWindow) => { collectionPath, onConsoleLog, processEnvVars, - allowScriptFilesystemAccess + scriptingConfig ); mainWindow.webContents.send('main:run-folder-event', { @@ -859,7 +859,7 @@ const registerNetworkIpc = (mainWindow) => { collectionPath, onConsoleLog, processEnvVars, - allowScriptFilesystemAccess + scriptingConfig ); mainWindow.webContents.send('main:run-folder-event', { From 8fadaf98aec9fbae3968d018ca0486598334edf0 Mon Sep 17 00:00:00 2001 From: Anoop M D Date: Sat, 7 Oct 2023 03:23:39 +0530 Subject: [PATCH 12/71] feat(#306): bru cli v0.13.0 release --- packages/bruno-cli/changelog.md | 4 ++++ packages/bruno-cli/package.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/bruno-cli/changelog.md b/packages/bruno-cli/changelog.md index 1b83060f4..44130498a 100644 --- a/packages/bruno-cli/changelog.md +++ b/packages/bruno-cli/changelog.md @@ -1,5 +1,9 @@ # Changelog +## 0.13.0 + +- feat(#306) Module whitelisting and filesystem access support + ## 0.12.0 - show response time in milliseconds per request and total diff --git a/packages/bruno-cli/package.json b/packages/bruno-cli/package.json index fd5a74faf..dca3a8231 100644 --- a/packages/bruno-cli/package.json +++ b/packages/bruno-cli/package.json @@ -1,6 +1,6 @@ { "name": "@usebruno/cli", - "version": "0.12.0", + "version": "0.13.0", "license": "MIT", "main": "src/index.js", "bin": { From 860a3b16ad06a44874341842301f24eab5a006f5 Mon Sep 17 00:00:00 2001 From: Anoop M D Date: Sat, 7 Oct 2023 03:26:12 +0530 Subject: [PATCH 13/71] fix(#440): bring back menu bar --- packages/bruno-electron/src/index.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/bruno-electron/src/index.js b/packages/bruno-electron/src/index.js index 3908373e9..3f67b8a96 100644 --- a/packages/bruno-electron/src/index.js +++ b/packages/bruno-electron/src/index.js @@ -37,8 +37,10 @@ app.on('ready', async () => { webviewTag: true }, title: 'Bruno', - icon: path.join(__dirname, 'about/256x256.png'), - autoHideMenuBar: true + icon: path.join(__dirname, 'about/256x256.png') + // we will bring this back + // see https://github.com/usebruno/bruno/issues/440 + // autoHideMenuBar: true }); const url = isDev From f2a8bd5d10bfadcf6d4bf4d3d130948fdcf62d02 Mon Sep 17 00:00:00 2001 From: Jonathan Gruber Date: Fri, 6 Oct 2023 23:57:50 +0200 Subject: [PATCH 14/71] chore: update package-lock.json --- package-lock.json | 416 ++++++++++++++-------------------------------- 1 file changed, 128 insertions(+), 288 deletions(-) diff --git a/package-lock.json b/package-lock.json index a7f0faa74..b7c518e36 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1826,37 +1826,6 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, - "node_modules/@codemirror/language": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-0.20.2.tgz", - "integrity": "sha512-WB3Bnuusw0xhVvhBocieYKwJm04SOk5bPoOEYksVHKHcGHFOaYaw+eZVxR4gIqMMcGzOIUil0FsCmFk8yrhHpw==", - "peer": true, - "dependencies": { - "@codemirror/state": "^0.20.0", - "@codemirror/view": "^0.20.0", - "@lezer/common": "^0.16.0", - "@lezer/highlight": "^0.16.0", - "@lezer/lr": "^0.16.0", - "style-mod": "^4.0.0" - } - }, - "node_modules/@codemirror/state": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-0.20.1.tgz", - "integrity": "sha512-ms0tlV5A02OK0pFvTtSUGMLkoarzh1F8mr6jy1cD7ucSC2X/VLHtQCxfhdSEGqTYlQF2hoZtmLv+amqhdgbwjQ==", - "peer": true - }, - "node_modules/@codemirror/view": { - "version": "0.20.7", - "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-0.20.7.tgz", - "integrity": "sha512-pqEPCb9QFTOtHgAH5XU/oVy9UR/Anj6r+tG5CRmkNVcqSKEPmBU05WtN/jxJCFZBXf6HumzWC9ydE4qstO3TxQ==", - "peer": true, - "dependencies": { - "@codemirror/state": "^0.20.0", - "style-mod": "^4.0.0", - "w3c-keyname": "^2.2.4" - } - }, "node_modules/@develar/schema-utils": { "version": "2.6.5", "resolved": "https://registry.npmjs.org/@develar/schema-utils/-/schema-utils-2.6.5.tgz", @@ -2961,30 +2930,6 @@ "@jridgewell/sourcemap-codec": "1.4.14" } }, - "node_modules/@lezer/common": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/@lezer/common/-/common-0.16.1.tgz", - "integrity": "sha512-qPmG7YTZ6lATyTOAWf8vXE+iRrt1NJd4cm2nJHK+v7X9TsOF6+HtuU/ctaZy2RCrluxDb89hI6KWQ5LfQGQWuA==", - "peer": true - }, - "node_modules/@lezer/highlight": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-0.16.0.tgz", - "integrity": "sha512-iE5f4flHlJ1g1clOStvXNLbORJoiW4Kytso6ubfYzHnaNo/eo5SKhxs4wv/rtvwZQeZrK3we8S9SyA7OGOoRKQ==", - "peer": true, - "dependencies": { - "@lezer/common": "^0.16.0" - } - }, - "node_modules/@lezer/lr": { - "version": "0.16.3", - "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-0.16.3.tgz", - "integrity": "sha512-pau7um4eAw94BEuuShUIeQDTf3k4Wt6oIUOYxMmkZgDHdqtIcxWND4LRxi8nI9KuT4I1bXQv67BCapkxt7Ywqw==", - "peer": true, - "dependencies": { - "@lezer/common": "^0.16.0" - } - }, "node_modules/@malept/cross-spawn-promise": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz", @@ -4839,39 +4784,6 @@ "node": ">=10.12.0" } }, - "node_modules/autoprefixer": { - "version": "10.4.13", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.13.tgz", - "integrity": "sha512-49vKpMqcZYsJjwotvt4+h/BCjJVnhGwcLpDt5xkcaOG3eLrG/HUYLagrihYsQ+qrIBgIzX1Rw7a6L8I/ZA1Atg==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/autoprefixer" - } - ], - "peer": true, - "dependencies": { - "browserslist": "^4.21.4", - "caniuse-lite": "^1.0.30001426", - "fraction.js": "^4.2.0", - "normalize-range": "^0.1.2", - "picocolors": "^1.0.0", - "postcss-value-parser": "^4.2.0" - }, - "bin": { - "autoprefixer": "bin/autoprefixer" - }, - "engines": { - "node": "^10 || ^12 || >=14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, "node_modules/aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", @@ -5300,6 +5212,7 @@ "version": "4.21.4", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz", "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==", + "dev": true, "funding": [ { "type": "opencollective", @@ -7338,7 +7251,8 @@ "node_modules/electron-to-chromium": { "version": "1.4.284", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz", - "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==" + "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==", + "dev": true }, "node_modules/electron-util": { "version": "0.17.2", @@ -8140,19 +8054,6 @@ "node": ">= 0.6" } }, - "node_modules/fraction.js": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", - "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==", - "peer": true, - "engines": { - "node": "*" - }, - "funding": { - "type": "patreon", - "url": "https://www.patreon.com/infusion" - } - }, "node_modules/fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", @@ -8643,18 +8544,6 @@ "node": ">= 6" } }, - "node_modules/graphql-ws": { - "version": "5.11.2", - "resolved": "https://registry.npmjs.org/graphql-ws/-/graphql-ws-5.11.2.tgz", - "integrity": "sha512-4EiZ3/UXYcjm+xFGP544/yW1+DVI8ZpKASFbzrV5EDTFWJp0ZvLl4Dy2fSZAzz9imKp5pZMIcjB0x/H69Pv/6w==", - "peer": true, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "graphql": ">=0.11 <=16" - } - }, "node_modules/handlebars": { "version": "4.7.8", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", @@ -11641,7 +11530,8 @@ "node_modules/node-releases": { "version": "2.0.8", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.8.tgz", - "integrity": "sha512-dFSmB8fFHEH/s81Xi+Y/15DQY6VHW81nXRj86EMSL3lmuTmK1e+aT4wrFCkTbm+gSwkw4KpX+rT/pMM2c1mF+A==" + "integrity": "sha512-dFSmB8fFHEH/s81Xi+Y/15DQY6VHW81nXRj86EMSL3lmuTmK1e+aT4wrFCkTbm+gSwkw4KpX+rT/pMM2c1mF+A==", + "dev": true }, "node_modules/normalize-package-data": { "version": "2.5.0", @@ -11678,15 +11568,6 @@ "node": ">=0.10.0" } }, - "node_modules/normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/normalize-url": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", @@ -13626,7 +13507,8 @@ "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==" + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true }, "node_modules/react-redux": { "version": "7.2.9", @@ -15018,12 +14900,6 @@ "webpack": "^5.0.0" } }, - "node_modules/style-mod": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.0.0.tgz", - "integrity": "sha512-OPhtyEjyyN9x3nhPsu76f52yUGXiZcgvsrFVtvTkyGRQJ0XK+GPc6ov1z+lRpbeabka+MYEQxOYRnt5nF30aMw==", - "peer": true - }, "node_modules/styled-components": { "version": "5.3.6", "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-5.3.6.tgz", @@ -15954,6 +15830,7 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", + "dev": true, "funding": [ { "type": "opencollective", @@ -16236,12 +16113,6 @@ "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.2.tgz", "integrity": "sha512-zHhCWatviizPIq9B7Vh9uvrH6x3sK8itC84HkamnBWoDFJtzBf7SWlpLCZUit72b3os45h6RWQNC9xHRDF8dRA==" }, - "node_modules/w3c-keyname": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.6.tgz", - "integrity": "sha512-f+fciywl1SJEniZHD6H+kUO8gOnwIr7f4ijKA6+ZvJFjeGi1r4PDLl53Ayud9O/rk64RqgoQine0feoeOU0kXg==", - "peer": true - }, "node_modules/walker": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", @@ -16788,6 +16659,8 @@ "form-data": "^4.0.0", "fs-extra": "^10.1.0", "handlebars": "^4.7.8", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.2", "inquirer": "^9.1.4", "lodash": "^4.17.21", "mustache": "^4.2.0", @@ -16798,6 +16671,17 @@ "bru": "bin/bru.js" } }, + "packages/bruno-cli/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" + } + }, "packages/bruno-cli/node_modules/axios": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/axios/-/axios-1.5.1.tgz", @@ -16820,6 +16704,30 @@ "node": ">=8" } }, + "packages/bruno-cli/node_modules/http-proxy-agent": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz", + "integrity": "sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "packages/bruno-cli/node_modules/https-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz", + "integrity": "sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, "packages/bruno-electron": { "name": "bruno", "version": "v0.20.0", @@ -16841,6 +16749,7 @@ "fs-extra": "^10.1.0", "graphql": "^16.6.0", "handlebars": "^4.7.8", + "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.2", "is-valid-path": "^0.1.1", "lodash": "^4.17.21", @@ -16950,6 +16859,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "packages/bruno-electron/node_modules/http-proxy-agent": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz", + "integrity": "sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, "packages/bruno-electron/node_modules/https-proxy-agent": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz", @@ -18378,37 +18299,6 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, - "@codemirror/language": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-0.20.2.tgz", - "integrity": "sha512-WB3Bnuusw0xhVvhBocieYKwJm04SOk5bPoOEYksVHKHcGHFOaYaw+eZVxR4gIqMMcGzOIUil0FsCmFk8yrhHpw==", - "peer": true, - "requires": { - "@codemirror/state": "^0.20.0", - "@codemirror/view": "^0.20.0", - "@lezer/common": "^0.16.0", - "@lezer/highlight": "^0.16.0", - "@lezer/lr": "^0.16.0", - "style-mod": "^4.0.0" - } - }, - "@codemirror/state": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-0.20.1.tgz", - "integrity": "sha512-ms0tlV5A02OK0pFvTtSUGMLkoarzh1F8mr6jy1cD7ucSC2X/VLHtQCxfhdSEGqTYlQF2hoZtmLv+amqhdgbwjQ==", - "peer": true - }, - "@codemirror/view": { - "version": "0.20.7", - "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-0.20.7.tgz", - "integrity": "sha512-pqEPCb9QFTOtHgAH5XU/oVy9UR/Anj6r+tG5CRmkNVcqSKEPmBU05WtN/jxJCFZBXf6HumzWC9ydE4qstO3TxQ==", - "peer": true, - "requires": { - "@codemirror/state": "^0.20.0", - "style-mod": "^4.0.0", - "w3c-keyname": "^2.2.4" - } - }, "@develar/schema-utils": { "version": "2.6.5", "resolved": "https://registry.npmjs.org/@develar/schema-utils/-/schema-utils-2.6.5.tgz", @@ -19280,30 +19170,6 @@ "@jridgewell/sourcemap-codec": "1.4.14" } }, - "@lezer/common": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/@lezer/common/-/common-0.16.1.tgz", - "integrity": "sha512-qPmG7YTZ6lATyTOAWf8vXE+iRrt1NJd4cm2nJHK+v7X9TsOF6+HtuU/ctaZy2RCrluxDb89hI6KWQ5LfQGQWuA==", - "peer": true - }, - "@lezer/highlight": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-0.16.0.tgz", - "integrity": "sha512-iE5f4flHlJ1g1clOStvXNLbORJoiW4Kytso6ubfYzHnaNo/eo5SKhxs4wv/rtvwZQeZrK3we8S9SyA7OGOoRKQ==", - "peer": true, - "requires": { - "@lezer/common": "^0.16.0" - } - }, - "@lezer/lr": { - "version": "0.16.3", - "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-0.16.3.tgz", - "integrity": "sha512-pau7um4eAw94BEuuShUIeQDTf3k4Wt6oIUOYxMmkZgDHdqtIcxWND4LRxi8nI9KuT4I1bXQv67BCapkxt7Ywqw==", - "peer": true, - "requires": { - "@lezer/common": "^0.16.0" - } - }, "@malept/cross-spawn-promise": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz", @@ -19630,8 +19496,7 @@ "@tabler/icons": { "version": "1.119.0", "resolved": "https://registry.npmjs.org/@tabler/icons/-/icons-1.119.0.tgz", - "integrity": "sha512-Fk3Qq4w2SXcTjc/n1cuL5bccPkylrOMo7cYpQIf/yw6zP76LQV9dtLcHQUjFiUnaYuswR645CnURIhlafyAh9g==", - "requires": {} + "integrity": "sha512-Fk3Qq4w2SXcTjc/n1cuL5bccPkylrOMo7cYpQIf/yw6zP76LQV9dtLcHQUjFiUnaYuswR645CnURIhlafyAh9g==" }, "@tauri-apps/cli": { "version": "1.2.2", @@ -20111,6 +19976,8 @@ "form-data": "^4.0.0", "fs-extra": "^10.1.0", "handlebars": "^4.7.8", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.2", "inquirer": "^9.1.4", "lodash": "^4.17.21", "mustache": "^4.2.0", @@ -20118,6 +19985,14 @@ "yargs": "^17.6.2" }, "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" + } + }, "axios": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/axios/-/axios-1.5.1.tgz", @@ -20136,6 +20011,24 @@ "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } + }, + "http-proxy-agent": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz", + "integrity": "sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==", + "requires": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + } + }, + "https-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz", + "integrity": "sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==", + "requires": { + "agent-base": "^7.0.2", + "debug": "4" + } } } }, @@ -20224,8 +20117,7 @@ } }, "@usebruno/schema": { - "version": "file:packages/bruno-schema", - "requires": {} + "version": "file:packages/bruno-schema" }, "@usebruno/testbench": { "version": "file:packages/bruno-testbench", @@ -20401,8 +20293,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.2.0.tgz", "integrity": "sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg==", - "dev": true, - "requires": {} + "dev": true }, "@webpack-cli/info": { "version": "1.5.0", @@ -20417,8 +20308,7 @@ "version": "1.7.0", "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.7.0.tgz", "integrity": "sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q==", - "dev": true, - "requires": {} + "dev": true }, "@xtuc/ieee754": { "version": "1.2.0", @@ -20523,8 +20413,7 @@ "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "requires": {} + "dev": true }, "amdefine": { "version": "0.0.8", @@ -20857,20 +20746,6 @@ "resolved": "https://registry.npmjs.org/atomically/-/atomically-1.7.0.tgz", "integrity": "sha512-Xcz9l0z7y9yQ9rdDaxlmaI4uJHf/T8g9hOEzJcsEqX2SjCj4J20uK7+ldkDHMbpJDK76wF7xEIgxc/vSlsfw5w==" }, - "autoprefixer": { - "version": "10.4.13", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.13.tgz", - "integrity": "sha512-49vKpMqcZYsJjwotvt4+h/BCjJVnhGwcLpDt5xkcaOG3eLrG/HUYLagrihYsQ+qrIBgIzX1Rw7a6L8I/ZA1Atg==", - "peer": true, - "requires": { - "browserslist": "^4.21.4", - "caniuse-lite": "^1.0.30001426", - "fraction.js": "^4.2.0", - "normalize-range": "^0.1.2", - "picocolors": "^1.0.0", - "postcss-value-parser": "^4.2.0" - } - }, "aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", @@ -21200,6 +21075,7 @@ "version": "4.21.4", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz", "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==", + "dev": true, "requires": { "caniuse-lite": "^1.0.30001400", "electron-to-chromium": "^1.4.251", @@ -21231,6 +21107,7 @@ "fs-extra": "^10.1.0", "graphql": "^16.6.0", "handlebars": "^4.7.8", + "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.2", "is-valid-path": "^0.1.1", "lodash": "^4.17.21", @@ -21300,6 +21177,15 @@ "pump": "^3.0.0" } }, + "http-proxy-agent": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz", + "integrity": "sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==", + "requires": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + } + }, "https-proxy-agent": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz", @@ -22125,8 +22011,7 @@ "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, - "requires": {} + "dev": true }, "css-loader": { "version": "6.7.3", @@ -22271,8 +22156,7 @@ "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, - "requires": {} + "dev": true }, "csso": { "version": "4.2.0", @@ -22845,7 +22729,8 @@ "electron-to-chromium": { "version": "1.4.284", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz", - "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==" + "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==", + "dev": true }, "electron-util": { "version": "0.17.2", @@ -23470,12 +23355,6 @@ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" }, - "fraction.js": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", - "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==", - "peer": true - }, "fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", @@ -23738,8 +23617,7 @@ "goober": { "version": "2.1.11", "resolved": "https://registry.npmjs.org/goober/-/goober-2.1.11.tgz", - "integrity": "sha512-5SS2lmxbhqH0u9ABEWq7WPU69a4i2pYcHeCxqaNq6Cw3mnrF0ghWNM4tEGid4dKy8XNIAUbuThuozDHHKJVh3A==", - "requires": {} + "integrity": "sha512-5SS2lmxbhqH0u9ABEWq7WPU69a4i2pYcHeCxqaNq6Cw3mnrF0ghWNM4tEGid4dKy8XNIAUbuThuozDHHKJVh3A==" }, "got": { "version": "9.6.0", @@ -23862,13 +23740,6 @@ } } }, - "graphql-ws": { - "version": "5.11.2", - "resolved": "https://registry.npmjs.org/graphql-ws/-/graphql-ws-5.11.2.tgz", - "integrity": "sha512-4EiZ3/UXYcjm+xFGP544/yW1+DVI8ZpKASFbzrV5EDTFWJp0ZvLl4Dy2fSZAzz9imKp5pZMIcjB0x/H69Pv/6w==", - "peer": true, - "requires": {} - }, "handlebars": { "version": "4.7.8", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", @@ -24219,8 +24090,7 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", - "dev": true, - "requires": {} + "dev": true }, "idb": { "version": "7.1.1", @@ -24999,8 +24869,7 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", - "dev": true, - "requires": {} + "dev": true }, "jest-regex-util": { "version": "29.2.0", @@ -25762,8 +25631,7 @@ "meros": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/meros/-/meros-1.2.1.tgz", - "integrity": "sha512-R2f/jxYqCAGI19KhAvaxSOxALBMkaXWH2a7rOyqQw+ZmizX5bKkEYWLzdhC+U82ZVVPVp6MCXe3EkVligh+12g==", - "requires": {} + "integrity": "sha512-R2f/jxYqCAGI19KhAvaxSOxALBMkaXWH2a7rOyqQw+ZmizX5bKkEYWLzdhC+U82ZVVPVp6MCXe3EkVligh+12g==" }, "methods": { "version": "1.1.2", @@ -26097,7 +25965,8 @@ "node-releases": { "version": "2.0.8", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.8.tgz", - "integrity": "sha512-dFSmB8fFHEH/s81Xi+Y/15DQY6VHW81nXRj86EMSL3lmuTmK1e+aT4wrFCkTbm+gSwkw4KpX+rT/pMM2c1mF+A==" + "integrity": "sha512-dFSmB8fFHEH/s81Xi+Y/15DQY6VHW81nXRj86EMSL3lmuTmK1e+aT4wrFCkTbm+gSwkw4KpX+rT/pMM2c1mF+A==", + "dev": true }, "normalize-package-data": { "version": "2.5.0", @@ -26130,12 +25999,6 @@ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" }, - "normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", - "peer": true - }, "normalize-url": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", @@ -26798,29 +26661,25 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz", "integrity": "sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==", - "dev": true, - "requires": {} + "dev": true }, "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, - "requires": {} + "dev": true }, "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, - "requires": {} + "dev": true }, "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, - "requires": {} + "dev": true }, "postcss-js": { "version": "3.0.3", @@ -26922,8 +26781,7 @@ "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, - "requires": {} + "dev": true }, "postcss-modules-local-by-default": { "version": "4.0.0", @@ -26966,8 +26824,7 @@ "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, - "requires": {} + "dev": true }, "postcss-normalize-display-values": { "version": "5.1.0", @@ -27488,13 +27345,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==", - "requires": {} + "integrity": "sha512-x+b7LxhmHXjHoU/VrFAzw5iutsILRoYyDq97EDYdFpPLcvqtEzk4ZSZSQjnFPbr5T57tLXnHcqFYoN1pI6u8uQ==" }, "react-is": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true }, "react-redux": { "version": "7.2.9", @@ -27681,8 +27538,7 @@ "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==", - "requires": {} + "integrity": "sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==" }, "regenerate": { "version": "1.4.2", @@ -27984,8 +27840,7 @@ "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, - "requires": {} + "dev": true }, "rollup-plugin-postcss": { "version": "4.0.2", @@ -28598,14 +28453,7 @@ "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, - "requires": {} - }, - "style-mod": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.0.0.tgz", - "integrity": "sha512-OPhtyEjyyN9x3nhPsu76f52yUGXiZcgvsrFVtvTkyGRQJ0XK+GPc6ov1z+lRpbeabka+MYEQxOYRnt5nF30aMw==", - "peer": true + "dev": true }, "styled-components": { "version": "5.3.6", @@ -28642,8 +28490,7 @@ "styled-jsx": { "version": "5.0.7", "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.0.7.tgz", - "integrity": "sha512-b3sUzamS086YLRuvnaDigdAewz1/EFYlHpYBP5mZovKEdQQOIIYq8lApylub3HHZ6xFjV051kkGU7cudJmrXEA==", - "requires": {} + "integrity": "sha512-b3sUzamS086YLRuvnaDigdAewz1/EFYlHpYBP5mZovKEdQQOIIYq8lApylub3HHZ6xFjV051kkGU7cudJmrXEA==" }, "stylehacks": { "version": "5.1.1", @@ -29292,6 +29139,7 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", + "dev": true, "requires": { "escalade": "^3.1.1", "picocolors": "^1.0.0" @@ -29380,8 +29228,7 @@ "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==", - "requires": {} + "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==" }, "utf8-byte-length": { "version": "1.0.4", @@ -29514,12 +29361,6 @@ "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.2.tgz", "integrity": "sha512-zHhCWatviizPIq9B7Vh9uvrH6x3sK8itC84HkamnBWoDFJtzBf7SWlpLCZUit72b3os45h6RWQNC9xHRDF8dRA==" }, - "w3c-keyname": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.6.tgz", - "integrity": "sha512-f+fciywl1SJEniZHD6H+kUO8gOnwIr7f4ijKA6+ZvJFjeGi1r4PDLl53Ayud9O/rk64RqgoQine0feoeOU0kXg==", - "peer": true - }, "walker": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", @@ -29600,8 +29441,7 @@ "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, - "requires": {} + "dev": true }, "schema-utils": { "version": "3.1.1", From 1e27427d09b40e5aaf95cf59b36c914f0c5feb5d Mon Sep 17 00:00:00 2001 From: Anoop M D Date: Sat, 7 Oct 2023 03:28:11 +0530 Subject: [PATCH 15/71] chore: bump version to 0.21.0 --- packages/bruno-app/src/components/Sidebar/index.js | 2 +- packages/bruno-electron/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/bruno-app/src/components/Sidebar/index.js b/packages/bruno-app/src/components/Sidebar/index.js index ad7164371..25156be84 100644 --- a/packages/bruno-app/src/components/Sidebar/index.js +++ b/packages/bruno-app/src/components/Sidebar/index.js @@ -105,7 +105,7 @@ const Sidebar = () => { Star
-
v0.20.0
+
v0.21.0
diff --git a/packages/bruno-electron/package.json b/packages/bruno-electron/package.json index b66dd0434..6cdd6914d 100644 --- a/packages/bruno-electron/package.json +++ b/packages/bruno-electron/package.json @@ -1,5 +1,5 @@ { - "version": "v0.20.0", + "version": "v0.21.0", "name": "bruno", "description": "Opensource API Client for Exploring and Testing APIs", "homepage": "https://www.usebruno.com", From ae78ed36efdeaa7c440b104de164ee55860303b8 Mon Sep 17 00:00:00 2001 From: Sebastien Dionne Date: Fri, 6 Oct 2023 22:17:10 -0400 Subject: [PATCH 16/71] 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 12f3f802a758613629abd90b56fd17e2acb9fcef Mon Sep 17 00:00:00 2001 From: Anoop M D Date: Sat, 7 Oct 2023 09:02:19 +0530 Subject: [PATCH 17/71] request save control --- .../bruno-app/src/components/Modal/index.js | 20 +++++--- .../RequestPane/QueryUrl/StyledWrapper.js | 44 +++++++++++++++++ .../components/RequestPane/QueryUrl/index.js | 27 ++++++++++- .../RequestTab/ConfirmRequestClose/index.js | 30 ++++++++++++ .../RequestTabs/RequestTab/index.js | 48 ++++++++++++++++++- .../ReduxStore/slices/collections/actions.js | 6 ++- .../ReduxStore/slices/collections/index.js | 12 +++++ .../bruno-app/src/utils/common/platform.js | 7 +++ 8 files changed, 183 insertions(+), 11 deletions(-) create mode 100644 packages/bruno-app/src/components/RequestTabs/RequestTab/ConfirmRequestClose/index.js diff --git a/packages/bruno-app/src/components/Modal/index.js b/packages/bruno-app/src/components/Modal/index.js index 213c62efe..ec715a03d 100644 --- a/packages/bruno-app/src/components/Modal/index.js +++ b/packages/bruno-app/src/components/Modal/index.js @@ -61,19 +61,20 @@ const Modal = ({ children, confirmDisabled, hideCancel, - hideFooter + hideFooter, + closeModalFadeTimeout = 500 }) => { const [isClosing, setIsClosing] = useState(false); const escFunction = (event) => { const escKeyCode = 27; if (event.keyCode === escKeyCode) { - closeModal(); + closeModal({ type: 'esc' }); } }; - const closeModal = () => { + const closeModal = (args) => { setIsClosing(true); - setTimeout(() => handleCancel(), 500); + setTimeout(() => handleCancel(args), closeModalFadeTimeout); }; useEffect(() => { @@ -94,12 +95,12 @@ const Modal = ({ return (
- closeModal()} /> + closeModal({ type: 'icon' })} /> {children} closeModal()} + handleCancel={() => closeModal({ type: 'button' })} handleSubmit={handleConfirm} confirmDisabled={confirmDisabled} hideCancel={hideCancel} @@ -108,7 +109,12 @@ const Modal = ({
{/* Clicking on backdrop closes the modal */} -
closeModal()} /> +
{ + closeModal({ type: 'backdrop' }); + }} + /> ); }; diff --git a/packages/bruno-app/src/components/RequestPane/QueryUrl/StyledWrapper.js b/packages/bruno-app/src/components/RequestPane/QueryUrl/StyledWrapper.js index 7ec35f33e..2308dec4f 100644 --- a/packages/bruno-app/src/components/RequestPane/QueryUrl/StyledWrapper.js +++ b/packages/bruno-app/src/components/RequestPane/QueryUrl/StyledWrapper.js @@ -32,6 +32,50 @@ const Wrapper = styled.div` position: relative; top: 1px; } + + .tooltip { + position: relative; + display: inline-block; + cursor: pointer; + } + + .tooltip:hover .tooltiptext { + visibility: visible; + opacity: 1; + } + + .tooltiptext { + visibility: hidden; + width: auto; + background-color: ${(props) => props.theme.requestTabs.active.bg}; + color: ${(props) => props.theme.text}; + text-align: center; + border-radius: 4px; + padding: 4px 8px; + position: absolute; + z-index: 1; + bottom: 34px; + left: 50%; + transform: translateX(-50%); + opacity: 0; + transition: opacity 0.3s; + white-space: nowrap; + } + + .tooltiptext::after { + content: ''; + position: absolute; + top: 100%; + left: 50%; + margin-left: -4px; + border-width: 4px; + border-style: solid; + border-color: ${(props) => props.theme.requestTabs.active.bg} transparent transparent transparent; + } + + .shortcut { + font-size: 0.625rem; + } `; export default Wrapper; diff --git a/packages/bruno-app/src/components/RequestPane/QueryUrl/index.js b/packages/bruno-app/src/components/RequestPane/QueryUrl/index.js index f783bb9d5..4b5b68a00 100644 --- a/packages/bruno-app/src/components/RequestPane/QueryUrl/index.js +++ b/packages/bruno-app/src/components/RequestPane/QueryUrl/index.js @@ -6,7 +6,9 @@ import { saveRequest } from 'providers/ReduxStore/slices/collections/actions'; import HttpMethodSelector from './HttpMethodSelector'; import { useTheme } from 'providers/Theme'; import SendIcon from 'components/Icons/Send'; +import { IconDeviceFloppy } from '@tabler/icons'; import SingleLineEditor from 'components/SingleLineEditor'; +import { isMacOS } from 'utils/common/platform'; import StyledWrapper from './StyledWrapper'; const QueryUrl = ({ item, collection, handleRun }) => { @@ -14,6 +16,8 @@ const QueryUrl = ({ item, collection, handleRun }) => { const dispatch = useDispatch(); const method = item.draft ? get(item, 'draft.request.method') : get(item, 'request.method'); const url = item.draft ? get(item, 'draft.request.url') : get(item, 'request.url'); + const isMac = isMacOS(); + const saveShortcut = isMac ? 'Cmd + S' : 'Ctrl + S'; const [methodSelectorWidth, setMethodSelectorWidth] = useState(90); @@ -22,7 +26,10 @@ const QueryUrl = ({ item, collection, handleRun }) => { setMethodSelectorWidth(el.offsetWidth); }, [method]); - const onSave = () => dispatch(saveRequest(item.uid, collection.uid)); + const onSave = () => { + dispatch(saveRequest(item.uid, collection.uid)); + }; + const onUrlChange = (value) => { dispatch( requestUrlChanged({ @@ -65,6 +72,24 @@ const QueryUrl = ({ item, collection, handleRun }) => { collection={collection} />
+
{ + e.stopPropagation(); + if (!item.draft) return; + onSave(); + }} + > + + + Save ({saveShortcut}) + +
diff --git a/packages/bruno-app/src/components/RequestTabs/RequestTab/ConfirmRequestClose/index.js b/packages/bruno-app/src/components/RequestTabs/RequestTab/ConfirmRequestClose/index.js new file mode 100644 index 000000000..94460cf48 --- /dev/null +++ b/packages/bruno-app/src/components/RequestTabs/RequestTab/ConfirmRequestClose/index.js @@ -0,0 +1,30 @@ +import React from 'react'; +import Modal from 'components/Modal'; + +const ConfirmRequestClose = ({ onCancel, onCloseWithoutSave, onSaveAndClose }) => { + const _handleCancel = ({ type }) => { + if (type === 'button') { + return onCloseWithoutSave(); + } + + return onCancel(); + }; + + return ( + +
You have unsaved changes in you request.
+
+ ); +}; + +export default ConfirmRequestClose; diff --git a/packages/bruno-app/src/components/RequestTabs/RequestTab/index.js b/packages/bruno-app/src/components/RequestTabs/RequestTab/index.js index 9b7b59a30..8fc27e90c 100644 --- a/packages/bruno-app/src/components/RequestTabs/RequestTab/index.js +++ b/packages/bruno-app/src/components/RequestTabs/RequestTab/index.js @@ -1,10 +1,13 @@ -import React from 'react'; +import React, { useState } from 'react'; import get from 'lodash/get'; import { closeTabs } from 'providers/ReduxStore/slices/tabs'; +import { saveRequest } from 'providers/ReduxStore/slices/collections/actions'; +import { deleteRequestDraft } from 'providers/ReduxStore/slices/collections'; import { useDispatch } from 'react-redux'; import { findItemInCollection } from 'utils/collections'; import StyledWrapper from './StyledWrapper'; import RequestTabNotFound from './RequestTabNotFound'; +import ConfirmRequestClose from './ConfirmRequestClose'; import SpecialTab from './SpecialTab'; import { useTheme } from 'providers/Theme'; import darkTheme from 'themes/dark'; @@ -13,6 +16,7 @@ import lightTheme from 'themes/light'; const RequestTab = ({ tab, collection }) => { const dispatch = useDispatch(); const { storedTheme } = useTheme(); + const [showConfirmClose, setShowConfirmClose] = useState(false); const handleCloseClick = (event) => { event.stopPropagation(); @@ -86,6 +90,39 @@ const RequestTab = ({ tab, collection }) => { return ( + {showConfirmClose && ( + setShowConfirmClose(false)} + onCloseWithoutSave={() => { + dispatch( + deleteRequestDraft({ + itemUid: item.uid, + collectionUid: collection.uid + }) + ); + dispatch( + closeTabs({ + tabUids: [tab.uid] + }) + ); + setShowConfirmClose(false); + }} + onSaveAndClose={() => { + dispatch(saveRequest(item.uid, collection.uid)) + .then(() => { + dispatch( + closeTabs({ + tabUids: [tab.uid] + }) + ); + setShowConfirmClose(false); + }) + .catch((err) => { + console.log('err', err); + }); + }} + /> + )}
{method} @@ -94,7 +131,14 @@ const RequestTab = ({ tab, collection }) => { {item.name}
-
handleCloseClick(e)}> +
{ + if (!item.draft) return handleCloseClick(e); + + setShowConfirmClose(true); + }} + > {!item.draft ? ( (dispatch, getState) => { itemSchema .validate(itemToSave) .then(() => ipcRenderer.invoke('renderer:save-request', item.pathname, itemToSave)) + .then(() => toast.success('Request saved successfully')) .then(resolve) - .catch(reject); + .catch((err) => { + toast.error('Failed to save request!'); + reject(err); + }); }); }; diff --git a/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js b/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js index 31cf6d6ca..f1f9699a8 100644 --- a/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js +++ b/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js @@ -258,6 +258,17 @@ export const collectionsSlice = createSlice({ } } }, + deleteRequestDraft: (state, action) => { + const collection = findCollectionByUid(state.collections, action.payload.collectionUid); + + if (collection) { + const item = findItemInCollection(collection, action.payload.itemUid); + + if (item && item.draft) { + item.draft = null; + } + } + }, newEphemeralHttpRequest: (state, action) => { const collection = findCollectionByUid(state.collections, action.payload.collectionUid); @@ -1224,6 +1235,7 @@ export const { requestCancelled, responseReceived, saveRequest, + deleteRequestDraft, newEphemeralHttpRequest, collectionClicked, collectionFolderClicked, diff --git a/packages/bruno-app/src/utils/common/platform.js b/packages/bruno-app/src/utils/common/platform.js index e49a66ec9..771daaf14 100644 --- a/packages/bruno-app/src/utils/common/platform.js +++ b/packages/bruno-app/src/utils/common/platform.js @@ -41,3 +41,10 @@ export const isWindowsOS = () => { return osFamily.includes('windows'); }; + +export const isMacOS = () => { + const os = platform.os; + const osFamily = os.family.toLowerCase(); + + return osFamily.includes('os x'); +}; From 6421148dc1ce95a758306ee9b5096d34dd8ac222 Mon Sep 17 00:00:00 2001 From: therealrinku Date: Sat, 7 Oct 2023 12:50:19 +0545 Subject: [PATCH 18/71] minor styling fixes --- packages/bruno-app/src/components/Modal/StyledWrapper.js | 1 + packages/bruno-app/src/styles/globals.css | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/packages/bruno-app/src/components/Modal/StyledWrapper.js b/packages/bruno-app/src/components/Modal/StyledWrapper.js index 4ec5d4a25..eb32c9655 100644 --- a/packages/bruno-app/src/components/Modal/StyledWrapper.js +++ b/packages/bruno-app/src/components/Modal/StyledWrapper.js @@ -22,6 +22,7 @@ const Wrapper = styled.div` justify-content: center; overflow-y: auto; z-index: 10; + background-color: rgba(0, 0, 0, 0.5); } .bruno-modal-card { diff --git a/packages/bruno-app/src/styles/globals.css b/packages/bruno-app/src/styles/globals.css index fb8eb5b5f..ee784ff1f 100644 --- a/packages/bruno-app/src/styles/globals.css +++ b/packages/bruno-app/src/styles/globals.css @@ -53,3 +53,9 @@ body::-webkit-scrollbar-thumb, background-color: #cdcdcd; border-radius: 5rem; } + +/* making all the checkboxes and radios bigger */ +input[type='checkbox'], +input[type='radio'] { + transform: scale(1.25); +} From 460021760657298376c3ee7412978f58d97b57aa Mon Sep 17 00:00:00 2001 From: Jarne Date: Sat, 7 Oct 2023 14:27:24 +0200 Subject: [PATCH 19/71] Add basic window state persistance --- packages/bruno-electron/src/index.js | 12 ++++++-- .../bruno-electron/src/store/window-state.js | 21 ++++++++++++++ packages/bruno-electron/src/utils/window.js | 28 +++++++++++++++++++ 3 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 packages/bruno-electron/src/store/window-state.js create mode 100644 packages/bruno-electron/src/utils/window.js diff --git a/packages/bruno-electron/src/index.js b/packages/bruno-electron/src/index.js index 3f67b8a96..5e9916ef0 100644 --- a/packages/bruno-electron/src/index.js +++ b/packages/bruno-electron/src/index.js @@ -9,6 +9,7 @@ const LastOpenedCollections = require('./store/last-opened-collections'); const registerNetworkIpc = require('./ipc/network'); const registerCollectionsIpc = require('./ipc/collection'); const Watcher = require('./app/watcher'); +const { loadWindowState, saveWindowState } = require('./utils/window'); const lastOpenedCollections = new LastOpenedCollections(); @@ -27,9 +28,13 @@ let watcher; // Prepare the renderer once the app is ready app.on('ready', async () => { + const { x, y, width, height } = loadWindowState(); + mainWindow = new BrowserWindow({ - width: 1280, - height: 768, + x, + y, + width, + height, webPreferences: { nodeIntegration: true, contextIsolation: true, @@ -54,6 +59,9 @@ app.on('ready', async () => { mainWindow.loadURL(url); watcher = new Watcher(); + mainWindow.on('resize', () => saveWindowState(mainWindow)); + mainWindow.on('move', () => saveWindowState(mainWindow)); + mainWindow.webContents.on('new-window', function (e, url) { e.preventDefault(); require('electron').shell.openExternal(url); diff --git a/packages/bruno-electron/src/store/window-state.js b/packages/bruno-electron/src/store/window-state.js new file mode 100644 index 000000000..4b2520380 --- /dev/null +++ b/packages/bruno-electron/src/store/window-state.js @@ -0,0 +1,21 @@ +const _ = require('lodash'); +const Store = require('electron-store'); + +class WindowStateStore { + constructor() { + this.store = new Store({ + name: 'window-state', + clearInvalidConfig: true + }); + } + + getBounds() { + return this.store.get('window-bounds') || {}; + } + + setBounds(bounds) { + this.store.set('window-bounds', bounds); + } +} + +module.exports = WindowStateStore; diff --git a/packages/bruno-electron/src/utils/window.js b/packages/bruno-electron/src/utils/window.js new file mode 100644 index 000000000..db1aff11d --- /dev/null +++ b/packages/bruno-electron/src/utils/window.js @@ -0,0 +1,28 @@ +const WindowStateStore = require('../store/window-state'); + +const windowStateStore = new WindowStateStore(); + +const DEFAULT_WINDOW_WIDTH = 1280; +const DEFAULT_WINDOW_HEIGHT = 768; + +const loadWindowState = () => { + const bounds = windowStateStore.getBounds(); + + return { + x: bounds.x || undefined, + y: bounds.y || undefined, + width: bounds.width || DEFAULT_WINDOW_WIDTH, + height: bounds.height || DEFAULT_WINDOW_HEIGHT + }; +}; + +const saveWindowState = (window) => { + const bounds = window.getBounds(); + + windowStateStore.setBounds(bounds); +}; + +module.exports = { + loadWindowState, + saveWindowState +}; From fab350a32dfed1466d6f884ca0777c248d0680ed Mon Sep 17 00:00:00 2001 From: Jarne Date: Sat, 7 Oct 2023 14:51:47 +0200 Subject: [PATCH 20/71] Add some checks if position/size is inside screen border --- packages/bruno-electron/src/utils/window.js | 33 ++++++++++++++++++--- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/packages/bruno-electron/src/utils/window.js b/packages/bruno-electron/src/utils/window.js index db1aff11d..d824141d3 100644 --- a/packages/bruno-electron/src/utils/window.js +++ b/packages/bruno-electron/src/utils/window.js @@ -1,3 +1,4 @@ +const { screen } = require('electron'); const WindowStateStore = require('../store/window-state'); const windowStateStore = new WindowStateStore(); @@ -8,11 +9,14 @@ const DEFAULT_WINDOW_HEIGHT = 768; const loadWindowState = () => { const bounds = windowStateStore.getBounds(); + const positionValid = isPositionValid(bounds); + const sizeValid = isSizeValid(bounds); + return { - x: bounds.x || undefined, - y: bounds.y || undefined, - width: bounds.width || DEFAULT_WINDOW_WIDTH, - height: bounds.height || DEFAULT_WINDOW_HEIGHT + x: bounds.x && positionValid ? bounds.x : undefined, + y: bounds.y && positionValid ? bounds.y : undefined, + width: bounds.width && sizeValid ? bounds.width : DEFAULT_WINDOW_WIDTH, + height: bounds.height && sizeValid ? bounds.height : DEFAULT_WINDOW_HEIGHT }; }; @@ -22,6 +26,27 @@ const saveWindowState = (window) => { windowStateStore.setBounds(bounds); }; +const isPositionValid = (bounds) => { + const area = getArea(bounds); + + return ( + bounds.x >= area.x && + bounds.y >= area.y && + bounds.x + bounds.width <= area.x + area.width && + bounds.y + bounds.height <= area.y + area.height + ); +}; + +const isSizeValid = (bounds) => { + const area = getArea(bounds); + + return bounds.width <= area.width && bounds.height <= area.height; +}; + +const getArea = (bounds) => { + return screen.getDisplayMatching(bounds).workArea; +}; + module.exports = { loadWindowState, saveWindowState From 50f2f54335e427a359b04760b394d335a9a34175 Mon Sep 17 00:00:00 2001 From: Anoop M D Date: Sat, 7 Oct 2023 19:10:11 +0530 Subject: [PATCH 21/71] fix(#150): fixed arrow direction --- .../ResponsePane/Overlay/StyledWrapper.js | 5 +++++ .../components/ResponsePane/Overlay/index.js | 2 +- packages/bruno-app/src/globalStyles.js | 18 ++++++++++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/packages/bruno-app/src/components/ResponsePane/Overlay/StyledWrapper.js b/packages/bruno-app/src/components/ResponsePane/Overlay/StyledWrapper.js index f5440aaaf..573872ce9 100644 --- a/packages/bruno-app/src/components/ResponsePane/Overlay/StyledWrapper.js +++ b/packages/bruno-app/src/components/ResponsePane/Overlay/StyledWrapper.js @@ -14,6 +14,11 @@ const StyledWrapper = styled.div` padding-top: 20%; overflow: hidden; text-align: center; + + .loading-icon { + transform: scaleY(-1); + animation: rotateCounterClockwise 1s linear infinite; + } } `; diff --git a/packages/bruno-app/src/components/ResponsePane/Overlay/index.js b/packages/bruno-app/src/components/ResponsePane/Overlay/index.js index 8145a2b50..b525460dc 100644 --- a/packages/bruno-app/src/components/ResponsePane/Overlay/index.js +++ b/packages/bruno-app/src/components/ResponsePane/Overlay/index.js @@ -20,7 +20,7 @@ const ResponseLoadingOverlay = ({ item, collection }) => {
- +
-
{getTabPanel(focusedTab.responsePaneTab)}
+
+ {getTabPanel(focusedTab.responsePaneTab)} +
); }; From 81b1982d4f29c0d8d101e840f35018a0ea7c1524 Mon Sep 17 00:00:00 2001 From: Anoop M D Date: Sun, 8 Oct 2023 00:03:32 +0530 Subject: [PATCH 23/71] feat: response overlay polish --- .../bruno-app/src/components/RequestPane/QueryUrl/index.js | 5 ++--- .../src/components/ResponsePane/Overlay/StyledWrapper.js | 5 +++++ .../bruno-app/src/components/ResponsePane/Overlay/index.js | 6 +++--- packages/bruno-app/src/components/ResponsePane/index.js | 7 ++++--- .../src/providers/ReduxStore/slices/collections/index.js | 1 - packages/bruno-app/src/themes/dark.js | 3 ++- packages/bruno-app/src/themes/light.js | 3 ++- 7 files changed, 18 insertions(+), 12 deletions(-) diff --git a/packages/bruno-app/src/components/RequestPane/QueryUrl/index.js b/packages/bruno-app/src/components/RequestPane/QueryUrl/index.js index 4b5b68a00..0a45f1a7d 100644 --- a/packages/bruno-app/src/components/RequestPane/QueryUrl/index.js +++ b/packages/bruno-app/src/components/RequestPane/QueryUrl/index.js @@ -5,8 +5,7 @@ import { requestUrlChanged, updateRequestMethod } from 'providers/ReduxStore/sli import { saveRequest } from 'providers/ReduxStore/slices/collections/actions'; import HttpMethodSelector from './HttpMethodSelector'; import { useTheme } from 'providers/Theme'; -import SendIcon from 'components/Icons/Send'; -import { IconDeviceFloppy } from '@tabler/icons'; +import { IconDeviceFloppy, IconArrowRight } from '@tabler/icons'; import SingleLineEditor from 'components/SingleLineEditor'; import { isMacOS } from 'utils/common/platform'; import StyledWrapper from './StyledWrapper'; @@ -90,7 +89,7 @@ const QueryUrl = ({ item, collection, handleRun }) => { Save ({saveShortcut}) - + diff --git a/packages/bruno-app/src/components/ResponsePane/Overlay/StyledWrapper.js b/packages/bruno-app/src/components/ResponsePane/Overlay/StyledWrapper.js index 573872ce9..68779c3c2 100644 --- a/packages/bruno-app/src/components/ResponsePane/Overlay/StyledWrapper.js +++ b/packages/bruno-app/src/components/ResponsePane/Overlay/StyledWrapper.js @@ -1,6 +1,11 @@ import styled from 'styled-components'; const StyledWrapper = styled.div` + position: absolute; + z-index: 1; + height: 100vh; + background-color: ${(props) => props.theme.requestTabPanel.responseOverlayBg}; + div.overlay { position: absolute; top: 0; diff --git a/packages/bruno-app/src/components/ResponsePane/Overlay/index.js b/packages/bruno-app/src/components/ResponsePane/Overlay/index.js index b525460dc..e5f659862 100644 --- a/packages/bruno-app/src/components/ResponsePane/Overlay/index.js +++ b/packages/bruno-app/src/components/ResponsePane/Overlay/index.js @@ -13,17 +13,17 @@ const ResponseLoadingOverlay = ({ item, collection }) => { }; return ( - +
-
+
+ {isLoading ? : null} {getTabPanel(focusedTab.responsePaneTab)}
diff --git a/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js b/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js index f1f9699a8..f4eebec66 100644 --- a/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js +++ b/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js @@ -1114,7 +1114,6 @@ export const collectionsSlice = createSlice({ const { cancelTokenUid } = action.payload; item.requestUid = requestUid; item.requestState = 'queued'; - item.response = null; item.cancelTokenUid = cancelTokenUid; } diff --git a/packages/bruno-app/src/themes/dark.js b/packages/bruno-app/src/themes/dark.js index f93fc646a..3dda2505d 100644 --- a/packages/bruno-app/src/themes/dark.js +++ b/packages/bruno-app/src/themes/dark.js @@ -109,7 +109,8 @@ const darkTheme = { responseSendIcon: '#555', responseStatus: '#ccc', responseOk: '#8cd656', - responseError: '#f06f57' + responseError: '#f06f57', + responseOverlayBg: 'rgba(30, 30, 30, 0.6)' }, collection: { diff --git a/packages/bruno-app/src/themes/light.js b/packages/bruno-app/src/themes/light.js index b461f44de..5b9f1a8bc 100644 --- a/packages/bruno-app/src/themes/light.js +++ b/packages/bruno-app/src/themes/light.js @@ -109,7 +109,8 @@ const lightTheme = { responseSendIcon: 'rgb(209, 213, 219)', responseStatus: 'rgb(117 117 117)', responseOk: '#047857', - responseError: 'rgb(185, 28, 28)' + responseError: 'rgb(185, 28, 28)', + responseOverlayBg: 'rgba(255, 255, 255, 0.6)' }, collection: { From ed95b8349eeb8ff31a91710942e3757ae9f90303 Mon Sep 17 00:00:00 2001 From: Anoop M D Date: Sun, 8 Oct 2023 00:05:10 +0530 Subject: [PATCH 24/71] chore: bump version v0.21.1 --- packages/bruno-app/src/components/Sidebar/index.js | 2 +- packages/bruno-electron/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/bruno-app/src/components/Sidebar/index.js b/packages/bruno-app/src/components/Sidebar/index.js index 25156be84..0766908cd 100644 --- a/packages/bruno-app/src/components/Sidebar/index.js +++ b/packages/bruno-app/src/components/Sidebar/index.js @@ -105,7 +105,7 @@ const Sidebar = () => { Star
-
v0.21.0
+
v0.21.1
diff --git a/packages/bruno-electron/package.json b/packages/bruno-electron/package.json index 6cdd6914d..033d4b696 100644 --- a/packages/bruno-electron/package.json +++ b/packages/bruno-electron/package.json @@ -1,5 +1,5 @@ { - "version": "v0.21.0", + "version": "v0.21.1", "name": "bruno", "description": "Opensource API Client for Exploring and Testing APIs", "homepage": "https://www.usebruno.com", From 640692abc733b23d05aaa96e24c4eaf98ee52971 Mon Sep 17 00:00:00 2001 From: Sebastien Dionne Date: Sat, 7 Oct 2023 14:59:55 -0400 Subject: [PATCH 25/71] typo in the error message there was a little typo --- packages/bruno-app/src/components/Sidebar/NewRequest/index.js | 2 +- 1 file changed, 1 insertion(+), 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..a98a77ae4 100644 --- a/packages/bruno-app/src/components/Sidebar/NewRequest/index.js +++ b/packages/bruno-app/src/components/Sidebar/NewRequest/index.js @@ -25,7 +25,7 @@ const NewRequest = ({ collection, item, isEphemeral, onClose }) => { }, validationSchema: Yup.object({ requestName: Yup.string() - .min(1, 'must be atleast 1 characters') + .min(1, 'must be at least 1 characters') .required('name is required') .test({ name: 'requestName', From 47992288c44642997ec94dcba8bea419c2b0451a Mon Sep 17 00:00:00 2001 From: Sebastien Dionne Date: Sat, 7 Oct 2023 15:04:45 -0400 Subject: [PATCH 26/71] Use singular instead --- packages/bruno-app/src/components/Sidebar/NewRequest/index.js | 2 +- 1 file changed, 1 insertion(+), 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 a98a77ae4..6a753fd97 100644 --- a/packages/bruno-app/src/components/Sidebar/NewRequest/index.js +++ b/packages/bruno-app/src/components/Sidebar/NewRequest/index.js @@ -25,7 +25,7 @@ const NewRequest = ({ collection, item, isEphemeral, onClose }) => { }, validationSchema: Yup.object({ requestName: Yup.string() - .min(1, 'must be at least 1 characters') + .min(1, 'must be at least 1 character') .required('name is required') .test({ name: 'requestName', From faf8581ddf5d4ad4ba6d2831b094fa3e6c2bc94e Mon Sep 17 00:00:00 2001 From: Anoop M D Date: Sun, 8 Oct 2023 00:55:09 +0530 Subject: [PATCH 27/71] feat(#253): hide hotkey --- packages/bruno-electron/src/app/menu-template.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/bruno-electron/src/app/menu-template.js b/packages/bruno-electron/src/app/menu-template.js index 2efd93cde..6b4707729 100644 --- a/packages/bruno-electron/src/app/menu-template.js +++ b/packages/bruno-electron/src/app/menu-template.js @@ -24,7 +24,10 @@ const template = [ { role: 'cut' }, { role: 'copy' }, { role: 'paste' }, - { role: 'selectAll' } + { role: 'selectAll' }, + { type: 'separator' }, + { role: 'hide' }, + { role: 'hideOthers' } ] }, { From 21536f9a27666a35e151e0579f7c35ec7ff88c17 Mon Sep 17 00:00:00 2001 From: Sebastien Dionne Date: Sat, 7 Oct 2023 15:28:17 -0400 Subject: [PATCH 28/71] 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 c6fef2f1be446e8ffa591eda36b33097156b0512 Mon Sep 17 00:00:00 2001 From: Anoop M D Date: Sun, 8 Oct 2023 01:01:40 +0530 Subject: [PATCH 29/71] chore: removed legacy code --- packages/bruno-electron/src/app/watcher.js | 37 ++-------------------- packages/bruno-electron/src/bru/index.js | 3 +- 2 files changed, 3 insertions(+), 37 deletions(-) diff --git a/packages/bruno-electron/src/app/watcher.js b/packages/bruno-electron/src/app/watcher.js index 96822ec64..6b5d57381 100644 --- a/packages/bruno-electron/src/app/watcher.js +++ b/packages/bruno-electron/src/app/watcher.js @@ -2,8 +2,8 @@ const _ = require('lodash'); const fs = require('fs'); const path = require('path'); const chokidar = require('chokidar'); -const { hasBruExtension, writeFile } = require('../utils/filesystem'); -const { bruToEnvJson, envJsonToBru, bruToJson, jsonToBru } = require('../bru'); +const { hasBruExtension } = require('../utils/filesystem'); +const { bruToEnvJson, bruToJson } = require('../bru'); const { dotenvToJson } = require('@usebruno/lang'); const { uuid } = require('../utils/common'); @@ -15,13 +15,6 @@ const EnvironmentSecretsStore = require('../store/env-secrets'); const environmentSecretsStore = new EnvironmentSecretsStore(); -const isJsonEnvironmentConfig = (pathname, collectionPath) => { - const dirname = path.dirname(pathname); - const basename = path.basename(pathname); - - return dirname === collectionPath && basename === 'environments.json'; -}; - const isDotEnvFile = (pathname, collectionPath) => { const dirname = path.dirname(pathname); const basename = path.basename(pathname); @@ -198,32 +191,6 @@ const add = async (win, pathname, collectionUid, collectionPath) => { } } - if (isJsonEnvironmentConfig(pathname, collectionPath)) { - try { - const dirname = path.dirname(pathname); - const bruContent = fs.readFileSync(pathname, 'utf8'); - - const jsonData = JSON.parse(bruContent); - - const envDirectory = path.join(dirname, 'environments'); - if (!fs.existsSync(envDirectory)) { - fs.mkdirSync(envDirectory); - } - - for (const env of jsonData) { - const bruEnvFilename = path.join(envDirectory, `${env.name}.bru`); - const bruContent = envJsonToBru(env); - await writeFile(bruEnvFilename, bruContent); - } - - await fs.unlinkSync(pathname); - } catch (err) { - // do nothing - } - - return; - } - if (isBruEnvironmentConfig(pathname, collectionPath)) { return addEnvironmentFile(win, pathname, collectionUid, collectionPath); } diff --git a/packages/bruno-electron/src/bru/index.js b/packages/bruno-electron/src/bru/index.js index a28c04a7b..ad4299593 100644 --- a/packages/bruno-electron/src/bru/index.js +++ b/packages/bruno-electron/src/bru/index.js @@ -1,6 +1,5 @@ const _ = require('lodash'); const { bruToJsonV2, jsonToBruV2, bruToEnvJsonV2, envJsonToBruV2 } = require('@usebruno/lang'); -const { each } = require('lodash'); const bruToEnvJson = (bru) => { try { @@ -10,7 +9,7 @@ const bruToEnvJson = (bru) => { // this need to be evaluated and safely removed // i don't see it being used in schema validation if (json && json.variables && json.variables.length) { - each(json.variables, (v) => (v.type = 'text')); + _.each(json.variables, (v) => (v.type = 'text')); } return json; From 5ef0de2e4d2e8f4e42e667ae5b7af0e3bebb2754 Mon Sep 17 00:00:00 2001 From: Sebastien Dionne Date: Sat, 7 Oct 2023 15:33:38 -0400 Subject: [PATCH 30/71] 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 515381b9303cb98caa06a1c996c929111869420d Mon Sep 17 00:00:00 2001 From: Sebastien Dionne Date: Sat, 7 Oct 2023 15:53:34 -0400 Subject: [PATCH 31/71] fix typo and use singular --- .../Environments/EnvironmentSettings/CopyEnvironment/index.js | 2 +- .../EnvironmentSettings/CreateEnvironment/index.js | 2 +- .../EnvironmentSettings/RenameEnvironment/index.js | 2 +- .../Collection/CollectionItem/CloneCollectionItem/index.js | 2 +- .../Collection/CollectionItem/RenameCollectionItem/index.js | 2 +- .../Sidebar/Collections/Collection/RenameCollection/index.js | 2 +- .../src/components/Sidebar/CreateCollection/index.js | 4 ++-- .../src/components/Sidebar/ImportCollectionLocation/index.js | 2 +- packages/bruno-app/src/components/Sidebar/NewFolder/index.js | 2 +- 9 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/bruno-app/src/components/Environments/EnvironmentSettings/CopyEnvironment/index.js b/packages/bruno-app/src/components/Environments/EnvironmentSettings/CopyEnvironment/index.js index 87b833e40..a9fdf3b4a 100644 --- a/packages/bruno-app/src/components/Environments/EnvironmentSettings/CopyEnvironment/index.js +++ b/packages/bruno-app/src/components/Environments/EnvironmentSettings/CopyEnvironment/index.js @@ -17,7 +17,7 @@ const CopyEnvironment = ({ collection, environment, onClose }) => { }, validationSchema: Yup.object({ name: Yup.string() - .min(1, 'must be atleast 1 characters') + .min(1, 'must be at least 1 character') .max(50, 'must be 50 characters or less') .required('name is required') }), diff --git a/packages/bruno-app/src/components/Environments/EnvironmentSettings/CreateEnvironment/index.js b/packages/bruno-app/src/components/Environments/EnvironmentSettings/CreateEnvironment/index.js index d412687e2..c0ca7f5ec 100644 --- a/packages/bruno-app/src/components/Environments/EnvironmentSettings/CreateEnvironment/index.js +++ b/packages/bruno-app/src/components/Environments/EnvironmentSettings/CreateEnvironment/index.js @@ -17,7 +17,7 @@ const CreateEnvironment = ({ collection, onClose }) => { }, validationSchema: Yup.object({ name: Yup.string() - .min(1, 'must be atleast 1 characters') + .min(1, 'must be at least 1 character') .max(50, 'must be 50 characters or less') .required('name is required') }), diff --git a/packages/bruno-app/src/components/Environments/EnvironmentSettings/RenameEnvironment/index.js b/packages/bruno-app/src/components/Environments/EnvironmentSettings/RenameEnvironment/index.js index dc928d4c6..84572db90 100644 --- a/packages/bruno-app/src/components/Environments/EnvironmentSettings/RenameEnvironment/index.js +++ b/packages/bruno-app/src/components/Environments/EnvironmentSettings/RenameEnvironment/index.js @@ -17,7 +17,7 @@ const RenameEnvironment = ({ onClose, environment, collection }) => { }, validationSchema: Yup.object({ name: Yup.string() - .min(1, 'must be atleast 1 characters') + .min(1, 'must be at least 1 character') .max(50, 'must be 50 characters or less') .required('name is required') }), diff --git a/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/CloneCollectionItem/index.js b/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/CloneCollectionItem/index.js index 96a1da61d..55c2b86dd 100644 --- a/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/CloneCollectionItem/index.js +++ b/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/CloneCollectionItem/index.js @@ -18,7 +18,7 @@ const CloneCollectionItem = ({ collection, item, onClose }) => { }, validationSchema: Yup.object({ name: Yup.string() - .min(1, 'must be atleast 1 characters') + .min(1, 'must be at least 1 character') .max(50, 'must be 50 characters or less') .required('name is required') }), diff --git a/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/RenameCollectionItem/index.js b/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/RenameCollectionItem/index.js index 9b485e992..97c3399ae 100644 --- a/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/RenameCollectionItem/index.js +++ b/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/RenameCollectionItem/index.js @@ -17,7 +17,7 @@ const RenameCollectionItem = ({ collection, item, onClose }) => { }, validationSchema: Yup.object({ name: Yup.string() - .min(1, 'must be atleast 1 characters') + .min(1, 'must be at least 1 character') .max(50, 'must be 50 characters or less') .required('name is required') }), diff --git a/packages/bruno-app/src/components/Sidebar/Collections/Collection/RenameCollection/index.js b/packages/bruno-app/src/components/Sidebar/Collections/Collection/RenameCollection/index.js index 70311bd75..07a927415 100644 --- a/packages/bruno-app/src/components/Sidebar/Collections/Collection/RenameCollection/index.js +++ b/packages/bruno-app/src/components/Sidebar/Collections/Collection/RenameCollection/index.js @@ -16,7 +16,7 @@ const RenameCollection = ({ collection, onClose }) => { }, validationSchema: Yup.object({ name: Yup.string() - .min(1, 'must be atleast 1 characters') + .min(1, 'must be at least 1 character') .max(50, 'must be 50 characters or less') .required('name is required') }), diff --git a/packages/bruno-app/src/components/Sidebar/CreateCollection/index.js b/packages/bruno-app/src/components/Sidebar/CreateCollection/index.js index bfe59ae86..9f9097637 100644 --- a/packages/bruno-app/src/components/Sidebar/CreateCollection/index.js +++ b/packages/bruno-app/src/components/Sidebar/CreateCollection/index.js @@ -21,11 +21,11 @@ const CreateCollection = ({ onClose }) => { }, validationSchema: Yup.object({ collectionName: Yup.string() - .min(1, 'must be atleast 1 characters') + .min(1, 'must be at least 1 character') .max(50, 'must be 50 characters or less') .required('collection name is required'), collectionFolderName: Yup.string() - .min(1, 'must be atleast 1 characters') + .min(1, 'must be at least 1 character') .max(50, 'must be 50 characters or less') .matches(/^[\w\-. ]+$/, 'Folder name contains invalid characters') .required('folder name is required'), diff --git a/packages/bruno-app/src/components/Sidebar/ImportCollectionLocation/index.js b/packages/bruno-app/src/components/Sidebar/ImportCollectionLocation/index.js index 779c8dfa3..dc75a910b 100644 --- a/packages/bruno-app/src/components/Sidebar/ImportCollectionLocation/index.js +++ b/packages/bruno-app/src/components/Sidebar/ImportCollectionLocation/index.js @@ -16,7 +16,7 @@ const ImportCollectionLocation = ({ onClose, handleSubmit, collectionName }) => }, validationSchema: Yup.object({ collectionLocation: Yup.string() - .min(1, 'must be atleast 1 characters') + .min(1, 'must be at least 1 character') .max(500, 'must be 500 characters or less') .required('name is required') }), diff --git a/packages/bruno-app/src/components/Sidebar/NewFolder/index.js b/packages/bruno-app/src/components/Sidebar/NewFolder/index.js index 9245d7abc..bc13f50df 100644 --- a/packages/bruno-app/src/components/Sidebar/NewFolder/index.js +++ b/packages/bruno-app/src/components/Sidebar/NewFolder/index.js @@ -16,7 +16,7 @@ const NewFolder = ({ collection, item, onClose }) => { }, validationSchema: Yup.object({ folderName: Yup.string() - .min(1, 'must be atleast 1 characters') + .min(1, 'must be at least 1 character') .required('name is required') .test({ name: 'folderName', From 0179c58cd2f9be5e0f5f30d2d159d74789eda200 Mon Sep 17 00:00:00 2001 From: Sebastien Dionne Date: Sat, 7 Oct 2023 15:54:33 -0400 Subject: [PATCH 32/71] fix typo and use singular --- packages/bruno-schema/src/collections/index.js | 4 ++-- packages/bruno-schema/src/collections/itemSchema.spec.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/bruno-schema/src/collections/index.js b/packages/bruno-schema/src/collections/index.js index 81cd2528b..337f0147b 100644 --- a/packages/bruno-schema/src/collections/index.js +++ b/packages/bruno-schema/src/collections/index.js @@ -123,7 +123,7 @@ const itemSchema = Yup.object({ uid: uidSchema, type: Yup.string().oneOf(['http-request', 'graphql-request', 'folder']).required('type is required'), seq: Yup.number().min(1), - name: Yup.string().min(1, 'name must be atleast 1 characters').required('name is required'), + name: Yup.string().min(1, 'name must be at least 1 character').required('name is required'), request: requestSchema.when('type', { is: (type) => ['http-request', 'graphql-request'].includes(type), then: (schema) => schema.required('request is required when item-type is request') @@ -138,7 +138,7 @@ const itemSchema = Yup.object({ const collectionSchema = Yup.object({ version: Yup.string().oneOf(['1']).required('version is required'), uid: uidSchema, - name: Yup.string().min(1, 'name must be atleast 1 characters').required('name is required'), + name: Yup.string().min(1, 'name must be at least 1 character').required('name is required'), items: Yup.array().of(itemSchema), activeEnvironmentUid: Yup.string() .length(21, 'activeEnvironmentUid must be 21 characters in length') diff --git a/packages/bruno-schema/src/collections/itemSchema.spec.js b/packages/bruno-schema/src/collections/itemSchema.spec.js index a949f3c2b..8c46bed2c 100644 --- a/packages/bruno-schema/src/collections/itemSchema.spec.js +++ b/packages/bruno-schema/src/collections/itemSchema.spec.js @@ -34,7 +34,7 @@ describe('Item Schema Validation', () => { return Promise.all([ expect(itemSchema.validate(item)).rejects.toEqual( - validationErrorWithMessages('name must be atleast 1 characters') + validationErrorWithMessages('name must be at least 1 character') ) ]); }); From 856236c918f7c02c983316c508a00f37e8450a5e Mon Sep 17 00:00:00 2001 From: Anoop M D Date: Sun, 8 Oct 2023 01:57:30 +0530 Subject: [PATCH 33/71] feat(#334): Bru lang updates for collection.bru file --- .../bruno-lang/v2/src/collectionBruToJson.js | 273 ++++++++++++++++++ .../bruno-lang/v2/src/jsonToCollectionBru.js | 185 ++++++++++++ .../bruno-lang/v2/tests/collection.spec.js | 24 ++ .../v2/tests/fixtures/collection.bru | 43 +++ .../v2/tests/fixtures/collection.json | 61 ++++ 5 files changed, 586 insertions(+) create mode 100644 packages/bruno-lang/v2/src/collectionBruToJson.js create mode 100644 packages/bruno-lang/v2/src/jsonToCollectionBru.js create mode 100644 packages/bruno-lang/v2/tests/collection.spec.js create mode 100644 packages/bruno-lang/v2/tests/fixtures/collection.bru create mode 100644 packages/bruno-lang/v2/tests/fixtures/collection.json diff --git a/packages/bruno-lang/v2/src/collectionBruToJson.js b/packages/bruno-lang/v2/src/collectionBruToJson.js new file mode 100644 index 000000000..d78f752c0 --- /dev/null +++ b/packages/bruno-lang/v2/src/collectionBruToJson.js @@ -0,0 +1,273 @@ +const ohm = require('ohm-js'); +const _ = require('lodash'); +const { outdentString } = require('../../v1/src/utils'); + +const grammar = ohm.grammar(`Bru { + BruFile = (meta | query | headers | auth | auths | vars | script | tests | docs)* + auths = authbasic | authbearer + + nl = "\\r"? "\\n" + st = " " | "\\t" + stnl = st | nl + tagend = nl "}" + optionalnl = ~tagend nl + keychar = ~(tagend | st | nl | ":") any + valuechar = ~(nl | tagend) any + + // Dictionary Blocks + dictionary = st* "{" pairlist? tagend + pairlist = optionalnl* pair (~tagend stnl* pair)* (~tagend space)* + pair = st* key st* ":" st* value st* + key = keychar* + value = valuechar* + + // Text Blocks + textblock = textline (~tagend nl textline)* + textline = textchar* + textchar = ~nl any + + meta = "meta" dictionary + + auth = "auth" dictionary + + headers = "headers" dictionary + + query = "query" dictionary + + vars = varsreq | varsres + varsreq = "vars:pre-request" dictionary + varsres = "vars:post-response" dictionary + + authbasic = "auth:basic" dictionary + authbearer = "auth:bearer" dictionary + + script = scriptreq | scriptres + scriptreq = "script:pre-request" st* "{" nl* textblock tagend + scriptres = "script:post-response" st* "{" nl* textblock tagend + tests = "tests" st* "{" nl* textblock tagend + docs = "docs" st* "{" nl* textblock tagend +}`); + +const mapPairListToKeyValPairs = (pairList = [], parseEnabled = true) => { + if (!pairList.length) { + return []; + } + return _.map(pairList[0], (pair) => { + let name = _.keys(pair)[0]; + let value = pair[name]; + + if (!parseEnabled) { + return { + name, + value + }; + } + + let enabled = true; + if (name && name.length && name.charAt(0) === '~') { + name = name.slice(1); + enabled = false; + } + + return { + name, + value, + enabled + }; + }); +}; + +const concatArrays = (objValue, srcValue) => { + if (_.isArray(objValue) && _.isArray(srcValue)) { + return objValue.concat(srcValue); + } +}; + +const mapPairListToKeyValPair = (pairList = []) => { + if (!pairList || !pairList.length) { + return {}; + } + + return _.merge({}, ...pairList[0]); +}; + +const sem = grammar.createSemantics().addAttribute('ast', { + BruFile(tags) { + if (!tags || !tags.ast || !tags.ast.length) { + return {}; + } + + return _.reduce( + tags.ast, + (result, item) => { + return _.mergeWith(result, item, concatArrays); + }, + {} + ); + }, + dictionary(_1, _2, pairlist, _3) { + return pairlist.ast; + }, + pairlist(_1, pair, _2, rest, _3) { + return [pair.ast, ...rest.ast]; + }, + pair(_1, key, _2, _3, _4, value, _5) { + let res = {}; + res[key.ast] = value.ast ? value.ast.trim() : ''; + return res; + }, + key(chars) { + return chars.sourceString ? chars.sourceString.trim() : ''; + }, + value(chars) { + return chars.sourceString ? chars.sourceString.trim() : ''; + }, + textblock(line, _1, rest) { + return [line.ast, ...rest.ast].join('\n'); + }, + textline(chars) { + return chars.sourceString; + }, + textchar(char) { + return char.sourceString; + }, + nl(_1, _2) { + return ''; + }, + st(_) { + return ''; + }, + tagend(_1, _2) { + return ''; + }, + _iter(...elements) { + return elements.map((e) => e.ast); + }, + meta(_1, dictionary) { + let meta = mapPairListToKeyValPair(dictionary.ast) || {}; + + meta.type = 'collection'; + + return { + meta + }; + }, + auth(_1, dictionary) { + let auth = mapPairListToKeyValPair(dictionary.ast) || {}; + + return { + auth: { + mode: auth ? auth.mode : 'none' + } + }; + }, + query(_1, dictionary) { + return { + query: mapPairListToKeyValPairs(dictionary.ast) + }; + }, + headers(_1, dictionary) { + return { + headers: mapPairListToKeyValPairs(dictionary.ast) + }; + }, + authbasic(_1, dictionary) { + const auth = mapPairListToKeyValPairs(dictionary.ast, false); + const usernameKey = _.find(auth, { name: 'username' }); + const passwordKey = _.find(auth, { name: 'password' }); + const username = usernameKey ? usernameKey.value : ''; + const password = passwordKey ? passwordKey.value : ''; + return { + auth: { + basic: { + username, + password + } + } + }; + }, + authbearer(_1, dictionary) { + const auth = mapPairListToKeyValPairs(dictionary.ast, false); + const tokenKey = _.find(auth, { name: 'token' }); + const token = tokenKey ? tokenKey.value : ''; + return { + auth: { + bearer: { + token + } + } + }; + }, + varsreq(_1, dictionary) { + const vars = mapPairListToKeyValPairs(dictionary.ast); + _.each(vars, (v) => { + let name = v.name; + if (name && name.length && name.charAt(0) === '@') { + v.name = name.slice(1); + v.local = true; + } else { + v.local = false; + } + }); + + return { + vars: { + req: vars + } + }; + }, + varsres(_1, dictionary) { + const vars = mapPairListToKeyValPairs(dictionary.ast); + _.each(vars, (v) => { + let name = v.name; + if (name && name.length && name.charAt(0) === '@') { + v.name = name.slice(1); + v.local = true; + } else { + v.local = false; + } + }); + + return { + vars: { + res: vars + } + }; + }, + scriptreq(_1, _2, _3, _4, textblock, _5) { + return { + script: { + req: outdentString(textblock.sourceString) + } + }; + }, + scriptres(_1, _2, _3, _4, textblock, _5) { + return { + script: { + res: outdentString(textblock.sourceString) + } + }; + }, + tests(_1, _2, _3, _4, textblock, _5) { + return { + tests: outdentString(textblock.sourceString) + }; + }, + docs(_1, _2, _3, _4, textblock, _5) { + return { + docs: outdentString(textblock.sourceString) + }; + } +}); + +const parser = (input) => { + const match = grammar.match(input); + + if (match.succeeded()) { + return sem(match).ast; + } else { + throw new Error(match.message); + } +}; + +module.exports = parser; diff --git a/packages/bruno-lang/v2/src/jsonToCollectionBru.js b/packages/bruno-lang/v2/src/jsonToCollectionBru.js new file mode 100644 index 000000000..f20fbc680 --- /dev/null +++ b/packages/bruno-lang/v2/src/jsonToCollectionBru.js @@ -0,0 +1,185 @@ +const _ = require('lodash'); + +const { indentString } = require('../../v1/src/utils'); + +const enabled = (items = []) => items.filter((item) => item.enabled); +const disabled = (items = []) => items.filter((item) => !item.enabled); + +// remove the last line if two new lines are found +const stripLastLine = (text) => { + if (!text || !text.length) return text; + + return text.replace(/(\r?\n)$/, ''); +}; + +const jsonToBru = (json) => { + const { meta, query, headers, auth, script, tests, vars, docs } = json; + + let bru = ''; + + if (meta) { + bru += 'meta {\n'; + for (const key in meta) { + bru += ` ${key}: ${meta[key]}\n`; + } + bru += '}\n\n'; + } + + if (query && query.length) { + bru += 'query {'; + if (enabled(query).length) { + bru += `\n${indentString( + enabled(query) + .map((item) => `${item.name}: ${item.value}`) + .join('\n') + )}`; + } + + if (disabled(query).length) { + bru += `\n${indentString( + disabled(query) + .map((item) => `~${item.name}: ${item.value}`) + .join('\n') + )}`; + } + + bru += '\n}\n\n'; + } + + if (headers && headers.length) { + bru += 'headers {'; + if (enabled(headers).length) { + bru += `\n${indentString( + enabled(headers) + .map((item) => `${item.name}: ${item.value}`) + .join('\n') + )}`; + } + + if (disabled(headers).length) { + bru += `\n${indentString( + disabled(headers) + .map((item) => `~${item.name}: ${item.value}`) + .join('\n') + )}`; + } + + bru += '\n}\n\n'; + } + + if (auth && auth.mode) { + bru += `auth { +${indentString(`mode: ${auth.mode}`)} +} + +`; + } + + if (auth && auth.basic) { + bru += `auth:basic { +${indentString(`username: ${auth.basic.username}`)} +${indentString(`password: ${auth.basic.password}`)} +} + +`; + } + + if (auth && auth.bearer) { + bru += `auth:bearer { +${indentString(`token: ${auth.bearer.token}`)} +} + +`; + } + + let reqvars = _.get(vars, 'req'); + let resvars = _.get(vars, 'res'); + if (reqvars && reqvars.length) { + const varsEnabled = _.filter(reqvars, (v) => v.enabled && !v.local); + const varsDisabled = _.filter(reqvars, (v) => !v.enabled && !v.local); + const varsLocalEnabled = _.filter(reqvars, (v) => v.enabled && v.local); + const varsLocalDisabled = _.filter(reqvars, (v) => !v.enabled && v.local); + + bru += `vars:pre-request {`; + + if (varsEnabled.length) { + bru += `\n${indentString(varsEnabled.map((item) => `${item.name}: ${item.value}`).join('\n'))}`; + } + + if (varsLocalEnabled.length) { + bru += `\n${indentString(varsLocalEnabled.map((item) => `@${item.name}: ${item.value}`).join('\n'))}`; + } + + if (varsDisabled.length) { + bru += `\n${indentString(varsDisabled.map((item) => `~${item.name}: ${item.value}`).join('\n'))}`; + } + + if (varsLocalDisabled.length) { + bru += `\n${indentString(varsLocalDisabled.map((item) => `~@${item.name}: ${item.value}`).join('\n'))}`; + } + + bru += '\n}\n\n'; + } + if (resvars && resvars.length) { + const varsEnabled = _.filter(resvars, (v) => v.enabled && !v.local); + const varsDisabled = _.filter(resvars, (v) => !v.enabled && !v.local); + const varsLocalEnabled = _.filter(resvars, (v) => v.enabled && v.local); + const varsLocalDisabled = _.filter(resvars, (v) => !v.enabled && v.local); + + bru += `vars:post-response {`; + + if (varsEnabled.length) { + bru += `\n${indentString(varsEnabled.map((item) => `${item.name}: ${item.value}`).join('\n'))}`; + } + + if (varsLocalEnabled.length) { + bru += `\n${indentString(varsLocalEnabled.map((item) => `@${item.name}: ${item.value}`).join('\n'))}`; + } + + if (varsDisabled.length) { + bru += `\n${indentString(varsDisabled.map((item) => `~${item.name}: ${item.value}`).join('\n'))}`; + } + + if (varsLocalDisabled.length) { + bru += `\n${indentString(varsLocalDisabled.map((item) => `~@${item.name}: ${item.value}`).join('\n'))}`; + } + + bru += '\n}\n\n'; + } + + if (script && script.req && script.req.length) { + bru += `script:pre-request { +${indentString(script.req)} +} + +`; + } + + if (script && script.res && script.res.length) { + bru += `script:post-response { +${indentString(script.res)} +} + +`; + } + + if (tests && tests.length) { + bru += `tests { +${indentString(tests)} +} + +`; + } + + if (docs && docs.length) { + bru += `docs { +${indentString(docs)} +} + +`; + } + + return stripLastLine(bru); +}; + +module.exports = jsonToBru; diff --git a/packages/bruno-lang/v2/tests/collection.spec.js b/packages/bruno-lang/v2/tests/collection.spec.js new file mode 100644 index 000000000..4bdb7f9dc --- /dev/null +++ b/packages/bruno-lang/v2/tests/collection.spec.js @@ -0,0 +1,24 @@ +const fs = require('fs'); +const path = require('path'); +const collectionBruToJson = require('../src/collectionBruToJson'); +const jsonToCollectionBru = require('../src/jsonToCollectionBru'); + +describe('collectionBruToJson', () => { + it('should parse the collection bru file', () => { + const input = fs.readFileSync(path.join(__dirname, 'fixtures', 'collection.bru'), 'utf8'); + const expected = require('./fixtures/collection.json'); + const output = collectionBruToJson(input); + + expect(output).toEqual(expected); + }); +}); + +describe('jsonToCollectionBru', () => { + it('should convert the collection json to bru', () => { + const input = require('./fixtures/collection.json'); + const expected = fs.readFileSync(path.join(__dirname, 'fixtures', 'collection.bru'), 'utf8'); + const output = jsonToCollectionBru(input); + + expect(output).toEqual(expected); + }); +}); diff --git a/packages/bruno-lang/v2/tests/fixtures/collection.bru b/packages/bruno-lang/v2/tests/fixtures/collection.bru new file mode 100644 index 000000000..a02be30cb --- /dev/null +++ b/packages/bruno-lang/v2/tests/fixtures/collection.bru @@ -0,0 +1,43 @@ +meta { + type: collection +} + +headers { + content-type: application/json + Authorization: Bearer 123 + ~transaction-id: {{transactionId}} +} + +auth { + mode: none +} + +auth:basic { + username: john + password: secret +} + +auth:bearer { + token: 123 +} + +vars:pre-request { + departingDate: 2020-01-01 + ~returningDate: 2020-01-02 +} + +vars:post-response { + ~transactionId: $res.body.transactionId +} + +script:pre-request { + console.log("In Collection pre Request Script"); +} + +script:post-response { + console.log("In Collection post Request Script"); +} + +docs { + This request needs auth token to be set in the headers. +} diff --git a/packages/bruno-lang/v2/tests/fixtures/collection.json b/packages/bruno-lang/v2/tests/fixtures/collection.json new file mode 100644 index 000000000..de827d11e --- /dev/null +++ b/packages/bruno-lang/v2/tests/fixtures/collection.json @@ -0,0 +1,61 @@ +{ + "meta": { + "type": "collection" + }, + "headers": [ + { + "name": "content-type", + "value": "application/json", + "enabled": true + }, + { + "name": "Authorization", + "value": "Bearer 123", + "enabled": true + }, + { + "name": "transaction-id", + "value": "{{transactionId}}", + "enabled": false + } + ], + "auth": { + "mode": "none", + "basic": { + "username": "john", + "password": "secret" + }, + "bearer": { + "token": "123" + } + }, + "vars": { + "req": [ + { + "name": "departingDate", + "value": "2020-01-01", + "enabled": true, + "local": false + }, + { + "name": "returningDate", + "value": "2020-01-02", + "enabled": false, + "local": false + } + ], + "res": [ + { + "name": "transactionId", + "value": "$res.body.transactionId", + "enabled": false, + "local": false + } + ] + }, + "script": { + "req": "console.log(\"In Collection pre Request Script\");", + "res": "console.log(\"In Collection post Request Script\");" + }, + "docs": "This request needs auth token to be set in the headers." +} From 024f61a95e3f977964f0e1780d766ab19117ebdf Mon Sep 17 00:00:00 2001 From: Oleksii Slabchenko Date: Sat, 7 Oct 2023 22:42:13 +0200 Subject: [PATCH 34/71] Fix 'between' assertion --- packages/bruno-js/src/runtime/assert-runtime.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/bruno-js/src/runtime/assert-runtime.js b/packages/bruno-js/src/runtime/assert-runtime.js index f0f84fbc0..a9588263a 100644 --- a/packages/bruno-js/src/runtime/assert-runtime.js +++ b/packages/bruno-js/src/runtime/assert-runtime.js @@ -268,7 +268,7 @@ class AssertRuntime { expect(lhs).to.endWith(rhs); break; case 'between': - const [min, max] = value.split(','); + const [min, max] = rhs; expect(lhs).to.be.within(min, max); break; case 'isEmpty': From 6d8bdfa27631fc21ccb867113771faebf36e1009 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Szymborski?= Date: Sat, 7 Oct 2023 23:41:55 +0200 Subject: [PATCH 35/71] fix(#440) open dev tools from menu --- .../src/components/Sidebar/TitleBar/index.js | 14 ++++++++++++++ packages/bruno-electron/src/ipc/collection.js | 4 ++++ 2 files changed, 18 insertions(+) diff --git a/packages/bruno-app/src/components/Sidebar/TitleBar/index.js b/packages/bruno-app/src/components/Sidebar/TitleBar/index.js index daaf1f452..ebf8c608d 100644 --- a/packages/bruno-app/src/components/Sidebar/TitleBar/index.js +++ b/packages/bruno-app/src/components/Sidebar/TitleBar/index.js @@ -18,6 +18,7 @@ const TitleBar = () => { const [importCollectionModalOpen, setImportCollectionModalOpen] = useState(false); const [importCollectionLocationModalOpen, setImportCollectionLocationModalOpen] = useState(false); const dispatch = useDispatch(); + const { ipcRenderer } = window; const handleImportCollection = (collection) => { setImportedCollection(collection); @@ -50,6 +51,10 @@ const TitleBar = () => { ); }; + const openDevTools = () => { + ipcRenderer.invoke('renderer:open-devtools'); + }; + return ( {createCollectionModalOpen ? setCreateCollectionModalOpen(false)} /> : null} @@ -104,6 +109,15 @@ const TitleBar = () => { > Import Collection +
{ + menuDropdownTippyRef.current.hide(); + openDevTools(); + }} + > + Devtools +
diff --git a/packages/bruno-electron/src/ipc/collection.js b/packages/bruno-electron/src/ipc/collection.js index 864aff82e..03a15305b 100644 --- a/packages/bruno-electron/src/ipc/collection.js +++ b/packages/bruno-electron/src/ipc/collection.js @@ -486,6 +486,10 @@ const registerRendererEventHandlers = (mainWindow, watcher, lastOpenedCollection return Promise.reject(error); } }); + + ipcMain.handle('renderer:open-devtools', async () => { + mainWindow.webContents.openDevTools(); + }); }; const registerMainEventHandlers = (mainWindow, watcher, lastOpenedCollections) => { From 159dd90b038fbcd78618c97b51be6c233075b889 Mon Sep 17 00:00:00 2001 From: Anoop M D Date: Sun, 8 Oct 2023 05:26:49 +0530 Subject: [PATCH 36/71] fix: fixed issue where window width and height were not set for first time users --- packages/bruno-electron/src/store/window-state.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/packages/bruno-electron/src/store/window-state.js b/packages/bruno-electron/src/store/window-state.js index 4b2520380..bb0a61b64 100644 --- a/packages/bruno-electron/src/store/window-state.js +++ b/packages/bruno-electron/src/store/window-state.js @@ -1,16 +1,26 @@ const _ = require('lodash'); const Store = require('electron-store'); +const DEFAULT_WINDOW_WIDTH = 1280; +const DEFAULT_WINDOW_HEIGHT = 768; + class WindowStateStore { constructor() { this.store = new Store({ - name: 'window-state', + name: 'preferences', clearInvalidConfig: true }); } getBounds() { - return this.store.get('window-bounds') || {}; + return ( + this.store.get('window-bounds') || { + x: 0, + y: 0, + width: DEFAULT_WINDOW_WIDTH, + height: DEFAULT_WINDOW_HEIGHT + } + ); } setBounds(bounds) { From 905e993a13d2855d1be2dbfc3dcd56f895db814f Mon Sep 17 00:00:00 2001 From: game5413 Date: Sun, 8 Oct 2023 21:46:13 +0700 Subject: [PATCH 37/71] 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 38/71] 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 39/71] 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 40/71] 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