Compare commits

...

441 Commits

Author SHA1 Message Date
lohit
85ccc21151 Revert "raw file body - fixes (#3913)"
This reverts commit a075cc71d4.
2025-02-04 12:31:07 +05:30
lohit
a075cc71d4 raw file body - fixes (#3913)
---------

Co-authored-by: lohit <lohit@usebruno.com>
Co-authored-by: Sanjai Kumar <161328623+sanjaikumar-bruno@users.noreply.github.com>
2025-02-04 12:27:45 +05:30
Marcos Adriano
364b0f523a feat: raw binary files handling in request body (#3734)
--------------
Co-authored-by: lohit <lohit@usebruno.com>
Co-authored-by: Anoop M D <anoop.md1421@gmail.com>
2025-02-03 19:22:45 +05:30
Pooja Belaramani
4598acd068 fix 2025-02-03 13:49:35 +05:30
Pooja Belaramani
062ab00a66 fix: ensure API key values are converted to strings in Postman collection importer. 2025-02-03 13:49:35 +05:30
Pooja Belaramani
650cb47a8b fix: resolve function recusion 2025-02-03 13:01:24 +05:30
Pooja Belaramani
08139a8f3e fix 2025-01-30 09:58:38 +05:30
Pooja Belaramani
51e087efba add: hint word for runRequest, sendNextRequest, skipRequest, getTestResults 2025-01-30 09:58:38 +05:30
lohxt1
ff5683f19f add runRequest and runner utils functions to cli
~ add bru.runRequest support for cli
~ add bru.runner.skipRequest, bru.runner.stopExecution support for cli
2025-01-29 11:53:02 +05:30
lohxt1
d13e4b3b54 ensure variables set in scripts/tests during bru.runRequest reflect in original request scripts/tests 2025-01-29 11:53:02 +05:30
Jarod Gowgiel
2d08567d8d Add an npm script to run the Electron app for debugging (#3616)
This allows for developers to attach Dev Tools, e.g. the Chrome
"dedicated DevTools for node", to the main Electron process
for debugging operations that occur on the main process.
2025-01-29 11:25:41 +05:30
ramki-bruno
b51f8109a2 Review changes and minor-refactoring in Reveal in Finder feature 2025-01-29 11:18:57 +05:30
Naman
8f241a32ae Feature: Reveal in Finder (#3698)
* feat: Reveal in Finder

* added support for linux
2025-01-29 11:18:57 +05:30
Sanjai Kumar
b7fda331dc Fix: Comment toggling for JSON modes in CodeEditor 2025-01-29 11:16:15 +05:30
lohxt1
10e0fde2a8 use lowercase header keys while making requests 2025-01-29 08:34:01 +05:30
Anoop M D
9f5f975f70 feat: async parser workers (#3834) (#3887)
feat: async parser workers (#3834)
Co-authored-by: lohit <lohit.jiddimani@gmail.com>
2025-01-29 02:53:53 +05:30
Pragadesh-45
b5bd259a1b fix: handle Windows paths in cloneItem and getDirectoryName functions (fixes: #3401) (#3646)
* fix: handle Windows paths in cloneItem and getDirectoryName functions

* chore: removed commented lines

---------

Co-authored-by: Anoop M D <anoop.md1421@gmail.com>
2025-01-28 21:32:51 +05:30
lohit
0633d45a10 upgraded axios libarary (#3899) 2025-01-28 18:55:59 +05:30
Pragadesh-45
16e27d2ca4 feat: make BrunoResponse callable to access body data using expressions fixes (#481) (#3710)
* feat: make `BrunoResponse` callable to access body data using expressions
2025-01-28 14:57:00 +05:30
Alex
956d5a38e9 fix: bump axios version to handle ivp6 (#3878)
Co-authored-by: alex.chua <alex.chua@bytedance.com>
2025-01-28 14:36:29 +05:30
Sanjai Kumar
bfc1101371 refactor: update GitHub Actions workflow to add permissions for checks and pull requests for the cli-tests job (#3844) 2025-01-28 14:13:14 +05:30
sanish chirayath
05be59f00c style: update StyledWrapper to use flex layout and adjust dialog positioning (#3888) 2025-01-27 18:49:05 +05:30
tlaloc911
fee631d496 passing defaults instead of axiosInstance to NTLMClient (#3841) 2025-01-18 21:34:19 +05:30
Bobby Bonestell
d03de2b622 fix: Inherited apikey auth mapping for bruno-cli (#3512)
* Added bruno-cli support for mapping inherited apikey auth from collection

Co-authored-by: Anoop M D <anoop.md1421@gmail.com>
2025-01-17 20:33:53 +05:30
sanish chirayath
31b2818821 fix: modal - provide default handleConfirm function and update dependencies in useEffect (#3830) 2025-01-17 14:52:06 +05:30
naman-bruno
8a71dfc022 enhancement: moved collection click area from name to div (#3813) 2025-01-17 13:20:53 +05:30
naman-bruno
3e6204e49b Fix: Horizontal Rules missing in markdown docs preview (#3814) 2025-01-17 13:10:16 +05:30
naman-bruno
dab4bb6a1c fix: hide env dropdown on configure (#3826) 2025-01-17 13:07:39 +05:30
Anoop M D
3c8cb702f5 feat: added icons to env modal buttons 2025-01-17 02:46:06 +05:30
Hadi
2df7fd6588 Added activate button to environment window. (#1531)
Co-authored-by: Anoop M D <anoop.md1421@gmail.com>
2025-01-17 02:12:33 +05:30
Sanjai Kumar
e5d7cd1be9 feat: add rspack dynamic import configuration to rsbuild (#3819) 2025-01-16 20:11:49 +05:30
pooja-bruno
2bce9b3716 add: document save button for folder and collection settings (#3742) 2025-01-16 20:09:51 +05:30
naman-bruno
5bfcc9b6e7 Fix: Path table is removed when we rearrange items (#3804) 2025-01-16 20:08:30 +05:30
naman-bruno
472b5452f7 Allow rearrangement of table items in params, body, vars, headers, etc… (#3801)
* Allow rearrangement of table items in params, body, vars, headers, and assert

* updated drag function name
2025-01-16 20:06:53 +05:30
pooja-bruno
5b04e0c189 fix: renaming first collection env (#3735) 2025-01-16 20:04:34 +05:30
pooja-bruno
3da12a05db fix: body formurl value disappearing (#3803) 2025-01-16 20:01:48 +05:30
naman-bruno
a73d2a02cf fix: Request vars displayed in red color in body even if they are valid (#3812)
* fix: Request vars displayed in red color in body
* chore: removing index import
---------

Co-authored-by: Anoop M D <anoop.md1421@gmail.com>
2025-01-16 19:59:14 +05:30
lohit
63d3cb380d Merge pull request #3806 from Pragadesh-45/fix/handle-assert-results
Chore/ Remove Unused `RemoveQuotes` function
2025-01-15 20:47:31 +05:30
Pragadesh-45
10a5935a12 Merge branch 'usebruno:main' into fix/handle-assert-results 2025-01-15 20:43:10 +05:30
Pragadesh-45
cf2cb0736e fix: remove commented-out removeQuotes() function 2025-01-15 20:42:02 +05:30
lohit
6abd063749 Merge pull request #3805 from Pragadesh-45/fix/handle-assert-results
Refactor: Improve expression handling across different runtimes (Fix: #3758)
2025-01-15 20:36:07 +05:30
Pragadesh-45
dbf1cad124 fix: remove removeQuotes() 2025-01-15 19:57:06 +05:30
lohit
00c5298b7d Merge pull request #3798 from Pragadesh-45/main
chore: version bump
2025-01-15 15:12:03 +05:30
Pragadesh-45
27ef28ae9b chore: version bump 2025-01-15 13:15:21 +05:30
Pragadesh-45
abb0a7b0db chore: version bump 2025-01-15 13:08:44 +05:30
Anoop M D
d2d7638a54 chore: updated package-lock 2025-01-13 18:49:45 +05:30
tlaloc911
5500070b49 ntlm auth (#3329)
Co-authored-by: Anoop M D <anoop.md1421@gmail.com>
2025-01-13 18:48:26 +05:30
Tim Nikischin
72b8c547b2 Order Variables alphabetically (#2982)
Order variables in Variables Tab alphabetically by name
2025-01-13 18:36:08 +05:30
lohit
15b870996d fix: cli - missing iconv-lite import, removed other unused imports (#3767) 2025-01-09 12:09:43 +05:30
lohit
3cb15fc001 fix: cli -- collection run -- clone request item at start (#3760) 2025-01-08 21:26:01 +05:30
Pragadesh-45
96d6bf1664 fix: remove redundant error logging in JSON parsing (#3759) 2025-01-08 21:24:15 +05:30
lohit
f5ff40abfa fix: file input element - missing path property (#3757) 2025-01-08 17:01:57 +05:30
ramki-bruno
c5de2343e9 Added Redux DevTools and React Developer Tools in dev build (#3750)
* Checkin `npm install --package-lock-only` changes

* Added `Redux DevTools` and `React Developer Tools` in dev build
2025-01-08 15:33:13 +05:30
lohit
39e8b66135 Merge pull request #3728 from ganesh-bruno/patch-1
Update package.json with keywords
2025-01-08 12:23:25 +05:30
lohit
9f9294d161 fix: indentation for package json 2025-01-08 12:22:23 +05:30
pooja-bruno
5f63cc4ab4 fix: collection/folder docs when importing postman collection (#3745)
* fix: collection/folder docs when importing postman collection

* fix
2025-01-07 14:27:13 +05:30
lohit
539d22125c Merge pull request #3725 from lohxt1/fix/collection-run-reset-item
fix: collection run - clone request at the start
2025-01-06 16:52:33 +05:30
lohit
36343b30b3 Merge pull request #3738 from Pragadesh-45/refactor/generate-code-item
fix: enhance keyboard navigation for language selection in `GenerateCodeItem`
2025-01-06 16:50:38 +05:30
Pragadesh-45
b5ae2b2b45 fix: enhance keyboard navigation for language selection in GenerateCodeItem 2025-01-06 16:33:17 +05:30
Pragadesh-45
704977f20f Merge remote-tracking branch 'origin/main' into refactor/generate-code-item 2025-01-06 11:40:38 +05:30
ganesh
c852257bda Update package.json with keywords 2025-01-03 07:17:36 -08:00
lohxt1
55eac64ca5 fix: collection run - clone request at the start 2025-01-03 17:31:28 +05:30
lohit
52672e67a2 Merge pull request #3697 from Pragadesh-45/feat/digest-auth-updates
Feat/digest auth updates
2025-01-02 18:24:54 +05:30
Pragadesh-45
d32f987bc6 Merge branch 'usebruno:main' into feat/digest-auth-updates 2025-01-02 18:06:36 +05:30
lohit
5fe9208089 Merge pull request #3641 from lohxt1/fix/cli-system-env-vars
feat: cli -- system level proxy fix
2025-01-02 18:05:39 +05:30
lohit
14ecc09cde Merge pull request #3719 from lohxt1/feat/bru-runner-fns
feat: bru util fns -- skipRequest, stopExecution, getTestResults, getAssertionResults, runRequest
2025-01-02 18:02:42 +05:30
lohit
949bf539b8 Merge pull request #3720 from pooja-bruno/fix/global-env-names-overflow
fix: global env names overflow
2025-01-02 18:01:58 +05:30
lohxt1
c4be6a88e4 fix: removed commented code 2025-01-02 17:56:36 +05:30
lohxt1
99302e3a1d fix: pr review updates 2025-01-02 17:54:29 +05:30
Pragadesh-45
1d3cbd2335 Merge branch 'usebruno:main' into feat/digest-auth-updates 2025-01-02 17:37:33 +05:30
Pooja Belaramani
218d6527df fix: global env names overflow 2025-01-02 16:45:03 +05:30
lohit
42ada4a364 Merge pull request #3708 from sanjaikumar-bruno/handle-invalid-auth-in-pm-export
fix: handle unsupported auth mode by returning 'noauth' type
2025-01-02 12:48:57 +05:30
Pragadesh-45
548f958a0f Refactor/ Implement Focusable Buttons in the Generate Code Modal (#3310)
* refactor: GenerateCodeItem component to fix width issue

* feat: tab switch for languages

* style: add logic to handle different screen sizes

* feat: enhance keyboard navigation for language selection in GenerateCodeItem
2025-01-02 11:17:56 +05:30
lohxt1
005eb273bf chore: fix tests 2025-01-01 20:03:01 +05:30
lohxt1
343e6dae47 chore: updated package lock 2025-01-01 19:56:32 +05:30
lohxt1
7b86febc87 feat: summarize test and assertion results for getTestResults and getAssertionResults fns 2025-01-01 18:06:13 +05:30
lohxt1
ca5fbea7b6 chore: removed console log 2025-01-01 17:52:01 +05:30
lohxt1
f34711c6e0 feat: bru.runRequest in collection run context 2025-01-01 17:50:57 +05:30
lohxt1
cd722a2bd9 feat: bru.runner.setNextRequest 2025-01-01 17:12:57 +05:30
lohxt1
75a9959d47 feat: add quick-js shims for bru runner fns 2025-01-01 15:37:42 +05:30
lohxt1
754a15dd58 feat: add runner functions hintwords for codemirror editor 2025-01-01 15:09:47 +05:30
lohxt1
2a6f6704c3 feat: update skipRequest and stopExecution logic 2025-01-01 15:01:26 +05:30
lohit
7d67239b11 Merge pull request #3664 from pooja-bruno/fix/environment-names-wrapping
fix: env names wrap
2024-12-31 18:10:10 +05:30
lohit
e0ab274452 Merge pull request #3682 from pooja-bruno/fix/asset-cursor-issue-while-editing
fix: asset value cursor issue while editing
2024-12-31 16:39:09 +05:30
lohit
776afbd28a Merge pull request #3674 from pooja-bruno/fix/assertion-clear-value
fix: assertion clear value
2024-12-31 16:38:35 +05:30
lohit
ca8f96fba0 Merge pull request #3712 from pooja-bruno/feature/open-setting-for-folder-and-collection
feat: open setting for folder and collection when
2024-12-31 16:38:13 +05:30
Pooja Belaramani
5c1ab647fc fix: collapse collection on clicking name 2024-12-31 13:01:41 +05:30
Pooja Belaramani
83e63e749e feat: open setting for folder and collection when 2024-12-31 12:25:03 +05:30
lohit
9d94ad9b73 Merge pull request #3711 from lohxt1/fix/aikido--library-version-upgrades
fix: aikido -- library version upgrades
2024-12-30 16:40:24 +05:30
lohit
395fb188fe Merge pull request #53 from lohxt1/fix/aikido-vul
chore: updates
2024-12-30 16:39:56 +05:30
lohxt1
f09fd19ca0 chore: updates 2024-12-30 16:38:41 +05:30
lohxt1
f578c188fb chore: updates 2024-12-30 16:32:46 +05:30
lohxt1
0d2b449b27 chore: aikido -- library version upgrades 2024-12-30 16:26:38 +05:30
lohit
e897dc1eb0 Merge pull request #3706 from Pragadesh-45/fix/response-format-updates
fix: improve JSON parsing logic for `bruno-cli`
2024-12-30 12:44:14 +05:30
lohit
85b6cae03d Merge pull request #3709 from usebruno/fix/cli-gh-workflow
fix: added input block to the cli workflow
2024-12-30 11:30:44 +05:30
lohit
d215cf740b fix: added input block to the cli workflow 2024-12-30 11:30:30 +05:30
Sanjai Kumar
4b277aa874 Merge branch 'usebruno:main' into handle-invalid-auth-in-pm-export 2024-12-30 11:07:23 +05:30
Sanjai Kumar
e9378d7895 fix: handle unsupported auth mode by returning 'noauth' type 2024-12-30 11:04:41 +05:30
lohit
78aa0d07ae Merge pull request #3707 from lohxt1/fix/multipart-tests
fix: multipart tests
2024-12-30 10:49:35 +05:30
lohit
e4574e3a56 Merge pull request #3701 from lohxt1/fix/cli-multipart
fix: cli multipart
2024-12-30 10:48:54 +05:30
lohxt1
795cd196f2 fix: multipart tests 2024-12-30 10:46:12 +05:30
Pragadesh-45
7b935bd206 fix: improve JSON parsing logic 2024-12-30 10:05:23 +05:30
lohxt1
43e892f9b0 fix: cli multipart 2024-12-27 16:50:12 +05:30
lohit
1f2bee1f90 Merge pull request #3676 from pooja-bruno/fix/string-json-response
fix: string json response error
2024-12-27 16:30:32 +05:30
Pooja Belaramani
767db75730 update: comment 2024-12-27 16:10:57 +05:30
Pooja Belaramani
b6b4b7362f fix: condition 2024-12-27 15:51:06 +05:30
Pooja Belaramani
54d8fbc478 rm: json stringfy from json string data res 2024-12-27 11:16:26 +05:30
Pooja Belaramani
9a2d8bfff3 adding quotes in text response 2024-12-27 11:12:46 +05:30
Pragadesh-45
907f6a19ad revert: digest auth testbench 2024-12-26 10:40:51 +05:30
Pragadesh-45
b612da4f3c fix: updates 2024-12-26 08:17:43 +05:30
Pragadesh-45
625140d1f4 fix: enhance digest authentication 2024-12-26 08:10:40 +05:30
Pragadesh-45
284519cd43 fix: improve digest authorization header opaque 2024-12-26 07:51:55 +05:30
Pragadesh-45
26daee5d98 fix: improve parsing of authentication details in digest interceptor 2024-12-24 15:37:59 +05:30
Pooja Belaramani
87988b6879 fix: tooltip for env name and rm trash overflow changes 2024-12-24 12:57:41 +05:30
pooja-bruno
f8711a91d9 fix: plain text curl data (#3677) 2024-12-23 17:29:06 +05:30
Pooja Belaramani
582e8e5eac fix: condition 2024-12-23 13:36:58 +05:30
Pooja Belaramani
236bc48d98 fix: null data response 2024-12-23 12:11:46 +05:30
Pooja Belaramani
a63afd6c0b fix: asset value cursor issue while editing 2024-12-19 16:04:52 +05:30
Pragadesh-45
fec99f0780 Merge branch 'usebruno:main' into main 2024-12-19 11:05:27 +05:30
Pooja Belaramani
bf142af6d9 fix: env name truncate 2024-12-19 11:00:51 +05:30
Pragadesh-45
57a85e535c fix: add lodash import for utility functions 2024-12-18 19:03:19 +05:30
lohxt1
f72d643e02 feat: updates 2024-12-18 18:57:23 +05:30
Pooja Belaramani
aea25842ce fix: string json response error 2024-12-18 15:01:06 +05:30
Pooja Belaramani
0831b610cf fix: assertion clear value 2024-12-17 21:19:34 +05:30
Anoop M D
f871bc0fa2 feat: setup script 2024-12-17 13:46:48 +05:30
lohit
db90d31b3f Merge pull request #3670 from lohxt1/fix/validations
fix: validations
2024-12-17 11:14:42 +05:30
lohxt1
e44dcad01a fix: updates 2024-12-16 22:13:26 +05:30
lohxt1
7a8d1624d1 fix: updates 2024-12-16 22:09:10 +05:30
lohxt1
0ad0af041b fix: validations updates 2024-12-16 18:46:16 +05:30
Pooja Belaramani
ad59e3f8d1 fix: env names wrap and trash icon overflow 2024-12-16 18:10:33 +05:30
lohit
b9ec0acab4 Merge pull request #3662 from lohxt1/revert/rename-item-watcher-fix
revert: rename-item watcher fix -- tbd
2024-12-16 14:53:12 +05:30
lohit
0d126abfbd Merge branch 'main' into revert/rename-item-watcher-fix 2024-12-16 14:52:52 +05:30
lohxt1
a5096ce413 revert: rename-item watcher fix -- tbd 2024-12-16 14:51:02 +05:30
lohit
3bf98aab3b Merge pull request #3661 from Pragadesh-45/main
fix: update condition for renaming items in Windows OS
2024-12-16 12:12:24 +05:30
Pragadesh-45
9b83cd7b84 fix: update condition for renaming items in Windows OS 2024-12-16 12:01:42 +05:30
lohit
21f9e80706 Merge pull request #3660 from lohxt1/fix/add-tests-scripts-to-request
fix: add tests to request object
2024-12-16 10:14:24 +05:30
lohxt1
e8bc32b39b fix: add tests to request object 2024-12-16 10:12:25 +05:30
lohit
380047e025 Merge pull request #1043 from nelup20/bugfix/521-error_accessing_response_property_with_context_as_key
fix(#521): Allow "context" as the name of a key/var in a JS expression
2024-12-15 20:01:33 +05:30
lohit
434ae6c70f _BrunoNewFunctionInnerContext to __bruno__functionInnerContext 2024-12-15 20:00:57 +05:30
lohit
22612a7dbe _BrunoNewFunctionInnerContext to __bruno__functionInnerContext 2024-12-15 20:00:13 +05:30
lohit
06c0b7c78a Merge pull request #3659 from lohxt1/followup-pr/close-tab-after-rename-folders-only
fix: followup pr - only close folder tab on rename pr-3607
2024-12-15 19:56:32 +05:30
lohxt1
c154dec2b5 fix: followup pr - only close folder tab on rename 2024-12-15 19:55:15 +05:30
lohit
3abe611752 Merge pull request #3658 from lohxt1/followup-pr/multipart-content-type
refactor: multipart content-type pr review fixes
2024-12-15 19:15:00 +05:30
lohxt1
f3cfacdd43 fix: updates 2024-12-15 19:11:19 +05:30
lohit
af4b2105be Merge pull request #3657 from lohxt1/followup-pr/multipart-content-type
refactor: multipart content-type pr-2121
2024-12-15 18:25:01 +05:30
lohxt1
7ae64605c2 chore: updates 2024-12-15 18:19:55 +05:30
lohit
83bbbe3fb3 Merge pull request #2121 from end3rbyte/feature/1602-multipart-content-type
feature: Multi-part requests: user should be able to set content-type for each part in a multi-part request. #1602
2024-12-15 18:08:44 +05:30
lohit
73ea5f155d Merge branch 'main' into feature/1602-multipart-content-type 2024-12-15 18:08:05 +05:30
lohit
366bd99e92 Merge pull request #3642 from lohxt1/fix/remove-jsonbigint-from-cli
fix: cli -- json response parsing
2024-12-15 18:00:45 +05:30
lohit
6b6fc9a3dc Merge branch 'main' into fix/remove-jsonbigint-from-cli 2024-12-15 18:00:38 +05:30
lohit
6323b54c38 Merge pull request #3656 from sanjaikumar-bruno/move-createFormData-function
refactor createFormData function
2024-12-15 17:57:39 +05:30
Sanjai Kumar
57e6af703c refactor createFormData to handle data as an array of objects and improve file handling 2024-12-15 17:55:52 +05:30
lohit
09120a96e8 Merge pull request #3586 from sanjaikumar-bruno/fix/multipart-file-with-same-key-name
fix: refactor createFormData function
2024-12-15 17:38:49 +05:30
lohit
f1e6d5eefe add createFormData import from utils 2024-12-15 17:38:22 +05:30
lohit
ba41f17439 Merge branch 'main' into fix/multipart-file-with-same-key-name 2024-12-15 17:34:39 +05:30
lohit
d37e9aaafa Merge pull request #3522 from sanjai0py/feat/add-isNotEmpty-assertion
feat: add 'isNotEmpty' assertion operator
2024-12-15 17:28:23 +05:30
lohit
5a9bda2a0f use to.not.be.empty 2024-12-15 17:27:47 +05:30
Sanjai Kumar
eaa4f4e57b Fix/global env duplicate name error (#3590)
* fix: enhance environment name validation for global environments

* fix: improve environment name validation logic in CreateEnvironment component

* Update index.js

---------

Co-authored-by: Anoop M D <anoop.md1421@gmail.com>
2024-12-15 16:47:08 +05:30
_Pragadesh M
8992a457a8 Feat/displaying variable hints as secrets for Global Environment Secrets (#3591)
* feat: added new utility function `getEnvironmentVariablesMasked`

* refactor: Update `getAllVariables` function in `collections/index.js`

* refactor: Update `brunoVarInfo.js` to handle masked environment variables

* code cleanup

* feat: Add masked global environment variables functionality

* refactor: Rename variables for clarity in RequestTabPanel component

* feat: updates

* Update index.js

---------

Co-authored-by: Pragadesh-45 <temporaryg7904@gmail.com>
2024-12-15 16:45:54 +05:30
Pragadesh-45
b181aba646 feat: enhance collection item deletion and renaming functionality (#3607) 2024-12-15 16:44:32 +05:30
Pragadesh-45
47179535d5 fix: update content-type header for XML requests to application/xml (#3648) 2024-12-15 16:40:12 +05:30
Pragadesh-45
316b632338 refactor: add sanitization for collection names and improve directory name handling (#3559) 2024-12-15 16:38:56 +05:30
Filip Gaľa
dc469afeea feat: folder documentation (#3206)
* add docs, save not working yet

* working folder docs

* revert unrelated changes

* prettier fix

* allow save folder with command

* include folder docs in `bruno-collection` json export

* docs

---------

Co-authored-by: Filip Gala <filip.gala@student.tuke.sk>
Co-authored-by: lohit <lohxt.space@gmail.com>
2024-12-15 16:33:30 +05:30
lohit
ee715a6dc6 chore: headers/vars/script merge fns refactor (#3654)
* chore: cli code refactoring
* chore: code refactoring
2024-12-15 15:40:49 +05:30
lohit
19ad0ecef7 fix: rsbuild related error fixes (#3655) 2024-12-15 15:30:58 +05:30
lohit
993424a2b8 fix: bruno-app tests (#3653) 2024-12-15 15:30:09 +05:30
Pragadesh-45
086c4c063e fix: update pathname validation to use basename for directory checks #2193 (#3550)
* fix: implement custom pathname validation #2193

* fix: update pathname validation to use basename for directory checks

* fix: improve error message for invalid pathname in collection.js
2024-12-15 15:08:36 +05:30
Sanjai Kumar
a6ac98b709 feat: add support for importing collection-level variables from PM collections (#3481)
* feat: add support for importing collection-level variables from Postman collections

* fix: add optional chaining for collection variables in Postman importer

* Update postman-collection.js

---------

Co-authored-by: Anoop M D <anoop.md1421@gmail.com>
2024-12-15 14:53:53 +05:30
Anoop M D
22ecd0284f chore: updated package-lock 2024-12-14 20:29:22 +05:30
lohit
33e86a9097 feat: replace nextjs with rsbuild (#3617)
* poc: bruno app rsbuild
* fix: updates

---------

Co-authored-by: Anoop M D <anoop.md1421@gmail.com>
2024-12-14 19:57:04 +05:30
Anoop M D
3efcdf254e fix(#3627): fix rename issues on windows os 2024-12-14 19:42:39 +05:30
lohit
ea1f385d1c fix: rename folder case insensitive (#3635)
* fix: rename folder case insensitive

* fix: add hasSubFolders utility and update folder moving logic for Windows OS

* fix: validations

* fix: updates

* fix: updates

---------

Co-authored-by: Pragadesh-45 <temporaryg7904@gmail.com>
2024-12-14 18:55:28 +05:30
lohit
4dcaaab52c Merge branch 'main' into fix/remove-jsonbigint-from-cli 2024-12-12 17:31:59 +05:30
lohxt1
6326dc3d9c feat: updates 2024-12-12 17:28:15 +05:30
lohxt1
a55ed9bd50 feat: cli -- system level proxy fix 2024-12-12 14:09:06 +05:30
lohit
57d86eb118 Merge pull request #3624 from lohxt1/fix/cli-brutojson
fix: cli -- brutojson fn -- req script should be obj by default
2024-12-10 13:26:45 +05:30
lohxt1
85c6b2d97f fix: cli -- brutojson fn -- script obj 2024-12-10 12:57:03 +05:30
lohit
0c574aeb1e Merge pull request #3605 from lohxt1/fix/cli-updates
fix: cli - include collection level script, updated testbench
2024-12-09 18:52:23 +05:30
lohxt1
3fe0d43bdc fix: cli - collection level script, added tests 2024-12-06 22:58:02 +05:30
Anoop M D
67ead9739e chore: temporarily reverting npm cli test runs on windows 2024-12-06 19:33:53 +05:30
Anoop M D
36021b5b38 feat: run npm cli tests on macos and windows 2024-12-06 19:23:56 +05:30
lohit
1e45725ba1 Merge pull request #3601 from lohxt1/fix/cli--env
fix: cli -- envs path resolution
2024-12-06 17:51:57 +05:30
lohxt1
d4616c78c8 fix: cli envs path resolution 2024-12-06 17:47:27 +05:30
lohit
5e5656d268 Merge pull request #3598 from Pragadesh-45/feat/folder-recursive-rename-win32
bugfix/folder recursive rename win32 (fixes: #3597) updates: #3236
2024-12-05 23:08:21 +05:30
Pragadesh-45
52e01935f5 Merge remote-tracking branch 'origin/main' into feat/folder-recursive-rename-win32 2024-12-05 17:33:21 +05:30
Pragadesh-45
99f912312d fix: add renameSync 2024-12-05 17:27:24 +05:30
lohit
915ebf3387 Merge pull request #3186 from lohxt1/feat/cli-collection-vars
feat: adds collection/folder/request vars and scripts support to cli
2024-12-05 16:01:06 +05:30
lohxt1
bb18c532da chore: updated lock file 2024-12-05 15:47:41 +05:30
lohxt1
4b4bd3bc95 fix: updates 2024-12-05 15:45:36 +05:30
lohxt1
482cb05d63 fix: updates 2024-12-05 11:42:23 +05:30
lohit
32153c4dbf Merge pull request #3592 from lohxt1/main
chore: version bump
2024-12-04 20:58:12 +05:30
lohxt1
7535b3d4ba chore: version bump 2024-12-04 20:55:31 +05:30
lohxt1
4dd4800ee9 fix: tests 2024-12-04 18:44:20 +05:30
lohxt1
e1ebaabcc7 Merge branch 'main' of lohxt1:lohxt1/bruno into feat/cli-collection-vars 2024-12-04 17:28:55 +05:30
Sanjai Kumar
f110d898f5 fix: refactor createFormData function 2024-12-03 18:01:22 +05:30
Pragadesh-45
5b6172e5ac feat: enhance keyboard navigation for language selection in GenerateCodeItem 2024-12-03 17:59:48 +05:30
lohit
fd22ff8962 Merge pull request #3578 from lohxt1/fix/validate-env-name-validations
fix: validate env name fn null checks
2024-12-02 14:14:53 +05:30
lohit
5f5cc5eb22 fix: validate env name fn null checks 2024-12-02 14:14:10 +05:30
Anoop M D
eb6944a1c9 fix(#163) - removed max limit on request names 2024-12-01 13:52:59 +05:30
Sanjai Kumar
b4ea101350 Fix/xml body not getting added during curl import. (#3547)
* Add support for XML data handling in curl-to-json utility

* Refactor XML content type handling in curl utility
2024-11-30 19:23:39 +05:30
Marc Pfister
0a8217e4ab add "docs" to copy for export (#3551) 2024-11-30 19:19:05 +05:30
Sanjai Kumar
514da55923 Fix/improve env modal error when duplicate names (#3557)
* Enhance environment creation validation and improve error handling

Co-authored-by: Anoop M D <anoop.md1421@gmail.com>
2024-11-30 19:16:09 +05:30
lohit
bd2cf554b6 fix: response pane width shift styling for timeline tab (#3573)
* fix: posthog api key as a process env var
* fix: response pane timeline tab inconsistent width
2024-11-30 18:55:10 +05:30
Pragadesh-45
2f752085f3 fix: humanize-date fixes: #3556 (#3565)
* fix: humanize-date
* fix: improve notification handling and enhance date validation
2024-11-30 18:51:44 +05:30
Pragadesh-45
f2cfcab091 feat: Graceful handle rename/move: Fix EPERM Error When Renaming Parent Folders on Windows (#3236)
* refactor filesystem.js to use isWindowsOS()

* add tempDir logic to gracefully rename the parent folder in a collection. fix: `EPERM`

---------

Co-authored-by: Anoop M D <anoop.md1421@gmail.com>
2024-11-29 12:18:11 +05:30
Anoop M D
4283bb4bb0 Merge branch 'main' into feat/folder-recursive-rename-win32 2024-11-29 12:16:27 +05:30
Pragadesh-45
707cddea90 Fix/invalid file name handling (#3274)
* feat: implement utility function `isValidFilename`
* refactor: added filename validator checks for `rename-item` and `new-request`
* chore: added `fileName.startsWith('.')`
2024-11-29 12:04:59 +05:30
Ryan
39a44e9b4f Update readme.md (#3520) 2024-11-22 17:37:07 +05:30
lohit
fb8c54dd7a Merge pull request #3467 from Pragadesh-45/feat/cli-improvements
feat: add option to omit headers and skip specific headers in CLI run command output
2024-11-21 20:56:16 +05:30
lohit
7400d890e4 Merge branch 'main' into feat/cli-improvements 2024-11-21 20:56:05 +05:30
lohit
3a29e2e333 Merge pull request #3504 from Pragadesh-45/feat/cli-improvements-ssl-related
feat: add --client-cert-config option for secure connections in CLI run command
2024-11-21 20:53:36 +05:30
lohit
1fb4298681 Merge pull request #2820 from matthewdickinson/feature/cli-cookies
Added cookie support to CLI requests
2024-11-21 17:56:29 +05:30
lohit
6d8cc38946 changed use-cookies to disable-cookies 2024-11-21 17:53:09 +05:30
lohit
9d4246d74b changed use-cookies to disable-cookies
support for sending cookies by default
2024-11-21 17:51:18 +05:30
lohit
1238bf7270 Merge pull request #3523 from lohxt1/fix/tests-editior-style-fix
fix: codemirror editors background styling fix
2024-11-21 17:15:50 +05:30
Pragadesh-45
e9d459fa5e feat: create cert cert config cli command 2024-11-21 17:13:52 +05:30
lohxt1
1c4acf7301 fix: codemirror editor background styling fix 2024-11-21 16:50:11 +05:30
lohxt1
6385d00807 fix: codemirror editor background styling fix 2024-11-21 16:49:20 +05:30
Pragadesh-45
157389424d feat: rename CLI option for omitting headers to clarify functionality 2024-11-21 16:28:28 +05:30
Pragadesh-45
1b30229903 Feat/displaying variable hints as secrets (#3268)
* feat: added new utility function `getEnvironmentVariablesMasked`
2024-11-21 15:48:32 +05:30
Pragadesh-45
72bd1b4cbf feat: rename CLI options for omitting and skipping headers to clarify reporter context 2024-11-21 15:36:15 +05:30
Sanjai Kumar
4a4481a26f feat: add 'isNotEmpty' assertion operator 2024-11-21 12:00:25 +05:30
lohit
0bec17facd Merge pull request #3518 from lohxt1/main
chore: update package lock file
2024-11-20 19:57:44 +05:30
lohxt1
1c86b5f340 chore: update package lock file 2024-11-20 19:56:44 +05:30
lohit
917205299a Merge pull request #3517 from lohxt1/fix/video-preview-comp--memo-import
fix: video preview comp memo import
2024-11-20 19:21:41 +05:30
lohxt1
916f28633e fix: video preview comp memo import 2024-11-20 19:20:43 +05:30
lohit
6c2451b6f2 Merge pull request #3516 from lohxt1/fix/server_rendered-logic
fix: server_rendered codemirror logic for newer versions of nextjs
2024-11-20 19:05:20 +05:30
lohxt1
24563bdaaf fix: server_rendered codemirror logic for newer versions of nextjs 2024-11-20 19:03:36 +05:30
lohit
28d30b1ef7 Merge pull request #3515 from lohxt1/feat/delete-env-var--safe-mode-shim
feat: deleteEnvVar safe mode shim
2024-11-20 18:29:54 +05:30
lohxt1
6442e3ceca feat: deleteEnvVar safe mode shim 2024-11-20 18:29:19 +05:30
arshan1019
56c3bf0899 Fix: (#3383) openapi yaml req body not importing (#3459) 2024-11-20 18:16:53 +05:30
Sanjai Kumar
11a3ea9fbb remove error logging for missing global environment (#3447) 2024-11-20 18:16:08 +05:30
Sanjai Kumar
84095a4183 fix/ Script execution is prevented by line comments (#3462)
* refactor: simplify mode settings and update comment toggle functionality
---------

Co-authored-by: Anoop M D <anoop.md1421@gmail.com>
2024-11-20 18:14:37 +05:30
Pragadesh-45
d92dd46d4e fix: added missing translation (#3352)
Co-authored-by: Anoop M D <anoop.md1421@gmail.com>
2024-11-20 18:08:39 +05:30
Pragadesh-45
a752921413 feat: add validation to prevent duplicate global environment names (#3450) 2024-11-20 18:07:37 +05:30
Pragadesh-45
44debfd9b9 fix: improve masking logic in MaskedEditor for large content handling (fixes #2842) (#3472)
* fix: improve masking logic in MaskedEditor for large content handling

* fix: remove comment in MaskedEditor masking logic
2024-11-20 18:06:07 +05:30
Pragadesh-45
278ca8bf29 fix: enhance path normalization for WSL compatibility in watcher (#3482) 2024-11-20 18:02:06 +05:30
Pragadesh-45
23c22a96bc Feat/import translation for deprecated pm import (#3388)
* feat: add translation for pm `tests[]`
* feat: add bru.deleteEnvVar function and update translations

---------

Co-authored-by: Pragadesh-45 <temporary7904@gmail.com>
2024-11-20 17:58:59 +05:30
Sanjai Kumar
77d3fa7e1e bugfix / Update video preview functionality (#3433)
* Add video preview functionality and update dependencies
* Refactor video preview component to use Buffer for base64 decoding and update muted prop syntax

---------

Co-authored-by: Anoop M D <anoop.md1421@gmail.com>
2024-11-20 17:34:00 +05:30
Sanjai Kumar
412a0ed078 Now based on the request type appropriate views are shown. (#3340)
* Now based on the request type appropriate views are shown.

Co-authored-by: Anoop M D <anoop.md1421@gmail.com>
2024-11-20 17:22:04 +05:30
lohit
1cb0d4e191 chore: node version bump -- v22.11.0 (#3508)
node version bump with updates to cipher logic
2024-11-20 17:09:02 +05:30
lohit
aff7c405cd fix: import openapi -- baseUrl env value should not include trailing slash (#3440)
* fix: openapi baseUrl env value should remove trailing slash

* feat: updates
2024-11-20 03:38:59 +05:30
lohit
59108472a2 fix: codemirror styling updates (#3439) 2024-11-20 03:35:55 +05:30
lohit
c4492b5d94 fix: exclude Meta, Alt, Home and End key press for autocomplete trigger (#3441) 2024-11-20 03:31:44 +05:30
lohit
7fd7eafdcb fix: incorrect call of dispatch fn (#3452) 2024-11-20 03:30:50 +05:30
Pragadesh-45
41040bc296 fix: update image URL and adjust tests for age variable in bruno.bru files (#3483)
Co-authored-by: Anoop M D <anoop.md1421@gmail.com>
2024-11-20 03:29:27 +05:30
lohit
ad5b625655 fix: checkov CKV_GHA_7 warning (#3489)
* fix: posthog api key as a process env var

* fix: checkov bru cli workflow warning

---------

Co-authored-by: Anoop M D <anoop.md1421@gmail.com>
2024-11-20 03:26:22 +05:30
lohit
cd629451e4 fix: checkov CKV2_GHA_1 warning (#3488)
* fix: posthog api key as a process env var

* fix: checkov tests workflow warning

* revert: updates
2024-11-20 03:25:32 +05:30
lohit
dc77ee7c04 feat: moved posthog key to process env (#3490) 2024-11-20 03:24:29 +05:30
lohit
c322baa9c8 fix: server_rendered logic for newer versions of nextjs (#3509)
* fix: server_rendered condition update
2024-11-20 03:22:39 +05:30
lohxt1
b206b70d2e feat: fix tests 2024-11-19 12:36:20 +05:30
Pragadesh-45
9a325caeee feat: add ssl-cert-list option for secure connections in CLI run command 2024-11-19 10:22:55 +05:30
lohxt1
d0ef70473d fix: remove json bigint from cli 2024-11-18 13:39:55 +05:30
Anoop M D
4894ac2754 fix: fixed failing test 2024-11-15 19:26:30 +05:30
lohxt1
df206dc4d9 fix: posthog api key as a process env var 2024-11-15 10:38:16 +05:30
Pragadesh-45
45cc97ee20 feat: add option to skip specific headers in CLI run command output 2024-11-13 14:51:48 +05:30
Pragadesh-45
642413e35c Merge remote-tracking branch 'origin/main' into feat/cli-improvements 2024-11-13 11:37:29 +05:30
Pragadesh-45
abb6490232 feat: add option to omit headers in CLI run command output 2024-11-12 13:27:58 +05:30
ganesh
40001949b8 Add a proper example for using the usebruno query library in the README file. (#3464) 2024-11-12 07:06:11 +05:30
lohit
bdfe9c16f1 fix: cli run-summary count fix for requests with ECONNREFUSED error (#3451)
* fix: cli run summary for requests with ECONNREFUSED error
* feat: updates
2024-11-08 16:57:37 +05:30
Anoop M D
d007feb3d1 release: v1.34.2 2024-11-05 19:28:24 +05:30
lohit
f827b85f47 Merge pull request #3414 from Pragadesh-45/refactor/collection-folder-settings-check
Refactor script checking in CollectionSettings and FolderSettings
2024-11-04 22:07:42 +05:30
Pragadesh-45
e025ed8436 refactor script checking in CollectionSettings and FolderSettings 2024-11-04 14:57:03 +05:30
Anoop M D
be4fc2d9ad release: v1.34.1 2024-10-30 21:03:52 +05:30
lohit
5fa7a75284 Merge pull request #3397 from lohxt1/fix/graphql-editor-search-box
fix: graphql editor search box styling
2024-10-30 19:37:01 +05:30
lohxt1
7ddb8c3f4d fix: graphql editor search box styling 2024-10-30 19:34:08 +05:30
lohit
fa22c728ef Merge pull request #3396 from lohxt1/fix/codeeditor-search-box-text-alignment
fix: codeeditor search box desc alignment fix
2024-10-30 18:52:00 +05:30
lohxt1
ca2ee673f3 fix: codeeditor search box desc alignment fix 2024-10-30 18:50:40 +05:30
lohit
9e07c698d8 Merge pull request #3394 from lohxt1/fix/codeeditor-search-box
fix: codemirror styling css vars
2024-10-30 18:16:33 +05:30
lohxt1
c4148b9e40 fix: codemirror styling css vars 2024-10-30 18:15:12 +05:30
lohit
a580f88f63 Merge pull request #3392 from lohxt1/fix/oauth2-global-env-values
fix: include global env varaibles for oauth2
2024-10-30 18:02:54 +05:30
lohit
fe2b45f9ea Merge pull request #3393 from lohxt1/fix/codeeditor-search-box
fix: code editor styling fixes -- search box, folding marker
2024-10-30 18:02:39 +05:30
lohxt1
381103663f fix: codemirror editor folding marker styling 2024-10-30 17:00:36 +05:30
lohxt1
425c90b6eb fix: code editor search box styling 2024-10-30 16:54:55 +05:30
lohxt1
6bebbfe9f3 fix: include global env varaibles for oauth2 2024-10-30 16:35:52 +05:30
Pragadesh-45
22bc1d4ac5 Feat/content indication for collections and folders (#3359)
feat: content indication for collections and folders
2024-10-30 16:19:14 +05:30
lohit
e8530a1022 Merge pull request #3375 from lohxt1/chore/upgrade-electron-builder-lib
chore: upgrade electron-build version
2024-10-28 17:25:33 +05:30
lohxt1
f8f00f1daa chore: upgrade electron-build version 2024-10-28 15:53:11 +05:30
Sai K K
9aa84a259c fix: can't create collection on empty directory (#3256) 2024-10-28 02:28:11 +05:30
lohit
4ea141fd73 feat: library upgrades (#3361) 2024-10-25 19:40:54 +05:30
Anoop M D
2f9d54151e chore: updated node version as v20 in contributing readme 2024-10-25 18:21:59 +05:30
Anoop M D
796fa0c27c release: v1.34.0 2024-10-24 20:50:26 +05:30
lohit
a7f05db1d6 Merge pull request #3348 from lohxt1/fix/electron-build-package-lock
chore: update lock file
2024-10-24 15:34:20 +05:30
lohxt1
0c7d513d9e chore: update lock file 2024-10-24 15:33:34 +05:30
lohit
d92e806899 fix: selected global env switch (#3344) 2024-10-24 15:00:14 +05:30
lohit
d70d4a482b feat:add res() function shim to safe-mode (#3345) 2024-10-24 14:59:54 +05:30
lohit
c82203a059 Merge pull request #3347 from lohxt1/fix/revert-electron-builder-version
fix: revert electron-builder version
2024-10-24 14:57:13 +05:30
lohxt1
66bb32a683 fix: revert electron-builder version 2024-10-24 14:56:37 +05:30
Giuseppe
6588dcf2fd Fixes Issue #3233: set httpsAgentRequestFields on request.httpsAgent when shouldProxy or shouldUseSystemProxy was false (#3317)
* fix: set httpsAgentRequestFields on request.httpsAgent when shouldProxy is false
* fix: set httpsAgentRequestFields on request.httpsAgent when shouldUseSystemProxy is false
2024-10-23 21:00:27 +05:30
Spencer
432d54acca fix: Add missing postman translation functions (#3324)
Co-authored-by: Spencerhutch <spencer.hutchinson@trustflight.com>
2024-10-23 17:46:53 +05:30
Pragadesh-45
0af5f72374 Feat/import folder and collection level scripts from postman (#3334)
* feat: import folder and collection level scripts

* refactor: importScriptsFromEvents function and remove duplicate code

* refactor: Improve importScriptsFromEvents function and handle different types of event.script.exec

* refactor: add info about translation log near its definition
2024-10-23 17:44:32 +05:30
lohit
f43775e245 chore: removed unused libraries (#3330)
* chore: posthog-node lib version upgrade

* chore: removed github button

* chore: removed lossless-json and json-bignt lib

* chore: updated package lock

* chore: removed unused libraries
2024-10-21 18:31:42 +05:30
Matthew Dickinson
b82a2c3312 Added cookie support to CLI requests 2024-10-18 17:48:35 -04:00
lohit
ac67c4c0d8 Merge pull request #3322 from lohxt1/fix/next-js-app-build-output-command
fix: bruno-app build command update
2024-10-17 18:36:43 +05:30
lohxt1
e947a8335a fix: next js build output command update 2024-10-17 18:22:36 +05:30
lohit
cc8f3de8be feat: upgrade libraries for dependabot alerts (#3300)
* feat: upgrade libraries and code cleanup
2024-10-17 11:04:47 +05:30
Pragadesh-45
ca6c2ebb03 style: add logic to handle different screen sizes 2024-10-16 22:05:38 +05:30
lohit
bb14ec22f7 fix: add global env vars to the active collection properly (#3312) 2024-10-16 12:32:47 +05:30
lohit
dddc79c709 fix: global env ui fixes (#3305) 2024-10-16 12:30:04 +05:30
Pragadesh-45
b900d3070d feat: tab switch for languages 2024-10-15 14:16:51 +05:30
Pragadesh-45
a0fcb6c91f refactor: GenerateCodeItem component to fix width issue 2024-10-15 14:15:06 +05:30
Anoop M D
a4ad4f6073 release: v1.33.1 2024-10-15 13:50:02 +05:30
Sanjai Kumar
a2d9249515 Refactor environment variable styling and error handling (#3291) 2024-10-14 18:23:32 +05:30
anusreesubash
a880e030eb using yaml CORE_SCHEMA instead of DEFAULT_SCHEMA (#3303)
Co-authored-by: Anusree Subash <anusree@usebruno.com>
2024-10-14 18:20:18 +05:30
lohit
3ef7df57e2 fix(#3287): res.setbody safe mode (#3299) 2024-10-14 12:27:12 +05:30
anusreesubash
40fad99803 Create default environments on openapi import using server url (#3267)
* added option to create environments using server urls

* Update openapi-collection.js

---------

Co-authored-by: Anusree Subash <anusree@usebruno.com>
Co-authored-by: Anoop M D <anoop.md1421@gmail.com>
2024-10-14 12:18:26 +05:30
Pragadesh-45
43cb2b82f3 Style: Update Toolhint Z-Index and Add Toolhint for GlobalEnvironmentSelector (#3284)
* style: add z-index for `ToolHint`

* chore: add toohint for global env selector
2024-10-14 12:06:06 +05:30
Jake Owen
2fc79e0e7f fix: failing to import insomnia collection when username/password in auth is null (#3293)
* fix: sanitize authentication input
 edgecase where value is null instead of expected empty string

* fix: refactor to be immutable

* Revert "fix: refactor to be immutable"

This reverts commit eec0e51d98.
2024-10-13 17:55:13 +05:30
Anoop M D
dce96e0f13 release: v1.33.0 2024-10-09 23:37:37 +05:30
lohit
c0dc329861 Merge pull request #3271 from lohxt1/main
fix: copy global env
2024-10-08 18:33:16 +05:30
lohxt1
d4814569ed fix: global env copy 2024-10-08 18:31:39 +05:30
lohit
ec5c593de4 Merge pull request #3269 from lohxt1/main
fix: global env generate code updates
2024-10-08 16:49:53 +05:30
lohxt1
0fa0b3ef85 fix: generate code updates 2024-10-08 16:46:26 +05:30
lohit
4211575f01 Merge pull request #3222 from lohxt1/feat/global-environments
feat: global env
2024-10-08 10:28:30 +05:30
lohit
90834b8c7d Merge branch 'main' into feat/global-environments 2024-10-08 10:26:13 +05:30
lohxt1
7a77afc64a feat: updates 2024-10-08 10:20:54 +05:30
lohxt1
8ab8af6b3f feat: updates 2024-10-07 22:32:53 +05:30
Anoop M D
4e8e2e87dc release: v1.32.1 2024-10-04 19:50:45 +05:30
lohit
ce8ebb0c1a fix: no env select issue (#3247) 2024-10-04 16:55:49 +05:30
Pragadesh-45
5c5e3d18fc add logic to check for key existence in post response (#3249) 2024-10-04 16:53:35 +05:30
Sanjai Kumar
7a5b309664 refactor: Update color variable in Keybindings component (#3251) 2024-10-03 23:24:08 +05:30
dwolter-emarsys
93f8d916c4 INTERNAL | correcting WSSE logic (#3252) 2024-10-03 23:23:40 +05:30
lohxt1
5afafb5944 feat: updates 2024-10-03 11:52:00 +05:30
lohit
6bc8acd1e1 feat: bru fns update (#3231) 2024-10-01 23:45:05 +05:30
Anoop M D
96e58f2f40 release: v1.32.0 2024-10-01 20:35:26 +05:30
lohit
4797119657 fix: interpolate form-urlencoded and multipart formdata values individually (#3237)
* fix: interpolate form-urlencoded and multipart values individually

* feat: cli updates
2024-10-01 18:24:03 +05:30
Pragadesh-45
1fe7af4fad add tempDir logic to gracefully rename the parent folder in a collection. fix: EPERM 2024-10-01 15:00:55 +05:30
Pragadesh-45
de2053f988 refactor filesystem.js to use isWindowsOS() 2024-10-01 14:57:19 +05:30
Sanjai Kumar
95e56cd9c9 Added Keybindings tab. (#3204)
* Added Keybindings tab.

* Minor Refactoring
2024-09-30 17:20:46 +05:30
Pragadesh-45
02a82c5371 refactor: ReorderTable component to use useMemo for rowsOrder (#3227) 2024-09-30 17:19:18 +05:30
lohit
e2baed6724 fix: interpolate json body for type object -- graphql variables (#3212) 2024-09-30 17:14:58 +05:30
lohit
d448599a53 feat: ui-state-snapshot (#3215)
* wip: save env

* feat: updates

* feat: updates
2024-09-30 16:51:49 +05:30
lohit
f35b715c6f feat: restrict access to system process env vars (#3226) 2024-09-30 16:39:05 +05:30
lohxt1
f088cdb504 feat: updates 2024-09-30 16:36:19 +05:30
lohxt1
d8bf27f288 feat: updates 2024-09-30 11:53:23 +05:30
lohxt1
a8fce54e97 feat: global env var highlight and interpolation 2024-09-30 11:48:30 +05:30
Sanjai Kumar
727fa26e44 Refactor CodeMirror styling to remove glow outline around folded JSON (#3208)
* Refactor CodeMirror styling to remove glow outline around folded JSON

* Improved font color for better legibility.

* chore: used colot from theme for codemirror fold count

---------

Co-authored-by: Anoop M D <anoop.md1421@gmail.com>
2024-09-30 11:18:02 +05:30
Anoop M D
1adfad6316 release: v1.31.0 2024-09-30 11:01:30 +05:30
lohxt1
72de78025e draft: global env ui and store 2024-09-28 18:05:31 +05:30
Pragadesh-45
2e4051b022 Bugfix/rename with same name for Environments (#3199)
* added safe to rename for rename-environment to enable case insensitive file change

* chore: removed else block

---------

Co-authored-by: Anoop M D <anoop.md1421@gmail.com>
2024-09-26 16:02:15 +05:30
lohit
25f43f12c7 feat: request execution mode (#3200) 2024-09-26 15:54:20 +05:30
Sam Briggs
2dd5ae400c Fix #2760: Path params trailing slash (#3065)
As reported in #2670, if a URL has a trailing slash and also contains
path parameters then the original logic had a bug that would drop the
trailing slash.
This implements the fix proposed by @ThenTech.
2024-09-26 11:18:18 +05:30
Pragadesh-45
8e222189bc Bugfix/rename with same name (#3171)
* fix rename with same name with different case

* added `_temp` to the filename to change the request name (handle case insensitivity) on Win and macOS

* chore: remove whitespaces and added path added path resolver

* refactor: wslpath check

* feat: safeToRename check added

* refactor

* refactor: code cleanup

* chore: improved error message

---------

Co-authored-by: Linhart Lukáš <Lukas.Linhart@tescosw.cz>
Co-authored-by: Anoop M D <anoop.md1421@gmail.com>
2024-09-26 11:07:45 +05:30
Pragadesh-45
a1719a33fc Bugfix/rename request open tab not found (#3192)
* Refactor: Normalize and resolve paths in renameItem action

* Refactor: Normalize and resolve paths in renameItem action (handler side)

* :
2024-09-26 10:15:09 +05:30
lohit
1f17d39a91 feat: remove pre-request var tooltip (#3188) 2024-09-25 14:11:35 +05:30
Sanjai Kumar
63d4757bfa Refactor CollectionItem component to conditionally render dropdown item for non-folder items with type 'http-request' or 'graphql-request' (#3190) 2024-09-25 14:10:49 +05:30
ajubin
5889e114d4 feat(code-export): add support to grapqhl (#1288)
Co-authored-by: Anoop M D <anoop.md1421@gmail.com>
2024-09-25 10:38:41 +05:30
lohxt1
1c110f0cb0 feat: removed console 2024-09-24 21:51:18 +05:30
lohxt1
5fd6773f43 feat: added support for collection/folder/request scripts 2024-09-24 21:49:49 +05:30
lohxt1
9c2c86baf6 feat: add collection vars, folder vars, request vars support to cli 2024-09-24 19:09:47 +05:30
anusreesubash
3a58c6d3bd Bugfix/openapi ensure url (#3183)
* added validations for spec and ref

* openapi import - cleanup url

---------

Co-authored-by: Anusree Subash <anusree@usebruno.com>
2024-09-24 12:34:14 +05:30
Pragadesh-45
4ef5534d41 Enhancement: Accessibility issues on the Welcome page (#3173)
* fix: accessibility issue in Welcome page
  - use button tag for collection instead of div
  - hide decorative image for assistive technology
  - give meaningful label to links in Links section

* enhance: accessibility over the buttons on the welcome page

* chore: fix translations

---------

Co-authored-by: Shrilakshmi Shastry <shrilakshmi.shastry@smallcase.com>
2024-09-23 17:54:24 +05:30
Anoop M D
641f261733 chore: disabling smooth scroll in env vars view 2024-09-23 17:50:55 +05:30
Sanjai Kumar
4d820af4e0 Improved Feat/wsse auth (#3172)
* adding wsse auth logic

* adding wsse auth logic to electron

* adding wsse auth formatting

* Refactoring WSSE 'secret' to 'password'

* Incorporating PR feedback

* Removed unused packages from package.json

* Fixed issue caused when resolving merge conflicts and added new route to test wsse

* Removed deprecated package usages from bruno-cli

* Fixed tests

---------

Co-authored-by: dwolter-emarsys <dylan.wolter@emarsys.com>
2024-09-23 17:46:31 +05:30
lohit
bebb18fc99 fix: close saved tabs (#3174) 2024-09-23 16:02:16 +05:30
lohit
6e4d7a6f76 fix: request timer issue (#3175) 2024-09-23 16:01:17 +05:30
lohit
da9f669a2d fix: runner result error display (#3176) 2024-09-23 15:57:13 +05:30
lohit
ed20eccc25 fix: multipart/form-data body interpolation (#3142)
* feat: updates

* feat: updates

* feat: updates

* feat: updates
2024-09-23 15:54:54 +05:30
Sanjai Kumar
eb33504f19 bugfix(#2431) Refactor URL construction in Postman collection processing (#2445)
* Refactor URL construction in Postman collection processing

* Updated the constructUrl function and made it more loose. Also now when there is a param with its key as undefined we discard it.

* Handled the case when the url is an object and dosen't have a raw value.

* Added missing return.

* Removed the URL fragments

* Removed unused destructures.

* Minor changes.
2024-09-23 12:22:03 +05:30
lohit
858afdbf03 feat: preferences sidebar restructure (#3170) 2024-09-23 11:32:03 +05:30
Arijit Ray
7107fa37a1 Fix application/xml import issue for insomnia (#3168) 2024-09-23 10:48:54 +05:30
Anoop M D
03e7c27d8d release: v1.30.1 2024-09-21 22:31:53 +05:30
lohit
fc79436787 fix: updates (#3158) 2024-09-21 19:49:50 +05:30
lohit
6c6693757e fix: add missing import (#3157) 2024-09-21 17:56:28 +05:30
Anoop M D
bad1302cb5 release: v1.30.0 2024-09-21 13:43:34 +05:30
lohit
f5a4525161 fix: stringify response data is not a string (#3155) 2024-09-21 11:26:38 +05:30
Sitaram Rathi
d7ff4e7ee0 added generate code button in query url bar (#3099) 2024-09-21 09:31:38 +05:30
Sanjai Kumar
637e53421e Feat/api key auth (#2478)
* feat: Added ApiKeyAuth component

* feat: Add support for API Key authentication

- Added the ApiKeyAuth component to handle API Key authentication mode.
- Updated the AuthMode component to include an option for API Key authentication.
- Updated the collections schema to include validation for API Key authentication.
- Updated the collectionsSlice to handle API Key authentication in the Redux store.

* refactor: input value handlers

- Removed the separate handleKeyChange, handlePlacementChange and handleValueChange functions and consolidated them into handleAuthChange.

* feat: Update prepare-request to handle API Key authentication in query parameters

* refactor: handling the queryparams placement api key values in the ConfigureRequest function

* refactor: added collection level api key auth

* refactor: updated collection export function

* refactor: add default placement for API key authentication in ApiKeyAuth component

* refactor: add default placement for API key authentication in ApiKeyAuth component in CollectionSettings

* refactor: update generateAuth function to handle API key authentication in postman collection exporter

* refactor: fix typo in API key placement for collection export

* Made minor changes in the logic.

* Updated the importers for postman to handle new auth type.
2024-09-20 17:28:53 +05:30
Pragadesh-45
b60c799645 fix: accessibility issue in side bar's footer (#3130)
* fix: accessibility issues in side bar footer icons

* small accessibility changes & formatting

* chore: fixed misspell

* chore: code cleanup

* added proper aria-labels and added with the footer as `ul`

* chore: code cleanup

---------

Co-authored-by: Shrilakshmi Shastry <shrilakshmi.shastry@smallcase.com>
2024-09-20 14:22:12 +05:30
Pragadesh-45
563683b5c1 feature/useFocusTrap: Support focusable tab cycles in Modal (Update of PR #3075) (#3133)
* enhance useFocusTrap: implemented focus trapping, hide non-focusable elements

* add reference link
2024-09-20 14:19:23 +05:30
Pragadesh-45
e019a96cd5 feat: add logic to handle saving collection settings on shortcut (preview mode) (#3145) 2024-09-20 14:12:19 +05:30
Lukáš Linhart
dd2b93e8cd fix: Allow to set custom user agent (#3146)
Co-authored-by: Linhart Lukáš <Lukas.Linhart@tescosw.cz>
2024-09-20 14:09:11 +05:30
Anoop M D
89c8956523 release: v1.29.1 2024-09-19 01:28:04 +05:30
Sanjai Kumar
00fcd30348 Improve how the URL values are transformed in postman export. (#3025)
* Improve how the URL values are transformed.

* Made few changes and also added jsdoc comments

* Removed the querystring values that are getting appended in the host array by filtering you the the queryvalues as we already have the queryparams values inside the request.params object.

* Moved the transformUrl logic to a different file for testing. Added new tests.

* Added tests and updated sanitizeUrl function.

* Updates made in jsdocs.

* Updated function params.

* Review: Code restructure.

* Small changes made.

* Updated the return value when there is an error.

* Changes
2024-09-18 18:07:55 +05:30
lohit
07baa63e9d fix: validate docs links (#3122)
* fix: validate docs links

* fix: only allow external urls, ignore filesystem paths

* fix: updates

* chore: revert spacing
2024-09-18 17:02:39 +05:30
Théo D
938e0560a2 fix: handle case of text when invalid JSON (#3119) (#3120)
* fix: handle case of text when invalid JSON (#3119)

* don't stringify if json is invalid, and maintain indentation if stringified

* stringify check

---------

Co-authored-by: lohit <lohxt.space@gmail.com>
2024-09-18 15:24:33 +05:30
lohit
8b6e55dfc0 fix: axios transform request bind (#3123) 2024-09-18 15:08:04 +05:30
Anoop M D
572c7ea2ae release: v1.29.0 2024-09-17 17:43:52 +05:30
lohit
260996a0ce fix: revert enter key submit logic for new request form (#3114) 2024-09-17 15:20:54 +05:30
lohit
3cb3f8094f chore: disableParsingResponseJson shim fn in safe mode (#3110) 2024-09-16 17:13:19 +05:30
lohit
4f7cefe41d Feat/support for multiple preview modes of same response type (#2606)
* pr review changes
* collection root object in export json

* import environment updates

* tests run execution order fix for collection runs

* support for multiple preview modes of same type
2024-09-16 16:46:47 +05:30
Shishir Karanth
238c790f9b fix: handle functions while marshalling (#3102)
* fix: handle functions while marshalling

* fix: js style
2024-09-16 16:40:29 +05:30
David Francis
5e4a96792e feat: Feature/cli support multiple reporters (#2911)
* Support multiple reporters at once in the CLI

* Typos

* Better logging string after writing file

* Remove double blank line

* More double blank lines

* Switch reporter schema to one from discussion

* Typo

* Add comment
2024-09-16 16:33:18 +05:30
juprem
4419634db7 feat(#1222): trigger modal's handleConfirm on ENTER key down (#1223)
* feat(#1222): trigger modal's handleConfirm on ENTER key down

* Update index.js

---------

Co-authored-by: Anoop M D <anoop.md1421@gmail.com>
2024-09-16 01:35:44 +05:30
Apoorv Yadav
19501812fc handle multiple env vars (#3107)
Co-authored-by: ayadav16 <ayadav7@binghamton.edu>
2024-09-16 01:24:51 +05:30
Anoop M D
6d239929da docs: Dutch (NL) documenatation 2024-09-16 01:21:23 +05:30
Anoop M D
0ddfca4c22 chore: removed cross referencing docs across locale specific docs 2024-09-16 01:14:24 +05:30
Anoop M D
50d93bc249 chore: reorganized folder structure for tab icons 2024-09-16 01:00:23 +05:30
Ed Brannin
ea9111748f Refactor: Extract CloseTabIcon, DraftTabIcon (#1166)
Co-authored-by: Anoop M D <anoop.md1421@gmail.com>
2024-09-16 00:55:30 +05:30
anusreesubash
721d0e1e49 Improved Request Count Calculation and UI Handling in RunCollectionItem (#2959)
* Fix | properl calculates the request number for folder run

* Chore|formatted document

---------

Co-authored-by: Anusree Subash <anusree@usebruno.com>
2024-09-16 00:33:15 +05:30
anusreesubash
f31c997fed Bugfix/openapispec empty tag (#2935)
* test: added test for self closing tags in xml-json parser

* fix: allows import of openapispec with empty string as tags

---------

Co-authored-by: Anusree Subash <anusree@usebruno.com>
2024-09-16 00:22:59 +05:30
Anoop M D
3dfb27d447 feat: display shell code exporter at the top 2024-09-16 00:12:36 +05:30
Huynh Tien
7dd639192c Support more languages in Generate Code (#2991)
* generate languages for all targets

* change target client name

* add scroll bar

* remove debug log
2024-09-16 00:06:06 +05:30
Lukáš Linhart
b3c72b1640 bugfix/useragent-header (#2979)
* add bruno-specific userAgent header

* Update axios-instance.js

---------

Co-authored-by: Linhart Lukáš <Lukas.Linhart@tescosw.cz>
Co-authored-by: Anoop M D <anoop.md1421@gmail.com>
2024-09-16 00:03:45 +05:30
Anoop M D
e680d0d71d env variables view: scroll only when form is dirty 2024-09-15 23:59:49 +05:30
Anoop M D
1057f54f2f chore: fixed lint issue 2024-09-15 23:54:07 +05:30
Anoop M D
d971aa9596 chore: fixed lint issue 2024-09-15 23:53:32 +05:30
Sanjai Kumar
3d5ae98e04 Improved the Environments modal with accessibility fixes (#2153) 2024-09-15 23:50:58 +05:30
Anoop M D
83e505979c chore: fixed typo during import of postman graphql collection 2024-09-15 23:37:14 +05:30
Anil Tallam
0d3fde5efd Handling request name conflicts while importing postman V2 collections (#1298)
Issue: In Postman, multiple requests in same folder can have same name. current import code is creating bruneRequestItems with same name which is causing only one of the original requests to be actaully created. 
Looks like bruno doesn't allow multiple requests with same name in a given folder.

Fix:
Append _<duplicate_count> to conflicting request names within same folder.
2024-09-15 23:34:14 +05:30
Sanjai Kumar
0937bab7f5 bugfix(#1320):Now the form-url-encoded params in the body can contain multiple values with same name. (#2964)
* Now the form-url-encoded params in the body can contain multiple values with same name.

* Updated the tests and renamed the function name

* Added the inimported function

* Minor changes.
2024-09-15 23:27:16 +05:30
Pragadesh-45
8856e8ec71 fix cursor position restoration after URL trimming (#3087) 2024-09-15 00:08:35 +05:30
Harshmeet Singh
9614ab069f fix: cursor jump to start (#3082)
Co-authored-by: maxdiplogit <maxdiplo@Harshmeets-MacBook-Air.local>
2024-09-13 11:52:22 +05:30
Sergei Karetnikov
81d8c30d84 feat(usebruno#2441): Set response body function (#3076) 2024-09-13 11:48:05 +05:30
Pragadesh-45
a08573f120 Feature/use focus trap (#3075)
* addded tab order for modal elements

* fixed Tab Order

* feat: Add useFocusTrap hook for managing focus within modals

* chore: improvements

* chore: removed console log

---------

Co-authored-by: Srikar <srikar.y.12@gmail.com>
Co-authored-by: srikary12 <121927567+srikary12@users.noreply.github.com>
Co-authored-by: Anoop M D <anoop.md1421@gmail.com>
2024-09-13 11:42:55 +05:30
Pragadesh-45
776866b3b4 style: added bottom border for Table component (#3078) 2024-09-13 11:12:38 +05:30
chrisn
9a57f3870f fix: add hints of 'bru' object for 'getFolderVar' and 'getCollectionVar' methods (#3062)
Co-authored-by: Chris Nagel <mail@chrisnagel.de>
2024-09-12 11:33:06 +05:30
Pragadesh-45
98a7aa1357 fix: middle button click to close - SpecialTab and RequestTabNotFound tab (#3044) 2024-09-11 11:25:34 +05:30
Dawood F.K Morris
087bab6fb4 feat: display raw query response unformatted for readability (#2272)
* feat: display raw query response unformatted for readability

* chore: improved response json parsing

---------

Co-authored-by: Anoop M D <anoop.md1421@gmail.com>
2024-09-11 11:19:17 +05:30
Sanjai Kumar
0b4e9e7640 Now the special characters in the search value are escapec before constructing the regexp. (#3057) 2024-09-11 10:52:11 +05:30
busy-panda
62babef678 Merge branch 'main' into feature/1602-multipart-content-type
# Conflicts:
#	packages/bruno-lang/v2/src/jsonToBru.js
2024-09-09 11:49:38 +02:00
zachary-berdell-elliott
1c0ff13483 Added a more descriptive error message on create and clone collection. (#3046)
* Added a more descriptive error message on create and clone collection.

* Using - instead of :
2024-09-06 15:21:10 +05:30
Oleg Vaskevich
5d7f44fc61 Don't include state in OAuth 2 exchange flow (#3034)
* Don't include state in OAuth 2 exchange flow if not specified
* Remove state entirely
2024-09-06 15:18:31 +05:30
anusreesubash
c85d7b0c77 added validations for spec and ref (#2962)
Co-authored-by: Anusree Subash <anusree@usebruno.com>
2024-09-05 19:05:26 +05:30
anusreesubash
ab8afed8f9 Bugfix/openapi import array body (#3009)
* added validations for spec and ref

* Fix | openapispec import-show proper body for arrays of objects

* removed unwanted changes

* handles body schema of array of objects

* removed logs

---------

Co-authored-by: Anusree Subash <anusree@usebruno.com>
2024-09-05 19:03:47 +05:30
Grégoire Bellon
450b1d3ae3 fix: invalid json body mistakenly quoted (#2449)
* fix: invalid json body mistakenly quoted

* Update axios-instance.js

* chore: better code for json header check

---------

Co-authored-by: lohit <lohxt.space@gmail.com>
Co-authored-by: Anoop M D <anoop.md1421@gmail.com>
2024-09-05 12:26:12 +05:30
Pragadesh-45
2191550061 Feat table resize and reorder (#2641)
* feat-Table-resize-and-Reorder

* feat-Table-resize-and-Reorder

* feat-Table-resize-and-Reorder/fixed-table-resize-update
2024-09-05 12:19:36 +05:30
Adrian Riedel
4bd31fb083 feat(#2265): Support GraphQL variables formatting (#2267)
* feat: support GraphQL variables formatting

* Update index.js

* revert codeeditor component changes

* revert codeeditor component

---------

Co-authored-by: lohit <lohxt.space@gmail.com>
2024-09-05 02:57:28 +05:30
Jonathan Gruber
bcc8811f65 chore(#673): remove obsolete mustache.js library (#674)
Co-authored-by: Anoop M D <anoop.md1421@gmail.com>
2024-09-05 00:24:09 +05:30
Anoop M D
a10e6ee858 release: v1.28.0 2024-09-04 17:56:22 +05:30
Anoop M D
46017a6c50 chore: removed collection vars test as cli support is not yet ready 2024-09-04 11:20:03 +05:30
Anoop M D
cb395e7649 Collection Variables Support (#2963) (#3018)
Support for Collection Variables
---------

Co-authored-by: lohit <lohit.jiddimani@gmail.com>
Co-authored-by: lohit <lohxt.space@gmail.com>
2024-09-03 21:18:38 +05:30
j-lebek
5931f0bb4e feat: Store cookies received in Runner execution (#2951) 2024-09-03 21:12:54 +05:30
Anoop M D
2a93a6fa65 feat: content indicator for request docs 2024-09-03 20:16:50 +05:30
lohit
8a233fb489 fix: openapi collection import to not add protocol by default (#3011)
* Update package.json

* Update package.json

* Update package.json

* Update package.json

* revert jest command

* fix: openapi importwith server url

* fix: updates
2024-09-03 17:32:29 +05:30
lohit
b102898709 fix: multipart timeline (#3008)
* Update package.json

* Update package.json

* Update package.json

* Update package.json

* fix: multipart timeline

* revert jest command
2024-09-03 17:29:51 +05:30
Anoop M D
c5c343c543 feat: update proxy implementation in preferences (#2977) 2024-08-30 15:22:06 +05:30
lohit
c1ec95dc29 fix: option to toggle on/off system proxy env variables (#2724)
fix: option to toggle on/off system proxy env variables
2024-08-30 11:44:29 +05:30
Mateusz Pietryga
93080de2a8 fix: Issue with Parameters Passed in the URL(#2124) (#2139)
* fix: Issue with Parameters Passed in the URL(#2124)

The '=' should be allowed within query parameter value. While first equals sign separates parameter name from its value, any subsequent occurrences are valid and should not be discarded.
The '#' in URL always indicates the start of URI Fragment component, and should not be treated as part of any parameter value.

* chore: gracefully fail when URLSearchParams throws error

---------

Co-authored-by: Anoop M D <anoop.md1421@gmail.com>
2024-08-29 12:46:20 +05:30
dev.paramjot
36ef38be6a feat(#736): Switch tabs with keyboard shortcut (#812)
* feat(#736): Switch tabs with keyboard shortcut

1. Registered keyboard events in Hotkeys/index.js
2. Added logic for replacing `state.activeTabUid` to switch active tab as per keyboard event.
3. Maintained a stack `recentUsedTabsStack` for tab visit history and pop out on `Ctrl+Tab` keyboard event.

* feat(#736): Switch tabs with keyboard shortcut

Keeping this feature request only limited to CTRL+PGUP and CTRL_PGDN button clicks functionality. Hence removing logic for CTRL+TAB click functionality.

* feat(#736): Switch tabs with keyboard shortcut

clean up

* feate(#827): Switch tabs with keyboard shortcut

* Implimented logic of cyclic traversal of tabs array with % opreator.

---------

Co-authored-by: Anoop M D <anoop.md1421@gmail.com>
2024-08-29 11:12:28 +05:30
Pragadesh-45
4726f5008e style chore: make delete div bg important (#2949) 2024-08-29 10:43:32 +05:30
busy-panda
a703b84681 Merge branch 'main' into feature/1602-multipart-content-type
# Conflicts:
#	packages/bruno-lang/v2/src/bruToJson.js
#	packages/bruno-lang/v2/src/jsonToBru.js
2024-07-01 15:17:53 +02:00
busy-panda🐼🐼
9ba03a5f02 Merge branch 'usebruno:main' into feature/1602-multipart-content-type 2024-05-01 09:19:08 +02:00
busy-panda🐼🐼
cdf56fcec1 Merge branch 'usebruno:main' into feature/1602-multipart-content-type 2024-04-24 11:47:07 +02:00
busy-panda🐼🐼
f27e79cb01 Merge branch 'usebruno:main' into feature/1602-multipart-content-type 2024-04-20 10:25:02 +02:00
busy-panda
40872f6e9e Reduced the width of the Operator column in tab Assert 2024-04-19 17:14:44 +02:00
busy-panda
b7f4edac24 Reduced the width of the Operator column in tab Assert 2024-04-19 17:08:38 +02:00
busy-panda
8e99ed3258 moved assertions from Tests panel to Assert panel and 2024-04-19 17:06:49 +02:00
busy-panda
c3c91d61c8 added placeholder support to MultiLineEditor component 2024-04-19 15:01:41 +02:00
busy-panda
39f60daca7 feature: Multi-part requests: user should be able to set content-type for each part in a multi-part request. #1602 2024-04-18 15:43:09 +02:00
Nelu Platonov
dce1481185 fix(#521): Allow "context" as the name of a key/var in a JS expression 2023-11-23 23:38:43 +01:00
390 changed files with 25824 additions and 10258 deletions

View File

@@ -20,7 +20,10 @@ permissions:
jobs:
test:
name: CLI Tests
runs-on: ubuntu-latest
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v3

View File

@@ -5,6 +5,9 @@ on:
pull_request:
branches: [main]
permissions:
contents: read
jobs:
unit-test:
name: Unit Tests
@@ -49,6 +52,9 @@ jobs:
cli-test:
name: CLI Tests
runs-on: ubuntu-latest
permissions:
checks: write
pull-requests: write
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4

2
.nvmrc
View File

@@ -1 +1 @@
v20.9.0
v22.11.0

View File

@@ -15,6 +15,7 @@
| [正體中文](docs/contributing/contributing_zhtw.md)
| [日本語](docs/contributing/contributing_ja.md)
| [हिंदी](docs/contributing/contributing_hi.md)
| [Nederlands](docs/contributing/contributing_nl.md)
## Let's make Bruno better, together!!
@@ -47,7 +48,7 @@ Bruno is being developed as a desktop app. You need to load the app by running t
### Local Development
```bash
# use nodejs 18 version
# use nodejs 20 version
nvm use
# install deps

View File

@@ -1,20 +1,4 @@
[English](../../contributing.md)
| [Українська](./contributing_ua.md)
| [Русский](./contributing_ru.md)
| [Türkçe](./contributing_tr.md)
| [Deutsch](./contributing_de.md)
| [Français](./contributing_fr.md)
| [Português (BR)](./contributing_pt_br.md)
| [한국어](./contributing_kr.md)
| **বাংলা**
| [Español](./contributing_es.md)
| [Italiano](./contributing_it.md)
| [Română](./contributing_ro.md)
| [Polski](./contributing_pl.md)
| [简体中文](./contributing_cn.md)
| [正體中文](./contributing_zhtw.md)
| [日本語](./contributing_ja.md)
| [हिंदी](./contributing_hi.md)
## আসুন ব্রুনোকে আরও ভালো করি, একসাথে!!

View File

@@ -1,20 +1,4 @@
[English](../../contributing.md)
| [Українська](./contributing_ua.md)
| [Русский](./contributing_ru.md)
| [Türkçe](./contributing_tr.md)
| [Deutsch](./contributing_de.md)
| [Français](./contributing_fr.md)
| [Português (BR)](./contributing_pt_br.md)
| [한국어](./contributing_kr.md)
| [বাংলা](./contributing_bn.md)
| [Español](./contributing_es.md)
| [Italiano](./contributing_it.md)
| [Română](./contributing_ro.md)
| [Polski](./contributing_pl.md)
| **简体中文**
| [正體中文](./contributing_zhtw.md)
| [日本語](./contributing_ja.md)
| [हिंदी](./contributing_hi.md)
## 让我们一起改进 Bruno

View File

@@ -1,20 +1,4 @@
[English](../../contributing.md)
| [Українська](./contributing_ua.md)
| [Русский](./contributing_ru.md)
| [Türkçe](./contributing_tr.md)
| **Deutsch**
| [Français](./contributing_fr.md)
| [Português (BR)](./contributing_pt_br.md)
| [한국어](./contributing_kr.md)
| [বাংলা](./contributing_bn.md)
| [Español](./contributing_es.md)
| [Italiano](./contributing_it.md)
| [Română](./contributing_ro.md)
| [Polski](./contributing_pl.md)
| [简体中文](./contributing_cn.md)
| [正體中文](./contributing_zhtw.md)
| [日本語](./contributing_ja.md)
| [हिंदी](./contributing_hi.md)
## Lass uns Bruno noch besser machen, gemeinsam!!

View File

@@ -1,20 +1,4 @@
[English](../../contributing.md)
| [Українська](./contributing_ua.md)
| [Русский](./contributing_ru.md)
| [Türkçe](./contributing_tr.md)
| [Deutsch](./contributing_de.md)
| [Français](./contributing_fr.md)
| [Português (BR)](./contributing_pt_br.md)
| [한국어](./contributing_kr.md)
| [বাংলা](./contributing_bn.md)
| **Español**
| [Italiano](./contributing_it.md)
| [Română](./contributing_ro.md)
| [Polski](./contributing_pl.md)
| [简体中文](./contributing_cn.md)
| [正體中文](./contributing_zhtw.md)
| [日本語](./contributing_ja.md)
| [हिंदी](./contributing_hi.md)
## ¡Juntos, hagamos a Bruno mejor!

View File

@@ -1,20 +1,4 @@
[English](../../contributing.md)
| [Українська](./contributing_ua.md)
| [Русский](./contributing_ru.md)
| [Türkçe](./contributing_tr.md)
| [Deutsch](./contributing_de.md)
| **Français**
| [Português (BR)](./contributing_pt_br.md)
| [한국어](./contributing_kr.md)
| [বাংলা](./contributing_bn.md)
| [Español](./contributing_es.md)
| [Italiano](./contributing_it.md)
| [Română](./contributing_ro.md)
| [Polski](./contributing_pl.md)
| [简体中文](./contributing_cn.md)
| [正體中文](./contributing_zhtw.md)
| [日本語](./contributing_ja.md)
| [हिंदी](./contributing_hi.md)
## Ensemble, améliorons Bruno !

View File

@@ -1,20 +1,4 @@
[English](../../contributing.md)
| [Українська](./contributing_ua.md)
| [Русский](./contributing_ru.md)
| [Türkçe](./contributing_tr.md)
| [Deutsch](./contributing_de.md)
| [Français](./contributing_fr.md)
| [Português (BR)](./contributing_pt_br.md)
| [한국어](./contributing_kr.md)
| [বাংলা](./contributing_bn.md)
| [Español](./contributing_es.md)
| [Italiano](./contributing_it.md)
| [Română](./contributing_ro.md)
| [Polski](./contributing_pl.md)
| [简体中文](./contributing_cn.md)
| [正體中文](./contributing_zhtw.md)
| [日本語](./contributing_ja.md)
| **हिंदी**
## आइए मिलकर Bruno को बेहतर बनाएं !!

View File

@@ -1,20 +1,4 @@
[English](../../contributing.md)
| [Українська](./contributing_ua.md)
| [Русский](./contributing_ru.md)
| [Türkçe](./contributing_tr.md)
| [Deutsch](./contributing_de.md)
| [Français](./contributing_fr.md)
| [Português (BR)](./contributing_pt_br.md)
| [한국어](./contributing_kr.md)
| [বাংলা](./contributing_bn.md)
| [Español](./contributing_es.md)
| **Italiano**
| [Română](./contributing_ro.md)
| [Polski](./contributing_pl.md)
| [简体中文](./contributing_cn.md)
| [正體中文](./contributing_zhtw.md)
| [日本語](./contributing_ja.md)
| [हिंदी](./contributing_hi.md)
## Insieme, miglioriamo Bruno!

View File

@@ -1,20 +1,4 @@
[English](../../contributing.md)
| [Українська](./contributing_ua.md)
| [Русский](./contributing_ru.md)
| [Türkçe](./contributing_tr.md)
| [Deutsch](./contributing_de.md)
| [Français](./contributing_fr.md)
| [Português (BR)](./contributing_pt_br.md)
| [한국어](./contributing_kr.md)
| [বাংলা](./contributing_bn.md)
| [Español](./contributing_es.md)
| [Italiano](./contributing_it.md)
| [Română](./contributing_ro.md)
| [Polski](./contributing_pl.md)
| [简体中文](./contributing_cn.md)
| [正體中文](./contributing_zhtw.md)
| **日本語**
| [हिंदी](./contributing_hi.md)
## 一緒に Bruno をよりよいものにしていきましょう!!

View File

@@ -1,20 +1,4 @@
[English](../../contributing.md)
| [Українська](./contributing_ua.md)
| [Русский](./contributing_ru.md)
| [Türkçe](./contributing_tr.md)
| [Deutsch](./contributing_de.md)
| [Français](./contributing_fr.md)
| [Português (BR)](./contributing_pt_br.md)
| **한국어**
| [বাংলা](./contributing_bn.md)
| [Español](./contributing_es.md)
| [Italiano](./contributing_it.md)
| [Română](./contributing_ro.md)
| [Polski](./contributing_pl.md)
| [简体中文](./contributing_cn.md)
| [正體中文](./contributing_zhtw.md)
| [日本語](./contributing_ja.md)
| [हिंदी](./contributing_hi.md)
## 함께 Bruno를 더 좋게 만들어요!!

View File

@@ -0,0 +1,82 @@
[English](../../contributing.md)
## Laten we Bruno samen beter maken !!
We zijn blij dat je Bruno wilt verbeteren. Hieronder staan de richtlijnen om Bruno op je computer op te zetten.
### Technologiestack
Bruno is gebouwd met Next.js en React. We gebruiken ook Electron om een desktopversie te leveren (die lokale collecties ondersteunt).
Bibliotheken die we gebruiken:
- CSS - Tailwind
- Code Editors - Codemirror
- State Management - Redux
- Iconen - Tabler Icons
- Formulieren - formik
- Schema Validatie - Yup
- Request Client - axios
- Bestandsysteem Watcher - chokidar
### Afhankelijkheden
Je hebt [Node v18.x of de nieuwste LTS-versie](https://nodejs.org/en/) en npm 8.x nodig. We gebruiken npm workspaces in het project.
## Ontwikkeling
Bruno wordt ontwikkeld als een desktop-app. Je moet de app laden door de Next.js app in één terminal te draaien en daarna de Electron app in een andere terminal te draaien.
### Lokale Ontwikkeling
```bash
# gebruik voorgeschreven node versie
nvm use
# installeer afhankelijkheden
npm i --legacy-peer-deps
# build pakketten
npm run build:graphql-docs
npm run build:bruno-query
npm run build:bruno-common
# draai next app (terminal 1)
npm run dev:web
# draai electron app (terminal 2)
npm run dev:electron
```
### Problemen oplossen
Je kunt een `Unsupported platform`-fout tegenkomen wanneer je `npm install` uitvoert. Om dit te verhelpen, moet je `node_modules` en `package-lock.json` verwijderen en `npm install` uitvoeren. Dit zou alle benodigde afhankelijkheden moeten installeren om de app te draaien.
```shell
# Verwijder node_modules in subdirectories
find ./ -type d -name "node_modules" -print0 | while read -d $'\0' dir; do
rm -rf "$dir"
done
# Verwijder package-lock in subdirectories
find . -type f -name "package-lock.json" -delete
```
### Testen
```bash
# bruno-schema
npm test --workspace=packages/bruno-schema
# bruno-lang
npm test --workspace=packages/bruno-lang
```
### Pull Requests indienen
- Houd de PR's klein en gefocust op één ding
- Volg het formaat voor het aanmaken van branches
- feature/[feature naam]: Deze branch moet wijzigingen voor een specifieke functie bevatten
- Voorbeeld: feature/dark-mode
- bugfix/[bug naam]: Deze branch moet alleen bugfixes voor een specifieke bug bevatten
- Voorbeeld: bugfix/bug-1

View File

@@ -1,20 +1,4 @@
[English](../../contributing.md)
| [Українська](./contributing_ua.md)
| [Русский](./contributing_ru.md)
| [Türkçe](./contributing_tr.md)
| [Deutsch](./contributing_de.md)
| [Français](./contributing_fr.md)
| [Português (BR)](./contributing_pt_br.md)
| [한국어](./contributing_kr.md)
| [বাংলা](./contributing_bn.md)
| [Español](./contributing_es.md)
| [Italiano](./contributing_it.md)
| [Română](./contributing_ro.md)
| **Polski**
| [简体中文](./contributing_cn.md)
| [正體中文](./contributing_zhtw.md)
| [日本語](./contributing_ja.md)
| [हिंदी](./contributing_hi.md)
## Wspólnie uczynijmy Bruno lepszym !!

View File

@@ -1,20 +1,4 @@
[English](../../contributing.md)
| [Українська](./contributing_ua.md)
| [Русский](./contributing_ru.md)
| [Türkçe](./contributing_tr.md)
| [Deutsch](./contributing_de.md)
| [Français](./contributing_fr.md)
| **Português (BR)**
| [한국어](./contributing_kr.md)
| [বাংলা](./contributing_bn.md)
| [Español](./contributing_es.md)
| [Italiano](./contributing_it.md)
| [Română](./contributing_ro.md)
| [Polski](./contributing_pl.md)
| [简体中文](./contributing_cn.md)
| [正體中文](./contributing_zhtw.md)
| [日本語](./contributing_ja.md)
| [हिंदी](./contributing_hi.md)
## Vamos tornar o Bruno melhor, juntos!!

View File

@@ -1,20 +1,4 @@
[English](../../contributing.md)
| [Українська](./contributing_ua.md)
| [Русский](./contributing_ru.md)
| [Türkçe](./contributing_tr.md)
| [Deutsch](./contributing_de.md)
| [Français](./contributing_fr.md)
| [Português (BR)](./contributing_pt_br.md)
| [한국어](./contributing_kr.md)
| [বাংলা](./contributing_bn.md)
| [Español](./contributing_es.md)
| [Italiano](./contributing_it.md)
| **Română**
| [Polski](./contributing_pl.md)
| [简体中文](./contributing_cn.md)
| [正體中文](./contributing_zhtw.md)
| [日本語](./contributing_ja.md)
| [हिंदी](./contributing_hi.md)
## Haideţi să îmbunătățim Bruno, împreună!!

View File

@@ -1,20 +1,4 @@
[English](../../contributing.md)
| [Українська](./contributing_ua.md)
| **Русский**
| [Türkçe](./contributing_tr.md)
| [Deutsch](./contributing_de.md)
| [Français](./contributing_fr.md)
| [Português (BR)](./contributing_pt_br.md)
| [한국어](./contributing_kr.md)
| [বাংলা](./contributing_bn.md)
| [Español](./contributing_es.md)
| [Italiano](./contributing_it.md)
| [Română](./contributing_ro.md)
| [Polski](./contributing_pl.md)
| [简体中文](./contributing_cn.md)
| [正體中文](./contributing_zhtw.md)
| [日本語](./contributing_ja.md)
| [हिंदी](./contributing_hi.md)
## Давайте вместе сделаем Бруно лучше!!!

View File

@@ -1,20 +1,4 @@
[English](../../contributing.md)
| [Українська](./contributing_ua.md)
| [Русский](./contributing_ru.md)
| **Türkçe**
| [Deutsch](./contributing_de.md)
| [Français](./contributing_fr.md)
| [Português (BR)](./contributing_pt_br.md)
| [한국어](./contributing_kr.md)
| [বাংলা](./contributing_bn.md)
| [Español](./contributing_es.md)
| [Italiano](./contributing_it.md)
| [Română](./contributing_ro.md)
| [Polski](./contributing_pl.md)
| [简体中文](./contributing_cn.md)
| [正體中文](./contributing_zhtw.md)
| [日本語](./contributing_ja.md)
| [हिंदी](./contributing_hi.md)
## Bruno'yu birlikte daha iyi hale getirelim!!!

View File

@@ -1,20 +1,4 @@
[English](../../contributing.md)
| **Українська**
| [Русский](./contributing_ru.md)
| [Türkçe](./contributing_tr.md)
| [Deutsch](./contributing_de.md)
| [Français](./contributing_fr.md)
| [Português (BR)](./contributing_pt_br.md)
| [한국어](./contributing_kr.md)
| [বাংলা](./contributing_bn.md)
| [Español](./contributing_es.md)
| [Italiano](./contributing_it.md)
| [Română](./contributing_ro.md)
| [Polski](./contributing_pl.md)
| [简体中文](./contributing_cn.md)
| [正體中文](./contributing_zhtw.md)
| [日本語](./contributing_ja.md)
| [हिंदी](./contributing_hi.md)
## Давайте зробимо Bruno краще, разом !!

View File

@@ -1,20 +1,4 @@
[English](../../contributing.md)
| [Українська](./contributing_ua.md)
| [Русский](./contributing_ru.md)
| [Türkçe](./contributing_tr.md)
| [Deutsch](./contributing_de.md)
| [Français](./contributing_fr.md)
| [Português (BR)](./contributing_pt_br.md)
| [한국어](./contributing_kr.md)
| [বাংলা](./contributing_bn.md)
| [Español](./contributing_es.md)
| [Italiano](./contributing_it.md)
| [Română](./contributing_ro.md)
| [Polski](./contributing_pl.md)
| [简体中文](./contributing_cn.md)
| **正體中文**
| [日本語](./contributing_ja.md)
| [हिंदी](./contributing_hi.md)
## 讓我們一起來讓 Bruno 變得更好!

View File

@@ -0,0 +1,7 @@
[English](../../publishing.md)
### Bruno publiceren naar een nieuwe pakketbeheerder
Hoewel onze code open source is en beschikbaar voor iedereen, verzoeken we je vriendelijk om contact met ons op te nemen voordat je publicatie overweegt op nieuwe pakketbeheerders. Als de maker van Bruno houd ik het handelsmerk `Bruno` voor dit project en wil ik het distributieproces beheren. Als je Bruno op een nieuwe pakketbeheerder wilt zien, dien dan een GitHub-issue in.
Hoewel de meerderheid van onze functies gratis en open source zijn (die REST en GraphQL API's dekken), streven we ernaar een harmonieuze balans te vinden tussen open-source principes en duurzaamheid - https://github.com/usebruno/bruno/discussions/269

View File

@@ -1,14 +1,4 @@
[English](../../publishing.md)
| [Türkçe](./publishing_tr.md)
| [Deutsch](./publishing_de.md)
| [Français](./publishing_fr.md)
| [Português (BR)](./publishing_pt_br.md)
| **বাংলা**
| [Română](./publishing_ro.md)
| [Polski](./publishing_pl.md)
| [简体中文](./publishing_cn.md)
| [正體中文](./publishing_zhtw.md)
| [日本語](./publishing_ja.md)
### ব্রুনোকে নতুন প্যাকেজ ম্যানেজারে প্রকাশ করা

View File

@@ -1,14 +1,4 @@
[English](../../publishing.md)
| [Türkçe](./publishing_tr.md)
| [Deutsch](./publishing_de.md)
| [Français](./publishing_fr.md)
| [Português (BR)](./publishing_pt_br.md)
| [বাংলা](./publishing_bn.md)
| [Română](./publishing_ro.md)
| [Polski](./publishing_pl.md)
| **简体中文**
| [正體中文](./publishing_zhtw.md)
| [日本語](./publishing_ja.md)
### 将 Bruno 发布到新的包管理器

View File

@@ -1,14 +1,4 @@
[English](../../publishing.md)
| [Türkçe](./publishing_tr.md)
| **Deutsch**
| [Français](./publishing_fr.md)
| [Português (BR)](./publishing_pt_br.md)
| [বাংলা](./publishing_bn.md)
| [Română](./publishing_ro.md)
| [Polski](./publishing_pl.md)
| [简体中文](./publishing_cn.md)
| [正體中文](./publishing_zhtw.md)
| [日本語](./publishing_ja.md)
### Veröffentlichung von Bruno über neue Paket-Manager

View File

@@ -1,14 +1,4 @@
[English](../../publishing.md)
| [Türkçe](./publishing_tr.md)
| [Deutsch](./publishing_de.md)
| **Français**
| [Português (BR)](./publishing_pt_br.md)
| [বাংলা](./publishing_bn.md)
| [Română](./publishing_ro.md)
| [Polski](./publishing_pl.md)
| [简体中文](./publishing_cn.md)
| [正體中文](./publishing_zhtw.md)
| [日本語](./publishing_ja.md)
### Publier Bruno dans un nouveau gestionnaire de paquets

View File

@@ -1,14 +1,4 @@
[English](../../publishing.md)
| [Türkçe](./publishing_tr.md)
| [Deutsch](./publishing_de.md)
| [Français](./publishing_fr.md)
| [Português (BR)](./publishing_pt_br.md)
| [বাংলা](./publishing_bn.md)
| [Română](./publishing_ro.md)
| [Polski](./publishing_pl.md)
| [简体中文](./publishing_cn.md)
| [正體中文](./publishing_zhtw.md)
| **日本語**
### Bruno を新しいパッケージマネージャに公開する場合の注意

View File

@@ -1,14 +1,4 @@
[English](../../publishing.md)
| [Türkçe](./publishing_tr.md)
| [Deutsch](./publishing_de.md)
| [Français](./publishing_fr.md)
| [Português (BR)](./publishing_pt_br.md)
| [বাংলা](./publishing_bn.md)
| [Română](./publishing_ro.md)
| **Polski**
| [简体中文](./publishing_cn.md)
| [正體中文](./publishing_zhtw.md)
| [日本語](./publishing_ja.md)
### Publikowanie Bruno w nowym menedżerze pakietów

View File

@@ -1,14 +1,4 @@
[English](../../publishing.md)
| [Türkçe](./publishing_tr.md)
| [Deutsch](./publishing_de.md)
| [Français](./publishing_fr.md)
| **Português (BR)**
| [বাংলা](./publishing_bn.md)
| [Română](./publishing_ro.md)
| [Polski](./publishing_pl.md)
| [简体中文](./publishing_cn.md)
| [正體中文](./publishing_zhtw.md)
| [日本語](./publishing_ja.md)
### Publicando Bruno em um novo gerenciador de pacotes

View File

@@ -1,14 +1,4 @@
[English](../../publishing.md)
| [Türkçe](./publishing_tr.md)
| [Deutsch](./publishing_de.md)
| [Français](./publishing_fr.md)
| [Português (BR)](./publishing_pt_br.md)
| [বাংলা](./publishing_bn.md)
| **Română**
| [Polski](./publishing_pl.md)
| [简体中文](./publishing_cn.md)
| [正體中文](./publishing_zhtw.md)
| [日本語](./publishing_ja.md)
### Publicarea lui Bruno la un gestionar de pachete nou

View File

@@ -1,14 +1,4 @@
[English](../../publishing.md)
| **Türkçe**
| [Deutsch](./publishing_de.md)
| [Français](./publishing_fr.md)
| [Português (BR)](./publishing_pt_br.md)
| [বাংলা](./publishing_bn.md)
| [Română](./publishing_ro.md)
| [Polski](./publishing_pl.md)
| [简体中文](./publishing_cn.md)
| [正體中文](./publishing_zhtw.md)
| [日本語](./publishing_ja.md)
### Bruno'yu yeni bir paket yöneticisine yayınlama

View File

@@ -1,14 +1,4 @@
[English](../../publishing.md)
| [Türkçe](./publishing_tr.md)
| [Deutsch](./publishing_de.md)
| [Français](./publishing_fr.md)
| [Português (BR)](./publishing_pt_br.md)
| [বাংলা](./publishing_bn.md)
| [Română](./publishing_ro.md)
| [Polski](./publishing_pl.md)
| [简体中文](./publishing_cn.md)
| **正體中文**
| [日本語](./publishing_ja.md)
### 將 Bruno 發佈到新的套件管理器

157
docs/readme/readme_nl.md Normal file
View File

@@ -0,0 +1,157 @@
<br />
<img src="../../assets/images/logo-transparent.png" width="80"/>
### Bruno - Open source IDE voor het verkennen en testen van API's.
[![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/tests.yml/badge.svg?branch=main)](https://github.com/usebruno/bruno/actions/workflows/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) | [Українська](docs/readme/readme_ua.md) | [Русский](docs/readme/readme_ru.md) | [Türkçe](docs/readme/readme_tr.md) | [Deutsch](docs/readme/readme_de.md) | ** Nederlands ** | [Français](docs/readme/readme_fr.md) | [Português (BR)](docs/readme/readme_pt_br.md) | [한국어](docs/readme/readme_kr.md) | [বাংলা](docs/readme/readme_bn.md) | [Español](docs/readme/readme_es.md) | [Italiano](docs/readme/readme_it.md) | [Română](docs/readme/readme_ro.md) | [Polski](docs/readme/readme_pl.md) | [简体中文](docs/readme/readme_cn.md) | [正體中文](docs/readme/readme_zhtw.md) | [العربية](docs/readme/readme_ar.md) | [日本語](docs/readme/readme_ja.md)
Bruno is een nieuwe en innovatieve API-client, gericht op het revolutioneren van de status quo die wordt vertegenwoordigd door Postman en vergelijkbare tools.
Bruno slaat je collecties direct op in een map op je bestandssysteem. We gebruiken een platte tekst opmaaktaal, Bru, om informatie over API-verzoeken op te slaan.
Je kunt Git of elke versiebeheertool naar keuze gebruiken om samen te werken aan je API-collecties.
Bruno is uitsluitend offline. Er zijn geen plannen om ooit cloud-synchronisatie aan Bruno toe te voegen. We waarderen je gegevensprivacy en geloven dat deze op je apparaat moet blijven. Lees onze langetermijnvisie [hier](https://github.com/usebruno/bruno/discussions/269)
[Download Bruno](https://www.usebruno.com/downloads)
📢 Bekijk onze recente presentatie op de India FOSS 3.0 Conference [hier](https://www.youtube.com/watch?v=7bSMFpbcPiY)
![bruno](/assets/images/landing-2.png) <br /><br />
### Golden Edition ✨
De meeste van onze functies zijn gratis en open source.
We streven naar een harmonieuze balans tussen [open-source principes en duurzaamheid](https://github.com/usebruno/bruno/discussions/269).
Je kunt de [Golden Edition](https://www.usebruno.com/pricing) kopen voor een eenmalige betaling van **$19**! <br/>
### Installatie
Bruno is beschikbaar als binaire download [op onze website](https://www.usebruno.com/downloads) voor Mac, Windows en Linux.
Je kunt Bruno ook installeren via pakketbeheerders zoals Homebrew, Chocolatey, Scoop, Snap, Flatpak en Apt.
```sh
# Op Mac via Homebrew
brew install bruno
# Op Windows via Chocolatey
choco install bruno
# Op Windows via Scoop
scoop bucket add extras
scoop install bruno
# Op Windows via winget
winget install Bruno.Bruno
# Op Linux via Snap
snap install bruno
# Op Linux via Flatpak
flatpak install com.usebruno.Bruno
# Op Linux via Apt
sudo mkdir -p /etc/apt/keyrings
sudo gpg --no-default-keyring --keyring /etc/apt/keyrings/bruno.gpg --keyserver keyserver.ubuntu.com --recv-keys 9FA6017ECABE0266
echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/bruno.gpg] http://debian.usebruno.com/ bruno stable" | sudo tee /etc/apt/sources.list.d/bruno.list
sudo apt update
sudo apt install bruno
```
### Draai op meerdere platformen 🖥️
![bruno](/assets/images/run-anywhere.png) <br /><br />
### Samenwerken via Git 👩‍💻🧑‍💻
Of elk versiebeheersysteem naar keuze
![bruno](/assets/images/version-control.png) <br /><br />
### Sponsors
#### Gouden Sponsors
<img src="../../assets/images/sponsors/samagata.png" width="150"/>
#### Zilveren Sponsors
<img src="../../assets/images/sponsors/commit-company.png" width="70"/>
#### Bronzen Sponsors
<a href="https://zuplo.link/bruno">
<img src="../../assets/images/sponsors/zuplo.png" width="120"/>
</a>
### Belangrijke Links 📌
- [Onze Langetermijnvisie](https://github.com/usebruno/bruno/discussions/269)
- [Roadmap](https://github.com/usebruno/bruno/discussions/384)
- [Documentatie](https://docs.usebruno.com)
- [Stack Overflow](https://stackoverflow.com/questions/tagged/bruno)
- [Website](https://www.usebruno.com)
- [Prijzen](https://www.usebruno.com/pricing)
- [Download](https://www.usebruno.com/downloads)
- [GitHub Sponsors](https://github.com/sponsors/helloanoop)
### Showcase 🎥
- [Getuigenissen](https://github.com/usebruno/bruno/discussions/343)
- [Kenniscentrum](https://github.com/usebruno/bruno/discussions/386)
- [Scriptmania](https://github.com/usebruno/bruno/discussions/385)
### Ondersteuning ❤️
Als je Bruno leuk vindt en ons open-source werk wilt ondersteunen, overweeg dan om ons te sponsoren via [GitHub Sponsors](https://github.com/sponsors/helloanoop).
### Deel Getuigenissen 📣
Als Bruno je heeft geholpen op je werk en in je teams, deel dan je [getuigenissen op onze GitHub-discussie](https://github.com/usebruno/bruno/discussions/343).
### Blijf in contact 🌐
[𝕏 (Twitter)](https://twitter.com/use_bruno) <br />
[Website](https://www.usebruno.com) <br />
[Discord](https://discord.com/invite/KgcZUncpjq) <br />
[LinkedIn](https://www.linkedin.com/company/usebruno)
### Handelsmerk
**Naam**
`Bruno` is een handelsmerk in bezit van [Anoop M D](https://www.helloanoop.com/).
**Logo**
Het logo is afkomstig van [OpenMoji](https://openmoji.org/library/emoji-1F436/). Licentie: CC [BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/)
### Bijdragen 👩‍💻🧑‍💻
Ik ben blij dat je Bruno wilt verbeteren. Bekijk de [bijdragegids](contributing.md).
Zelfs als je geen bijdragen via code kunt leveren, aarzel dan niet om bugs en functieverzoeken in te dienen die moeten worden geïmplementeerd om jouw gebruiksscenario op te lossen.
### Auteurs
<div align="center">
<a href="https://github.com/usebruno/bruno/graphs/contributors">
<img src="https://contrib.rocks/image?repo=usebruno/bruno" />
</a>
</div>
### Licentie 📄
[MIT](../../license.md)

19928
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -30,11 +30,13 @@
"ts-jest": "^29.0.5"
},
"scripts": {
"setup": "node ./scripts/setup.js",
"dev": "concurrently --kill-others \"npm run dev:web\" \"npm run dev:electron\"",
"dev:web": "npm run dev --workspace=packages/bruno-app",
"build:web": "npm run build --workspace=packages/bruno-app",
"prettier:web": "npm run prettier --workspace=packages/bruno-app",
"dev:electron": "npm run dev --workspace=packages/bruno-electron",
"dev:electron:debug": "npm run debug --workspace=packages/bruno-electron",
"build:bruno-common": "npm run build --workspace=packages/bruno-common",
"build:bruno-query": "npm run build --workspace=packages/bruno-query",
"build:graphql-docs": "npm run build --workspace=packages/bruno-graphql-docs",
@@ -51,10 +53,6 @@
"prepare": "husky install"
},
"overrides": {
"rollup":"3.29.4"
},
"dependencies": {
"json-bigint": "^1.0.0",
"lossless-json": "^4.0.1"
"rollup": "3.29.5"
}
}

View File

@@ -1,4 +1,4 @@
{
"presets": ["next/babel"],
"presets": ["@babel/preset-env"],
"plugins": [["styled-components", { "ssr": true }]]
}

View File

@@ -31,4 +31,6 @@ yarn-error.log*
# next.js
.next/
out/
dist/
.env

View File

@@ -0,0 +1,16 @@
module.exports = {
rootDir: '.',
moduleNameMapper: {
'^assets/(.*)$': '<rootDir>/src/assets/$1',
'^components/(.*)$': '<rootDir>/src/components/$1',
'^hooks/(.*)$': '<rootDir>/src/hooks/$1',
'^themes/(.*)$': '<rootDir>/src/themes/$1',
'^api/(.*)$': '<rootDir>/src/api/$1',
'^pageComponents/(.*)$': '<rootDir>/src/pageComponents/$1',
'^providers/(.*)$': '<rootDir>/src/providers/$1',
'^utils/(.*)$': '<rootDir>/src/utils/$1'
},
clearMocks: true,
moduleDirectories: ['node_modules', 'src'],
testEnvironment: 'node'
};

View File

@@ -1,15 +0,0 @@
module.exports = {
reactStrictMode: false,
publicRuntimeConfig: {
CI: process.env.CI,
PLAYWRIGHT: process.env.PLAYWRIGHT,
ENV: process.env.ENV
},
webpack: (config, { isServer }) => {
// Fixes npm packages that depend on `fs` module
if (!isServer) {
config.resolve.fallback.fs = false;
}
return config;
},
};

View File

@@ -3,74 +3,69 @@
"version": "0.3.0",
"private": true,
"scripts": {
"dev": "cross-env ENV=dev next dev -p 3000",
"build": "next build && next export",
"start": "next start",
"lint": "next lint",
"dev": "rsbuild dev",
"build": "rsbuild build -m production",
"preview": "rsbuild preview",
"test": "jest",
"test:prettier": "prettier --check \"./src/**/*.{js,jsx,json,ts,tsx}\"",
"prettier": "prettier --write \"./src/**/*.{js,jsx,json,ts,tsx}\""
},
"dependencies": {
"@babel/preset-env": "^7.26.0",
"@fontsource/inter": "^5.0.15",
"@fortawesome/fontawesome-svg-core": "^1.2.36",
"@fortawesome/free-solid-svg-icons": "^5.15.4",
"@fortawesome/react-fontawesome": "^0.1.16",
"@prantlf/jsonlint": "^16.0.0",
"@reduxjs/toolkit": "^1.8.0",
"@tabler/icons": "^1.46.0",
"@tippyjs/react": "^4.2.6",
"@usebruno/common": "0.1.0",
"@usebruno/graphql-docs": "0.1.0",
"@usebruno/schema": "0.7.0",
"axios": "^1.5.1",
"classnames": "^2.3.1",
"codemirror": "5.65.2",
"codemirror-graphql": "1.2.5",
"cookie": "^0.6.0",
"codemirror-graphql": "2.1.1",
"cookie": "0.7.1",
"escape-html": "^1.0.3",
"file": "^0.2.2",
"file-dialog": "^0.0.8",
"file-saver": "^2.0.5",
"formik": "^2.2.9",
"github-markdown-css": "^5.2.0",
"graphiql": "^1.5.9",
"graphiql": "3.7.1",
"graphql": "^16.6.0",
"graphql-request": "^3.7.0",
"httpsnippet": "^3.0.6",
"i18next": "^23.14.0",
"i18next": "24.1.2",
"idb": "^7.0.0",
"immer": "^9.0.15",
"jsesc": "^3.0.2",
"jshint": "^2.13.6",
"json5": "^2.2.3",
"jsonc-parser": "^3.2.1",
"jsonlint": "^1.6.3",
"jsonpath-plus": "^7.2.0",
"jsonpath-plus": "10.2.0",
"know-your-http-well": "^0.5.0",
"lodash": "^4.17.21",
"markdown-it": "^13.0.2",
"markdown-it-replace-link": "^1.2.0",
"mousetrap": "^1.6.5",
"nanoid": "3.3.4",
"next": "12.3.3",
"nanoid": "3.3.8",
"path": "^0.12.7",
"pdfjs-dist": "^3.11.174",
"pdfjs-dist": "4.4.168",
"platform": "^1.3.6",
"posthog-node": "^2.1.0",
"posthog-node": "4.2.1",
"prettier": "^2.7.1",
"qs": "^6.11.0",
"query-string": "^7.0.1",
"react": "18.2.0",
"react": "19.0.0",
"react-copy-to-clipboard": "^5.1.0",
"react-dnd": "^16.0.1",
"react-dnd-html5-backend": "^16.0.1",
"react-dom": "18.2.0",
"react-github-btn": "^1.4.0",
"react-dom": "19.0.0",
"react-hot-toast": "^2.4.0",
"react-i18next": "^15.0.1",
"react-inspector": "^6.0.2",
"react-pdf": "^7.5.1",
"react-redux": "^7.2.6",
"react-pdf": "9.1.1",
"react-player": "^2.16.0",
"react-redux": "^7.2.9",
"react-tooltip": "^5.5.2",
"sass": "^1.46.0",
"strip-json-comments": "^5.0.1",
@@ -82,20 +77,21 @@
"yup": "^0.32.11"
},
"devDependencies": {
"@babel/core": "^7.16.0",
"@babel/plugin-transform-spread": "^7.16.7",
"@babel/preset-env": "^7.16.4",
"@babel/preset-react": "^7.16.0",
"@babel/runtime": "^7.16.3",
"autoprefixer": "^10.4.17",
"babel-loader": "^8.2.3",
"@rsbuild/core": "^1.1.2",
"@rsbuild/plugin-babel": "^1.0.3",
"@rsbuild/plugin-node-polyfill": "^1.2.0",
"@rsbuild/plugin-react": "^1.0.7",
"@rsbuild/plugin-sass": "^1.1.0",
"@rsbuild/plugin-styled-components": "1.1.0",
"autoprefixer": "10.4.20",
"babel-plugin-react-compiler": "19.0.0-beta-a7bf2bd-20241110",
"cross-env": "^7.0.3",
"css-loader": "^6.5.1",
"css-loader": "7.1.2",
"file-loader": "^6.2.0",
"html-loader": "^3.0.1",
"html-webpack-plugin": "^5.5.0",
"mini-css-extract-plugin": "^2.4.5",
"postcss": "^8.4.35",
"postcss": "8.4.47",
"style-loader": "^3.3.1",
"tailwindcss": "^3.4.1",
"webpack": "^5.64.4",

View File

@@ -0,0 +1,39 @@
import { defineConfig } from '@rsbuild/core';
import { pluginReact } from '@rsbuild/plugin-react';
import { pluginBabel } from '@rsbuild/plugin-babel';
import { pluginStyledComponents } from '@rsbuild/plugin-styled-components';
import { pluginSass } from '@rsbuild/plugin-sass';
import { pluginNodePolyfill } from '@rsbuild/plugin-node-polyfill'
export default defineConfig({
plugins: [
pluginNodePolyfill(),
pluginReact(),
pluginStyledComponents(),
pluginSass(),
pluginBabel({
include: /\.(?:js|jsx|tsx)$/,
babelLoaderOptions(opts) {
opts.plugins?.unshift('babel-plugin-react-compiler');
}
})
],
source: {
tsconfigPath: './jsconfig.json', // Specifies the path to the JavaScript/TypeScript configuration file
},
html: {
title: 'Bruno'
},
tools: {
rspack: {
module: {
parser: {
javascript: {
// This loads the JavaScript contents from a library along with the main JavaScript bundle.
dynamicImportMode: "eager",
},
},
},
},
}
});

View File

@@ -8,6 +8,17 @@ const StyledWrapper = styled.div`
font-size: ${(props) => (props.fontSize ? `${props.fontSize}px` : 'inherit')};
line-break: anywhere;
flex: 1 1 0;
display: flex;
flex-direction: column-reverse;
}
/* Removes the glow outline around the folded json */
.CodeMirror-foldmarker {
text-shadow: none;
color: ${(props) => props.theme.textLink};
background: none;
padding: 0;
margin: 0;
}
.CodeMirror-overlayscroll-horizontal div,
@@ -17,6 +28,16 @@ const StyledWrapper = styled.div`
.CodeMirror-dialog {
overflow: visible;
position: relative;
top: unset;
left: unset;
input {
background: transparent;
border: 1px solid #d3d6db;
outline: none;
border-radius: 0px;
}
}
#search-results-count {
@@ -69,6 +90,18 @@ const StyledWrapper = styled.div`
.cm-variable-invalid {
color: red;
}
.CodeMirror-search-hint {
display: inline;
}
.cm-s-default span.cm-property {
color: #1f61a0 !important;
}
.cm-s-default span.cm-variable {
color: #397d13 !important;
}
`;
export default StyledWrapper;

View File

@@ -6,16 +6,16 @@
*/
import React from 'react';
import isEqual from 'lodash/isEqual';
import { getEnvironmentVariables } from 'utils/collections';
import { isEqual, escapeRegExp } from 'lodash';
import { defineCodeMirrorBrunoVariablesMode } from 'utils/common/codemirror';
import StyledWrapper from './StyledWrapper';
import jsonlint from 'jsonlint';
import * as jsonlint from '@prantlf/jsonlint';
import { JSHINT } from 'jshint';
import stripJsonComments from 'strip-json-comments';
import { getAllVariables } from 'utils/collections';
let CodeMirror;
const SERVER_RENDERED = typeof navigator === 'undefined' || global['PREVENT_CODEMIRROR_RENDER'] === true;
const SERVER_RENDERED = typeof window === 'undefined' || global['PREVENT_CODEMIRROR_RENDER'] === true;
const TAB_SIZE = 2;
if (!SERVER_RENDERED) {
@@ -55,21 +55,35 @@ if (!SERVER_RENDERED) {
'req.setMaxRedirects(maxRedirects)',
'req.getTimeout()',
'req.setTimeout(timeout)',
'req.getExecutionMode()',
'bru',
'bru.cwd()',
'bru.getEnvName(key)',
'bru.getEnvName()',
'bru.getProcessEnv(key)',
'bru.hasEnvVar(key)',
'bru.getEnvVar(key)',
'bru.getFolderVar(key)',
'bru.getCollectionVar(key)',
'bru.setEnvVar(key,value)',
'bru.deleteEnvVar(key)',
'bru.hasVar(key)',
'bru.getVar(key)',
'bru.setVar(key,value)',
'bru.deleteVar(key)',
'bru.deleteAllVars()',
'bru.setNextRequest(requestName)',
'req.disableParsingResponseJson()',
'bru.getRequestVar(key)',
'bru.sleep(ms)'
'bru.runRequest(requestPathName)',
'bru.getAssertionResults()',
'bru.getTestResults()',
'bru.sleep(ms)',
'bru.getGlobalEnvVar(key)',
'bru.setGlobalEnvVar(key, value)',
'bru.runner',
'bru.runner.setNextRequest(requestName)',
'bru.runner.skipRequest()',
'bru.runner.stopExecution()',
];
CodeMirror.registerHelper('hint', 'brunoJS', (editor, options) => {
const cursor = editor.getCursor();
@@ -91,7 +105,7 @@ if (!SERVER_RENDERED) {
if (curWordBru) {
hintWords.forEach((h) => {
if (h.includes('.') == curWordBru.includes('.') && h.startsWith(curWordBru)) {
result.list.push(curWordBru.includes('.') ? h.split('.')[1] : h);
result.list.push(curWordBru.includes('.') ? h.split('.')?.at(-1) : h);
}
});
result.list?.sort();
@@ -183,31 +197,19 @@ export default class CodeEditor extends React.Component {
'Cmd-Y': 'foldAll',
'Ctrl-I': 'unfoldAll',
'Cmd-I': 'unfoldAll',
'Cmd-/': (cm) => {
// comment/uncomment every selected line(s)
const selections = cm.listSelections();
selections.forEach((range) => {
for (let i = range.from().line; i <= range.to().line; i++) {
const selectedLine = cm.getLine(i);
// if commented line, remove comment
if (selectedLine.trim().startsWith('//')) {
cm.replaceRange(
selectedLine.replace(/^(\s*)\/\/\s?/, '$1'),
{ line: i, ch: 0 },
{ line: i, ch: selectedLine.length }
);
continue;
}
// otherwise add comment
cm.replaceRange(
selectedLine.search(/\S|$/) >= TAB_SIZE
? ' '.repeat(TAB_SIZE) + '// ' + selectedLine.trim()
: '// ' + selectedLine,
{ line: i, ch: 0 },
{ line: i, ch: selectedLine.length }
);
}
});
'Ctrl-/': () => {
if (['application/ld+json', 'application/json'].includes(this.props.mode)) {
this.editor.toggleComment({ lineComment: '//', blockComment: '/*' });
} else {
this.editor.toggleComment();
}
},
'Cmd-/': () => {
if (['application/ld+json', 'application/json'].includes(this.props.mode)) {
this.editor.toggleComment({ lineComment: '//', blockComment: '/*' });
} else {
this.editor.toggleComment();
}
}
},
foldOptions: {
@@ -245,17 +247,20 @@ export default class CodeEditor extends React.Component {
return found;
}
let jsonlint = window.jsonlint.parser || window.jsonlint;
jsonlint.parseError = function (str, hash) {
let loc = hash.loc;
found.push({
from: CodeMirror.Pos(loc.first_line - 1, loc.first_column),
to: CodeMirror.Pos(loc.last_line - 1, loc.last_column),
message: str
});
};
try {
jsonlint.parse(stripJsonComments(text.replace(/(?<!"[^":{]*){{[^}]*}}(?![^"},]*")/g, '1')));
} catch (e) {}
} catch (error) {
const { message, location } = error;
const line = location?.start?.line;
const column = location?.start?.column;
if (line && column) {
found.push({
from: CodeMirror.Pos(line - 1, column),
to: CodeMirror.Pos(line - 1, column),
message
});
}
}
return found;
});
if (editor) {
@@ -272,9 +277,9 @@ export default class CodeEditor extends React.Component {
while (end < currentLine.length && /[^{}();\s\[\]\,]/.test(currentLine.charAt(end))) ++end;
while (start && /[^{}();\s\[\]\,]/.test(currentLine.charAt(start - 1))) --start;
let curWord = start != end && currentLine.slice(start, end);
//Qualify if autocomplete will be shown
// Qualify if autocomplete will be shown
if (
/^(?!Shift|Tab|Enter|Escape|ArrowUp|ArrowDown|ArrowLeft|ArrowRight|\s)\w*/.test(event.key) &&
/^(?!Shift|Tab|Enter|Escape|ArrowUp|ArrowDown|ArrowLeft|ArrowRight|Meta|Alt|Home|End\s)\w*/.test(event.key) &&
curWord.length > 0 &&
!/\/\/|\/\*|.*{{|`[^$]*{|`[^{]*$/.test(currentLine.slice(0, end)) &&
/(?<!\d)[a-zA-Z\._]$/.test(curWord)
@@ -303,7 +308,7 @@ export default class CodeEditor extends React.Component {
}
if (this.editor) {
let variables = getEnvironmentVariables(this.props.collection);
let variables = getAllVariables(this.props.collection, this.props.item);
if (!isEqual(variables, this.variables)) {
this.addOverlay();
}
@@ -330,7 +335,7 @@ export default class CodeEditor extends React.Component {
}
return (
<StyledWrapper
className="h-full w-full flex flex-col relative"
className="h-full w-full flex flex-col relative graphiql-container"
aria-label="Code Editor"
font={this.props.font}
fontSize={this.props.fontSize}
@@ -343,7 +348,7 @@ export default class CodeEditor extends React.Component {
addOverlay = () => {
const mode = this.props.mode || 'application/ld+json';
let variables = getEnvironmentVariables(this.props.collection);
let variables = getAllVariables(this.props.collection, this.props.item);
this.variables = variables;
defineCodeMirrorBrunoVariablesMode(variables, mode);
@@ -406,7 +411,8 @@ export default class CodeEditor extends React.Component {
const searchInput = document.querySelector('.CodeMirror-search-field');
if (searchInput && searchInput.value.length > 0) {
const text = new RegExp(searchInput.value, 'gi');
// Escape special characters in search input to prevent RegExp crashes. Fixes #3051
const text = new RegExp(escapeRegExp(searchInput.value), 'gi');
const matches = this.editor.getValue().match(text);
count = matches ? matches.length : 0;
}

View File

@@ -0,0 +1,56 @@
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};
}
.auth-placement-selector {
padding: 0.5rem 0px;
border-radius: 3px;
border: solid 1px ${(props) => props.theme.input.border};
background-color: ${(props) => props.theme.input.bg};
.dropdown {
width: fit-content;
div[data-tippy-root] {
width: fit-content;
}
.tippy-box {
width: fit-content;
max-width: none !important;
.tippy-content: {
width: fit-content;
max-width: none !important;
}
}
}
.auth-type-label {
width: fit-content;
color: ${(props) => props.theme.colors.text.yellow};
justify-content: space-between;
padding: 0 0.5rem;
}
.dropdown-item {
padding: 0.2rem 0.6rem !important;
}
}
.caret {
color: rgb(140, 140, 140);
fill: rgb(140 140 140);
}
`;
export default Wrapper;

View File

@@ -0,0 +1,109 @@
import React, { useRef, forwardRef, useEffect } from 'react';
import { useDispatch } from 'react-redux';
import get from 'lodash/get';
import { IconCaretDown } from '@tabler/icons';
import Dropdown from 'components/Dropdown';
import { useTheme } from 'providers/Theme';
import SingleLineEditor from 'components/SingleLineEditor';
import { updateCollectionAuth } from 'providers/ReduxStore/slices/collections';
import { saveCollectionRoot } from 'providers/ReduxStore/slices/collections/actions';
import StyledWrapper from './StyledWrapper';
import { humanizeRequestAPIKeyPlacement } from 'utils/collections';
const ApiKeyAuth = ({ collection }) => {
const dispatch = useDispatch();
const { storedTheme } = useTheme();
const dropdownTippyRef = useRef();
const onDropdownCreate = (ref) => (dropdownTippyRef.current = ref);
const apikeyAuth = get(collection, 'root.request.auth.apikey', {});
const handleSave = () => dispatch(saveCollectionRoot(collection.uid));
const Icon = forwardRef((props, ref) => {
return (
<div ref={ref} className="flex items-center justify-end auth-type-label select-none">
{humanizeRequestAPIKeyPlacement(apikeyAuth?.placement)}
<IconCaretDown className="caret ml-1 mr-1" size={14} strokeWidth={2} />
</div>
);
});
const handleAuthChange = (property, value) => {
dispatch(
updateCollectionAuth({
mode: 'apikey',
collectionUid: collection.uid,
content: {
...apikeyAuth,
[property]: value
}
})
);
};
useEffect(() => {
!apikeyAuth?.placement &&
dispatch(
updateCollectionAuth({
mode: 'apikey',
collectionUid: collection.uid,
content: {
placement: 'header'
}
})
);
}, [apikeyAuth]);
return (
<StyledWrapper className="mt-2 w-full">
<label className="block font-medium mb-2">Key</label>
<div className="single-line-editor-wrapper mb-2">
<SingleLineEditor
value={apikeyAuth.key || ''}
theme={storedTheme}
onSave={handleSave}
onChange={(val) => handleAuthChange('key', val)}
collection={collection}
/>
</div>
<label className="block font-medium mb-2">Value</label>
<div className="single-line-editor-wrapper mb-2">
<SingleLineEditor
value={apikeyAuth.value || ''}
theme={storedTheme}
onSave={handleSave}
onChange={(val) => handleAuthChange('value', val)}
collection={collection}
/>
</div>
<label className="block font-medium mb-2">Add To</label>
<div className="inline-flex items-center cursor-pointer auth-placement-selector w-fit">
<Dropdown onCreate={onDropdownCreate} icon={<Icon />} placement="bottom-end">
<div
className="dropdown-item"
onClick={() => {
dropdownTippyRef.current.hide();
handleAuthChange('placement', 'header');
}}
>
Header
</div>
<div
className="dropdown-item"
onClick={() => {
dropdownTippyRef.current.hide();
handleAuthChange('placement', 'queryparams');
}}
>
Query Params
</div>
</Dropdown>
</div>
</StyledWrapper>
);
};
export default ApiKeyAuth;

View File

@@ -52,6 +52,15 @@ const AuthMode = ({ collection }) => {
>
Basic Auth
</div>
<div
className="dropdown-item"
onClick={() => {
dropdownTippyRef.current.hide();
onModeChange('wsse');
}}
>
WSSE Auth
</div>
<div
className="dropdown-item"
onClick={() => {
@@ -70,6 +79,15 @@ const AuthMode = ({ collection }) => {
>
Digest Auth
</div>
<div
className="dropdown-item"
onClick={() => {
dropdownTippyRef.current.hide();
onModeChange('ntlm');
}}
>
NTLM Auth
</div>
<div
className="dropdown-item"
onClick={() => {
@@ -79,6 +97,15 @@ const AuthMode = ({ collection }) => {
>
Oauth2
</div>
<div
className="dropdown-item"
onClick={() => {
dropdownTippyRef.current.hide();
onModeChange('apikey');
}}
>
API Key
</div>
<div
className="dropdown-item"
onClick={() => {

View File

@@ -0,0 +1,17 @@
import styled from 'styled-components';
const Wrapper = styled.div`
label {
font-size: 0.8125rem;
}
.single-line-editor-wrapper {
max-width: 400px;
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;

View File

@@ -0,0 +1,110 @@
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 NTLMAuth = ({ collection }) => {
const dispatch = useDispatch();
const { storedTheme } = useTheme();
const ntlmAuth = get(collection, 'root.request.auth.ntlm', {});
const handleSave = () => dispatch(saveCollectionRoot(collection.uid));
const handleUsernameChange = (username) => {
dispatch(
updateCollectionAuth({
mode: 'ntlm',
collectionUid: collection.uid,
content: {
username: username,
password: ntlmAuth.password,
domain: ntlmAuth.domain
}
})
);
};
const handlePasswordChange = (password) => {
dispatch(
updateCollectionAuth({
mode: 'ntlm',
collectionUid: collection.uid,
content: {
username: ntlmAuth.username,
password: password,
domain: ntlmAuth.domain
}
})
);
};
const handleDomainChange = (domain) => {
dispatch(
updateCollectionAuth({
mode: 'ntlm',
collectionUid: collection.uid,
content: {
username: ntlmAuth.username,
password: ntlmAuth.password,
domain: domain
}
})
);
};
return (
<StyledWrapper className="mt-2 w-full">
<label className="block font-medium mb-2">Username</label>
<div className="single-line-editor-wrapper mb-2">
<SingleLineEditor
value={ntlmAuth.username || ''}
theme={storedTheme}
onSave={handleSave}
onChange={(val) => handleUsernameChange(val)}
collection={collection}
/>
</div>
<label className="block font-medium mb-2">Password</label>
<div className="single-line-editor-wrapper">
<SingleLineEditor
value={ntlmAuth.password || ''}
theme={storedTheme}
onSave={handleSave}
onChange={(val) => handlePasswordChange(val)}
collection={collection}
isSecret={true}
/>
</div>
<label className="block font-medium mb-2">Domain</label>
<div className="single-line-editor-wrapper">
<SingleLineEditor
value={ntlmAuth.domain || ''}
theme={storedTheme}
onSave={handleSave}
onChange={(val) => handleDomainChange(val)}
collection={collection}
/>
</div>
</StyledWrapper>
);
};
export default NTLMAuth;

View File

@@ -1,5 +1,7 @@
import styled from 'styled-components';
const Wrapper = styled.div``;
const Wrapper = styled.div`
max-width: 800px;
`;
export default Wrapper;

View File

@@ -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;

View File

@@ -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 WsseAuth = ({ collection }) => {
const dispatch = useDispatch();
const { storedTheme } = useTheme();
const wsseAuth = get(collection, 'root.request.auth.wsse', {});
const handleSave = () => dispatch(saveCollectionRoot(collection.uid));
const handleUserChange = (username) => {
dispatch(
updateCollectionAuth({
mode: 'wsse',
collectionUid: collection.uid,
content: {
username,
password: wsseAuth.password
}
})
);
};
const handlePasswordChange = (password) => {
dispatch(
updateCollectionAuth({
mode: 'wsse',
collectionUid: collection.uid,
content: {
username: wsseAuth.username,
password
}
})
);
};
return (
<StyledWrapper className="mt-2 w-full">
<label className="block font-medium mb-2">Username</label>
<div className="single-line-editor-wrapper mb-2">
<SingleLineEditor
value={wsseAuth.username || ''}
theme={storedTheme}
onSave={handleSave}
onChange={(val) => handleUserChange(val)}
collection={collection}
/>
</div>
<label className="block font-medium mb-2">Password</label>
<div className="single-line-editor-wrapper">
<SingleLineEditor
value={wsseAuth.password || ''}
theme={storedTheme}
onSave={handleSave}
onChange={(val) => handlePasswordChange(val)}
collection={collection}
/>
</div>
</StyledWrapper>
);
};
export default WsseAuth;

View File

@@ -6,9 +6,13 @@ import AwsV4Auth from './AwsV4Auth';
import BearerAuth from './BearerAuth';
import BasicAuth from './BasicAuth';
import DigestAuth from './DigestAuth';
import WsseAuth from './WsseAuth';
import ApiKeyAuth from './ApiKeyAuth/';
import { saveCollectionRoot } from 'providers/ReduxStore/slices/collections/actions';
import StyledWrapper from './StyledWrapper';
import OAuth2 from './OAuth2';
import NTLMAuth from './NTLMAuth';
const Auth = ({ collection }) => {
const authMode = get(collection, 'root.request.auth.mode');
@@ -30,9 +34,18 @@ const Auth = ({ collection }) => {
case 'digest': {
return <DigestAuth collection={collection} />;
}
case 'ntlm': {
return <NTLMAuth collection={collection} />;
}
case 'oauth2': {
return <OAuth2 collection={collection} />;
}
case 'wsse': {
return <WsseAuth collection={collection} />;
}
case 'apikey': {
return <ApiKeyAuth collection={collection} />;
}
}
};

View File

@@ -68,12 +68,13 @@ const ClientCertSettings = ({ root, clientCertConfig, onUpdate, onRemove }) => {
});
const getFile = (e) => {
if (e.files?.[0]?.path) {
const filePath = window?.ipcRenderer?.getFilePath(e?.files?.[0]);
if (filePath) {
let relativePath;
if (isWindowsOS()) {
relativePath = slash(path.win32.relative(root, e.files[0].path));
relativePath = slash(path.win32.relative(root, filePath));
} else {
relativePath = path.posix.relative(root, e.files[0].path);
relativePath = path.posix.relative(root, filePath);
}
formik.setFieldValue(e.name, relativePath);
}

View File

@@ -2,16 +2,12 @@ import styled from 'styled-components';
const StyledWrapper = styled.div`
div.CodeMirror {
/* todo: find a better way */
height: calc(100vh - 240px);
.CodeMirror-scroll {
padding-bottom: 0px;
}
}
.editing-mode {
cursor: pointer;
color: ${(props) => props.theme.colors.text.yellow};
}
`;

View File

@@ -8,6 +8,7 @@ import { saveCollectionRoot } from 'providers/ReduxStore/slices/collections/acti
import Markdown from 'components/MarkDown';
import CodeEditor from 'components/CodeEditor';
import StyledWrapper from './StyledWrapper';
import { IconEdit, IconX, IconFileText } from '@tabler/icons';
const Docs = ({ collection }) => {
const dispatch = useDispatch();
@@ -29,19 +30,50 @@ const Docs = ({ collection }) => {
);
};
const onSave = () => dispatch(saveCollectionRoot(collection.uid));
const handleDiscardChanges = () => {
dispatch(
updateCollectionDocs({
collectionUid: collection.uid,
docs: docs
})
);
toggleViewMode();
}
const onSave = () => {
dispatch(saveCollectionRoot(collection.uid));
toggleViewMode();
}
return (
<StyledWrapper className="mt-1 h-full w-full relative">
<div className="editing-mode mb-2" role="tab" onClick={toggleViewMode}>
{isEditing ? 'Preview' : 'Edit'}
<StyledWrapper className="mt-1 h-full w-full relative flex flex-col">
<div className='flex flex-row w-full justify-between items-center mb-4'>
<div className='text-lg font-medium flex items-center gap-2'>
<IconFileText size={20} strokeWidth={1.5} />
Documentation
</div>
<div className='flex flex-row gap-2 items-center justify-center'>
{isEditing ? (
<>
<div className="editing-mode" role="tab" onClick={handleDiscardChanges}>
<IconX className="cursor-pointer" size={20} strokeWidth={1.5} />
</div>
<button type="submit" className="submit btn btn-sm btn-secondary" onClick={onSave}>
Save
</button>
</>
) : (
<div className="editing-mode" role="tab" onClick={toggleViewMode}>
<IconEdit className="cursor-pointer" size={20} strokeWidth={1.5} />
</div>
)}
</div>
</div>
{isEditing ? (
<CodeEditor
collection={collection}
theme={displayedTheme}
value={docs || ''}
value={docs}
onEdit={onEdit}
onSave={onSave}
mode="application/text"
@@ -49,10 +81,44 @@ const Docs = ({ collection }) => {
fontSize={get(preferences, 'font.codeFontSize')}
/>
) : (
<Markdown collectionPath={collection.pathname} onDoubleClick={toggleViewMode} content={docs} />
<div className='h-full overflow-auto pl-1'>
<div className='h-[1px] min-h-[500px]'>
{
docs?.length > 0 ?
<Markdown collectionPath={collection.pathname} onDoubleClick={toggleViewMode} content={docs} />
:
<Markdown collectionPath={collection.pathname} onDoubleClick={toggleViewMode} content={documentationPlaceholder} />
}
</div>
</div>
)}
</StyledWrapper>
);
};
export default Docs;
const documentationPlaceholder = `
Welcome to your collection documentation! This space is designed to help you document your API collection effectively.
## Overview
Use this section to provide a high-level overview of your collection. You can describe:
- The purpose of these API endpoints
- Key features and functionalities
- Target audience or users
## Best Practices
- Keep documentation up to date
- Include request/response examples
- Document error scenarios
- Add relevant links and references
## Markdown Support
This documentation supports Markdown formatting! You can use:
- **Bold** and *italic* text
- \`code blocks\` and syntax highlighting
- Tables and lists
- [Links](https://example.com)
- And more!
`;

View File

@@ -1,6 +1,8 @@
import styled from 'styled-components';
const Wrapper = styled.div`
max-width: 800px;
table {
width: 100%;
border-collapse: collapse;

View File

@@ -1,39 +0,0 @@
import React from 'react';
import StyledWrapper from './StyledWrapper';
import { getTotalRequestCountInCollection } from 'utils/collections/';
const Info = ({ collection }) => {
const totalRequestsInCollection = getTotalRequestCountInCollection(collection);
return (
<StyledWrapper className="w-full flex flex-col h-full">
<div className="text-xs mb-4 text-muted">General information about the collection.</div>
<table className="w-full border-collapse">
<tbody>
<tr className="">
<td className="py-2 px-2 text-right">Name&nbsp;:</td>
<td className="py-2 px-2">{collection.name}</td>
</tr>
<tr className="">
<td className="py-2 px-2 text-right">Location&nbsp;:</td>
<td className="py-2 px-2 break-all">{collection.pathname}</td>
</tr>
<tr className="">
<td className="py-2 px-2 text-right">Ignored files&nbsp;:</td>
<td className="py-2 px-2 break-all">{collection.brunoConfig?.ignore?.map((x) => `'${x}'`).join(', ')}</td>
</tr>
<tr className="">
<td className="py-2 px-2 text-right">Environments&nbsp;:</td>
<td className="py-2 px-2">{collection.environments?.length || 0}</td>
</tr>
<tr className="">
<td className="py-2 px-2 text-right">Requests&nbsp;:</td>
<td className="py-2 px-2">{totalRequestsInCollection}</td>
</tr>
</tbody>
</table>
</StyledWrapper>
);
};
export default Info;

View File

@@ -0,0 +1,56 @@
import React from 'react';
import { getTotalRequestCountInCollection } from 'utils/collections/';
import { IconFolder, IconFileOff, IconWorld, IconApi } from '@tabler/icons';
const Info = ({ collection }) => {
const totalRequestsInCollection = getTotalRequestCountInCollection(collection);
return (
<div className="w-full flex flex-col h-fit">
<div className="rounded-lg py-6">
<div className="grid gap-6">
{/* Location Row */}
<div className="flex items-start">
<div className="flex-shrink-0 p-3 bg-blue-50 dark:bg-blue-900/20 rounded-lg">
<IconFolder className="w-5 h-5 text-blue-500" stroke={1.5} />
</div>
<div className="ml-4">
<div className="font-semibold text-sm">Location</div>
<div className="mt-1 text-sm text-muted break-all">
{collection.pathname}
</div>
</div>
</div>
{/* Environments Row */}
<div className="flex items-start">
<div className="flex-shrink-0 p-3 bg-green-50 dark:bg-green-900/20 rounded-lg">
<IconWorld className="w-5 h-5 text-green-500" stroke={1.5} />
</div>
<div className="ml-4">
<div className="font-semibold text-sm">Environments</div>
<div className="mt-1 text-sm text-muted">
{collection.environments?.length || 0} environment{collection.environments?.length !== 1 ? 's' : ''} configured
</div>
</div>
</div>
{/* Requests Row */}
<div className="flex items-start">
<div className="flex-shrink-0 p-3 bg-purple-50 dark:bg-purple-900/20 rounded-lg">
<IconApi className="w-5 h-5 text-purple-500" stroke={1.5} />
</div>
<div className="ml-4">
<div className="font-semibold text-sm">Requests</div>
<div className="mt-1 text-sm text-muted">
{totalRequestsInCollection} request{totalRequestsInCollection !== 1 ? 's' : ''} in collection
</div>
</div>
</div>
</div>
</div>
</div>
);
};
export default Info;

View File

@@ -0,0 +1,25 @@
import styled from 'styled-components';
const StyledWrapper = styled.div`
&.card {
background-color: ${(props) => props.theme.requestTabPanel.card.bg};
.title {
border-top: 1px solid ${(props) => props.theme.requestTabPanel.cardTable.border};
border-left: 1px solid ${(props) => props.theme.requestTabPanel.cardTable.border};
border-right: 1px solid ${(props) => props.theme.requestTabPanel.cardTable.border};
border-top-left-radius: 3px;
border-top-right-radius: 3px;
}
.table {
thead {
background-color: ${(props) => props.theme.requestTabPanel.cardTable.table.thead.bg};
color: ${(props) => props.theme.requestTabPanel.cardTable.table.thead.color};
}
}
}
`;
export default StyledWrapper;

View File

@@ -0,0 +1,50 @@
import React from 'react';
import { flattenItems } from "utils/collections";
import { IconAlertTriangle } from '@tabler/icons';
import StyledWrapper from "./StyledWrapper";
const RequestsNotLoaded = ({ collection }) => {
const flattenedItems = flattenItems(collection.items);
const itemsFailedLoading = flattenedItems?.filter(item => item?.partial && !item?.loading);
if (!itemsFailedLoading?.length) {
return null;
}
return (
<StyledWrapper className="w-full card my-2">
<div className="flex items-center gap-2 px-3 py-2 title bg-yellow-50 dark:bg-yellow-900/20">
<IconAlertTriangle size={16} className="text-yellow-500" />
<span className="font-medium">Following requests were not loaded</span>
</div>
<table className="w-full border-collapse">
<thead>
<tr>
<th className="py-2 px-3 text-left font-medium">
Pathname
</th>
<th className="py-2 px-3 text-left font-medium">
Size
</th>
</tr>
</thead>
<tbody>
{flattenedItems?.map((item, index) => (
item?.partial && !item?.loading ? (
<tr key={index}>
<td className="py-1.5 px-3">
{item?.pathname?.split(`${collection?.pathname}/`)?.[1]}
</td>
<td className="py-1.5 px-3">
{item?.size?.toFixed?.(2)}&nbsp;MB
</td>
</tr>
) : null
))}
</tbody>
</table>
</StyledWrapper>
);
};
export default RequestsNotLoaded;

View File

@@ -0,0 +1,25 @@
import styled from 'styled-components';
const StyledWrapper = styled.div`
.partial {
color: ${(props) => props.theme.colors.text.yellow};
opacity: 0.8;
}
.loading {
color: ${(props) => props.theme.colors.text.muted};
opacity: 0.8;
}
.completed {
color: ${(props) => props.theme.colors.text.green};
opacity: 0.8;
}
.failed {
color: ${(props) => props.theme.colors.text.danger};
opacity: 0.8;
}
`;
export default StyledWrapper;

View File

@@ -0,0 +1,27 @@
import StyledWrapper from "./StyledWrapper";
import Docs from "../Docs";
import Info from "./Info";
import { IconBox } from '@tabler/icons';
import RequestsNotLoaded from "./RequestsNotLoaded";
const Overview = ({ collection }) => {
return (
<div className="h-full">
<div className="grid grid-cols-5 gap-4 h-full">
<div className="col-span-2">
<div className="text-xl font-semibold flex items-center gap-2">
<IconBox size={24} stroke={1.5} />
{collection?.name}
</div>
<Info collection={collection} />
<RequestsNotLoaded collection={collection} />
</div>
<div className="col-span-3">
<Docs collection={collection} />
</div>
</div>
</div>
);
}
export default Overview;

View File

@@ -1,6 +1,8 @@
import styled from 'styled-components';
const StyledWrapper = styled.div`
max-width: 800px;
.settings-label {
width: 110px;
}

View File

@@ -336,4 +336,4 @@ const ProxySettings = ({ proxyConfig, onUpdate }) => {
);
};
export default ProxySettings;
export default ProxySettings;

View File

@@ -1,6 +1,8 @@
import styled from 'styled-components';
const StyledWrapper = styled.div`
max-width: 800px;
div.CodeMirror {
height: inherit;
}

View File

@@ -1,8 +1,6 @@
import styled from 'styled-components';
const StyledWrapper = styled.div`
max-width: 800px;
div.tabs {
div.tab {
padding: 6px 0px;

View File

@@ -1,5 +1,7 @@
import styled from 'styled-components';
const StyledWrapper = styled.div``;
const StyledWrapper = styled.div`
max-width: 800px;
`;
export default StyledWrapper;

View File

@@ -1,12 +1,10 @@
import styled from 'styled-components';
const StyledWrapper = styled.div`
table {
td {
&:first-child {
width: 120px;
}
}
max-width: 800px;
div.title {
color: var(--color-tab-inactive);
}
`;

View File

@@ -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-var {
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;

View File

@@ -0,0 +1,161 @@
import React from 'react';
import cloneDeep from 'lodash/cloneDeep';
import { IconTrash } from '@tabler/icons';
import { useDispatch } from 'react-redux';
import { useTheme } from 'providers/Theme';
import { saveCollectionRoot } from 'providers/ReduxStore/slices/collections/actions';
import SingleLineEditor from 'components/SingleLineEditor';
import InfoTip from 'components/InfoTip';
import StyledWrapper from './StyledWrapper';
import toast from 'react-hot-toast';
import { variableNameRegex } from 'utils/common/regex';
import {
addCollectionVar,
deleteCollectionVar,
updateCollectionVar
} from 'providers/ReduxStore/slices/collections/index';
const VarsTable = ({ collection, vars, varType }) => {
const dispatch = useDispatch();
const { storedTheme } = useTheme();
const addVar = () => {
dispatch(
addCollectionVar({
collectionUid: collection.uid,
type: varType
})
);
};
const onSave = () => dispatch(saveCollectionRoot(collection.uid));
const handleVarChange = (e, v, type) => {
const _var = cloneDeep(v);
switch (type) {
case 'name': {
const value = e.target.value;
if (variableNameRegex.test(value) === false) {
toast.error(
'Variable contains invalid characters! Variables must only contain alpha-numeric characters, "-", "_", "."'
);
return;
}
_var.name = value;
break;
}
case 'value': {
_var.value = e.target.value;
break;
}
case 'enabled': {
_var.enabled = e.target.checked;
break;
}
}
dispatch(
updateCollectionVar({
type: varType,
var: _var,
collectionUid: collection.uid
})
);
};
const handleRemoveVar = (_var) => {
dispatch(
deleteCollectionVar({
type: varType,
varUid: _var.uid,
collectionUid: collection.uid
})
);
};
return (
<StyledWrapper className="w-full">
<table>
<thead>
<tr>
<td>Name</td>
{varType === 'request' ? (
<td>
<div className="flex items-center">
<span>Value</span>
</div>
</td>
) : (
<td>
<div className="flex items-center">
<span>Expr</span>
<InfoTip text="You can write any valid JS Template Literal here" infotipId="request-var" />
</div>
</td>
)}
<td></td>
</tr>
</thead>
<tbody>
{vars && vars.length
? vars.map((_var) => {
return (
<tr key={_var.uid}>
<td>
<input
type="text"
autoComplete="off"
autoCorrect="off"
autoCapitalize="off"
spellCheck="false"
value={_var.name}
className="mousetrap"
onChange={(e) => handleVarChange(e, _var, 'name')}
/>
</td>
<td>
<SingleLineEditor
value={_var.value}
theme={storedTheme}
onSave={onSave}
onChange={(newValue) =>
handleVarChange(
{
target: {
value: newValue
}
},
_var,
'value'
)
}
collection={collection}
/>
</td>
<td>
<div className="flex items-center">
<input
type="checkbox"
checked={_var.enabled}
tabIndex="-1"
className="mr-3 mousetrap"
onChange={(e) => handleVarChange(e, _var, 'enabled')}
/>
<button tabIndex="-1" onClick={() => handleRemoveVar(_var)}>
<IconTrash strokeWidth={1.5} size={20} />
</button>
</div>
</td>
</tr>
);
})
: null}
</tbody>
</table>
<button className="btn-add-var text-link pr-2 py-3 mt-2 select-none" onClick={addVar}>
+ Add
</button>
</StyledWrapper>
);
};
export default VarsTable;

View File

@@ -0,0 +1,32 @@
import React from 'react';
import get from 'lodash/get';
import VarsTable from './VarsTable';
import StyledWrapper from './StyledWrapper';
import { saveCollectionRoot } from 'providers/ReduxStore/slices/collections/actions';
import { useDispatch } from 'react-redux';
const Vars = ({ collection }) => {
const dispatch = useDispatch();
const requestVars = get(collection, 'root.request.vars.req', []);
const responseVars = get(collection, 'root.request.vars.res', []);
const handleSave = () => dispatch(saveCollectionRoot(collection.uid));
return (
<StyledWrapper className="w-full flex flex-col">
<div className="flex-1 mt-2">
<div className="mb-1 title text-xs">Pre Request</div>
<VarsTable collection={collection} vars={requestVars} varType="request" />
</div>
<div className="flex-1">
<div className="mt-1 mb-1 title text-xs">Post Response</div>
<VarsTable collection={collection} vars={responseVars} varType="response" />
</div>
<div className="mt-6">
<button type="submit" className="submit btn btn-sm btn-secondary" onClick={handleSave}>
Save
</button>
</div>
</StyledWrapper>
);
};
export default Vars;

View File

@@ -12,10 +12,19 @@ import Headers from './Headers';
import Auth from './Auth';
import Script from './Script';
import Test from './Tests';
import Docs from './Docs';
import Presets from './Presets';
import Info from './Info';
import StyledWrapper from './StyledWrapper';
import Vars from './Vars/index';
import DotIcon from 'components/Icons/Dot';
import Overview from './Overview/index';
const ContentIndicator = () => {
return (
<sup className="ml-[.125rem] opacity-80 font-medium">
<DotIcon width="10"></DotIcon>
</sup>
);
};
const CollectionSettings = ({ collection }) => {
const dispatch = useDispatch();
@@ -29,10 +38,23 @@ const CollectionSettings = ({ collection }) => {
);
};
const proxyConfig = get(collection, 'brunoConfig.proxy', {});
const root = collection?.root;
const hasScripts = root?.request?.script?.res || root?.request?.script?.req;
const hasTests = root?.request?.tests;
const hasDocs = root?.docs;
const headers = get(collection, 'root.request.headers', []);
const activeHeadersCount = headers.filter((header) => header.enabled).length;
const requestVars = get(collection, 'root.request.vars.req', []);
const responseVars = get(collection, 'root.request.vars.res', []);
const activeVarsCount = requestVars.filter((v) => v.enabled).length + responseVars.filter((v) => v.enabled).length;
const auth = get(collection, 'root.request.auth', {}).mode;
const proxyConfig = get(collection, 'brunoConfig.proxy', {});
const clientCertConfig = get(collection, 'brunoConfig.clientCertificates.certs', []);
const onProxySettingsUpdate = (config) => {
const brunoConfig = cloneDeep(collection.brunoConfig);
brunoConfig.proxy = config;
@@ -74,9 +96,15 @@ const CollectionSettings = ({ collection }) => {
const getTabPanel = (tab) => {
switch (tab) {
case 'overview': {
return <Overview collection={collection} />;
}
case 'headers': {
return <Headers collection={collection} />;
}
case 'vars': {
return <Vars collection={collection} />;
}
case 'auth': {
return <Auth collection={collection} />;
}
@@ -102,12 +130,6 @@ const CollectionSettings = ({ collection }) => {
/>
);
}
case 'docs': {
return <Docs collection={collection} />;
}
case 'info': {
return <Info collection={collection} />;
}
}
};
@@ -120,32 +142,39 @@ const CollectionSettings = ({ collection }) => {
return (
<StyledWrapper className="flex flex-col h-full relative px-4 py-4">
<div className="flex flex-wrap items-center tabs" role="tablist">
<div className={getTabClassname('overview')} role="tab" onClick={() => setTab('overview')}>
Overview
</div>
<div className={getTabClassname('headers')} role="tab" onClick={() => setTab('headers')}>
Headers
{activeHeadersCount > 0 && <sup className="ml-1 font-medium">{activeHeadersCount}</sup>}
</div>
<div className={getTabClassname('vars')} role="tab" onClick={() => setTab('vars')}>
Vars
{activeVarsCount > 0 && <sup className="ml-1 font-medium">{activeVarsCount}</sup>}
</div>
<div className={getTabClassname('auth')} role="tab" onClick={() => setTab('auth')}>
Auth
{auth !== 'none' && <ContentIndicator />}
</div>
<div className={getTabClassname('script')} role="tab" onClick={() => setTab('script')}>
Script
{hasScripts && <ContentIndicator />}
</div>
<div className={getTabClassname('tests')} role="tab" onClick={() => setTab('tests')}>
Tests
{hasTests && <ContentIndicator />}
</div>
<div className={getTabClassname('presets')} role="tab" onClick={() => setTab('presets')}>
Presets
</div>
<div className={getTabClassname('proxy')} role="tab" onClick={() => setTab('proxy')}>
Proxy
{Object.keys(proxyConfig).length > 0 && <ContentIndicator />}
</div>
<div className={getTabClassname('clientCert')} role="tab" onClick={() => setTab('clientCert')}>
Client Certificates
</div>
<div className={getTabClassname('docs')} role="tab" onClick={() => setTab('docs')}>
Docs
</div>
<div className={getTabClassname('info')} role="tab" onClick={() => setTab('info')}>
Info
{clientCertConfig.length > 0 && <ContentIndicator />}
</div>
</div>
<section className="mt-4 h-full">{getTabPanel(tab)}</section>

View File

@@ -3,7 +3,6 @@ import styled from 'styled-components';
const StyledWrapper = styled.div`
.editing-mode {
cursor: pointer;
color: ${(props) => props.theme.colors.text.yellow};
}
`;

View File

@@ -36,6 +36,13 @@ const Wrapper = styled.div`
padding: 0.35rem 0.6rem;
cursor: pointer;
&.active {
color: ${(props) => props.theme.colors.text.yellow} !important;
.icon {
color: ${(props) => props.theme.colors.text.yellow} !important;
}
}
.icon {
color: ${(props) => props.theme.dropdown.iconColor};
}

View File

@@ -2,9 +2,9 @@ import React from 'react';
import Tippy from '@tippyjs/react';
import StyledWrapper from './StyledWrapper';
const Dropdown = ({ icon, children, onCreate, placement }) => {
const Dropdown = ({ icon, children, onCreate, placement, transparent }) => {
return (
<StyledWrapper className="dropdown">
<StyledWrapper className="dropdown" transparent={transparent}>
<Tippy
content={children}
placement={placement || 'bottom-end'}

View File

@@ -19,7 +19,7 @@ const EnvironmentSelector = ({ collection }) => {
const Icon = forwardRef((props, ref) => {
return (
<div ref={ref} className="current-environment flex items-center justify-center pl-3 pr-2 py-1 select-none">
{activeEnvironment ? activeEnvironment.name : 'No Environment'}
<p className="text-nowrap truncate max-w-32">{activeEnvironment ? activeEnvironment.name : 'No Environment'}</p>
<IconCaretDown className="caret" size={14} strokeWidth={2} />
</div>
);
@@ -53,10 +53,11 @@ const EnvironmentSelector = ({ collection }) => {
<StyledWrapper>
<div className="flex items-center cursor-pointer environment-selector">
<Dropdown onCreate={onDropdownCreate} icon={<Icon />} placement="bottom-end">
<div className="label-item font-medium">Collection Environments</div>
{environments && environments.length
? environments.map((e) => (
<div
className="dropdown-item"
className={`dropdown-item ${e?.uid === activeEnvironmentUid ? 'active' : ''}`}
key={e.uid}
onClick={() => {
onSelect(e);
@@ -77,7 +78,10 @@ const EnvironmentSelector = ({ collection }) => {
<IconDatabaseOff size={18} strokeWidth={1.5} />
<span className="ml-2">No Environment</span>
</div>
<div className="dropdown-item border-top" onClick={handleSettingsIconClick}>
<div className="dropdown-item border-top" onClick={() => {
handleSettingsIconClick();
dropdownTippyRef.current.hide();
}}>
<div className="pr-2 text-gray-600">
<IconSettings size={18} strokeWidth={1.5} />
</div>

View File

@@ -44,7 +44,7 @@ const CopyEnvironment = ({ collection, environment, onClose }) => {
return (
<Portal>
<Modal size="sm" title={'Copy Environment'} confirmText="Copy" handleConfirm={onSubmit} handleCancel={onClose}>
<form className="bruno-form" onSubmit={formik.handleSubmit}>
<form className="bruno-form" onSubmit={e => e.preventDefault()}>
<div>
<label htmlFor="name" className="block font-semibold">
New Environment Name

View File

@@ -10,6 +10,11 @@ import Modal from 'components/Modal';
const CreateEnvironment = ({ collection, onClose }) => {
const dispatch = useDispatch();
const inputRef = useRef();
const validateEnvironmentName = (name) => {
return !collection?.environments?.some((env) => env?.name?.toLowerCase().trim() === name?.toLowerCase().trim());
};
const formik = useFormik({
enableReinitialize: true,
initialValues: {
@@ -17,9 +22,10 @@ const CreateEnvironment = ({ collection, onClose }) => {
},
validationSchema: Yup.object({
name: Yup.string()
.min(1, 'must be at least 1 character')
.max(50, 'must be 50 characters or less')
.required('name is required')
.min(1, 'Must be at least 1 character')
.max(50, 'Must be 50 characters or less')
.required('Name is required')
.test('duplicate-name', 'Environment already exists', validateEnvironmentName)
}),
onSubmit: (values) => {
dispatch(addEnvironment(values.name, collection.uid))
@@ -50,7 +56,7 @@ const CreateEnvironment = ({ collection, onClose }) => {
handleConfirm={onSubmit}
handleCancel={onClose}
>
<form className="bruno-form" onSubmit={formik.handleSubmit}>
<form className="bruno-form" onSubmit={e => e.preventDefault()}>
<div>
<label htmlFor="name" className="block font-semibold">
Environment Name

View File

@@ -39,6 +39,11 @@ const Wrapper = styled.div`
font-size: 0.8125rem;
}
.tooltip-mod {
font-size: 11px !important;
width: 150px !important;
}
input[type='text'] {
width: 100%;
border: solid 1px transparent;

View File

@@ -1,7 +1,9 @@
import React from 'react';
import { IconTrash } from '@tabler/icons';
import React, { useRef, useEffect } from 'react';
import cloneDeep from 'lodash/cloneDeep';
import { IconTrash, IconAlertCircle, IconDeviceFloppy, IconRefresh, IconCircleCheck } from '@tabler/icons';
import { useTheme } from 'providers/Theme';
import { useDispatch } from 'react-redux';
import { selectEnvironment } from 'providers/ReduxStore/slices/collections/actions';
import SingleLineEditor from 'components/SingleLineEditor';
import StyledWrapper from './StyledWrapper';
import { uuid } from 'utils/common';
@@ -9,12 +11,13 @@ import { useFormik } from 'formik';
import * as Yup from 'yup';
import { variableNameRegex } from 'utils/common/regex';
import { saveEnvironment } from 'providers/ReduxStore/slices/collections/actions';
import cloneDeep from 'lodash/cloneDeep';
import toast from 'react-hot-toast';
import { Tooltip } from 'react-tooltip';
const EnvironmentVariables = ({ environment, collection, setIsModified, originalEnvironmentVariables }) => {
const EnvironmentVariables = ({ environment, collection, setIsModified, originalEnvironmentVariables, onClose }) => {
const dispatch = useDispatch();
const { storedTheme } = useTheme();
const addButtonRef = useRef(null);
const formik = useFormik({
enableReinitialize: true,
@@ -58,14 +61,15 @@ const EnvironmentVariables = ({ environment, collection, setIsModified, original
const ErrorMessage = ({ name }) => {
const meta = formik.getFieldMeta(name);
if (!meta.error) {
const id = uuid();
if (!meta.error || !meta.touched) {
return null;
}
return (
<label htmlFor={name} className="text-red-500">
{meta.error}
</label>
<span>
<IconAlertCircle id={id} className="text-red-600 cursor-pointer " size={20} />
<Tooltip className="tooltip-mod" anchorId={id} html={meta.error || ''} />
</span>
);
};
@@ -81,10 +85,31 @@ const EnvironmentVariables = ({ environment, collection, setIsModified, original
formik.setFieldValue(formik.values.length, newVariable, false);
};
const onActivate = () => {
dispatch(selectEnvironment(environment ? environment.uid : null, collection.uid))
.then(() => {
if (environment) {
toast.success(`Environment changed to ${environment.name}`);
onClose();
} else {
toast.success(`No Environments are active now`);
}
})
.catch((err) => console.log(err) && toast.error('An error occurred while selecting the environment'));
};
const handleRemoveVar = (id) => {
formik.setValues(formik.values.filter((variable) => variable.uid !== id));
};
useEffect(() => {
if (formik.dirty) {
// Smooth scrolling to the changed parameter is temporarily disabled
// due to UX issues when editing the first row in a long list of environment variables.
// addButtonRef.current?.scrollIntoView({ behavior: 'smooth' });
}
}, [formik.values, formik.dirty]);
const handleReset = () => {
formik.resetForm({ originalEnvironmentVariables });
};
@@ -115,19 +140,21 @@ const EnvironmentVariables = ({ environment, collection, setIsModified, original
/>
</td>
<td>
<input
type="text"
autoComplete="off"
autoCorrect="off"
autoCapitalize="off"
spellCheck="false"
className="mousetrap"
id={`${index}.name`}
name={`${index}.name`}
value={variable.name}
onChange={formik.handleChange}
/>
<ErrorMessage name={`${index}.name`} />
<div className="flex items-center">
<input
type="text"
autoComplete="off"
autoCorrect="off"
autoCapitalize="off"
spellCheck="false"
className="mousetrap"
id={`${index}.name`}
name={`${index}.name`}
value={variable.name}
onChange={formik.handleChange}
/>
<ErrorMessage name={`${index}.name`} />
</div>
</td>
<td className="flex flex-row flex-nowrap">
<div className="overflow-hidden grow w-full relative">
@@ -159,20 +186,30 @@ const EnvironmentVariables = ({ environment, collection, setIsModified, original
))}
</tbody>
</table>
</div>
<div>
<button className="btn-add-param text-link pr-2 py-3 mt-2 select-none" onClick={addVariable}>
+ Add Variable
</button>
<div>
<button
ref={addButtonRef}
className="btn-add-param text-link pr-2 py-3 mt-2 select-none"
onClick={addVariable}
>
+ Add Variable
</button>
</div>
</div>
<div>
<button type="submit" className="submit btn btn-md btn-secondary mt-2" onClick={formik.handleSubmit}>
<div className="flex items-center">
<button type="submit" className="submit btn btn-sm btn-secondary mt-2 flex items-center" onClick={formik.handleSubmit}>
<IconDeviceFloppy size={16} strokeWidth={1.5} className="mr-1" />
Save
</button>
<button type="submit" className="ml-2 px-1 submit btn btn-md btn-secondary mt-2" onClick={handleReset}>
<button type="submit" className="ml-2 px-1 submit btn btn-sm btn-close mt-2 flex items-center" onClick={handleReset}>
<IconRefresh size={16} strokeWidth={1.5} className="mr-1" />
Reset
</button>
<button type="submit" className="submit btn btn-sm btn-close mt-2 flex items-center" onClick={onActivate}>
<IconCircleCheck size={16} strokeWidth={1.5} className="mr-1" />
Activate
</button>
</div>
</StyledWrapper>
);

View File

@@ -5,7 +5,7 @@ import DeleteEnvironment from '../../DeleteEnvironment';
import RenameEnvironment from '../../RenameEnvironment';
import EnvironmentVariables from './EnvironmentVariables';
const EnvironmentDetails = ({ environment, collection, setIsModified }) => {
const EnvironmentDetails = ({ environment, collection, setIsModified, onClose }) => {
const [openEditModal, setOpenEditModal] = useState(false);
const [openDeleteModal, setOpenDeleteModal] = useState(false);
const [openCopyModal, setOpenCopyModal] = useState(false);
@@ -38,7 +38,7 @@ const EnvironmentDetails = ({ environment, collection, setIsModified }) => {
</div>
<div>
<EnvironmentVariables environment={environment} collection={collection} setIsModified={setIsModified} />
<EnvironmentVariables environment={environment} collection={collection} setIsModified={setIsModified} onClose={onClose} />
</div>
</div>
);

View File

@@ -23,6 +23,10 @@ const StyledWrapper = styled.div`
padding: 8px 10px;
border-left: solid 2px transparent;
text-decoration: none;
max-width: 200px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
&:hover {
text-decoration: none;

View File

@@ -8,8 +8,10 @@ import ImportEnvironment from '../ImportEnvironment';
import ManageSecrets from '../ManageSecrets';
import StyledWrapper from './StyledWrapper';
import ConfirmSwitchEnv from './ConfirmSwitchEnv';
import ToolHint from 'components/ToolHint';
import { isEqual } from 'lodash';
const EnvironmentList = ({ selectedEnvironment, setSelectedEnvironment, collection, isModified, setIsModified }) => {
const EnvironmentList = ({ selectedEnvironment, setSelectedEnvironment, collection, isModified, setIsModified, onClose }) => {
const { environments } = collection;
const [openCreateModal, setOpenCreateModal] = useState(false);
const [openImportModal, setOpenImportModal] = useState(false);
@@ -23,6 +25,11 @@ const EnvironmentList = ({ selectedEnvironment, setSelectedEnvironment, collecti
useEffect(() => {
if (selectedEnvironment) {
const _selectedEnvironment = environments?.find(env => env?.uid === selectedEnvironment?.uid);
const hasSelectedEnvironmentChanged = !isEqual(selectedEnvironment, _selectedEnvironment);
if (hasSelectedEnvironmentChanged) {
setSelectedEnvironment(_selectedEnvironment);
}
setOriginalEnvironmentVariables(selectedEnvironment.variables);
return;
}
@@ -103,13 +110,15 @@ const EnvironmentList = ({ selectedEnvironment, setSelectedEnvironment, collecti
{environments &&
environments.length &&
environments.map((env) => (
<div
key={env.uid}
className={selectedEnvironment.uid === env.uid ? 'environment-item active' : 'environment-item'}
onClick={() => handleEnvironmentClick(env)} // Use handleEnvironmentClick to handle clicks
>
<span className="break-all">{env.name}</span>
</div>
<ToolHint key={env.uid} text={env.name} toolhintId={env.uid} place="right">
<div
id={env.uid}
className={selectedEnvironment.uid === env.uid ? 'environment-item active' : 'environment-item'}
onClick={() => handleEnvironmentClick(env)} // Use handleEnvironmentClick to handle clicks
>
<span className="break-all">{env.name}</span>
</div>
</ToolHint>
))}
<div className="btn-create-environment" onClick={() => handleCreateEnvClick()}>
+ <span>Create</span>
@@ -132,6 +141,7 @@ const EnvironmentList = ({ selectedEnvironment, setSelectedEnvironment, collecti
collection={collection}
setIsModified={setIsModified}
originalEnvironmentVariables={originalEnvironmentVariables}
onClose={onClose}
/>
</div>
</StyledWrapper>

View File

@@ -22,6 +22,9 @@ const RenameEnvironment = ({ onClose, environment, collection }) => {
.required('name is required')
}),
onSubmit: (values) => {
if (values.name === environment.name) {
return;
}
dispatch(renameEnvironment(values.name, environment.uid, collection.uid))
.then(() => {
toast.success('Environment renamed successfully');
@@ -50,7 +53,7 @@ const RenameEnvironment = ({ onClose, environment, collection }) => {
handleConfirm={onSubmit}
handleCancel={onClose}
>
<form className="bruno-form" onSubmit={formik.handleSubmit}>
<form className="bruno-form" onSubmit={e => e.preventDefault()}>
<div>
<label htmlFor="name" className="block font-semibold">
Environment Name

View File

@@ -72,6 +72,7 @@ const EnvironmentSettings = ({ collection, onClose }) => {
collection={collection}
isModified={isModified}
setIsModified={setIsModified}
onClose={onClose}
/>
</Modal>
);

View File

@@ -6,7 +6,7 @@ import { IconX } from '@tabler/icons';
import { isWindowsOS } from 'utils/common/platform';
import slash from 'utils/common/slash';
const FilePickerEditor = ({ value, onChange, collection }) => {
const FilePickerEditor = ({ value, onChange, collection, isSingleFilePicker = false}) => {
value = value || [];
const dispatch = useDispatch();
const filenames = value
@@ -20,7 +20,7 @@ const FilePickerEditor = ({ value, onChange, collection }) => {
const title = filenames.map((v) => `- ${v}`).join('\n');
const browse = () => {
dispatch(browseFiles())
dispatch(browseFiles([],['']))
.then((filePaths) => {
// If file is in the collection's directory, then we use relative path
// Otherwise, we use the absolute path
@@ -49,7 +49,7 @@ const FilePickerEditor = ({ value, onChange, collection }) => {
if (filenames.length == 1) {
return filenames[0];
}
return filenames.length + ' files selected';
return filenames.length + ' file(s) selected';
};
return filenames.length > 0 ? (
@@ -66,7 +66,7 @@ const FilePickerEditor = ({ value, onChange, collection }) => {
</div>
) : (
<button className="btn btn-secondary px-1" style={{ width: '100%' }} onClick={browse}>
Select Files
{isSingleFilePicker? 'Select File' : 'Select Files'}
</button>
);
};

View File

@@ -0,0 +1,10 @@
import styled from 'styled-components';
const StyledWrapper = styled.div`
.editing-mode {
cursor: pointer;
color: ${(props) => props.theme.colors.text.yellow};
}
`;
export default StyledWrapper;

View File

@@ -0,0 +1,66 @@
import 'github-markdown-css/github-markdown.css';
import get from 'lodash/get';
import { updateFolderDocs } from 'providers/ReduxStore/slices/collections';
import { useTheme } from 'providers/Theme';
import { useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { saveFolderRoot } from 'providers/ReduxStore/slices/collections/actions';
import Markdown from 'components/MarkDown';
import CodeEditor from 'components/CodeEditor';
import StyledWrapper from './StyledWrapper';
const Documentation = ({ collection, folder }) => {
const dispatch = useDispatch();
const { displayedTheme } = useTheme();
const preferences = useSelector((state) => state.app.preferences);
const [isEditing, setIsEditing] = useState(false);
const docs = get(folder, 'root.docs', '');
const toggleViewMode = () => {
setIsEditing((prev) => !prev);
};
const onEdit = (value) => {
dispatch(
updateFolderDocs({
folderUid: folder.uid,
collectionUid: collection.uid,
docs: value
})
);
};
const onSave = () => dispatch(saveFolderRoot(collection.uid, folder.uid));
if (!folder) {
return null;
}
return (
<StyledWrapper className="mt-1 h-full w-full relative flex flex-col">
<div className="editing-mode flex justify-between items-center" role="tab" onClick={toggleViewMode}>
{isEditing ? 'Preview' : 'Edit'}
</div>
{isEditing ? (
<div className="mt-2 flex-1 max-h-[70vh]">
<CodeEditor
collection={collection}
theme={displayedTheme}
value={docs || ''}
onEdit={onEdit}
onSave={onSave}
mode="application/text"
/>
<button type="submit" className="submit btn btn-sm btn-secondary my-6" onClick={onSave}>
Save
</button>
</div>
) : (
<Markdown collectionPath={collection.pathname} onDoubleClick={toggleViewMode} content={docs} />
)}
</StyledWrapper>
);
};
export default Documentation;

View File

@@ -116,6 +116,7 @@ const Headers = ({ collection, folder }) => {
)
}
collection={collection}
item={folder}
/>
</td>
<td>

View File

@@ -82,7 +82,6 @@ const VarsTable = ({ folder, collection, vars, varType }) => {
<td>
<div className="flex items-center">
<span>Value</span>
<InfoTip text="You can write any valid JS Template Literal here" infotipId="request-var" />
</div>
</td>
) : (
@@ -130,6 +129,7 @@ const VarsTable = ({ folder, collection, vars, varType }) => {
)
}
collection={collection}
item={folder}
/>
</td>
<td>

View File

@@ -7,6 +7,16 @@ import Script from './Script';
import Tests from './Tests';
import StyledWrapper from './StyledWrapper';
import Vars from './Vars';
import Documentation from './Documentation';
import DotIcon from 'components/Icons/Dot';
const ContentIndicator = () => {
return (
<sup className="ml-[.125rem] opacity-80 font-medium">
<DotIcon width="10"></DotIcon>
</sup>
);
};
const FolderSettings = ({ collection, folder }) => {
const dispatch = useDispatch();
@@ -16,6 +26,17 @@ const FolderSettings = ({ collection, folder }) => {
tab = folderLevelSettingsSelectedTab[folder?.uid];
}
const folderRoot = collection?.items.find((item) => item.uid === folder?.uid)?.root;
const hasScripts = folderRoot?.request?.script?.res || folderRoot?.request?.script?.req;
const hasTests = folderRoot?.request?.tests;
const headers = folderRoot?.request?.headers || [];
const activeHeadersCount = headers.filter((header) => header.enabled).length;
const requestVars = folderRoot?.request?.vars?.req || [];
const responseVars = folderRoot?.request?.vars?.res || [];
const activeVarsCount = requestVars.filter((v) => v.enabled).length + responseVars.filter((v) => v.enabled).length;
const setTab = (tab) => {
dispatch(
updatedFolderSettingsSelectedTab({
@@ -40,6 +61,9 @@ const FolderSettings = ({ collection, folder }) => {
case 'vars': {
return <Vars collection={collection} folder={folder} />;
}
case 'docs': {
return <Documentation collection={collection} folder={folder} />;
}
}
};
@@ -55,15 +79,22 @@ const FolderSettings = ({ collection, folder }) => {
<div className="flex flex-wrap items-center tabs" role="tablist">
<div className={getTabClassname('headers')} role="tab" onClick={() => setTab('headers')}>
Headers
{activeHeadersCount > 0 && <sup className="ml-1 font-medium">{activeHeadersCount}</sup>}
</div>
<div className={getTabClassname('script')} role="tab" onClick={() => setTab('script')}>
Script
{hasScripts && <ContentIndicator />}
</div>
<div className={getTabClassname('test')} role="tab" onClick={() => setTab('test')}>
Test
{hasTests && <ContentIndicator />}
</div>
<div className={getTabClassname('vars')} role="tab" onClick={() => setTab('vars')}>
Vars
{activeVarsCount > 0 && <sup className="ml-1 font-medium">{activeVarsCount}</sup>}
</div>
<div className={getTabClassname('docs')} role="tab" onClick={() => setTab('docs')}>
Docs
</div>
</div>
<section className={`flex mt-4 h-full`}>{getTabPanel(tab)}</section>

View File

@@ -0,0 +1,18 @@
import styled from 'styled-components';
const Wrapper = styled.div`
.current-environment {
}
.environment-active {
padding: 0.3rem 0.4rem;
color: ${(props) => props.theme.colors.text.yellow};
border: solid 1px ${(props) => props.theme.colors.text.yellow} !important;
}
.environment-selector {
.active: {
color: ${(props) => props.theme.colors.text.yellow};
}
}
`;
export default Wrapper;

View File

@@ -0,0 +1,97 @@
import React, { useRef, forwardRef, useState } from 'react';
import find from 'lodash/find';
import Dropdown from 'components/Dropdown';
import { IconSettings, IconWorld, IconDatabase, IconDatabaseOff, IconCheck } from '@tabler/icons';
import EnvironmentSettings from '../EnvironmentSettings';
import toast from 'react-hot-toast';
import { useDispatch, useSelector } from 'react-redux';
import StyledWrapper from './StyledWrapper';
import { selectGlobalEnvironment } from 'providers/ReduxStore/slices/global-environments';
import ToolHint from 'components/ToolHint/index';
const EnvironmentSelector = () => {
const dispatch = useDispatch();
const dropdownTippyRef = useRef();
const globalEnvironments = useSelector((state) => state.globalEnvironments.globalEnvironments);
const activeGlobalEnvironmentUid = useSelector((state) => state.globalEnvironments.activeGlobalEnvironmentUid);
const [openSettingsModal, setOpenSettingsModal] = useState(false);
const activeEnvironment = activeGlobalEnvironmentUid ? find(globalEnvironments, (e) => e.uid === activeGlobalEnvironmentUid) : null;
const Icon = forwardRef((props, ref) => {
return (
<div ref={ref} className={`current-environment flex flex-row gap-1 rounded-xl text-xs cursor-pointer items-center justify-center select-none ${activeGlobalEnvironmentUid? 'environment-active': ''}`}>
<ToolHint text="Global Environments" toolhintId="GlobalEnvironmentsToolhintId" className='flex flex-row'>
<IconWorld className="globe" size={16} strokeWidth={1.5} />
{
activeEnvironment ? <div className='text-nowrap truncate max-w-32'>{activeEnvironment?.name}</div> : null
}
</ToolHint>
</div>
);
});
const handleSettingsIconClick = () => {
setOpenSettingsModal(true);
};
const handleModalClose = () => {
setOpenSettingsModal(false);
};
const onDropdownCreate = (ref) => (dropdownTippyRef.current = ref);
const onSelect = (environment) => {
dispatch(selectGlobalEnvironment({ environmentUid: environment ? environment.uid : null }))
.then(() => {
if (environment) {
toast.success(`Environment changed to ${environment.name}`);
} else {
toast.success(`No Environments are active now`);
}
})
.catch((err) => console.log(err) && toast.error('An error occurred while selecting the environment'));
};
return (
<StyledWrapper>
<div className="flex items-center cursor-pointer environment-selector mr-3">
<Dropdown onCreate={onDropdownCreate} icon={<Icon />} placement="bottom-end" transparent={true}>
<div className="label-item font-medium">Global Environments</div>
{globalEnvironments && globalEnvironments.length
? globalEnvironments.map((e) => (
<div
className={`dropdown-item ${e?.uid === activeGlobalEnvironmentUid ? 'active' : ''}`}
key={e.uid}
onClick={() => {
onSelect(e);
dropdownTippyRef.current.hide();
}}
>
<IconDatabase size={18} strokeWidth={1.5} /> <span className="ml-2 break-all">{e.name}</span>
</div>
))
: null}
<div
className="dropdown-item"
onClick={() => {
dropdownTippyRef.current.hide();
onSelect(null);
}}
>
<IconDatabaseOff size={18} strokeWidth={1.5} />
<span className="ml-2">No Environment</span>
</div>
<div className="dropdown-item border-top" onClick={handleSettingsIconClick}>
<div className="pr-2 text-gray-600">
<IconSettings size={18} strokeWidth={1.5} />
</div>
<span>Configure</span>
</div>
</Dropdown>
</div>
{openSettingsModal && <EnvironmentSettings globalEnvironments={globalEnvironments} activeGlobalEnvironmentUid={activeGlobalEnvironmentUid} onClose={handleModalClose} />}
</StyledWrapper>
);
};
export default EnvironmentSelector;

View File

@@ -0,0 +1,78 @@
import Modal from 'components/Modal/index';
import Portal from 'components/Portal/index';
import { useFormik } from 'formik';
import { copyGlobalEnvironment } from 'providers/ReduxStore/slices/global-environments';
import { useEffect, useRef } from 'react';
import toast from 'react-hot-toast';
import { useDispatch } from 'react-redux';
import * as Yup from 'yup';
const CopyEnvironment = ({ environment, onClose }) => {
const dispatch = useDispatch();
const inputRef = useRef();
const formik = useFormik({
enableReinitialize: true,
initialValues: {
name: environment.name + ' - Copy'
},
validationSchema: Yup.object({
name: Yup.string()
.min(1, 'must be at least 1 character')
.max(50, 'must be 50 characters or less')
.required('name is required')
}),
onSubmit: (values) => {
dispatch(copyGlobalEnvironment({ name: values.name, environmentUid: environment.uid }))
.then(() => {
toast.success('Global environment created!');
onClose();
})
.catch((error) => {
toast.error('An error occurred while created the environment');
console.error(error);
});
}
});
useEffect(() => {
if (inputRef && inputRef.current) {
inputRef.current.focus();
}
}, [inputRef]);
const onSubmit = () => {
formik.handleSubmit();
};
return (
<Portal>
<Modal size="sm" title={'Copy Global Environment'} confirmText="Copy" handleConfirm={onSubmit} handleCancel={onClose}>
<form className="bruno-form" onSubmit={e => e.preventDefault()}>
<div>
<label htmlFor="name" className="block font-semibold">
New Environment Name
</label>
<input
id="environment-name"
type="text"
name="name"
ref={inputRef}
className="block textbox mt-2 w-full"
autoComplete="off"
autoCorrect="off"
autoCapitalize="off"
spellCheck="false"
onChange={formik.handleChange}
value={formik.values.name || ''}
/>
{formik.touched.name && formik.errors.name ? (
<div className="text-red-500">{formik.errors.name}</div>
) : null}
</div>
</form>
</Modal>
</Portal>
);
};
export default CopyEnvironment;

View File

@@ -0,0 +1,91 @@
import React, { useEffect, useRef } from 'react';
import toast from 'react-hot-toast';
import { useFormik } from 'formik';
import * as Yup from 'yup';
import { useDispatch, useSelector } from 'react-redux';
import Portal from 'components/Portal';
import Modal from 'components/Modal';
import { addGlobalEnvironment } from 'providers/ReduxStore/slices/global-environments';
const CreateEnvironment = ({ onClose }) => {
const globalEnvs = useSelector((state) => state?.globalEnvironments?.globalEnvironments);
const validateEnvironmentName = (name) => {
const trimmedName = name?.toLowerCase().trim();
return globalEnvs.every((env) => env?.name?.toLowerCase().trim() !== trimmedName);
};
const dispatch = useDispatch();
const inputRef = useRef();
const formik = useFormik({
enableReinitialize: true,
initialValues: {
name: ''
},
validationSchema: Yup.object({
name: Yup.string()
.min(1, 'Must be at least 1 character')
.max(50, 'Must be 50 characters or less')
.required('Name is required')
.test('duplicate-name', 'Global Environment already exists', validateEnvironmentName)
}),
onSubmit: (values) => {
dispatch(addGlobalEnvironment({ name: values.name }))
.then(() => {
toast.success('Global environment created!');
onClose();
})
.catch(() => toast.error('An error occurred while creating the environment'));
}
});
useEffect(() => {
if (inputRef && inputRef.current) {
inputRef.current.focus();
}
}, [inputRef]);
const onSubmit = () => {
formik.handleSubmit();
};
return (
<Portal>
<Modal
size="sm"
title={'Create Global Environment'}
confirmText="Create"
handleConfirm={onSubmit}
handleCancel={onClose}
>
<form className="bruno-form" onSubmit={e => e.preventDefault()}>
<div>
<label htmlFor="name" className="block font-semibold">
Environment Name
</label>
<div className="flex items-center mt-2">
<input
id="environment-name"
type="text"
name="name"
ref={inputRef}
className="block textbox w-full"
autoComplete="off"
autoCorrect="off"
autoCapitalize="off"
spellCheck="false"
onChange={formik.handleChange}
value={formik.values.name || ''}
/>
</div>
{formik.touched.name && formik.errors.name ? (
<div className="text-red-500">{formik.errors.name}</div>
) : null}
</div>
</form>
</Modal>
</Portal>
);
};
export default CreateEnvironment;

View File

@@ -0,0 +1,15 @@
import styled from 'styled-components';
const Wrapper = styled.div`
button.submit {
color: white;
background-color: var(--color-background-danger) !important;
border: inherit !important;
&:hover {
border: inherit !important;
}
}
`;
export default Wrapper;

View File

@@ -0,0 +1,37 @@
import React from 'react';
import Portal from 'components/Portal/index';
import toast from 'react-hot-toast';
import Modal from 'components/Modal/index';
import { useDispatch } from 'react-redux';
import StyledWrapper from './StyledWrapper';
import { deleteGlobalEnvironment } from 'providers/ReduxStore/slices/global-environments';
const DeleteEnvironment = ({ onClose, environment }) => {
const dispatch = useDispatch();
const onConfirm = () => {
dispatch(deleteGlobalEnvironment({ environmentUid: environment.uid }))
.then(() => {
toast.success('Global Environment deleted successfully');
onClose();
})
.catch(() => toast.error('An error occurred while deleting the environment'));
};
return (
<Portal>
<StyledWrapper>
<Modal
size="sm"
title={'Delete Global Environment'}
confirmText="Delete"
handleConfirm={onConfirm}
handleCancel={onClose}
>
Are you sure you want to delete <span className="font-semibold">{environment.name}</span> ?
</Modal>
</StyledWrapper>
</Portal>
);
};
export default DeleteEnvironment;

View File

@@ -0,0 +1,42 @@
import React from 'react';
import { IconAlertTriangle } from '@tabler/icons';
import Modal from 'components/Modal';
import { createPortal } from 'react-dom';
const ConfirmSwitchEnv = ({ onCancel }) => {
return createPortal(
<Modal
size="md"
title="Unsaved changes"
confirmText="Save and Close"
cancelText="Close without saving"
disableEscapeKey={true}
disableCloseOnOutsideClick={true}
closeModalFadeTimeout={150}
handleCancel={onCancel}
onClick={(e) => {
e.stopPropagation();
e.preventDefault();
}}
hideFooter={true}
>
<div className="flex items-center font-normal">
<IconAlertTriangle size={32} strokeWidth={1.5} className="text-yellow-600" />
<h1 className="ml-2 text-lg font-semibold">Hold on..</h1>
</div>
<div className="font-normal mt-4">You have unsaved changes in this environment.</div>
<div className="flex justify-between mt-6">
<div>
<button className="btn btn-sm btn-danger" onClick={onCancel}>
Close
</button>
</div>
<div></div>
</div>
</Modal>,
document.body
);
};
export default ConfirmSwitchEnv;

View File

@@ -0,0 +1,66 @@
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.collection.environment.settings.gridBorder};
padding: 4px 10px;
&:nth-child(1),
&:nth-child(4) {
width: 70px;
}
&:nth-child(5) {
width: 40px;
}
&:nth-child(2) {
width: 25%;
}
}
thead {
color: ${(props) => props.theme.table.thead.color};
font-size: 0.8125rem;
user-select: none;
}
thead td {
padding: 6px 10px;
}
}
.btn-add-param {
font-size: 0.8125rem;
}
.tooltip-mod {
font-size: 11px !important;
width: 150px !important;
}
input[type='text'] {
width: 100%;
border: solid 1px transparent;
outline: none !important;
background-color: transparent;
&:focus {
outline: none !important;
border: solid 1px transparent;
}
}
input[type='checkbox'] {
cursor: pointer;
position: relative;
top: 1px;
}
`;
export default Wrapper;

View File

@@ -0,0 +1,199 @@
import React, { useRef, useEffect } from 'react';
import cloneDeep from 'lodash/cloneDeep';
import { IconTrash, IconAlertCircle } from '@tabler/icons';
import { useTheme } from 'providers/Theme';
import { useDispatch } from 'react-redux';
import SingleLineEditor from 'components/SingleLineEditor';
import StyledWrapper from './StyledWrapper';
import { uuid } from 'utils/common';
import { useFormik } from 'formik';
import * as Yup from 'yup';
import { variableNameRegex } from 'utils/common/regex';
import toast from 'react-hot-toast';
import { saveGlobalEnvironment } from 'providers/ReduxStore/slices/global-environments';
import { Tooltip } from 'react-tooltip';
const EnvironmentVariables = ({ environment, setIsModified, originalEnvironmentVariables }) => {
const dispatch = useDispatch();
const { storedTheme } = useTheme();
const addButtonRef = useRef(null);
const formik = useFormik({
enableReinitialize: true,
initialValues: environment.variables || [],
validationSchema: Yup.array().of(
Yup.object({
enabled: Yup.boolean(),
name: Yup.string()
.required('Name cannot be empty')
.matches(
variableNameRegex,
'Name contains invalid characters. Must only contain alphanumeric characters, "-", "_", "." and cannot start with a digit.'
)
.trim(),
secret: Yup.boolean(),
type: Yup.string(),
uid: Yup.string(),
value: Yup.string().trim().nullable()
})
),
onSubmit: (values) => {
if (!formik.dirty) {
toast.error('Nothing to save');
return;
}
dispatch(saveGlobalEnvironment({ environmentUid: environment.uid, variables: cloneDeep(values) }))
.then(() => {
toast.success('Changes saved successfully');
formik.resetForm({ values });
setIsModified(false);
})
.catch((error) => {
console.error(error);
toast.error('An error occurred while saving the changes')
});
}
});
// Effect to track modifications.
React.useEffect(() => {
setIsModified(formik.dirty);
}, [formik.dirty]);
const ErrorMessage = ({ name }) => {
const meta = formik.getFieldMeta(name);
const id = uuid();
if (!meta.error || !meta.touched) {
return null;
}
return (
<span>
<IconAlertCircle id={id} className="text-red-600 cursor-pointer " size={20} />
<Tooltip className="tooltip-mod" anchorId={id} html={meta.error || ''} />
</span>
);
};
const addVariable = () => {
const newVariable = {
uid: uuid(),
name: '',
value: '',
type: 'text',
secret: false,
enabled: true
};
formik.setFieldValue(formik.values.length, newVariable, false);
};
const handleRemoveVar = (id) => {
formik.setValues(formik.values.filter((variable) => variable.uid !== id));
};
useEffect(() => {
if (formik.dirty) {
// Smooth scrolling to the changed parameter is temporarily disabled
// due to UX issues when editing the first row in a long list of environment variables.
// addButtonRef.current?.scrollIntoView({ behavior: 'smooth' });
}
}, [formik.values, formik.dirty]);
const handleReset = () => {
formik.resetForm({ originalEnvironmentVariables });
};
return (
<StyledWrapper className="w-full mt-6 mb-6">
<div className="h-[50vh] overflow-y-auto w-full">
<table>
<thead>
<tr>
<td className="text-center">Enabled</td>
<td>Name</td>
<td>Value</td>
<td className="text-center">Secret</td>
<td></td>
</tr>
</thead>
<tbody>
{formik.values.map((variable, index) => (
<tr key={variable.uid}>
<td className="text-center">
<input
type="checkbox"
className="mousetrap"
name={`${index}.enabled`}
checked={variable.enabled}
onChange={formik.handleChange}
/>
</td>
<td>
<div className="flex items-center">
<input
type="text"
autoComplete="off"
autoCorrect="off"
autoCapitalize="off"
spellCheck="false"
className="mousetrap"
id={`${index}.name`}
name={`${index}.name`}
value={variable.name}
onChange={formik.handleChange}
/>
<ErrorMessage name={`${index}.name`} />
</div>
</td>
<td className="flex flex-row flex-nowrap">
<div className="overflow-hidden grow w-full relative">
<SingleLineEditor
theme={storedTheme}
name={`${index}.value`}
value={variable.value}
isSecret={variable.secret}
onChange={(newValue) => formik.setFieldValue(`${index}.value`, newValue, true)}
/>
</div>
</td>
<td className="text-center">
<input
type="checkbox"
className="mousetrap"
name={`${index}.secret`}
checked={variable.secret}
onChange={formik.handleChange}
/>
</td>
<td>
<button onClick={() => handleRemoveVar(variable.uid)}>
<IconTrash strokeWidth={1.5} size={20} />
</button>
</td>
</tr>
))}
</tbody>
</table>
<div>
<button
ref={addButtonRef}
className="btn-add-param text-link pr-2 py-3 mt-2 select-none"
onClick={addVariable}
>
+ Add Variable
</button>
</div>
</div>
<div>
<button type="submit" className="submit btn btn-md btn-secondary mt-2" onClick={formik.handleSubmit}>
Save
</button>
<button type="submit" className="ml-2 px-1 submit btn btn-md btn-secondary mt-2" onClick={handleReset}>
Reset
</button>
</div>
</StyledWrapper>
);
};
export default EnvironmentVariables;

Some files were not shown because too many files have changed in this diff Show More