From 094bf7bc60122c94ff16caf51a6df58125a7a3af Mon Sep 17 00:00:00 2001 From: Jack Scotson Date: Sun, 8 Oct 2023 10:47:34 +0100 Subject: [PATCH 01/31] fix(#251): Uses os.release to get correct pathsep for windows --- .../src/providers/ReduxStore/slices/collections/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 495989eb1..72c82f8ce 100644 --- a/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js +++ b/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js @@ -1,4 +1,3 @@ -import path from 'path'; import { uuid } from 'utils/common'; import find from 'lodash/find'; import map from 'lodash/map'; @@ -24,8 +23,9 @@ import { } from 'utils/collections'; import { parseQueryParams, stringifyQueryParams } from 'utils/url'; import { getSubdirectoriesFromRoot, getDirectoryName } from 'utils/common/platform'; +import os from 'os'; -const PATH_SEPARATOR = path.sep; +const PATH_SEPARATOR = /Windows/i.test(os.release()) ? '\\' : '/'; const initialState = { collections: [] From ff3c666f485b983efa52f4849757b2191d358a8a Mon Sep 17 00:00:00 2001 From: Jack Scotson Date: Tue, 10 Oct 2023 17:32:17 +0100 Subject: [PATCH 02/31] use isWindowsOS() --- .../src/providers/ReduxStore/slices/collections/index.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) 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 c0e904399..bd78d4c4f 100644 --- a/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js +++ b/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js @@ -22,10 +22,9 @@ import { areItemsTheSameExceptSeqUpdate } from 'utils/collections'; import { parseQueryParams, stringifyQueryParams } from 'utils/url'; -import { getSubdirectoriesFromRoot, getDirectoryName } from 'utils/common/platform'; -import os from 'os'; +import { getSubdirectoriesFromRoot, getDirectoryName, isWindowsOS } from 'utils/common/platform'; -const PATH_SEPARATOR = /Windows/i.test(os.release()) ? '\\' : '/'; +const PATH_SEPARATOR = isWindowsOS() ? '\\' : '/'; const initialState = { collections: [], From 6d7f397d7bea88f31f58d9fd66bcdbd3935aab95 Mon Sep 17 00:00:00 2001 From: Jeremy Benoist Date: Wed, 11 Oct 2023 12:57:12 +0200 Subject: [PATCH 03/31] Update GitHub workflows - jump to `actions/checkout` v4 (latest version) - retrieve node version from NVM instead of hard-coded - add a new job to run prettier (in case people skip pre-commit hook) --- .github/workflows/unit-tests.yml | 22 ++++++++++++++++------ package.json | 1 + packages/bruno-app/package.json | 1 + 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 86a9e0ebd..a2c73beec 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -5,18 +5,16 @@ on: pull_request: branches: [main] jobs: - test: + tests: timeout-minutes: 60 runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions/setup-node@v3 with: - node-version: 16 - - name: Check package-lock.json - run: npm ci + node-version-file: '.nvmrc' - name: Install dependencies - run: npm i --legacy-peer-deps + run: npm ci --legacy-peer-deps - name: Test Package bruno-query run: npm run test --workspace=packages/bruno-query - name: Build Package bruno-query @@ -33,3 +31,15 @@ jobs: run: npm run test --workspace=packages/bruno-cli - name: Test Package bruno-electron run: npm run test --workspace=packages/bruno-electron + + prettier: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v3 + with: + node-version-file: '.nvmrc' + - name: Install dependencies + run: npm ci --legacy-peer-deps + - name: Run Prettier + run: npm run test:prettier:web diff --git a/package.json b/package.json index 9aaaf23f2..dbe318946 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "build:electron": "./scripts/build-electron.sh", "test:e2e": "npx playwright test", "test:report": "npx playwright show-report", + "test:prettier:web": "npm run test:prettier --workspace=packages/bruno-app", "prepare": "husky install" }, "overrides": { diff --git a/packages/bruno-app/package.json b/packages/bruno-app/package.json index 625e9dc0d..13c0cd882 100644 --- a/packages/bruno-app/package.json +++ b/packages/bruno-app/package.json @@ -8,6 +8,7 @@ "start": "next start", "lint": "next lint", "test": "jest", + "test:prettier": "prettier --check \"./src/**/*.{js,jsx,json,ts,tsx}\"", "prettier": "prettier --write \"./src/**/*.{js,jsx,json,ts,tsx}\"" }, "dependencies": { From 8a0f7c6b8fe53da6cd03ccbbf268b4404b2c9631 Mon Sep 17 00:00:00 2001 From: Jarne Date: Wed, 11 Oct 2023 19:22:50 +0200 Subject: [PATCH 04/31] Save window maximized state --- packages/bruno-electron/src/index.js | 15 +++++++++++---- packages/bruno-electron/src/store/window-state.js | 10 ++++++++++ packages/bruno-electron/src/utils/window.js | 11 +++++++++-- 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/packages/bruno-electron/src/index.js b/packages/bruno-electron/src/index.js index 3a38e21ae..a57faddea 100644 --- a/packages/bruno-electron/src/index.js +++ b/packages/bruno-electron/src/index.js @@ -9,7 +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 { loadWindowState, saveBounds, saveMaximized } = require('./utils/window'); const lastOpenedCollections = new LastOpenedCollections(); @@ -32,7 +32,7 @@ let watcher; // Prepare the renderer once the app is ready app.on('ready', async () => { - const { x, y, width, height } = loadWindowState(); + const { maximized, x, y, width, height } = loadWindowState(); mainWindow = new BrowserWindow({ x, @@ -52,6 +52,10 @@ app.on('ready', async () => { // autoHideMenuBar: true }); + if (maximized) { + mainWindow.maximize(); + } + const url = isDev ? 'http://localhost:3000' : format({ @@ -63,8 +67,11 @@ app.on('ready', async () => { mainWindow.loadURL(url); watcher = new Watcher(); - mainWindow.on('resize', () => saveWindowState(mainWindow)); - mainWindow.on('move', () => saveWindowState(mainWindow)); + mainWindow.on('resize', () => saveBounds(mainWindow)); + mainWindow.on('move', () => saveBounds(mainWindow)); + + mainWindow.on('maximize', () => saveMaximized(true)); + mainWindow.on('unmaximize', () => saveMaximized(false)); mainWindow.webContents.on('new-window', function (e, url) { e.preventDefault(); diff --git a/packages/bruno-electron/src/store/window-state.js b/packages/bruno-electron/src/store/window-state.js index bb0a61b64..51c6060b7 100644 --- a/packages/bruno-electron/src/store/window-state.js +++ b/packages/bruno-electron/src/store/window-state.js @@ -4,6 +4,8 @@ const Store = require('electron-store'); const DEFAULT_WINDOW_WIDTH = 1280; const DEFAULT_WINDOW_HEIGHT = 768; +const DEFAULT_MAXIMIZED = false; + class WindowStateStore { constructor() { this.store = new Store({ @@ -26,6 +28,14 @@ class WindowStateStore { setBounds(bounds) { this.store.set('window-bounds', bounds); } + + getMaximized() { + return this.store.get('maximized') || DEFAULT_MAXIMIZED; + } + + setMaximized(isMaximized) { + this.store.set('maximized', isMaximized); + } } module.exports = WindowStateStore; diff --git a/packages/bruno-electron/src/utils/window.js b/packages/bruno-electron/src/utils/window.js index d824141d3..949a2aaa2 100644 --- a/packages/bruno-electron/src/utils/window.js +++ b/packages/bruno-electron/src/utils/window.js @@ -7,12 +7,14 @@ const DEFAULT_WINDOW_WIDTH = 1280; const DEFAULT_WINDOW_HEIGHT = 768; const loadWindowState = () => { + const maximized = windowStateStore.getMaximized(); const bounds = windowStateStore.getBounds(); const positionValid = isPositionValid(bounds); const sizeValid = isSizeValid(bounds); return { + maximized, x: bounds.x && positionValid ? bounds.x : undefined, y: bounds.y && positionValid ? bounds.y : undefined, width: bounds.width && sizeValid ? bounds.width : DEFAULT_WINDOW_WIDTH, @@ -20,12 +22,16 @@ const loadWindowState = () => { }; }; -const saveWindowState = (window) => { +const saveBounds = (window) => { const bounds = window.getBounds(); windowStateStore.setBounds(bounds); }; +const saveMaximized = (isMaximized) => { + windowStateStore.setMaximized(isMaximized); +}; + const isPositionValid = (bounds) => { const area = getArea(bounds); @@ -49,5 +55,6 @@ const getArea = (bounds) => { module.exports = { loadWindowState, - saveWindowState + saveBounds, + saveMaximized }; From 72521a6007c742a0e3edc278e31b86915eecfdf0 Mon Sep 17 00:00:00 2001 From: Its-treason <39559178+Its-treason@users.noreply.github.com> Date: Wed, 11 Oct 2023 22:09:11 +0200 Subject: [PATCH 05/31] fix(#529): Fix Ctrl+W closes Bruno The default shortcut to close in the menu is Ctrl+W, I changed it to Ctrl+Shift+Q because firefox uses this shortcut for closing --- packages/bruno-electron/src/app/menu-template.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/bruno-electron/src/app/menu-template.js b/packages/bruno-electron/src/app/menu-template.js index 6b4707729..cc0f1267e 100644 --- a/packages/bruno-electron/src/app/menu-template.js +++ b/packages/bruno-electron/src/app/menu-template.js @@ -44,7 +44,7 @@ const template = [ }, { role: 'window', - submenu: [{ role: 'minimize' }, { role: 'close' }] + submenu: [{ role: 'minimize' }, { role: 'close', accelerator: 'CommandOrControl+Shift+Q' }] }, { role: 'help', From 78eec9ea5cc52ca4c594019dcfc0115be7e6bdcd Mon Sep 17 00:00:00 2001 From: rayoz12 Date: Sat, 14 Oct 2023 21:05:44 +1100 Subject: [PATCH 06/31] Fixes: #552 Runs Post response vars and scripts on error. This normalises behaviour between: - Assertions - Scripts - Tests --- .../bruno-electron/src/ipc/network/index.js | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/packages/bruno-electron/src/ipc/network/index.js b/packages/bruno-electron/src/ipc/network/index.js index 8e8cb6247..9a5251825 100644 --- a/packages/bruno-electron/src/ipc/network/index.js +++ b/packages/bruno-electron/src/ipc/network/index.js @@ -435,6 +435,56 @@ const registerNetworkIpc = (mainWindow) => { }); } + // run post-response vars + const postResponseVars = get(request, 'vars.res', []); + if (postResponseVars && postResponseVars.length) { + const varsRuntime = new VarsRuntime(); + const result = varsRuntime.runPostResponseVars( + postResponseVars, + request, + error.response, + envVars, + collectionVariables, + collectionPath, + processEnvVars + ); + + if (result) { + mainWindow.webContents.send('main:script-environment-update', { + envVariables: result.envVariables, + collectionVariables: result.collectionVariables, + requestUid, + collectionUid + }); + } + } + + // run post-response script + const responseScript = compact([get(collectionRoot, 'request.script.res'), get(request, 'script.res')]).join( + os.EOL + ); + if (responseScript && responseScript.length) { + const scriptRuntime = new ScriptRuntime(); + const result = await scriptRuntime.runResponseScript( + decomment(responseScript), + request, + error.response, + envVars, + collectionVariables, + collectionPath, + onConsoleLog, + processEnvVars, + scriptingConfig + ); + + mainWindow.webContents.send('main:script-environment-update', { + envVariables: result.envVariables, + collectionVariables: result.collectionVariables, + requestUid, + collectionUid + }); + } + // run tests const testFile = compact([ get(collectionRoot, 'request.tests'), From a0be0e10acc55d087e1b475ea5788f53d36a8c1b Mon Sep 17 00:00:00 2001 From: game5413 Date: Sat, 14 Oct 2023 18:10:49 +0700 Subject: [PATCH 07/31] fix event triggered when hold mouse click and release at sidebar --- .../Collection/CollectionItem/index.js | 71 +++++++++---------- .../Sidebar/Collections/Collection/index.js | 29 ++++---- 2 files changed, 50 insertions(+), 50 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 0b33941f7..db5bfc02c 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,44 +88,41 @@ const CollectionItem = ({ item, collection, searchText }) => { }); const handleClick = (event) => { - 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; - } + if (isItemARequest(item)) { + dispatch(hideHomePage()); + if (itemIsOpenedInTabs(item, tabs)) { dispatch( - collectionFolderClicked({ - itemUid: item.uid, - collectionUid: collection.uid + focusTab({ + uid: item.uid }) ); return; - case 2: // right click - const _menuDropdown = dropdownTippyRef.current; - if (_menuDropdown) { - let menuDropdownBehavior = 'show'; - if (_menuDropdown.state.isShown) { - menuDropdownBehavior = 'hide'; - } - _menuDropdown[menuDropdownBehavior](); - } - return; + } + dispatch( + addTab({ + uid: item.uid, + collectionUid: collection.uid, + requestPaneTab: getDefaultRequestPaneTab(item) + }) + ); + return; + } + dispatch( + collectionFolderClicked({ + itemUid: item.uid, + collectionUid: collection.uid + }) + ); + }; + + const handleRightClick = (event) => { + const _menuDropdown = dropdownTippyRef.current; + if (_menuDropdown) { + let menuDropdownBehavior = 'show'; + if (_menuDropdown.state.isShown) { + menuDropdownBehavior = 'hide'; + } + _menuDropdown[menuDropdownBehavior](); } }; @@ -203,7 +200,8 @@ const CollectionItem = ({ item, collection, searchText }) => { ? indents.map((i) => { return (
{ }) : null}
{ }); const handleClick = (event) => { + dispatch(collectionClicked(collection.uid)); + }; + + const handleRightClick = (event) => { 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; + if (_menuDropdown) { + let menuDropdownBehavior = 'show'; + if (_menuDropdown.state.isShown) { + menuDropdownBehavior = 'hide'; + } + _menuDropdown[menuDropdownBehavior](); } }; @@ -138,7 +135,11 @@ const Collection = ({ collection, searchText }) => { setCollectionPropertiesModal(false)} /> )}
-
+
Date: Sat, 14 Oct 2023 16:32:29 +0100 Subject: [PATCH 08/31] adds PATH_SEPARATOR constant --- .../src/providers/ReduxStore/slices/collections/actions.js | 4 +--- .../src/providers/ReduxStore/slices/collections/index.js | 4 +--- packages/bruno-app/src/utils/common/platform.js | 2 ++ 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/packages/bruno-app/src/providers/ReduxStore/slices/collections/actions.js b/packages/bruno-app/src/providers/ReduxStore/slices/collections/actions.js index 111f26d3e..f18c7edfa 100644 --- a/packages/bruno-app/src/providers/ReduxStore/slices/collections/actions.js +++ b/packages/bruno-app/src/providers/ReduxStore/slices/collections/actions.js @@ -21,7 +21,7 @@ import { } from 'utils/collections'; import { collectionSchema, itemSchema, environmentSchema, environmentsSchema } from '@usebruno/schema'; import { waitForNextTick } from 'utils/common'; -import { getDirectoryName, isWindowsOS } from 'utils/common/platform'; +import { getDirectoryName, isWindowsOS, PATH_SEPARATOR } from 'utils/common/platform'; import { sendNetworkRequest, cancelNetworkRequest } from 'utils/network'; import { @@ -46,8 +46,6 @@ import { import { closeAllCollectionTabs } from 'providers/ReduxStore/slices/tabs'; import { resolveRequestFilename } from 'utils/common/platform'; -const PATH_SEPARATOR = path.sep; - export const renameCollection = (newName, collectionUid) => (dispatch, getState) => { const state = getState(); const collection = findCollectionByUid(state.collections.collections, collectionUid); 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 70e12a3f8..9e64ff0f4 100644 --- a/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js +++ b/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js @@ -24,9 +24,7 @@ import { areItemsTheSameExceptSeqUpdate } from 'utils/collections'; import { parseQueryParams, stringifyQueryParams } from 'utils/url'; -import { getSubdirectoriesFromRoot, getDirectoryName, isWindowsOS } from 'utils/common/platform'; - -const PATH_SEPARATOR = isWindowsOS() ? '\\' : '/'; +import { getSubdirectoriesFromRoot, getDirectoryName, PATH_SEPARATOR } from 'utils/common/platform'; const initialState = { collections: [], diff --git a/packages/bruno-app/src/utils/common/platform.js b/packages/bruno-app/src/utils/common/platform.js index 771daaf14..03ff9539e 100644 --- a/packages/bruno-app/src/utils/common/platform.js +++ b/packages/bruno-app/src/utils/common/platform.js @@ -48,3 +48,5 @@ export const isMacOS = () => { return osFamily.includes('os x'); }; + +export const PATH_SEPARATOR = isWindowsOS() ? '\\' : '/'; From 7808a6db05bdf123ab47237ef94a7b3172c5fbfb Mon Sep 17 00:00:00 2001 From: Jack Scotson Date: Sat, 14 Oct 2023 16:36:10 +0100 Subject: [PATCH 09/31] Revert "fix(#251, #265): phantoms folders fix on rename/delete needs to be run only on windows" This reverts commit fcc12fb089472716328054665d767d7b0ae48e04. # Conflicts: # packages/bruno-app/src/providers/ReduxStore/slices/collections/actions.js # packages/bruno-app/src/utils/common/platform.js --- .../ReduxStore/slices/collections/actions.js | 36 ++++++------------- .../bruno-app/src/utils/common/platform.js | 1 - 2 files changed, 10 insertions(+), 27 deletions(-) diff --git a/packages/bruno-app/src/providers/ReduxStore/slices/collections/actions.js b/packages/bruno-app/src/providers/ReduxStore/slices/collections/actions.js index f18c7edfa..79f3384b8 100644 --- a/packages/bruno-app/src/providers/ReduxStore/slices/collections/actions.js +++ b/packages/bruno-app/src/providers/ReduxStore/slices/collections/actions.js @@ -171,11 +171,7 @@ export const cancelRequest = (cancelTokenUid, item, collection) => (dispatch) => .catch((err) => console.log(err)); }; -// todo: this can be directly put inside the collections/index.js file -// the coding convention is to put only actions that need ipc in this file -export const sortCollections = (order) => (dispatch) => { - dispatch(_sortCollections(order)); -}; + export const runCollectionFolder = (collectionUid, folderUid, recursive) => (dispatch, getState) => { const state = getState(); const collection = findCollectionByUid(state.collections.collections, collectionUid); @@ -293,19 +289,10 @@ export const renameItem = (newName, itemUid, collectionUid) => (dispatch, getSta } const { ipcRenderer } = window; - ipcRenderer - .invoke('renderer:rename-item', item.pathname, newPathname, newName) - .then(() => { - // In case of Mac and Linux, we get the unlinkDir and addDir IPC events from electron which takes care of updating the state - // But in windows we don't get those events, so we need to update the state manually - // This looks like an issue in our watcher library chokidar - // GH: https://github.com/usebruno/bruno/issues/251 - if (isWindowsOS()) { - dispatch(_renameItem({ newName, itemUid, collectionUid })); - } - resolve(); - }) - .catch(reject); + ipcRenderer.invoke('renderer:rename-item', item.pathname, newPathname, newName).then(() => { + dispatch(_renameItem({ newName, itemUid, collectionUid })) + resolve() + }).catch(reject); }); }; @@ -390,14 +377,8 @@ export const deleteItem = (itemUid, collectionUid) => (dispatch, getState) => { ipcRenderer .invoke('renderer:delete-item', item.pathname, item.type) .then(() => { - // In case of Mac and Linux, we get the unlinkDir IPC event from electron which takes care of updating the state - // But in windows we don't get those events, so we need to update the state manually - // This looks like an issue in our watcher library chokidar - // GH: https://github.com/usebruno/bruno/issues/265 - if (isWindowsOS()) { - dispatch(_deleteItem({ itemUid, collectionUid })); - } - resolve(); + dispatch(_deleteItem({ itemUid, collectionUid })) + resolve() }) .catch((error) => reject(error)); } @@ -405,6 +386,9 @@ export const deleteItem = (itemUid, collectionUid) => (dispatch, getState) => { }); }; +export const sortCollections = () => (dispatch) => { + dispatch(_sortCollections()) +} export const moveItem = (collectionUid, draggedItemUid, targetItemUid) => (dispatch, getState) => { const state = getState(); const collection = findCollectionByUid(state.collections.collections, collectionUid); diff --git a/packages/bruno-app/src/utils/common/platform.js b/packages/bruno-app/src/utils/common/platform.js index 03ff9539e..24b4a41ac 100644 --- a/packages/bruno-app/src/utils/common/platform.js +++ b/packages/bruno-app/src/utils/common/platform.js @@ -1,7 +1,6 @@ import trim from 'lodash/trim'; import path from 'path'; import slash from './slash'; -import platform from 'platform'; export const isElectron = () => { if (!window) { From 0f1fb72e216c7e56e98bcc770bc724af76de4ae6 Mon Sep 17 00:00:00 2001 From: Jack Scotson Date: Sat, 14 Oct 2023 16:38:12 +0100 Subject: [PATCH 10/31] fix(#251): Re-add platform var --- packages/bruno-app/src/utils/common/platform.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/bruno-app/src/utils/common/platform.js b/packages/bruno-app/src/utils/common/platform.js index 24b4a41ac..03ff9539e 100644 --- a/packages/bruno-app/src/utils/common/platform.js +++ b/packages/bruno-app/src/utils/common/platform.js @@ -1,6 +1,7 @@ import trim from 'lodash/trim'; import path from 'path'; import slash from './slash'; +import platform from 'platform'; export const isElectron = () => { if (!window) { From ead1225bc4d1d101e0a1751ddf99660aec5bfd3b Mon Sep 17 00:00:00 2001 From: Mykola Makhin Date: Sun, 15 Oct 2023 01:54:52 +0300 Subject: [PATCH 11/31] Ukrainian translation for contributing.md --- contributing.md | 2 +- contributing_ru.md | 2 +- contributing_ua.md | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 contributing_ua.md diff --git a/contributing.md b/contributing.md index abfcce4d3..966a6134b 100644 --- a/contributing.md +++ b/contributing.md @@ -1,4 +1,4 @@ -**English** | [Русский](/contributing_ru.md) +**English** | [Українська](/contributing_ua.md) | [Русский](/contributing_ru.md) ## Lets make bruno better, together !! diff --git a/contributing_ru.md b/contributing_ru.md index 316408162..061b60569 100644 --- a/contributing_ru.md +++ b/contributing_ru.md @@ -1,4 +1,4 @@ -[English](/contributing.md) | **Русский** +[English](/contributing.md) | [Українська](/contributing_ua.md) | **Русский** ## Давайте вместе сделаем Бруно лучше!!! diff --git a/contributing_ua.md b/contributing_ua.md new file mode 100644 index 000000000..75760f565 --- /dev/null +++ b/contributing_ua.md @@ -0,0 +1,37 @@ +[English](/contributing.md) | **Українська** | [Русский](/contributing_ru.md) + +## Давайте зробимо Bruno краще, разом !! + +Я дуже радий що Ви бажаєте покращити Bruno. Нижче наведені вказівки як розпочати розробку Bruno на Вашому комп'ютері. + +### Стек технологій + +Bruno побудований на NextJs та React. Також для десктопної версії (яка підтримує локальні колекції) використовується Electron + +Бібліотеки, які ми використовуємо + +- CSS - Tailwind +- Редактори коду - Codemirror +- Керування станом - Redux +- Іконки - Tabler Icons +- Форми - formik +- Валідація по схемі - Yup +- Клієнт запитів - axios +- Спостерігач за файловою системою - chokidar + +### Залежності + +Вам знадобиться [Node v18.x або остання LTS версія](https://nodejs.org/en/) та npm 8.x. Ми використовуєм npm workspaces в цьому проекті + +### Починаєм писати код + +Будь ласка, зверніться до [development_ua.md](docs/development_ua.md) за інструкціями щодо запуску локального середовища розробки. + +### Створення Pull Request-ів + +- Будь ласка, робіть PR-и маленькими і сфокусованими на одній речі +- Будь ласка, слідуйте формату назв гілок + - feature/[назва feature]: Така гілка має містити зміни лише щодо конкретної feature + - Приклад: feature/dark-mode + - bugfix/[назва баґу]: Така гілка має містити лише виправлення конкретного багу + - Приклад: bugfix/bug-1 From 211f941b9f9e56b2809890d295db953ceaf83be4 Mon Sep 17 00:00:00 2001 From: Jack Scotson Date: Sun, 15 Oct 2023 10:16:41 +0100 Subject: [PATCH 12/31] rm renameitem --- .../src/providers/ReduxStore/slices/collections/actions.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/bruno-app/src/providers/ReduxStore/slices/collections/actions.js b/packages/bruno-app/src/providers/ReduxStore/slices/collections/actions.js index 79f3384b8..3a5e17bce 100644 --- a/packages/bruno-app/src/providers/ReduxStore/slices/collections/actions.js +++ b/packages/bruno-app/src/providers/ReduxStore/slices/collections/actions.js @@ -31,7 +31,6 @@ import { requestCancelled, responseReceived, newItem as _newItem, - renameItem as _renameItem, cloneItem as _cloneItem, deleteItem as _deleteItem, saveRequest as _saveRequest, @@ -290,7 +289,6 @@ export const renameItem = (newName, itemUid, collectionUid) => (dispatch, getSta const { ipcRenderer } = window; ipcRenderer.invoke('renderer:rename-item', item.pathname, newPathname, newName).then(() => { - dispatch(_renameItem({ newName, itemUid, collectionUid })) resolve() }).catch(reject); }); From 074cbf0c03056e8ad5e8db2b340eea6520ad391c Mon Sep 17 00:00:00 2001 From: Jack Scotson Date: Sun, 15 Oct 2023 10:25:35 +0100 Subject: [PATCH 13/31] cleanup --- .../src/providers/ReduxStore/slices/collections/actions.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/bruno-app/src/providers/ReduxStore/slices/collections/actions.js b/packages/bruno-app/src/providers/ReduxStore/slices/collections/actions.js index 3a5e17bce..1c3295a19 100644 --- a/packages/bruno-app/src/providers/ReduxStore/slices/collections/actions.js +++ b/packages/bruno-app/src/providers/ReduxStore/slices/collections/actions.js @@ -288,9 +288,7 @@ export const renameItem = (newName, itemUid, collectionUid) => (dispatch, getSta } const { ipcRenderer } = window; - ipcRenderer.invoke('renderer:rename-item', item.pathname, newPathname, newName).then(() => { - resolve() - }).catch(reject); + ipcRenderer.invoke('renderer:rename-item', item.pathname, newPathname, newName).then(resolve).catch(reject); }); }; From ddd479ed4509ff2fa271a2bb2e0561be822b7fb6 Mon Sep 17 00:00:00 2001 From: Ross Gargett <73141350+Ross-Gargett@users.noreply.github.com> Date: Sun, 15 Oct 2023 19:38:47 -0700 Subject: [PATCH 14/31] fix: prevent non-numerical or negative timeouts --- .../bruno-app/src/components/Preferences/General/index.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/bruno-app/src/components/Preferences/General/index.js b/packages/bruno-app/src/components/Preferences/General/index.js index 2dbcfab76..917b5765d 100644 --- a/packages/bruno-app/src/components/Preferences/General/index.js +++ b/packages/bruno-app/src/components/Preferences/General/index.js @@ -25,8 +25,9 @@ const General = ({ close }) => { }; const handleTimeoutChange = (value) => { - const validTimeout = isNaN(Number(value)) ? timeout : Number(value); - setTimeout(validTimeout); + if (/^[0-9]\d*$/.test(value) || value === '') { + setTimeout(value); + } }; return ( @@ -47,13 +48,14 @@ const General = ({ close }) => { handleTimeoutChange(e.target.value)} defaultValue={timeout === 0 ? '' : timeout} + value={timeout} />
From 67218f5bb496ce7b5713e053d08d5cb8eb56763d Mon Sep 17 00:00:00 2001 From: Ross Gargett <73141350+Ross-Gargett@users.noreply.github.com> Date: Mon, 16 Oct 2023 21:08:22 -0700 Subject: [PATCH 15/31] feedback: use formik and Yup for preferences form --- .../components/Preferences/General/index.js | 121 +++++++++++------- .../src/providers/ReduxStore/slices/app.js | 3 +- 2 files changed, 76 insertions(+), 48 deletions(-) diff --git a/packages/bruno-app/src/components/Preferences/General/index.js b/packages/bruno-app/src/components/Preferences/General/index.js index 917b5765d..b67932eb6 100644 --- a/packages/bruno-app/src/components/Preferences/General/index.js +++ b/packages/bruno-app/src/components/Preferences/General/index.js @@ -1,69 +1,96 @@ -import React, { useState } from 'react'; +import React from 'react'; +import { useFormik } from 'formik'; import { useSelector, useDispatch } from 'react-redux'; import { savePreferences } from 'providers/ReduxStore/slices/app'; import StyledWrapper from './StyledWrapper'; +import * as Yup from 'yup'; +import toast from 'react-hot-toast'; const General = ({ close }) => { const preferences = useSelector((state) => state.app.preferences); const dispatch = useDispatch(); - const [sslVerification, setSslVerification] = useState(preferences.request.sslVerification); - const [timeout, setTimeout] = useState(preferences.request.timeout); + const preferencesSchema = Yup.object().shape({ + sslVerification: Yup.boolean(), + timeout: Yup.number('Request Timeout must be a number') + .positive('Request Timeout must be a positive number') + .typeError('Request Timeout must be a number') + .optional() + }); - const handleSave = () => { + const formik = useFormik({ + initialValues: { + sslVerification: preferences.request.sslVerification, + timeout: preferences.request.timeout + }, + validationSchema: preferencesSchema, + onSubmit: async (values) => { + try { + const newPreferences = await proxySchema.validate(values, { abortEarly: true }); + handleSave(newPreferences); + } catch (error) { + console.error('Preferences validation error:', error.message); + } + } + }); + + const handleSave = (newPreferences) => { dispatch( savePreferences({ ...preferences, request: { - sslVerification, - timeout + sslVerification: newPreferences.sslVerification, + timeout: newPreferences.timeout } }) - ).then(() => { - close(); - }); - }; - - const handleTimeoutChange = (value) => { - if (/^[0-9]\d*$/.test(value) || value === '') { - setTimeout(value); - } + ) + .then(() => { + close(); + }) + .catch((err) => console.log(err) && toast.error('Failed to update preferences')); }; return ( -
- - setSslVerification(!sslVerification)} - className="mousetrap mr-0" - /> -
-
- - handleTimeoutChange(e.target.value)} - defaultValue={timeout === 0 ? '' : timeout} - value={timeout} - /> -
- -
- -
+
+
+ + +
+
+ + +
+ {formik.touched.timeout && formik.errors.timeout ? ( +
{formik.errors.timeout}
+ ) : null} +
+ +
+
); }; diff --git a/packages/bruno-app/src/providers/ReduxStore/slices/app.js b/packages/bruno-app/src/providers/ReduxStore/slices/app.js index c3a3aa5a8..6f5c849f9 100644 --- a/packages/bruno-app/src/providers/ReduxStore/slices/app.js +++ b/packages/bruno-app/src/providers/ReduxStore/slices/app.js @@ -9,7 +9,8 @@ const initialState = { showHomePage: false, preferences: { request: { - sslVerification: true + sslVerification: true, + timeout: 0 }, font: { codeFont: 'default' From 544edfa7d770aa9a01373218a8eb670123e779f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Heikki=20P=C3=B6l=C3=B6nen?= Date: Tue, 17 Oct 2023 11:42:40 +0300 Subject: [PATCH 16/31] Adds variable interpolate to assert runtime --- packages/bruno-js/src/interpolate-string.js | 55 +++++++++++++++++++ .../bruno-js/src/runtime/assert-runtime.js | 13 +++-- 2 files changed, 64 insertions(+), 4 deletions(-) create mode 100644 packages/bruno-js/src/interpolate-string.js diff --git a/packages/bruno-js/src/interpolate-string.js b/packages/bruno-js/src/interpolate-string.js new file mode 100644 index 000000000..33701dd0b --- /dev/null +++ b/packages/bruno-js/src/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-js/src/runtime/assert-runtime.js b/packages/bruno-js/src/runtime/assert-runtime.js index 06f6adab4..fa3827097 100644 --- a/packages/bruno-js/src/runtime/assert-runtime.js +++ b/packages/bruno-js/src/runtime/assert-runtime.js @@ -4,6 +4,7 @@ const { nanoid } = require('nanoid'); const Bru = require('../bru'); const BrunoRequest = require('../bruno-request'); const { evaluateJsTemplateLiteral, evaluateJsExpression, createResponseParser } = require('../utils'); +const { interpolateString } = require('../interpolate-string'); const { expect } = chai; chai.use(require('chai-string')); @@ -167,11 +168,15 @@ const evaluateRhsOperand = (rhsOperand, operator, context) => { rhsOperand = rhsOperand.substring(1, rhsOperand.length - 1); } - return rhsOperand.split(',').map((v) => evaluateJsTemplateLiteral(v.trim(), context)); + return rhsOperand + .split(',') + .map((v) => evaluateJsTemplateLiteral(interpolateString(v.trim(), context.bru), context)); } if (operator === 'between') { - const [lhs, rhs] = rhsOperand.split(',').map((v) => evaluateJsTemplateLiteral(v.trim(), context)); + const [lhs, rhs] = rhsOperand + .split(',') + .map((v) => evaluateJsTemplateLiteral(interpolateString(v.trim(), context.bru), context)); return [lhs, rhs]; } @@ -181,10 +186,10 @@ const evaluateRhsOperand = (rhsOperand, operator, context) => { rhsOperand = rhsOperand.substring(1, rhsOperand.length - 1); } - return rhsOperand; + return interpolateString(rhsOperand, context.bru); } - return evaluateJsTemplateLiteral(rhsOperand, context); + return evaluateJsTemplateLiteral(interpolateString(rhsOperand, context.bru), context); }; class AssertRuntime { From 7e654a81bfe4db4b5fb52309329ca1dcfb5587d4 Mon Sep 17 00:00:00 2001 From: Mykola Makhin Date: Tue, 17 Oct 2023 12:06:45 +0300 Subject: [PATCH 17/31] Ukrainian translation for ReadMe page --- readme.md | 2 +- readme_ru.md | 2 +- readme_ua.md | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 readme_ua.md diff --git a/readme.md b/readme.md index 8021a5b7a..cf3d2dc61 100644 --- a/readme.md +++ b/readme.md @@ -10,7 +10,7 @@ [![Website](https://img.shields.io/badge/Website-Visit-blue)](https://www.usebruno.com) [![Download](https://img.shields.io/badge/Download-Latest-brightgreen)](https://www.usebruno.com/downloads) -**English** | [Русский](/readme_ru.md) +**English** | [Українська](/readme_ua.md) | [Русский](/readme_ru.md) Bruno is a new and innovative API client, aimed at revolutionizing the status quo represented by Postman and similar tools out there. diff --git a/readme_ru.md b/readme_ru.md index 8c25e5c57..d8b8255f7 100644 --- a/readme_ru.md +++ b/readme_ru.md @@ -10,7 +10,7 @@ [![Website](https://img.shields.io/badge/Website-Visit-blue)](https://www.usebruno.com) [![Download](https://img.shields.io/badge/Download-Latest-brightgreen)](https://www.usebruno.com/downloads) -[English](/readme.md) | **Русский** +[English](/readme.md) | [Українська](/readme_ua.md) | **Русский** Bruno - новый и инновационный клиент API, направленный на революцию в установившейся ситуации, представленной Postman и подобными инструментами. diff --git a/readme_ua.md b/readme_ua.md new file mode 100644 index 000000000..02df2bb49 --- /dev/null +++ b/readme_ua.md @@ -0,0 +1,80 @@ +
+ + +### Bruno - IDE із відкритим кодом для тестування та дослідження API + +[![GitHub version](https://badge.fury.io/gh/usebruno%2Fbruno.svg)](https://badge.fury.io/gh/usebruno%bruno) +[![CI](https://github.com/usebruno/bruno/actions/workflows/unit-tests.yml/badge.svg?branch=main)](https://github.com/usebruno/bruno/workflows/unit-tests.yml) +[![Commit Activity](https://img.shields.io/github/commit-activity/m/usebruno/bruno)](https://github.com/usebruno/bruno/pulse) +[![X](https://img.shields.io/twitter/follow/use_bruno?style=social&logo=x)](https://twitter.com/use_bruno) +[![Website](https://img.shields.io/badge/Website-Visit-blue)](https://www.usebruno.com) +[![Download](https://img.shields.io/badge/Download-Latest-brightgreen)](https://www.usebruno.com/downloads) + +[English](/readme.md) | **Українська** | [Русский](/readme_ru.md) + +Bruno це новий та іноваційний API клієнт, націлений на революційну зміну статус кво, запровадженого інструментами на кшталт Postman. + +Bruno зберігає ваші колекції напряму у теці на вашому диску. Він використовує текстову мову розмітки Bru для збереження інформації про ваші API запити. + +Ви можете використовувати git або будь-яку іншу систему контролю версій щоб спільно працювати над вашими колекціями API запитів. + +Bruno є повністю автономним. Немає жодних планів додавати будь-які синхронізації через хмару, ніколи. Ми цінуємо приватність ваших даних, і вважаєм, що вони мають залишитись лише на вашому комп'ютері. Взнати більше про наше бачення у довготривалій перспективі можна [тут](https://github.com/usebruno/bruno/discussions/269) + +![bruno](assets/images/landing-2.png)

+ +### Кросплатформенність 🖥️ + +![bruno](assets/images/run-anywhere.png)

+ +### Спільна робота через Git 👩‍💻🧑‍💻 + +Або будь-яку іншу систему контролю версій на ваш вибір + +![bruno](assets/images/version-control.png)

+ +### Важливі посилання 📌 + +- [Наше бачення довготривалої перспективи проекту](https://github.com/usebruno/bruno/discussions/269) +- [Дорожня карта проекту](https://github.com/usebruno/bruno/discussions/384) +- [Документація](https://docs.usebruno.com) +- [Сайт](https://www.usebruno.com) +- [Завантаження](https://www.usebruno.com/downloads) + +### Вітрина 🎥 + +- [Відгуки](https://github.com/usebruno/bruno/discussions/343) +- [Хаб знань](https://github.com/usebruno/bruno/discussions/386) +- [Scriptmania](https://github.com/usebruno/bruno/discussions/385) + +### Підтримка ❤️ + +Гав! Якщо вам сподобався проект, тисніть на ⭐ !! + +### Поділитись відгуками 📣 + +Якщо Bruno допоміг вам у вашій роботі і вашим командам, будь ласка не забудьте поділитись вашими [відгуками у github дискусії](https://github.com/usebruno/bruno/discussions/343) + +### Зробити свій внесок 👩‍💻🧑‍💻 + +Я радий що ви бажаєте покращити Bruno. Будь ласка переглянте [інструкцію по контрибуції](contributing.md) + +Навіть якщо ви не можете зробити свій внесок пишучи програмний код, будь ласка не соромтесь рапортувати про помилки і писати запити на новий функціонал, який потрібен вам у вашій роботі. + +### Автори + + + +### Залишайтесь на зв'язку 🌐 + +[Twitter](https://twitter.com/use_bruno)
+[Сайт](https://www.usebruno.com)
+[Discord](https://discord.com/invite/KgcZUncpjq) +[LinkedIn](https://www.linkedin.com/company/usebruno) + +### Ліцензія 📄 + +[MIT](license.md) From 0cf4f09608d44eda618470382c1e4c3d4eeddb9e Mon Sep 17 00:00:00 2001 From: Jarne Date: Tue, 17 Oct 2023 17:25:20 +0200 Subject: [PATCH 18/31] Save window bounds only if not maximized --- packages/bruno-electron/src/index.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/bruno-electron/src/index.js b/packages/bruno-electron/src/index.js index a57faddea..83e507830 100644 --- a/packages/bruno-electron/src/index.js +++ b/packages/bruno-electron/src/index.js @@ -67,8 +67,14 @@ app.on('ready', async () => { mainWindow.loadURL(url); watcher = new Watcher(); - mainWindow.on('resize', () => saveBounds(mainWindow)); - mainWindow.on('move', () => saveBounds(mainWindow)); + const handleBoundsChange = () => { + if (!mainWindow.isMaximized()) { + saveBounds(mainWindow); + } + }; + + mainWindow.on('resize', handleBoundsChange); + mainWindow.on('move', handleBoundsChange); mainWindow.on('maximize', () => saveMaximized(true)); mainWindow.on('unmaximize', () => saveMaximized(false)); From ad8e9c25610f9196e607df5fb12e45aa2fb28cb6 Mon Sep 17 00:00:00 2001 From: Prem Kumar Easwaran Date: Tue, 17 Oct 2023 21:07:32 +0530 Subject: [PATCH 19/31] Autofill folder name as collection name --- .../src/components/Sidebar/CreateCollection/index.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/bruno-app/src/components/Sidebar/CreateCollection/index.js b/packages/bruno-app/src/components/Sidebar/CreateCollection/index.js index 9f9097637..5c88178a3 100644 --- a/packages/bruno-app/src/components/Sidebar/CreateCollection/index.js +++ b/packages/bruno-app/src/components/Sidebar/CreateCollection/index.js @@ -76,7 +76,14 @@ const CreateCollection = ({ onClose }) => { name="collectionName" ref={inputRef} className="block textbox mt-2 w-full" - onChange={formik.handleChange} + onChange = { + (e) => { + formik.handleChange(e); + if (formik.values.collectionName === formik.values.collectionFolderName) { + formik.setFieldValue("collectionFolderName", e.target.value); + } + } + } autoComplete="off" autoCorrect="off" autoCapitalize="off" From d034d599c559933dd3bbe00c77197ddd7c695f66 Mon Sep 17 00:00:00 2001 From: Oleksii Slabchenko Date: Tue, 17 Oct 2023 20:45:58 +0200 Subject: [PATCH 20/31] Fix #646: show exact response size in bytes on mouse hover --- .../src/components/ResponsePane/ResponseSize/index.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/bruno-app/src/components/ResponsePane/ResponseSize/index.js b/packages/bruno-app/src/components/ResponsePane/ResponseSize/index.js index 2500474cb..b956b0813 100644 --- a/packages/bruno-app/src/components/ResponsePane/ResponseSize/index.js +++ b/packages/bruno-app/src/components/ResponsePane/ResponseSize/index.js @@ -13,6 +13,10 @@ const ResponseSize = ({ size }) => { sizeToDisplay = size + 'B'; } - return {sizeToDisplay}; + return ( + + {sizeToDisplay} + + ); }; export default ResponseSize; From b150694a5cda9170ea8d8223bf20fa252e7cc338 Mon Sep 17 00:00:00 2001 From: Mykola Makhin Date: Wed, 18 Oct 2023 02:21:10 +0300 Subject: [PATCH 21/31] Ukrainian translation for the development doc --- docs/development.md | 2 +- docs/development_ru.md | 2 +- docs/development_ua.md | 55 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 docs/development_ua.md diff --git a/docs/development.md b/docs/development.md index c1c402e08..d56d3e6cf 100644 --- a/docs/development.md +++ b/docs/development.md @@ -1,4 +1,4 @@ -**English** | [Русский](/docs/development_ru.md) +**English** | [Українська](/docs/development_ua.md) | [Русский](/docs/development_ru.md) ## Development diff --git a/docs/development_ru.md b/docs/development_ru.md index 4d4e3a80e..3816066e0 100644 --- a/docs/development_ru.md +++ b/docs/development_ru.md @@ -1,4 +1,4 @@ -[English](/docs/development.md) | **Русский** +[English](/docs/development.md) | [Українська](/docs/development_ua.md) | **Русский** ## Разработка diff --git a/docs/development_ua.md b/docs/development_ua.md new file mode 100644 index 000000000..d6d5bcdf8 --- /dev/null +++ b/docs/development_ua.md @@ -0,0 +1,55 @@ +[English](/docs/development.md) | **Українська** | [Русский](/docs/development_ru.md) + +## Розробка + +Bruno розробляється як декстопний застосунок. Вам потрібно запустити nextjs в одній сесії терміналу, та запустити застосунок Electron в іншій сесії терміналу. + +### Залежності + +- NodeJS v18 + +### Локальна розробка + +```bash +# Використовуйте nodejs 18-ї версії +nvm use + +# встановіть залежності +npm i --legacy-peer-deps + +# зберіть документацію graphql +npm run build:graphql-docs + +# зберіть bruno query +npm run build:bruno-query + +# запустіть додаток next (термінал 1) +npm run dev:web + +# запустіть додаток електрон (термінал 2) +npm run dev:electron +``` + +### Усунення несправностей + +Ви можете зтикнутись із помилкою `Unsupported platform` коли запускаєте `npm install`. Щоб усунути цю проблему, вам потрібно видалити `node_modules` та `package-lock.json`, і тоді запустити `npm install`. Це має встановити всі потрібні для запуску додатку пекеджі. + +```shell +# Видаліть node_modules в піддиректоріях +find ./ -type d -name "node_modules" -print0 | while read -d $'\0' dir; do + rm -rf "$dir" +done + +# Видаліть package-lock в піддиректоріях +find . -type f -name "package-lock.json" -delete +``` + +### Тестування + +```bash +# bruno-schema +npm test --workspace=packages/bruno-schema + +# bruno-lang +npm test --workspace=packages/bruno-lang +``` From 924f415176fbd0c126aa45c44513a4e3ae5f9c7d Mon Sep 17 00:00:00 2001 From: Mykola Makhin Date: Wed, 18 Oct 2023 02:25:35 +0300 Subject: [PATCH 22/31] Corrected link to contributing page from UA readme --- readme_ua.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme_ua.md b/readme_ua.md index 02df2bb49..793e11a8e 100644 --- a/readme_ua.md +++ b/readme_ua.md @@ -56,7 +56,7 @@ Bruno є повністю автономним. Немає жодних план ### Зробити свій внесок 👩‍💻🧑‍💻 -Я радий що ви бажаєте покращити Bruno. Будь ласка переглянте [інструкцію по контрибуції](contributing.md) +Я радий що ви бажаєте покращити Bruno. Будь ласка переглянте [інструкцію по контрибуції](contributing_ua.md) Навіть якщо ви не можете зробити свій внесок пишучи програмний код, будь ласка не соромтесь рапортувати про помилки і писати запити на новий функціонал, який потрібен вам у вашій роботі. From d809a58deb6bc1d5ea7bf3dcd4d6bd55307f976a Mon Sep 17 00:00:00 2001 From: Anoop M D Date: Wed, 18 Oct 2023 10:25:01 +0530 Subject: [PATCH 23/31] chore: pr polish (#596) --- .../CollectionSettings/ProxySettings/index.js | 82 +++++++++++-------- .../components/Preferences/General/index.js | 2 +- .../Preferences/ProxySettings/index.js | 36 ++++---- .../src/runner/run-single-request.js | 2 +- packages/bruno-cli/src/utils/proxy-util.js | 11 +-- packages/bruno-electron/src/ipc/collection.js | 1 - .../src/ipc/network/awsv4auth-helper.js | 4 +- .../bruno-electron/src/ipc/network/index.js | 18 ++-- .../bruno-electron/src/ipc/preferences.js | 59 +------------ packages/bruno-electron/src/store/index.js | 7 -- .../bruno-electron/src/store/preferences.js | 31 +++---- .../bruno-electron/src/utils/proxy-util.js | 12 +-- 12 files changed, 103 insertions(+), 162 deletions(-) delete mode 100644 packages/bruno-electron/src/store/index.js diff --git a/packages/bruno-app/src/components/CollectionSettings/ProxySettings/index.js b/packages/bruno-app/src/components/CollectionSettings/ProxySettings/index.js index 3f0981f8d..fd3cc8986 100644 --- a/packages/bruno-app/src/components/CollectionSettings/ProxySettings/index.js +++ b/packages/bruno-app/src/components/CollectionSettings/ProxySettings/index.js @@ -1,24 +1,24 @@ import React, { useEffect } from 'react'; import { useFormik } from 'formik'; - +import Tooltip from 'components/Tooltip'; import StyledWrapper from './StyledWrapper'; import * as Yup from 'yup'; import toast from 'react-hot-toast'; const ProxySettings = ({ proxyConfig, onUpdate }) => { const proxySchema = Yup.object({ - enabled: Yup.string().oneOf(['global', 'enabled', 'disabled']), + use: Yup.string().oneOf(['global', 'true', 'false']), protocol: Yup.string().oneOf(['http', 'https', 'socks4', 'socks5']), hostname: Yup.string() - .when('enabled', { - is: 'enabled', + .when('use', { + is: true, then: (hostname) => hostname.required('Specify the hostname for your proxy.'), otherwise: (hostname) => hostname.nullable() }) .max(1024), port: Yup.number() - .when('enabled', { - is: 'enabled', + .when('use', { + is: true, then: (port) => port.required('Specify port between 1 and 65535').typeError('Specify port between 1 and 65535'), otherwise: (port) => port.nullable().transform((_, val) => (val ? Number(val) : null)) }) @@ -26,11 +26,11 @@ const ProxySettings = ({ proxyConfig, onUpdate }) => { .max(65535), auth: Yup.object() .when('enabled', { - is: 'enabled', + is: true, then: Yup.object({ enabled: Yup.boolean(), username: Yup.string() - .when(['enabled'], { + .when('enabled', { is: true, then: (username) => username.required('Specify username for proxy authentication.') }) @@ -44,12 +44,12 @@ const ProxySettings = ({ proxyConfig, onUpdate }) => { }) }) .optional(), - noProxy: Yup.string().optional().max(1024) + bypassProxy: Yup.string().optional().max(1024) }); const formik = useFormik({ initialValues: { - enabled: proxyConfig.enabled || 'global', + use: proxyConfig.use || 'global', protocol: proxyConfig.protocol || 'http', hostname: proxyConfig.hostname || '', port: proxyConfig.port || '', @@ -58,13 +58,20 @@ const ProxySettings = ({ proxyConfig, onUpdate }) => { username: proxyConfig.auth ? proxyConfig.auth.username || '' : '', password: proxyConfig.auth ? proxyConfig.auth.password || '' : '' }, - noProxy: proxyConfig.noProxy || '' + bypassProxy: proxyConfig.bypassProxy || '' }, validationSchema: proxySchema, onSubmit: (values) => { proxySchema .validate(values, { abortEarly: true }) .then((validatedProxy) => { + // serialize 'use' to boolean + if (validatedProxy.use === 'true') { + validatedProxy.use = true; + } else if (validatedProxy.use === 'false') { + validatedProxy.use = false; + } + onUpdate(validatedProxy); }) .catch((error) => { @@ -76,7 +83,7 @@ const ProxySettings = ({ proxyConfig, onUpdate }) => { useEffect(() => { formik.setValues({ - enabled: proxyConfig.enabled || 'global', + use: proxyConfig.use === true ? 'true' : proxyConfig.use === false ? 'false' : 'global', protocol: proxyConfig.protocol || 'http', hostname: proxyConfig.hostname || '', port: proxyConfig.port || '', @@ -85,32 +92,37 @@ const ProxySettings = ({ proxyConfig, onUpdate }) => { username: proxyConfig.auth ? proxyConfig.auth.username || '' : '', password: proxyConfig.auth ? proxyConfig.auth.password || '' : '' }, - noProxy: proxyConfig.noProxy || '' + bypassProxy: proxyConfig.bypassProxy || '' }); }, [proxyConfig]); return (

Proxy Settings

-
-
+ `} + tooltipId="request-var" + />
-
diff --git a/packages/bruno-app/src/components/Preferences/General/index.js b/packages/bruno-app/src/components/Preferences/General/index.js index 2c7bf0228..077ef39fa 100644 --- a/packages/bruno-app/src/components/Preferences/General/index.js +++ b/packages/bruno-app/src/components/Preferences/General/index.js @@ -33,7 +33,7 @@ const General = ({ close }) => {
{ }) }) .optional(), - noProxy: Yup.string().optional().max(1024) + bypassProxy: Yup.string().optional().max(1024) }); const formik = useFormik({ @@ -63,7 +63,7 @@ const ProxySettings = ({ close }) => { username: preferences.proxy.auth ? preferences.proxy.auth.username || '' : '', password: preferences.proxy.auth ? preferences.proxy.auth.password || '' : '' }, - noProxy: preferences.proxy.noProxy || '' + bypassProxy: preferences.proxy.bypassProxy || '' }, validationSchema: proxySchema, onSubmit: (values) => { @@ -101,21 +101,21 @@ const ProxySettings = ({ close }) => { username: preferences.proxy.auth ? preferences.proxy.auth.username || '' : '', password: preferences.proxy.auth ? preferences.proxy.auth.password || '' : '' }, - noProxy: preferences.proxy.noProxy || '' + bypassProxy: preferences.proxy.bypassProxy || '' }); }, [preferences]); return ( -

Proxy Settings

+

Global Proxy Settings

-
+
-
+
@@ -166,7 +166,7 @@ const ProxySettings = ({ close }) => {
-
+
@@ -186,7 +186,7 @@ const ProxySettings = ({ close }) => {
{formik.errors.hostname}
) : null}
-
+
@@ -206,7 +206,7 @@ const ProxySettings = ({ close }) => {
{formik.errors.port}
) : null}
-
+
@@ -218,7 +218,7 @@ const ProxySettings = ({ close }) => { />
-
+
@@ -238,7 +238,7 @@ const ProxySettings = ({ close }) => {
{formik.errors.auth.username}
) : null}
-
+
@@ -259,24 +259,24 @@ const ProxySettings = ({ close }) => { ) : null}
-
-