├── .nvmrc ├── packages ├── bruno-tests │ ├── .nvmrc │ ├── collection │ │ ├── .nvmrc │ │ ├── .gitignore │ │ ├── .env │ │ ├── file.json │ │ ├── lib │ │ │ └── math.js │ │ ├── readme.md │ │ ├── auth │ │ │ ├── cookie │ │ │ │ ├── Login.bru │ │ │ │ └── Check.bru │ │ │ ├── basic │ │ │ │ ├── via auth │ │ │ │ │ ├── Basic Auth 401.bru │ │ │ │ │ └── Basic Auth 200.bru │ │ │ │ └── via script │ │ │ │ │ ├── Basic Auth 401.bru │ │ │ │ │ └── Basic Auth 200.bru │ │ │ ├── inherit auth │ │ │ │ └── inherit Bearer Auth 200.bru │ │ │ └── bearer │ │ │ │ ├── via auth │ │ │ │ └── Bearer Auth 200.bru │ │ │ │ └── via headers │ │ │ │ └── Bearer Auth 200.bru │ │ ├── echo │ │ │ ├── echo bom json.bru │ │ │ ├── echo xml raw.bru │ │ │ ├── echo plaintext.bru │ │ │ ├── echo xml parsed.bru │ │ │ └── echo json.bru │ │ ├── package.json │ │ ├── environments │ │ │ └── Prod.bru │ │ ├── collection.bru │ │ ├── graphql │ │ │ └── spacex.bru │ │ ├── preview │ │ │ ├── image │ │ │ │ └── bruno.bru │ │ │ └── html │ │ │ │ └── bruno.bru │ │ ├── redirects │ │ │ ├── Test Redirect.bru │ │ │ └── Disable Redirect.bru │ │ ├── string interpolation │ │ │ ├── env vars.bru │ │ │ ├── process env vars.bru │ │ │ └── missing values.bru │ │ ├── bruno.json │ │ └── scripting │ │ │ ├── local modules │ │ │ └── sum.bru │ │ │ └── npm modules │ │ │ └── fakerjs.bru │ ├── collection_oauth2 │ │ ├── .nvmrc │ │ ├── .gitignore │ │ ├── .env │ │ ├── file.json │ │ ├── readme.md │ │ ├── package.json │ │ ├── environments │ │ │ └── Prod.bru │ │ ├── collection.bru │ │ ├── auth │ │ │ └── oauth2 │ │ │ │ ├── password_credentials │ │ │ │ ├── resource.bru │ │ │ │ └── token.bru │ │ │ │ ├── authorization_code │ │ │ │ ├── resource.bru │ │ │ │ ├── token with authorize.bru │ │ │ │ ├── github token with authorize.bru │ │ │ │ └── google token with authorize.bru │ │ │ │ └── client_credentials │ │ │ │ ├── resource.bru │ │ │ │ └── token.bru │ │ ├── bruno.json │ │ └── package-lock.json │ ├── collection_level_oauth2 │ │ ├── .nvmrc │ │ ├── .gitignore │ │ ├── readme.md │ │ ├── package.json │ │ ├── environments │ │ │ └── Prod.bru │ │ ├── resource.bru │ │ ├── bruno.json │ │ ├── collection.bru │ │ └── package-lock.json │ ├── src │ │ └── auth │ │ │ ├── bearer.js │ │ │ ├── basic.js │ │ │ └── index.js │ ├── readme.md │ └── package.json ├── bruno-app │ ├── src │ │ ├── styles │ │ │ ├── _buttons.scss │ │ │ └── app.scss │ │ ├── utils │ │ │ ├── common │ │ │ │ ├── regex.js │ │ │ │ ├── cache.js │ │ │ │ └── error.js │ │ │ ├── network │ │ │ │ └── cancelTokens.js │ │ │ ├── tabs │ │ │ │ └── index.js │ │ │ ├── codegenerator │ │ │ │ └── auth.js │ │ │ ├── collections │ │ │ │ └── search.js │ │ │ └── idb │ │ │ │ └── index.js │ │ ├── providers │ │ │ ├── ReduxStore │ │ │ │ ├── middlewares │ │ │ │ │ ├── tasks │ │ │ │ │ │ └── utils.js │ │ │ │ │ └── debug │ │ │ │ │ │ └── middleware.js │ │ │ │ └── index.js │ │ │ ├── App │ │ │ │ ├── StyledWrapper.js │ │ │ │ └── ConfirmAppClose │ │ │ │ │ └── index.js │ │ │ └── Toaster │ │ │ │ └── index.js │ │ ├── themes │ │ │ └── index.js │ │ ├── components │ │ │ ├── CollectionSettings │ │ │ │ ├── Auth │ │ │ │ │ ├── StyledWrapper.js │ │ │ │ │ ├── OAuth2 │ │ │ │ │ │ ├── ClientCredentials │ │ │ │ │ │ │ ├── inputsConfig.js │ │ │ │ │ │ │ └── StyledWrapper.js │ │ │ │ │ │ ├── StyledWrapper.js │ │ │ │ │ │ ├── AuthorizationCode │ │ │ │ │ │ │ ├── StyledWrapper.js │ │ │ │ │ │ │ └── inputsConfig.js │ │ │ │ │ │ └── PasswordCredentials │ │ │ │ │ │ │ ├── StyledWrapper.js │ │ │ │ │ │ │ └── inputsConfig.js │ │ │ │ │ ├── AwsV4Auth │ │ │ │ │ │ └── StyledWrapper.js │ │ │ │ │ ├── BasicAuth │ │ │ │ │ │ └── StyledWrapper.js │ │ │ │ │ ├── BearerAuth │ │ │ │ │ │ └── StyledWrapper.js │ │ │ │ │ ├── DigestAuth │ │ │ │ │ │ └── StyledWrapper.js │ │ │ │ │ └── AuthMode │ │ │ │ │ │ └── StyledWrapper.js │ │ │ │ ├── Tests │ │ │ │ │ └── StyledWrapper.js │ │ │ │ ├── Info │ │ │ │ │ └── StyledWrapper.js │ │ │ │ ├── Script │ │ │ │ │ └── StyledWrapper.js │ │ │ │ ├── Docs │ │ │ │ │ └── StyledWrapper.js │ │ │ │ ├── Presets │ │ │ │ │ └── StyledWrapper.js │ │ │ │ └── ProxySettings │ │ │ │ │ └── StyledWrapper.js │ │ │ ├── FolderSettings │ │ │ │ ├── Tests │ │ │ │ │ └── StyledWrapper.js │ │ │ │ ├── Vars │ │ │ │ │ └── StyledWrapper.js │ │ │ │ └── Script │ │ │ │ │ └── StyledWrapper.js │ │ │ ├── RequestTabs │ │ │ │ ├── CollectionToolBar │ │ │ │ │ └── StyledWrapper.js │ │ │ │ └── RequestTab │ │ │ │ │ └── StyledWrapper.js │ │ │ ├── Preferences │ │ │ │ ├── Theme │ │ │ │ │ └── StyledWrapper.js │ │ │ │ ├── Font │ │ │ │ │ └── StyledWrapper.js │ │ │ │ ├── General │ │ │ │ │ └── StyledWrapper.js │ │ │ │ ├── Support │ │ │ │ │ └── StyledWrapper.js │ │ │ │ ├── ProxySettings │ │ │ │ │ └── StyledWrapper.js │ │ │ │ └── StyledWrapper.js │ │ │ ├── Sidebar │ │ │ │ ├── Collections │ │ │ │ │ ├── CreateOrOpenCollection │ │ │ │ │ │ └── StyledWrapper.js │ │ │ │ │ ├── Collection │ │ │ │ │ │ └── CollectionItem │ │ │ │ │ │ │ ├── RunCollectionItem │ │ │ │ │ │ │ └── StyledWrapper.js │ │ │ │ │ │ │ ├── DeleteCollectionItem │ │ │ │ │ │ │ └── StyledWrapper.js │ │ │ │ │ │ │ ├── GenerateCodeItem │ │ │ │ │ │ │ └── CodeView │ │ │ │ │ │ │ │ └── StyledWrapper.js │ │ │ │ │ │ │ └── RequestMethod │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ └── StyledWrapper.js │ │ │ │ │ ├── SelectCollection │ │ │ │ │ │ ├── StyledWrapper.js │ │ │ │ │ │ └── index.js │ │ │ │ │ └── StyledWrapper.js │ │ │ │ ├── TitleBar │ │ │ │ │ └── StyledWrapper.js │ │ │ │ └── GoldenEdition │ │ │ │ │ └── StyledWrapper.js │ │ │ ├── RequestPane │ │ │ │ ├── Vars │ │ │ │ │ ├── StyledWrapper.js │ │ │ │ │ └── index.js │ │ │ │ ├── RequestBody │ │ │ │ │ ├── StyledWrapper.js │ │ │ │ │ └── RequestBodyMode │ │ │ │ │ │ └── StyledWrapper.js │ │ │ │ ├── Tests │ │ │ │ │ └── StyledWrapper.js │ │ │ │ ├── Auth │ │ │ │ │ ├── StyledWrapper.js │ │ │ │ │ ├── OAuth2 │ │ │ │ │ │ ├── ClientCredentials │ │ │ │ │ │ │ ├── inputsConfig.js │ │ │ │ │ │ │ └── StyledWrapper.js │ │ │ │ │ │ ├── StyledWrapper.js │ │ │ │ │ │ ├── AuthorizationCode │ │ │ │ │ │ │ ├── StyledWrapper.js │ │ │ │ │ │ │ └── inputsConfig.js │ │ │ │ │ │ └── PasswordCredentials │ │ │ │ │ │ │ ├── StyledWrapper.js │ │ │ │ │ │ │ └── inputsConfig.js │ │ │ │ │ ├── AwsV4Auth │ │ │ │ │ │ └── StyledWrapper.js │ │ │ │ │ ├── BasicAuth │ │ │ │ │ │ └── StyledWrapper.js │ │ │ │ │ ├── BearerAuth │ │ │ │ │ │ └── StyledWrapper.js │ │ │ │ │ ├── DigestAuth │ │ │ │ │ │ └── StyledWrapper.js │ │ │ │ │ └── AuthMode │ │ │ │ │ │ └── StyledWrapper.js │ │ │ │ ├── GraphQLVariables │ │ │ │ │ └── StyledWrapper.js │ │ │ │ ├── Script │ │ │ │ │ └── StyledWrapper.js │ │ │ │ ├── SaveRequest │ │ │ │ │ └── StyledWrapper.js │ │ │ │ ├── QueryUrl │ │ │ │ │ └── HttpMethodSelector │ │ │ │ │ │ └── StyledWrapper.js │ │ │ │ ├── GraphQLRequestPane │ │ │ │ │ └── StyledWrapper.js │ │ │ │ └── HttpRequestPane │ │ │ │ │ └── StyledWrapper.js │ │ │ ├── Portal │ │ │ │ └── index.js │ │ │ ├── ResponsePane │ │ │ │ ├── ResponseSave │ │ │ │ │ ├── StyledWrapper.js │ │ │ │ │ └── index.js │ │ │ │ ├── ResponseClear │ │ │ │ │ ├── StyledWrapper.js │ │ │ │ │ └── index.js │ │ │ │ ├── ResponseSize │ │ │ │ │ ├── StyledWrapper.js │ │ │ │ │ └── index.js │ │ │ │ ├── ResponseTime │ │ │ │ │ ├── StyledWrapper.js │ │ │ │ │ └── index.js │ │ │ │ ├── Placeholder │ │ │ │ │ └── StyledWrapper.js │ │ │ │ ├── StatusCode │ │ │ │ │ ├── StyledWrapper.js │ │ │ │ │ └── index.js │ │ │ │ ├── TestResults │ │ │ │ │ └── StyledWrapper.js │ │ │ │ ├── Timeline │ │ │ │ │ └── StyledWrapper.js │ │ │ │ ├── ResponseHeaders │ │ │ │ │ ├── StyledWrapper.js │ │ │ │ │ └── index.js │ │ │ │ ├── Overlay │ │ │ │ │ └── StyledWrapper.js │ │ │ │ ├── NetworkError │ │ │ │ │ └── index.js │ │ │ │ └── StyledWrapper.js │ │ │ ├── Environments │ │ │ │ ├── EnvironmentSettings │ │ │ │ │ ├── StyledWrapper.js │ │ │ │ │ └── DeleteEnvironment │ │ │ │ │ │ └── StyledWrapper.js │ │ │ │ └── EnvironmentSelector │ │ │ │ │ └── StyledWrapper.js │ │ │ ├── Cookies │ │ │ │ └── StyledWrapper.js │ │ │ ├── Spinner │ │ │ │ ├── index.js │ │ │ │ └── StyledWrapper.js │ │ │ ├── Icons │ │ │ │ └── Send │ │ │ │ │ └── index.js │ │ │ ├── Navbar │ │ │ │ └── StyledWrapper.js │ │ │ ├── BrunoSupport │ │ │ │ └── StyledWrapper.js │ │ │ ├── Documentation │ │ │ │ └── StyledWrapper.js │ │ │ ├── VariablesEditor │ │ │ │ └── StyledWrapper.js │ │ │ ├── Welcome │ │ │ │ └── StyledWrapper.js │ │ │ ├── Dropdown │ │ │ │ └── index.js │ │ │ ├── RunnerResults │ │ │ │ ├── StyledWrapper.js │ │ │ │ └── ResponsePane │ │ │ │ │ └── StyledWrapper.js │ │ │ ├── StopWatch │ │ │ │ └── index.js │ │ │ ├── Toast │ │ │ │ └── index.js │ │ │ └── MarkDown │ │ │ │ └── index.jsx │ │ ├── assets │ │ │ ├── send.svg │ │ │ └── github.svg │ │ ├── hooks │ │ │ ├── usePrevious │ │ │ │ └── index.js │ │ │ └── useLocalStorage │ │ │ │ └── index.js │ │ └── pages │ │ │ ├── index.js │ │ │ └── Bruno │ │ │ └── StyledWrapper.js │ ├── .env.production │ ├── .babelrc │ ├── public │ │ ├── favicon.ico │ │ └── theme │ │ │ ├── index.js │ │ │ ├── dark.js │ │ │ └── light.js │ ├── postcss.config.js │ ├── .prettierrc.json │ ├── tailwind.config.js │ ├── next.config.js │ ├── .gitignore │ └── jsconfig.json ├── bruno-electron │ ├── .env.sample │ ├── src │ │ ├── about │ │ │ ├── 256x256.png │ │ │ └── about.css │ │ ├── utils │ │ │ ├── cancel-token.js │ │ │ └── filesystem.test.js │ │ ├── store │ │ │ ├── bruno-config.js │ │ │ └── window-state.js │ │ ├── preload.js │ │ └── ipc │ │ │ └── notifications.js │ ├── resources │ │ ├── icons │ │ │ ├── mac │ │ │ │ └── icon.icns │ │ │ ├── png │ │ │ │ ├── 16x16.png │ │ │ │ ├── 24x24.png │ │ │ │ ├── 32x32.png │ │ │ │ ├── 48x48.png │ │ │ │ ├── 64x64.png │ │ │ │ ├── 128x128.png │ │ │ │ ├── 256x256.png │ │ │ │ ├── 512x512.png │ │ │ │ └── 1024x1024.png │ │ │ └── win │ │ │ │ └── icon.ico │ │ └── entitlements.mac.plist │ ├── .gitignore │ ├── readme.md │ ├── tests │ │ └── network │ │ │ ├── authorize-user.spec.js │ │ │ ├── prepare-request.spec.js │ │ │ └── index.spec.js │ └── notarize.js ├── bruno-cli │ ├── bin │ │ └── bru.js │ ├── .gitignore │ ├── assets │ │ └── images │ │ │ └── cli-demo.png │ ├── src │ │ ├── utils │ │ │ └── common.js │ │ ├── reporters │ │ │ └── html.js │ │ ├── index.js │ │ └── constants.js │ └── tests │ │ └── runner │ │ └── prepare-request.spec.js ├── bruno-lang │ ├── .gitignore │ ├── v1 │ │ ├── tests │ │ │ ├── fixtures │ │ │ │ └── env.bru │ │ │ ├── bru-to-env-json.spec.js │ │ │ └── env-json-to-bru.spec.js │ │ └── src │ │ │ ├── tests-tag.js │ │ │ ├── params-tag.js │ │ │ ├── script-tag.js │ │ │ ├── headers-tag.js │ │ │ ├── env-vars-tag.js │ │ │ ├── utils.js │ │ │ └── inline-tag.js │ ├── readme.md │ ├── v2 │ │ ├── src │ │ │ ├── dotenvToJson.js │ │ │ └── jsonToEnv.js │ │ └── tests │ │ │ ├── assert.spec.js │ │ │ ├── index.spec.js │ │ │ ├── fixtures │ │ │ └── collection.bru │ │ │ ├── script.spec.js │ │ │ └── collection.spec.js │ ├── package.json │ ├── src │ │ └── index.js │ └── example │ │ └── request.json ├── bruno-schema │ ├── .gitignore │ ├── src │ │ ├── index.js │ │ ├── common │ │ │ └── index.js │ │ └── utils │ │ │ └── testUtils.js │ └── package.json ├── bruno-common │ ├── src │ │ ├── index.ts │ │ └── utils │ │ │ └── index.ts │ ├── jest.config.js │ ├── readme.md │ ├── .gitignore │ ├── tsconfig.json │ └── package.json ├── bruno-graphql-docs │ ├── src │ │ ├── index.ts │ │ ├── components │ │ │ └── DocExplorer │ │ │ │ ├── Directive.tsx │ │ │ │ ├── types.ts │ │ │ │ ├── MarkdownContent.tsx │ │ │ │ ├── Argument.tsx │ │ │ │ └── DefaultValue.tsx │ │ └── utility │ │ │ └── debounce.ts │ ├── readme.md │ ├── .gitignore │ ├── tsconfig.json │ └── package.json ├── bruno-query │ ├── jest.config.js │ ├── .gitignore │ ├── tsconfig.json │ ├── readme.md │ └── package.json ├── bruno-js │ ├── readme.md │ ├── src │ │ ├── test-results.js │ │ ├── index.js │ │ ├── interpolate-string.js │ │ ├── test.js │ │ └── bruno-response.js │ └── package.json ├── bruno-toml │ ├── tests │ │ ├── methods │ │ │ ├── get │ │ │ │ ├── request.toml │ │ │ │ └── request.json │ │ │ └── delete │ │ │ │ ├── request.toml │ │ │ │ └── request.json │ │ ├── scripts │ │ │ ├── pre-request │ │ │ │ ├── request.toml │ │ │ │ └── request.json │ │ │ ├── tests │ │ │ │ ├── request.toml │ │ │ │ └── request.json │ │ │ └── post-response │ │ │ │ ├── request.toml │ │ │ │ └── request.json │ │ └── headers │ │ │ ├── empty-header │ │ │ ├── request.toml │ │ │ └── request.json │ │ │ ├── simple-header │ │ │ ├── request.toml │ │ │ └── request.json │ │ │ ├── unicode-in-header │ │ │ ├── request.toml │ │ │ └── request.json │ │ │ ├── spaces-in-header │ │ │ ├── request.toml │ │ │ └── request.json │ │ │ ├── dotted-header │ │ │ ├── request.toml │ │ │ └── request.json │ │ │ ├── disabled-header │ │ │ ├── request.toml │ │ │ └── request.json │ │ │ ├── reserved-header │ │ │ ├── request.toml │ │ │ └── request.json │ │ │ └── duplicate-header │ │ │ ├── request.toml │ │ │ └── request.json │ └── package.json └── bruno-docs │ ├── package.json │ └── readme.md ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── config.yaml │ └── FeatureRequest.yaml └── PULL_REQUEST_TEMPLATE.md ├── assets └── images │ ├── logo.png │ ├── cli-demo.png │ ├── landing-2.png │ ├── run-anywhere.png │ ├── sponsors │ ├── zuplo.png │ ├── samagata.png │ └── commit-company.png │ ├── version-control.png │ ├── local-collections.png │ └── logo-transparent.png ├── .husky └── pre-commit ├── .prettierrc.json ├── tests └── utils │ └── data-faker.js ├── docs └── publishing │ ├── publishing_cn.md │ ├── publishing_zhtw.md │ ├── publishing_ja.md │ ├── publishing_tr.md │ ├── publishing_bn.md │ ├── publishing_pl.md │ ├── publishing_de.md │ ├── publishing_fr.md │ ├── publishing_pt_br.md │ └── publishing_ro.md └── .gitignore /.nvmrc: -------------------------------------------------------------------------------- 1 | v20.9.0 -------------------------------------------------------------------------------- /packages/bruno-tests/.nvmrc: -------------------------------------------------------------------------------- 1 | v20 2 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: helloanoop 2 | -------------------------------------------------------------------------------- /packages/bruno-app/src/styles/_buttons.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection/.nvmrc: -------------------------------------------------------------------------------- 1 | v18 -------------------------------------------------------------------------------- /packages/bruno-tests/collection/.gitignore: -------------------------------------------------------------------------------- 1 | !.env -------------------------------------------------------------------------------- /packages/bruno-tests/collection_oauth2/.nvmrc: -------------------------------------------------------------------------------- 1 | v18 -------------------------------------------------------------------------------- /packages/bruno-tests/collection/.env: -------------------------------------------------------------------------------- 1 | PROC_ENV_VAR=woof -------------------------------------------------------------------------------- /packages/bruno-tests/collection_level_oauth2/.nvmrc: -------------------------------------------------------------------------------- 1 | v18 -------------------------------------------------------------------------------- /packages/bruno-tests/collection_oauth2/.gitignore: -------------------------------------------------------------------------------- 1 | !.env -------------------------------------------------------------------------------- /packages/bruno-app/src/styles/app.scss: -------------------------------------------------------------------------------- 1 | @import 'buttons'; 2 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection_level_oauth2/.gitignore: -------------------------------------------------------------------------------- 1 | !.env -------------------------------------------------------------------------------- /packages/bruno-tests/collection_oauth2/.env: -------------------------------------------------------------------------------- 1 | PROC_ENV_VAR=woof -------------------------------------------------------------------------------- /packages/bruno-app/.env.production: -------------------------------------------------------------------------------- 1 | ENV=production 2 | 3 | NEXT_PUBLIC_ENV=prod -------------------------------------------------------------------------------- /packages/bruno-electron/.env.sample: -------------------------------------------------------------------------------- 1 | BRUNO_INFO_ENDPOINT = http://localhost:8081 -------------------------------------------------------------------------------- /packages/bruno-tests/collection/file.json: -------------------------------------------------------------------------------- 1 | { 2 | "hello": "bruno" 3 | } 4 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection_oauth2/file.json: -------------------------------------------------------------------------------- 1 | { 2 | "hello": "bruno" 3 | } 4 | -------------------------------------------------------------------------------- /packages/bruno-cli/bin/bru.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | require('../src').run(); 4 | -------------------------------------------------------------------------------- /assets/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PDDStudio/bruno/main/assets/images/logo.png -------------------------------------------------------------------------------- /packages/bruno-app/src/utils/common/regex.js: -------------------------------------------------------------------------------- 1 | export const variableNameRegex = /^[\w-.]*$/; 2 | -------------------------------------------------------------------------------- /assets/images/cli-demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PDDStudio/bruno/main/assets/images/cli-demo.png -------------------------------------------------------------------------------- /assets/images/landing-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PDDStudio/bruno/main/assets/images/landing-2.png -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | . "$(dirname -- "$0")/_/husky.sh" 3 | 4 | npx pretty-quick --staged 5 | -------------------------------------------------------------------------------- /assets/images/run-anywhere.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PDDStudio/bruno/main/assets/images/run-anywhere.png -------------------------------------------------------------------------------- /assets/images/sponsors/zuplo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PDDStudio/bruno/main/assets/images/sponsors/zuplo.png -------------------------------------------------------------------------------- /assets/images/version-control.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PDDStudio/bruno/main/assets/images/version-control.png -------------------------------------------------------------------------------- /assets/images/local-collections.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PDDStudio/bruno/main/assets/images/local-collections.png -------------------------------------------------------------------------------- /assets/images/logo-transparent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PDDStudio/bruno/main/assets/images/logo-transparent.png -------------------------------------------------------------------------------- /assets/images/sponsors/samagata.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PDDStudio/bruno/main/assets/images/sponsors/samagata.png -------------------------------------------------------------------------------- /packages/bruno-cli/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | web 3 | out 4 | 5 | pnpm-lock.yaml 6 | package-lock.json 7 | yarn.lock 8 | -------------------------------------------------------------------------------- /packages/bruno-lang/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | web 3 | out 4 | 5 | pnpm-lock.yaml 6 | package-lock.json 7 | yarn.lock 8 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection/lib/math.js: -------------------------------------------------------------------------------- 1 | const sum = (a, b) => a + b; 2 | 3 | module.exports = { 4 | sum 5 | }; 6 | -------------------------------------------------------------------------------- /packages/bruno-app/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["next/babel"], 3 | "plugins": [["styled-components", { "ssr": true }]] 4 | } -------------------------------------------------------------------------------- /packages/bruno-app/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PDDStudio/bruno/main/packages/bruno-app/public/favicon.ico -------------------------------------------------------------------------------- /packages/bruno-schema/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | web 3 | out 4 | 5 | pnpm-lock.yaml 6 | package-lock.json 7 | yarn.lock 8 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection/readme.md: -------------------------------------------------------------------------------- 1 | # bruno-tests collection 2 | 3 | API Collection to run sanity tests on Bruno CLI. 4 | -------------------------------------------------------------------------------- /assets/images/sponsors/commit-company.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PDDStudio/bruno/main/assets/images/sponsors/commit-company.png -------------------------------------------------------------------------------- /packages/bruno-common/src/index.ts: -------------------------------------------------------------------------------- 1 | import interpolate from './interpolate'; 2 | 3 | export default { 4 | interpolate 5 | }; 6 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection_oauth2/readme.md: -------------------------------------------------------------------------------- 1 | # bruno-tests collection 2 | 3 | API Collection to run sanity tests on Bruno CLI. 4 | -------------------------------------------------------------------------------- /packages/bruno-app/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {} 5 | } 6 | }; 7 | -------------------------------------------------------------------------------- /packages/bruno-app/src/providers/ReduxStore/middlewares/tasks/utils.js: -------------------------------------------------------------------------------- 1 | export const taskTypes = { 2 | OPEN_REQUEST: 'OPEN_REQUEST' 3 | }; 4 | -------------------------------------------------------------------------------- /packages/bruno-cli/assets/images/cli-demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PDDStudio/bruno/main/packages/bruno-cli/assets/images/cli-demo.png -------------------------------------------------------------------------------- /packages/bruno-electron/src/about/256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PDDStudio/bruno/main/packages/bruno-electron/src/about/256x256.png -------------------------------------------------------------------------------- /packages/bruno-tests/collection_level_oauth2/readme.md: -------------------------------------------------------------------------------- 1 | # bruno-tests collection 2 | 3 | API Collection to run sanity tests on Bruno CLI. 4 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "none", 3 | "tabWidth": 2, 4 | "semi": true, 5 | "singleQuote": true, 6 | "printWidth": 120 7 | } 8 | -------------------------------------------------------------------------------- /packages/bruno-electron/resources/icons/mac/icon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PDDStudio/bruno/main/packages/bruno-electron/resources/icons/mac/icon.icns -------------------------------------------------------------------------------- /packages/bruno-electron/resources/icons/png/16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PDDStudio/bruno/main/packages/bruno-electron/resources/icons/png/16x16.png -------------------------------------------------------------------------------- /packages/bruno-electron/resources/icons/png/24x24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PDDStudio/bruno/main/packages/bruno-electron/resources/icons/png/24x24.png -------------------------------------------------------------------------------- /packages/bruno-electron/resources/icons/png/32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PDDStudio/bruno/main/packages/bruno-electron/resources/icons/png/32x32.png -------------------------------------------------------------------------------- /packages/bruno-electron/resources/icons/png/48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PDDStudio/bruno/main/packages/bruno-electron/resources/icons/png/48x48.png -------------------------------------------------------------------------------- /packages/bruno-electron/resources/icons/png/64x64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PDDStudio/bruno/main/packages/bruno-electron/resources/icons/png/64x64.png -------------------------------------------------------------------------------- /packages/bruno-electron/resources/icons/win/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PDDStudio/bruno/main/packages/bruno-electron/resources/icons/win/icon.ico -------------------------------------------------------------------------------- /packages/bruno-lang/v1/tests/fixtures/env.bru: -------------------------------------------------------------------------------- 1 | vars 2 | 1 host https://www.google.com 3 | 1 jwt secret 4 | 0 Content-type application/json 5 | /vars 6 | -------------------------------------------------------------------------------- /packages/bruno-app/src/themes/index.js: -------------------------------------------------------------------------------- 1 | import light from './light'; 2 | import dark from './dark'; 3 | 4 | export default { 5 | light, 6 | dark 7 | }; 8 | -------------------------------------------------------------------------------- /packages/bruno-electron/resources/icons/png/128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PDDStudio/bruno/main/packages/bruno-electron/resources/icons/png/128x128.png -------------------------------------------------------------------------------- /packages/bruno-electron/resources/icons/png/256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PDDStudio/bruno/main/packages/bruno-electron/resources/icons/png/256x256.png -------------------------------------------------------------------------------- /packages/bruno-electron/resources/icons/png/512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PDDStudio/bruno/main/packages/bruno-electron/resources/icons/png/512x512.png -------------------------------------------------------------------------------- /packages/bruno-electron/resources/icons/png/1024x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PDDStudio/bruno/main/packages/bruno-electron/resources/icons/png/1024x1024.png -------------------------------------------------------------------------------- /packages/bruno-graphql-docs/src/index.ts: -------------------------------------------------------------------------------- 1 | import { DocExplorer } from './components/DocExplorer'; 2 | 3 | import './index.css'; 4 | 5 | export { DocExplorer }; 6 | -------------------------------------------------------------------------------- /packages/bruno-app/.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "none", 3 | "tabWidth": 2, 4 | "semi": true, 5 | "singleQuote": true, 6 | "printWidth": 120 7 | } 8 | -------------------------------------------------------------------------------- /packages/bruno-query/jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('ts-jest').JestConfigWithTsJest} */ 2 | module.exports = { 3 | preset: 'ts-jest', 4 | testEnvironment: 'node', 5 | }; -------------------------------------------------------------------------------- /packages/bruno-common/jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('ts-jest').JestConfigWithTsJest} */ 2 | module.exports = { 3 | preset: 'ts-jest', 4 | testEnvironment: 'node' 5 | }; 6 | -------------------------------------------------------------------------------- /packages/bruno-js/readme.md: -------------------------------------------------------------------------------- 1 | # bruno-js 2 | 3 | Provides the script, test, vars and assert runtimes. 4 | 5 | ### Publish to Npm Registry 6 | ```bash 7 | npm publish --access=public 8 | ``` -------------------------------------------------------------------------------- /packages/bruno-lang/readme.md: -------------------------------------------------------------------------------- 1 | # bruno-lang 2 | 3 | The language utils for working with `.bru` files 4 | 5 | ### Publish to Npm Registry 6 | ```bash 7 | npm publish --access=public 8 | ``` -------------------------------------------------------------------------------- /packages/bruno-app/src/components/CollectionSettings/Auth/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const Wrapper = styled.div``; 4 | 5 | export default Wrapper; 6 | -------------------------------------------------------------------------------- /packages/bruno-electron/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | web 3 | out 4 | dist 5 | .env 6 | 7 | // certs 8 | sectigo.* 9 | 10 | pnpm-lock.yaml 11 | package-lock.json 12 | yarn.lock 13 | -------------------------------------------------------------------------------- /packages/bruno-toml/tests/methods/get/request.toml: -------------------------------------------------------------------------------- 1 | [meta] 2 | name = 'Get users' 3 | type = 'http' 4 | seq = 1 5 | 6 | [http] 7 | method = 'GET' 8 | url = 'https://reqres.in/api/users' 9 | -------------------------------------------------------------------------------- /packages/bruno-app/public/theme/index.js: -------------------------------------------------------------------------------- 1 | import darkTheme from './dark'; 2 | import lightTheme from './light'; 3 | 4 | export default { 5 | Light: lightTheme, 6 | Dark: darkTheme 7 | }; 8 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/CollectionSettings/Tests/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const StyledWrapper = styled.div``; 4 | 5 | export default StyledWrapper; 6 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/FolderSettings/Tests/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const StyledWrapper = styled.div``; 4 | 5 | export default StyledWrapper; 6 | -------------------------------------------------------------------------------- /packages/bruno-electron/src/about/about.css: -------------------------------------------------------------------------------- 1 | .versions { 2 | -webkit-user-select: text; 3 | user-select: text; 4 | } 5 | .title { 6 | -webkit-user-select: text; 7 | user-select: text; 8 | } 9 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection_oauth2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usebruno/test-collection", 3 | "version": "0.0.1", 4 | "dependencies": { 5 | "@faker-js/faker": "^8.4.0" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/bruno-toml/tests/methods/delete/request.toml: -------------------------------------------------------------------------------- 1 | [meta] 2 | name = 'Delete User' 3 | type = 'http' 4 | seq = 1 5 | 6 | [http] 7 | method = 'DELETE' 8 | url = 'https://reqres.in/api/users/2' 9 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/RequestTabs/CollectionToolBar/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const StyledWrapper = styled.div``; 4 | 5 | export default StyledWrapper; 6 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection_level_oauth2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usebruno/test-collection", 3 | "version": "0.0.1", 4 | "dependencies": { 5 | "@faker-js/faker": "^8.4.0" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection/auth/cookie/Login.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: Login 3 | type: http 4 | seq: 1 5 | } 6 | 7 | post { 8 | url: {{host}}/api/auth/cookie/login 9 | body: none 10 | auth: none 11 | } 12 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/Preferences/Theme/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const StyledWrapper = styled.div` 4 | color: var(--color-text); 5 | `; 6 | 7 | export default StyledWrapper; 8 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection/auth/cookie/Check.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: Check 3 | type: http 4 | seq: 2 5 | } 6 | 7 | get { 8 | url: {{host}}/api/auth/cookie/protected 9 | body: none 10 | auth: none 11 | } 12 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection/echo/echo bom json.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: echo bom json 3 | type: http 4 | seq: 1 5 | } 6 | 7 | get { 8 | url: {{host}}/api/echo/bom-json-test 9 | body: none 10 | auth: none 11 | } -------------------------------------------------------------------------------- /packages/bruno-docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usebruno/docs", 3 | "version": "0.0.1", 4 | "main": "src/index.js", 5 | "files": [ 6 | "src", 7 | "package.json" 8 | ], 9 | "dependencies": { 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/Preferences/Font/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const StyledWrapper = styled.div` 4 | color: ${(props) => props.theme.text}; 5 | `; 6 | 7 | export default StyledWrapper; 8 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/Preferences/General/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const StyledWrapper = styled.div` 4 | color: ${(props) => props.theme.text}; 5 | `; 6 | 7 | export default StyledWrapper; 8 | -------------------------------------------------------------------------------- /packages/bruno-common/readme.md: -------------------------------------------------------------------------------- 1 | # bruno-common 2 | 3 | A collection of common utilities used across Bruno App, Electron and CLI packages. 4 | 5 | ### Publish to Npm Registry 6 | 7 | ```bash 8 | npm publish --access=public 9 | ``` 10 | -------------------------------------------------------------------------------- /packages/bruno-docs/readme.md: -------------------------------------------------------------------------------- 1 | # bruno-docs 2 | 3 | This is a wip. 4 | 5 | We have a request to generate docs in a html file that can be hosted on a server so that the visitor can view the API and make requests without downloading/installing anything. -------------------------------------------------------------------------------- /packages/bruno-electron/readme.md: -------------------------------------------------------------------------------- 1 | # bruno-electron 2 | 3 | ```bash 4 | # electron dev 5 | npm start 6 | 7 | # generate pfx file for signing windows build 8 | openssl pkcs12 -export -inkey sectigo.key -in sectigo.pem -out sectigo.pfx 9 | ``` 10 | -------------------------------------------------------------------------------- /packages/bruno-graphql-docs/readme.md: -------------------------------------------------------------------------------- 1 | # bruno-graphql-docs 2 | 3 | Standalone graphql docs explorer module forked from [graphiql](https://github.com/graphql/graphiql) 4 | 5 | ### Publish to Npm Registry 6 | ```bash 7 | npm publish --access=public 8 | ``` -------------------------------------------------------------------------------- /packages/bruno-toml/tests/methods/get/request.json: -------------------------------------------------------------------------------- 1 | { 2 | "meta": { 3 | "name": "Get users", 4 | "type": "http", 5 | "seq": 1 6 | }, 7 | "http": { 8 | "method": "GET", 9 | "url": "https://reqres.in/api/users" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/bruno-app/src/assets/send.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /packages/bruno-lang/v2/src/dotenvToJson.js: -------------------------------------------------------------------------------- 1 | const dotenv = require('dotenv'); 2 | 3 | const parser = (input) => { 4 | const buf = Buffer.from(input); 5 | const parsed = dotenv.parse(buf); 6 | return parsed; 7 | }; 8 | 9 | module.exports = parser; 10 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/Sidebar/Collections/CreateOrOpenCollection/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const Wrapper = styled.div` 4 | color: ${(props) => props.theme.colors.text.muted}; 5 | `; 6 | 7 | export default Wrapper; 8 | -------------------------------------------------------------------------------- /packages/bruno-app/src/utils/common/cache.js: -------------------------------------------------------------------------------- 1 | class Cache { 2 | get(key) { 3 | return window.localStorage.getItem(key); 4 | } 5 | set(key, val) { 6 | window.localStorage.setItem(key, val); 7 | } 8 | } 9 | 10 | module.exports = new Cache(); 11 | -------------------------------------------------------------------------------- /packages/bruno-app/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | darkMode: ['class'], 4 | content: ['./src/**/*.{js,jsx}'], 5 | prefix: '', 6 | theme: { 7 | extend: {} 8 | }, 9 | plugins: [] 10 | }; 11 | -------------------------------------------------------------------------------- /packages/bruno-schema/src/index.js: -------------------------------------------------------------------------------- 1 | const { collectionSchema, itemSchema, environmentSchema, environmentsSchema } = require('./collections'); 2 | 3 | module.exports = { 4 | itemSchema, 5 | environmentSchema, 6 | environmentsSchema, 7 | collectionSchema 8 | }; 9 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usebruno/test-collection", 3 | "version": "0.0.1", 4 | "dependencies": { 5 | "@faker-js/faker": "^8.4.0", 6 | "jsonwebtoken": "^9.0.2", 7 | "lru-map-cache": "^0.1.0" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/bruno-toml/tests/methods/delete/request.json: -------------------------------------------------------------------------------- 1 | { 2 | "meta": { 3 | "name": "Delete User", 4 | "type": "http", 5 | "seq": 1 6 | }, 7 | "http": { 8 | "method": "DELETE", 9 | "url": "https://reqres.in/api/users/2" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/RequestPane/Vars/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const StyledWrapper = styled.div` 4 | div.title { 5 | color: var(--color-tab-inactive); 6 | } 7 | `; 8 | 9 | export default StyledWrapper; 10 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/FolderSettings/Vars/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const StyledWrapper = styled.div` 4 | div.title { 5 | color: var(--color-tab-inactive); 6 | } 7 | `; 8 | 9 | export default StyledWrapper; 10 | -------------------------------------------------------------------------------- /packages/bruno-app/src/providers/App/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const StyledWrapper = styled.div` 4 | color: ${(props) => props.theme.text}; 5 | background-color: ${(props) => props.theme.bg}; 6 | `; 7 | 8 | export default StyledWrapper; 9 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection/environments/Prod.bru: -------------------------------------------------------------------------------- 1 | vars { 2 | host: https://testbench-sanity.usebruno.com 3 | bearer_auth_token: your_secret_token 4 | basic_auth_password: della 5 | env.var1: envVar1 6 | env-var2: envVar2 7 | bark: {{process.env.PROC_ENV_VAR}} 8 | } 9 | -------------------------------------------------------------------------------- /packages/bruno-toml/tests/scripts/pre-request/request.toml: -------------------------------------------------------------------------------- 1 | [meta] 2 | name = 'Get users' 3 | type = 'http' 4 | seq = 1 5 | 6 | [http] 7 | method = 'GET' 8 | url = 'https://reqres.in/api/users' 9 | 10 | [script] 11 | pre-request = ''' 12 | req.body.id = uuid(); 13 | ''' 14 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection_oauth2/environments/Prod.bru: -------------------------------------------------------------------------------- 1 | vars { 2 | host: https://testbench-sanity.usebruno.com 3 | bearer_auth_token: your_secret_token 4 | basic_auth_password: della 5 | env.var1: envVar1 6 | env-var2: envVar2 7 | bark: {{process.env.PROC_ENV_VAR}} 8 | } 9 | -------------------------------------------------------------------------------- /packages/bruno-toml/tests/headers/empty-header/request.toml: -------------------------------------------------------------------------------- 1 | [meta] 2 | name = 'Get users' 3 | type = 'http' 4 | seq = 1 5 | 6 | [http] 7 | method = 'GET' 8 | url = 'https://reqres.in/api/users' 9 | 10 | [headers] 11 | Content-Type = 'application/json' 12 | Empty-Header = '' 13 | -------------------------------------------------------------------------------- /packages/bruno-toml/tests/headers/simple-header/request.toml: -------------------------------------------------------------------------------- 1 | [meta] 2 | name = 'Get users' 3 | type = 'http' 4 | seq = 1 5 | 6 | [http] 7 | method = 'GET' 8 | url = 'https://reqres.in/api/users' 9 | 10 | [headers] 11 | Content-Type = 'application/json' 12 | Cookie = 'foo=bar' 13 | -------------------------------------------------------------------------------- /packages/bruno-toml/tests/headers/unicode-in-header/request.toml: -------------------------------------------------------------------------------- 1 | [meta] 2 | name = 'Get users' 3 | type = 'http' 4 | seq = 1 5 | 6 | [http] 7 | method = 'GET' 8 | url = 'https://reqres.in/api/users' 9 | 10 | [headers] 11 | Content-Type = 'application/json' 12 | '🐶' = '🚀' 13 | -------------------------------------------------------------------------------- /tests/utils/data-faker.js: -------------------------------------------------------------------------------- 1 | const { faker } = require('@faker-js/faker'); 2 | 3 | export let randomWords = faker.random.words(); 4 | export let randomVerb = faker.hacker.verb(); 5 | export let randomHttpMethod = faker.internet.httpMethod(); 6 | export let randomUrl = faker.internet.url(); 7 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection_level_oauth2/environments/Prod.bru: -------------------------------------------------------------------------------- 1 | vars { 2 | host: https://testbench-sanity.usebruno.com 3 | bearer_auth_token: your_secret_token 4 | basic_auth_password: della 5 | env.var1: envVar1 6 | env-var2: envVar2 7 | bark: {{process.env.PROC_ENV_VAR}} 8 | } 9 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection_oauth2/collection.bru: -------------------------------------------------------------------------------- 1 | headers { 2 | check: again 3 | } 4 | 5 | auth { 6 | mode: none 7 | } 8 | 9 | docs { 10 | # bruno-testbench 🐶 11 | 12 | This is a test collection that I am using to test various functionalities around bruno 13 | } 14 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection/echo/echo xml raw.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: echo xml raw 3 | type: http 4 | seq: 4 5 | } 6 | 7 | post { 8 | url: {{host}}/api/echo/xml-raw 9 | body: xml 10 | auth: none 11 | } 12 | 13 | body:xml { 14 | bruno 15 | } 16 | -------------------------------------------------------------------------------- /packages/bruno-toml/tests/headers/spaces-in-header/request.toml: -------------------------------------------------------------------------------- 1 | [meta] 2 | name = 'Get users' 3 | type = 'http' 4 | seq = 1 5 | 6 | [http] 7 | method = 'GET' 8 | url = 'https://reqres.in/api/users' 9 | 10 | [headers] 11 | Content-Type = 'application/json' 12 | 'Spaces In Header' = '' 13 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/Portal/index.js: -------------------------------------------------------------------------------- 1 | import { createPortal } from 'react-dom'; 2 | 3 | function Portal({ children, wrapperId }) { 4 | wrapperId = wrapperId || 'bruno-app-body'; 5 | 6 | return createPortal(children, document.getElementById(wrapperId)); 7 | } 8 | export default Portal; 9 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/ResponsePane/ResponseSave/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const StyledWrapper = styled.div` 4 | font-size: 0.8125rem; 5 | color: ${(props) => props.theme.requestTabPanel.responseStatus}; 6 | `; 7 | 8 | export default StyledWrapper; 9 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/RequestPane/RequestBody/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const Wrapper = styled.div` 4 | div.CodeMirror { 5 | /* todo: find a better way */ 6 | height: calc(100vh - 220px); 7 | } 8 | `; 9 | 10 | export default Wrapper; 11 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/ResponsePane/ResponseClear/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const StyledWrapper = styled.div` 4 | font-size: 0.8125rem; 5 | color: ${(props) => props.theme.requestTabPanel.responseStatus}; 6 | `; 7 | 8 | export default StyledWrapper; 9 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/RunCollectionItem/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const Wrapper = styled.div` 4 | .bruno-modal-content { 5 | padding-bottom: 1rem; 6 | } 7 | `; 8 | 9 | export default Wrapper; 10 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/RequestPane/Tests/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const StyledWrapper = styled.div` 4 | div.CodeMirror { 5 | /* todo: find a better way */ 6 | height: calc(100vh - 220px); 7 | } 8 | `; 9 | 10 | export default StyledWrapper; 11 | -------------------------------------------------------------------------------- /packages/bruno-toml/tests/headers/dotted-header/request.toml: -------------------------------------------------------------------------------- 1 | [meta] 2 | name = 'Get users' 3 | type = 'http' 4 | seq = 1 5 | 6 | [http] 7 | method = 'GET' 8 | url = 'https://reqres.in/api/users' 9 | 10 | [headers] 11 | Content-Type = 'application/json' 12 | 'Dots.In.Header.Key' = 'Dots.In.Header.Value' 13 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/ResponsePane/ResponseSize/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const Wrapper = styled.div` 4 | font-size: 0.75rem; 5 | font-weight: 600; 6 | color: ${(props) => props.theme.requestTabPanel.responseStatus}; 7 | `; 8 | 9 | export default Wrapper; 10 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/ResponsePane/ResponseTime/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const Wrapper = styled.div` 4 | font-size: 0.75rem; 5 | font-weight: 600; 6 | color: ${(props) => props.theme.requestTabPanel.responseStatus}; 7 | `; 8 | 9 | export default Wrapper; 10 | -------------------------------------------------------------------------------- /packages/bruno-toml/tests/headers/disabled-header/request.toml: -------------------------------------------------------------------------------- 1 | [meta] 2 | name = 'Get users' 3 | type = 'http' 4 | seq = 1 5 | 6 | [http] 7 | method = 'GET' 8 | url = 'https://reqres.in/api/users' 9 | 10 | [headers] 11 | Content-Type = 'application/json' 12 | 13 | [headers.disabled] 14 | Cookie = 'foo=bar' 15 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/CollectionSettings/Info/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const StyledWrapper = styled.div` 4 | table { 5 | td { 6 | &:first-child { 7 | width: 120px; 8 | } 9 | } 10 | } 11 | `; 12 | 13 | export default StyledWrapper; 14 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/RequestPane/Auth/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const Wrapper = styled.div` 4 | .inherit-mode-text { 5 | color: ${(props) => props.theme.colors.text.yellow}; 6 | } 7 | .inherit-mode-label { 8 | } 9 | `; 10 | 11 | export default Wrapper; 12 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/RequestPane/GraphQLVariables/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const StyledWrapper = styled.div` 4 | div.CodeMirror { 5 | /* todo: find a better way */ 6 | height: calc(100vh - 220px); 7 | } 8 | `; 9 | 10 | export default StyledWrapper; 11 | -------------------------------------------------------------------------------- /packages/bruno-toml/tests/scripts/pre-request/request.json: -------------------------------------------------------------------------------- 1 | { 2 | "meta": { 3 | "name": "Get users", 4 | "type": "http", 5 | "seq": 1 6 | }, 7 | "http": { 8 | "method": "GET", 9 | "url": "https://reqres.in/api/users" 10 | }, 11 | "script": { 12 | "req": "req.body.id = uuid();" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/FolderSettings/Script/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const StyledWrapper = styled.div` 4 | div.CodeMirror { 5 | height: inherit; 6 | } 7 | 8 | div.title { 9 | color: var(--color-tab-inactive); 10 | } 11 | `; 12 | 13 | export default StyledWrapper; 14 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/RequestPane/Script/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const StyledWrapper = styled.div` 4 | div.CodeMirror { 5 | height: inherit; 6 | } 7 | 8 | div.title { 9 | color: var(--color-tab-inactive); 10 | } 11 | `; 12 | 13 | export default StyledWrapper; 14 | -------------------------------------------------------------------------------- /packages/bruno-common/.gitignore: -------------------------------------------------------------------------------- 1 | # dependencies 2 | node_modules 3 | yarn.lock 4 | pnpm-lock.yaml 5 | package-lock.json 6 | .pnp 7 | .pnp.js 8 | 9 | # testing 10 | coverage 11 | 12 | # production 13 | dist 14 | 15 | # misc 16 | .DS_Store 17 | *.pem 18 | 19 | # debug 20 | npm-debug.log* 21 | yarn-debug.log* 22 | yarn-error.log* 23 | -------------------------------------------------------------------------------- /packages/bruno-query/.gitignore: -------------------------------------------------------------------------------- 1 | # dependencies 2 | node_modules 3 | yarn.lock 4 | pnpm-lock.yaml 5 | package-lock.json 6 | .pnp 7 | .pnp.js 8 | 9 | # testing 10 | coverage 11 | 12 | # production 13 | dist 14 | 15 | # misc 16 | .DS_Store 17 | *.pem 18 | 19 | # debug 20 | npm-debug.log* 21 | yarn-debug.log* 22 | yarn-error.log* 23 | -------------------------------------------------------------------------------- /packages/bruno-schema/src/common/index.js: -------------------------------------------------------------------------------- 1 | const Yup = require('yup'); 2 | 3 | const uidSchema = Yup.string() 4 | .length(21, 'uid must be 21 characters in length') 5 | .matches(/^[a-zA-Z0-9]*$/, 'uid must be alphanumeric') 6 | .required('uid is required') 7 | .strict(); 8 | 9 | module.exports = { 10 | uidSchema 11 | }; 12 | -------------------------------------------------------------------------------- /packages/bruno-toml/tests/scripts/tests/request.toml: -------------------------------------------------------------------------------- 1 | [meta] 2 | name = 'Get users' 3 | type = 'http' 4 | seq = 1 5 | 6 | [http] 7 | method = 'GET' 8 | url = 'https://reqres.in/api/users' 9 | 10 | [script] 11 | tests = ''' 12 | test('Status code is 200', function () { 13 | expect(res.statusCode).to.eql(200); 14 | }); 15 | ''' 16 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/CollectionSettings/Script/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const StyledWrapper = styled.div` 4 | div.CodeMirror { 5 | height: inherit; 6 | } 7 | 8 | div.title { 9 | color: var(--color-tab-inactive); 10 | } 11 | `; 12 | 13 | export default StyledWrapper; 14 | -------------------------------------------------------------------------------- /packages/bruno-graphql-docs/.gitignore: -------------------------------------------------------------------------------- 1 | # dependencies 2 | node_modules 3 | yarn.lock 4 | pnpm-lock.yaml 5 | package-lock.json 6 | .pnp 7 | .pnp.js 8 | 9 | # testing 10 | coverage 11 | 12 | # production 13 | dist 14 | 15 | # misc 16 | .DS_Store 17 | *.pem 18 | 19 | # debug 20 | npm-debug.log* 21 | yarn-debug.log* 22 | yarn-error.log* 23 | -------------------------------------------------------------------------------- /packages/bruno-toml/tests/scripts/post-response/request.toml: -------------------------------------------------------------------------------- 1 | [meta] 2 | name = 'Get users' 3 | type = 'http' 4 | seq = 1 5 | 6 | [http] 7 | method = 'GET' 8 | url = 'https://reqres.in/api/users' 9 | 10 | [script] 11 | post-response = ''' 12 | bru.setVar('token', res.body.token); 13 | console.log('token: ' + res.body.token); 14 | ''' 15 | -------------------------------------------------------------------------------- /packages/bruno-schema/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usebruno/schema", 3 | "version": "0.7.0", 4 | "license": "MIT", 5 | "main": "src/index.js", 6 | "files": [ 7 | "src", 8 | "package.json" 9 | ], 10 | "scripts": { 11 | "test": "jest" 12 | }, 13 | "peerDependencies": { 14 | "yup": "^0.32.11" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection/collection.bru: -------------------------------------------------------------------------------- 1 | headers { 2 | check: again 3 | } 4 | 5 | auth { 6 | mode: bearer 7 | } 8 | 9 | auth:bearer { 10 | token: {{bearer_auth_token}} 11 | } 12 | 13 | docs { 14 | # bruno-testbench 🐶 15 | 16 | This is a test collection that I am using to test various functionalities around bruno 17 | } 18 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/Environments/EnvironmentSettings/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const StyledWrapper = styled.div` 4 | button.btn-create-environment { 5 | &:hover { 6 | span { 7 | text-decoration: underline; 8 | } 9 | } 10 | } 11 | `; 12 | 13 | export default StyledWrapper; 14 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/ResponsePane/Placeholder/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const StyledWrapper = styled.div` 4 | padding-top: 20%; 5 | width: 100%; 6 | 7 | .send-icon { 8 | color: ${(props) => props.theme.requestTabPanel.responseSendIcon}; 9 | } 10 | `; 11 | 12 | export default StyledWrapper; 13 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection_level_oauth2/resource.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: resource 3 | type: http 4 | seq: 2 5 | } 6 | 7 | post { 8 | url: {{host}}/api/auth/oauth2/authorization_code/resource?token={{access_token_set_by_collection}} 9 | body: json 10 | auth: none 11 | } 12 | 13 | query { 14 | token: {{access_token_set_by_collection}} 15 | } 16 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection_oauth2/auth/oauth2/password_credentials/resource.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: resource 3 | type: http 4 | seq: 2 5 | } 6 | 7 | post { 8 | url: {{host}}/api/auth/oauth2/password_credentials/resource 9 | body: none 10 | auth: bearer 11 | } 12 | 13 | auth:bearer { 14 | token: {{passwordCredentials_access_token}} 15 | } 16 | -------------------------------------------------------------------------------- /packages/bruno-toml/tests/scripts/tests/request.json: -------------------------------------------------------------------------------- 1 | { 2 | "meta": { 3 | "name": "Get users", 4 | "type": "http", 5 | "seq": 1 6 | }, 7 | "http": { 8 | "method": "GET", 9 | "url": "https://reqres.in/api/users" 10 | }, 11 | "tests": "test('Status code is 200', function () {\n expect(res.statusCode).to.eql(200);\n});" 12 | } 13 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yaml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: true 2 | contact_links: 3 | - name: Discussions 4 | url: https://github.com/usebruno/bruno/discussions 5 | about: You can ask general questions or give feedback here. 6 | - name: Discord Server 7 | url: https://discord.com/invite/KgcZUncpjq 8 | about: Join our Discord community to chat about Bruno. 9 | -------------------------------------------------------------------------------- /packages/bruno-electron/src/utils/cancel-token.js: -------------------------------------------------------------------------------- 1 | const cancelTokens = {}; 2 | 3 | const saveCancelToken = (uid, abortController) => { 4 | cancelTokens[uid] = abortController; 5 | }; 6 | 7 | const deleteCancelToken = (uid) => { 8 | delete cancelTokens[uid]; 9 | }; 10 | 11 | module.exports = { 12 | cancelTokens, 13 | saveCancelToken, 14 | deleteCancelToken 15 | }; 16 | -------------------------------------------------------------------------------- /packages/bruno-js/src/test-results.js: -------------------------------------------------------------------------------- 1 | const { nanoid } = require('nanoid'); 2 | 3 | class TestResults { 4 | constructor() { 5 | this.results = []; 6 | } 7 | 8 | addResult(result) { 9 | result.uid = nanoid(); 10 | this.results.push(result); 11 | } 12 | 13 | getResults() { 14 | return this.results; 15 | } 16 | } 17 | 18 | module.exports = TestResults; 19 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection_oauth2/auth/oauth2/authorization_code/resource.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: resource 3 | type: http 4 | seq: 3 5 | } 6 | 7 | post { 8 | url: {{host}}/api/auth/oauth2/authorization_code/resource?token={{authorization_code_access_token}} 9 | body: json 10 | auth: none 11 | } 12 | 13 | query { 14 | token: {{authorization_code_access_token}} 15 | } -------------------------------------------------------------------------------- /packages/bruno-js/src/index.js: -------------------------------------------------------------------------------- 1 | const ScriptRuntime = require('./runtime/script-runtime'); 2 | const TestRuntime = require('./runtime/test-runtime'); 3 | const VarsRuntime = require('./runtime/vars-runtime'); 4 | const AssertRuntime = require('./runtime/assert-runtime'); 5 | 6 | module.exports = { 7 | ScriptRuntime, 8 | TestRuntime, 9 | VarsRuntime, 10 | AssertRuntime 11 | }; 12 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection/graphql/spacex.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: spacex 3 | type: graphql 4 | seq: 1 5 | } 6 | 7 | post { 8 | url: https://spacex-production.up.railway.app/ 9 | body: graphql 10 | auth: none 11 | } 12 | 13 | body:graphql { 14 | { 15 | company { 16 | ceo 17 | } 18 | } 19 | 20 | } 21 | 22 | assert { 23 | res.status: eq 200 24 | } 25 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection_oauth2/auth/oauth2/client_credentials/resource.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: resource 3 | type: http 4 | seq: 2 5 | } 6 | 7 | get { 8 | url: {{host}}/api/auth/oauth2/client_credentials/resource?token={{client_credentials_access_token}} 9 | body: none 10 | auth: none 11 | } 12 | 13 | query { 14 | token: {{client_credentials_access_token}} 15 | } 16 | -------------------------------------------------------------------------------- /packages/bruno-toml/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usebruno/toml", 3 | "version": "0.1.0", 4 | "license": "MIT", 5 | "main": "src/index.js", 6 | "files": [ 7 | "lib", 8 | "src", 9 | "package.json" 10 | ], 11 | "scripts": { 12 | "test": "jest" 13 | }, 14 | "dependencies": { 15 | "@iarna/toml": "^2.2.5", 16 | "lodash": "^4.17.21" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /packages/bruno-toml/tests/scripts/post-response/request.json: -------------------------------------------------------------------------------- 1 | { 2 | "meta": { 3 | "name": "Get users", 4 | "type": "http", 5 | "seq": 1 6 | }, 7 | "http": { 8 | "method": "GET", 9 | "url": "https://reqres.in/api/users" 10 | }, 11 | "script": { 12 | "res": "bru.setVar('token', res.body.token);\nconsole.log('token: ' + res.body.token);" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection/auth/basic/via auth/Basic Auth 401.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: Basic Auth 400 3 | type: http 4 | seq: 2 5 | } 6 | 7 | post { 8 | url: {{host}}/api/auth/basic/protected 9 | body: json 10 | auth: none 11 | } 12 | 13 | auth:basic { 14 | username: bruno 15 | password: invalid 16 | } 17 | 18 | assert { 19 | res.status: 401 20 | res.body: Unauthorized 21 | } 22 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/Cookies/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const Wrapper = styled.div` 4 | table { 5 | width: 100%; 6 | table-layout: fixed; 7 | 8 | thead { 9 | color: ${(props) => props.theme.table.thead.color}; 10 | font-size: 0.8125rem; 11 | user-select: none; 12 | } 13 | } 14 | `; 15 | 16 | export default Wrapper; 17 | -------------------------------------------------------------------------------- /packages/bruno-lang/v1/src/tests-tag.js: -------------------------------------------------------------------------------- 1 | const { between, regex, everyCharUntil } = require('arcsecond'); 2 | 3 | const testsBegin = regex(/^tests\s*\r?\n/); 4 | const testsEnd = regex(/^[\r?\n]+\/tests[\s\r?\n]*/); 5 | 6 | const testsTag = between(testsBegin)(testsEnd)(everyCharUntil(testsEnd)).map((tests) => { 7 | return { 8 | tests: tests 9 | }; 10 | }); 11 | 12 | module.exports = testsTag; 13 | -------------------------------------------------------------------------------- /packages/bruno-lang/v1/src/params-tag.js: -------------------------------------------------------------------------------- 1 | const { between, regex } = require('arcsecond'); 2 | const keyValLines = require('./key-val-lines'); 3 | 4 | const begin = regex(/^params\s*\r?\n/); 5 | const end = regex(/^[\r?\n]*\/params\s*[\r?\n]*/); 6 | 7 | const paramsTag = between(begin)(end)(keyValLines).map(([params]) => { 8 | return { 9 | params 10 | }; 11 | }); 12 | 13 | module.exports = paramsTag; 14 | -------------------------------------------------------------------------------- /packages/bruno-lang/v1/src/script-tag.js: -------------------------------------------------------------------------------- 1 | const { between, regex, everyCharUntil } = require('arcsecond'); 2 | 3 | const scriptBegin = regex(/^script\s*\r?\n/); 4 | const scriptEnd = regex(/^[\r?\n]+\/script[\s\r?\n]*/); 5 | 6 | const scriptTag = between(scriptBegin)(scriptEnd)(everyCharUntil(scriptEnd)).map((script) => { 7 | return { 8 | script: script 9 | }; 10 | }); 11 | 12 | module.exports = scriptTag; 13 | -------------------------------------------------------------------------------- /packages/bruno-electron/resources/entitlements.mac.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.cs.allow-jit 6 | 7 | com.apple.security.cs.allow-unsigned-executable-memory 8 | 9 | 10 | -------------------------------------------------------------------------------- /packages/bruno-lang/v1/src/headers-tag.js: -------------------------------------------------------------------------------- 1 | const { between, regex } = require('arcsecond'); 2 | const keyValLines = require('./key-val-lines'); 3 | 4 | const begin = regex(/^headers\s*\r?\n/); 5 | const end = regex(/^[\r?\n]*\/headers\s*[\r?\n]*/); 6 | 7 | const headersTag = between(begin)(end)(keyValLines).map(([headers]) => { 8 | return { 9 | headers 10 | }; 11 | }); 12 | 13 | module.exports = headersTag; 14 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection_oauth2/bruno.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1", 3 | "name": "collection_oauth2", 4 | "type": "collection", 5 | "scripts": { 6 | "moduleWhitelist": ["crypto"], 7 | "filesystemAccess": { 8 | "allow": true 9 | } 10 | }, 11 | "clientCertificates": { 12 | "enabled": true, 13 | "certs": [] 14 | }, 15 | "presets": { 16 | "requestType": "http" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection/preview/image/bruno.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: bruno 3 | type: http 4 | seq: 1 5 | } 6 | 7 | get { 8 | url: https://www.usebruno.com/images/landing-2.png 9 | body: none 10 | auth: none 11 | } 12 | 13 | tests { 14 | test("should return parsed xml", function() { 15 | const headers = res.getHeaders(); 16 | expect(headers['content-type']).to.eql("image/png"); 17 | }); 18 | 19 | } 20 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/Spinner/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import StyledWrapper from './StyledWrapper'; 3 | 4 | // Todo: Size, Color config support 5 | const Spinner = ({ size, color, children }) => { 6 | return ( 7 | 8 |
9 | {children &&
{children}
} 10 |
11 | ); 12 | }; 13 | 14 | export default Spinner; 15 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection_level_oauth2/bruno.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1", 3 | "name": "collection_level_oauth2", 4 | "type": "collection", 5 | "scripts": { 6 | "moduleWhitelist": ["crypto"], 7 | "filesystemAccess": { 8 | "allow": true 9 | } 10 | }, 11 | "clientCertificates": { 12 | "enabled": true, 13 | "certs": [] 14 | }, 15 | "presets": { 16 | "requestType": "http" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/Icons/Send/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const SendIcon = ({ color, width }) => { 4 | return ( 5 | 6 | 7 | 8 | 9 | ); 10 | }; 11 | 12 | export default SendIcon; 13 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/Navbar/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const StyledWrapper = styled.div` 4 | .collection-dropdown { 5 | color: rgb(110 110 110); 6 | 7 | &:hover { 8 | color: inherit; 9 | } 10 | 11 | .tippy-box { 12 | top: -0.5rem; 13 | position: relative; 14 | user-select: none; 15 | } 16 | } 17 | `; 18 | 19 | export default StyledWrapper; 20 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection/auth/basic/via auth/Basic Auth 200.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: Basic Auth 200 3 | type: http 4 | seq: 1 5 | } 6 | 7 | post { 8 | url: {{host}}/api/auth/basic/protected 9 | body: json 10 | auth: basic 11 | } 12 | 13 | auth:basic { 14 | username: bruno 15 | password: {{basic_auth_password}} 16 | } 17 | 18 | assert { 19 | res.status: 200 20 | res.body.message: Authentication successful 21 | } 22 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection/auth/inherit auth/inherit Bearer Auth 200.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: inherit Bearer Auth 200 3 | type: http 4 | seq: 2 5 | } 6 | 7 | get { 8 | url: {{host}}/api/auth/bearer/protected 9 | body: none 10 | auth: inherit 11 | } 12 | 13 | assert { 14 | res.status: 200 15 | res.body.message: Authentication successful 16 | } 17 | 18 | script:post-response { 19 | bru.setEnvVar("foo", "bar"); 20 | } 21 | -------------------------------------------------------------------------------- /packages/bruno-app/next.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | reactStrictMode: false, 3 | publicRuntimeConfig: { 4 | CI: process.env.CI, 5 | PLAYWRIGHT: process.env.PLAYWRIGHT, 6 | ENV: process.env.ENV 7 | }, 8 | webpack: (config, { isServer }) => { 9 | // Fixes npm packages that depend on `fs` module 10 | if (!isServer) { 11 | config.resolve.fallback.fs = false; 12 | } 13 | return config; 14 | }, 15 | }; 16 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/Environments/EnvironmentSettings/DeleteEnvironment/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const Wrapper = styled.div` 4 | button.submit { 5 | color: white; 6 | background-color: var(--color-background-danger) !important; 7 | border: inherit !important; 8 | 9 | &:hover { 10 | border: inherit !important; 11 | } 12 | } 13 | `; 14 | 15 | export default Wrapper; 16 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/ResponsePane/StatusCode/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const Wrapper = styled.div` 4 | font-size: 0.75rem; 5 | font-weight: 600; 6 | 7 | &.text-ok { 8 | color: ${(props) => props.theme.requestTabPanel.responseOk}; 9 | } 10 | 11 | &.text-error { 12 | color: ${(props) => props.theme.requestTabPanel.responseError}; 13 | } 14 | `; 15 | 16 | export default Wrapper; 17 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/RequestPane/Auth/OAuth2/ClientCredentials/inputsConfig.js: -------------------------------------------------------------------------------- 1 | const inputsConfig = [ 2 | { 3 | key: 'accessTokenUrl', 4 | label: 'Access Token URL' 5 | }, 6 | { 7 | key: 'clientId', 8 | label: 'Client ID' 9 | }, 10 | { 11 | key: 'clientSecret', 12 | label: 'Client Secret' 13 | }, 14 | { 15 | key: 'scope', 16 | label: 'Scope' 17 | } 18 | ]; 19 | 20 | export { inputsConfig }; 21 | -------------------------------------------------------------------------------- /packages/bruno-app/src/hooks/usePrevious/index.js: -------------------------------------------------------------------------------- 1 | import { useRef, useEffect } from 'react'; 2 | 3 | function usePrevious(value) { 4 | const ref = useRef(); 5 | 6 | useEffect(() => { 7 | ref.current = value; //assign the value of ref to the argument 8 | }, [value]); //this code will run when the value of 'value' changes 9 | 10 | return ref.current; //in the end, return the current ref value. 11 | } 12 | 13 | export default usePrevious; 14 | -------------------------------------------------------------------------------- /packages/bruno-lang/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usebruno/lang", 3 | "version": "0.12.0", 4 | "license": "MIT", 5 | "main": "src/index.js", 6 | "files": [ 7 | "src", 8 | "v1", 9 | "v2", 10 | "package.json" 11 | ], 12 | "scripts": { 13 | "test": "jest" 14 | }, 15 | "dependencies": { 16 | "arcsecond": "^5.0.0", 17 | "dotenv": "^16.3.1", 18 | "lodash": "^4.17.21", 19 | "ohm-js": "^16.6.0" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/CollectionSettings/Auth/OAuth2/ClientCredentials/inputsConfig.js: -------------------------------------------------------------------------------- 1 | const inputsConfig = [ 2 | { 3 | key: 'accessTokenUrl', 4 | label: 'Access Token URL' 5 | }, 6 | { 7 | key: 'clientId', 8 | label: 'Client ID' 9 | }, 10 | { 11 | key: 'clientSecret', 12 | label: 'Client Secret' 13 | }, 14 | { 15 | key: 'scope', 16 | label: 'Scope' 17 | } 18 | ]; 19 | 20 | export { inputsConfig }; 21 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection/redirects/Test Redirect.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: Test Redirect 3 | type: http 4 | seq: 2 5 | } 6 | 7 | get { 8 | url: {{host}}/redirect-to-ping 9 | body: none 10 | auth: none 11 | } 12 | 13 | assert { 14 | res.status: 200 15 | res.body: pong 16 | } 17 | 18 | tests { 19 | test("should redirect to ping", function() { 20 | const data = res.getBody(); 21 | expect(data).to.equal('pong'); 22 | }); 23 | } 24 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/DeleteCollectionItem/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const Wrapper = styled.div` 4 | button.submit { 5 | color: white; 6 | background-color: var(--color-background-danger) !important; 7 | border: inherit !important; 8 | 9 | &:hover { 10 | border: inherit !important; 11 | } 12 | } 13 | `; 14 | 15 | export default Wrapper; 16 | -------------------------------------------------------------------------------- /packages/bruno-app/src/utils/network/cancelTokens.js: -------------------------------------------------------------------------------- 1 | // we maintain cancel tokens for a request separately as redux does not recommend to store 2 | // non-serializable value in the store 3 | 4 | const cancelTokens = {}; 5 | 6 | export default cancelTokens; 7 | 8 | export const saveCancelToken = (uid, axiosRequest) => { 9 | cancelTokens[uid] = axiosRequest; 10 | }; 11 | 12 | export const deleteCancelToken = (uid) => { 13 | delete cancelTokens[uid]; 14 | }; 15 | -------------------------------------------------------------------------------- /packages/bruno-cli/src/utils/common.js: -------------------------------------------------------------------------------- 1 | const lpad = (str, width) => { 2 | let paddedStr = str; 3 | while (paddedStr.length < width) { 4 | paddedStr = ' ' + paddedStr; 5 | } 6 | return paddedStr; 7 | }; 8 | 9 | const rpad = (str, width) => { 10 | let paddedStr = str; 11 | while (paddedStr.length < width) { 12 | paddedStr = paddedStr + ' '; 13 | } 14 | return paddedStr; 15 | }; 16 | 17 | module.exports = { 18 | lpad, 19 | rpad 20 | }; 21 | -------------------------------------------------------------------------------- /packages/bruno-app/src/pages/index.js: -------------------------------------------------------------------------------- 1 | import Head from 'next/head'; 2 | import Bruno from './Bruno'; 3 | import GlobalStyle from '../globalStyles'; 4 | 5 | export default function Home() { 6 | return ( 7 |
8 | 9 | Bruno 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 |
18 |
19 | ); 20 | } 21 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/RequestPane/SaveRequest/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const Wrapper = styled.div` 4 | .folder-list { 5 | border: 1px solid #ccc; 6 | border-radius: 5px; 7 | 8 | .folder-name { 9 | padding-block: 8px; 10 | padding-inline: 12px; 11 | cursor: pointer; 12 | &:hover { 13 | background-color: #e8e8e8; 14 | } 15 | } 16 | `; 17 | 18 | export default Wrapper; 19 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection/preview/html/bruno.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: bruno 3 | type: http 4 | seq: 1 5 | } 6 | 7 | get { 8 | url: https://www.usebruno.com 9 | body: none 10 | auth: none 11 | } 12 | 13 | assert { 14 | res.status: eq 200 15 | } 16 | 17 | tests { 18 | test("should return parsed xml", function() { 19 | const headers = res.getHeaders(); 20 | expect(headers['content-type']).to.eql("text/html; charset=utf-8"); 21 | }); 22 | 23 | } 24 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/Environments/EnvironmentSelector/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const Wrapper = styled.div` 4 | .current-environment { 5 | background-color: ${(props) => props.theme.sidebar.badge.bg}; 6 | border-radius: 15px; 7 | 8 | .caret { 9 | margin-left: 0.25rem; 10 | color: rgb(140, 140, 140); 11 | fill: rgb(140, 140, 140); 12 | } 13 | } 14 | `; 15 | 16 | export default Wrapper; 17 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/Preferences/Support/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const StyledWrapper = styled.div` 4 | color: ${(props) => props.theme.text}; 5 | .rows { 6 | svg { 7 | position: relative; 8 | top: -1px; 9 | } 10 | 11 | .label { 12 | cursor: pointer; 13 | &:hover { 14 | text-decoration: underline; 15 | } 16 | } 17 | } 18 | `; 19 | 20 | export default StyledWrapper; 21 | -------------------------------------------------------------------------------- /packages/bruno-toml/tests/headers/reserved-header/request.toml: -------------------------------------------------------------------------------- 1 | [meta] 2 | name = 'Get users' 3 | type = 'http' 4 | seq = 1 5 | 6 | [http] 7 | method = 'GET' 8 | url = 'https://reqres.in/api/users' 9 | 10 | [headers] 11 | bru = ''' 12 | [ 13 | { 14 | "name": "disabled", 15 | "value": "foo", 16 | "enabled": true 17 | }, 18 | { 19 | "name": "disabled-header-name", 20 | "value": "disabled-header-value", 21 | "enabled": false 22 | } 23 | ] 24 | ''' 25 | -------------------------------------------------------------------------------- /packages/bruno-app/src/utils/tabs/index.js: -------------------------------------------------------------------------------- 1 | import find from 'lodash/find'; 2 | 3 | export const isItemARequest = (item) => { 4 | return item.hasOwnProperty('request') && ['http-request', 'graphql-request'].includes(item.type); 5 | }; 6 | 7 | export const isItemAFolder = (item) => { 8 | return !item.hasOwnProperty('request') && item.type === 'folder'; 9 | }; 10 | 11 | export const itemIsOpenedInTabs = (item, tabs) => { 12 | return find(tabs, (t) => t.uid === item.uid); 13 | }; 14 | -------------------------------------------------------------------------------- /packages/bruno-toml/tests/headers/duplicate-header/request.toml: -------------------------------------------------------------------------------- 1 | [meta] 2 | name = 'Get users' 3 | type = 'http' 4 | seq = 1 5 | 6 | [http] 7 | method = 'GET' 8 | url = 'https://reqres.in/api/users' 9 | 10 | [headers] 11 | bru = ''' 12 | [ 13 | { 14 | "name": "Content-Type", 15 | "value": "application/json", 16 | "enabled": true 17 | }, 18 | { 19 | "name": "Content-Type", 20 | "value": "application/ld+json", 21 | "enabled": true 22 | } 23 | ] 24 | ''' 25 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/BrunoSupport/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const StyledWrapper = styled.div` 4 | color: ${(props) => props.theme.text}; 5 | .collection-options { 6 | svg { 7 | position: relative; 8 | top: -1px; 9 | } 10 | 11 | .label { 12 | cursor: pointer; 13 | &:hover { 14 | text-decoration: underline; 15 | } 16 | } 17 | } 18 | `; 19 | 20 | export default StyledWrapper; 21 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/ResponsePane/TestResults/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const StyledWrapper = styled.div` 4 | .test-success { 5 | color: ${(props) => props.theme.colors.text.green}; 6 | } 7 | 8 | .test-failure { 9 | color: ${(props) => props.theme.colors.text.danger}; 10 | } 11 | 12 | .error-message { 13 | color: ${(props) => props.theme.colors.text.muted}; 14 | } 15 | `; 16 | 17 | export default StyledWrapper; 18 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/Sidebar/TitleBar/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const StyledWrapper = styled.div` 4 | .collection-dropdown { 5 | color: ${(props) => props.theme.sidebar.dropdownIcon.color}; 6 | 7 | &:hover { 8 | color: inherit; 9 | } 10 | 11 | .tippy-box { 12 | top: -0.5rem; 13 | position: relative; 14 | user-select: none; 15 | } 16 | } 17 | `; 18 | 19 | export default StyledWrapper; 20 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection/auth/bearer/via auth/Bearer Auth 200.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: Bearer Auth 200 3 | type: http 4 | seq: 1 5 | } 6 | 7 | get { 8 | url: {{host}}/api/auth/bearer/protected 9 | body: none 10 | auth: bearer 11 | } 12 | 13 | auth:bearer { 14 | token: {{bearer_auth_token}} 15 | } 16 | 17 | assert { 18 | res.status: 200 19 | res.body.message: Authentication successful 20 | } 21 | 22 | script:post-response { 23 | bru.setEnvVar("foo", "bar"); 24 | } 25 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/CollectionSettings/Auth/AwsV4Auth/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const Wrapper = styled.div` 4 | label { 5 | font-size: 0.8125rem; 6 | } 7 | 8 | .single-line-editor-wrapper { 9 | padding: 0.15rem 0.4rem; 10 | border-radius: 3px; 11 | border: solid 1px ${(props) => props.theme.input.border}; 12 | background-color: ${(props) => props.theme.input.bg}; 13 | } 14 | `; 15 | 16 | export default Wrapper; 17 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/CollectionSettings/Auth/BasicAuth/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const Wrapper = styled.div` 4 | label { 5 | font-size: 0.8125rem; 6 | } 7 | 8 | .single-line-editor-wrapper { 9 | padding: 0.15rem 0.4rem; 10 | border-radius: 3px; 11 | border: solid 1px ${(props) => props.theme.input.border}; 12 | background-color: ${(props) => props.theme.input.bg}; 13 | } 14 | `; 15 | 16 | export default Wrapper; 17 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/CollectionSettings/Auth/BearerAuth/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const Wrapper = styled.div` 4 | label { 5 | font-size: 0.8125rem; 6 | } 7 | 8 | .single-line-editor-wrapper { 9 | padding: 0.15rem 0.4rem; 10 | border-radius: 3px; 11 | border: solid 1px ${(props) => props.theme.input.border}; 12 | background-color: ${(props) => props.theme.input.bg}; 13 | } 14 | `; 15 | 16 | export default Wrapper; 17 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/CollectionSettings/Auth/DigestAuth/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const Wrapper = styled.div` 4 | label { 5 | font-size: 0.8125rem; 6 | } 7 | 8 | .single-line-editor-wrapper { 9 | padding: 0.15rem 0.4rem; 10 | border-radius: 3px; 11 | border: solid 1px ${(props) => props.theme.input.border}; 12 | background-color: ${(props) => props.theme.input.bg}; 13 | } 14 | `; 15 | 16 | export default Wrapper; 17 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/Documentation/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const StyledWrapper = styled.div` 4 | div.CodeMirror { 5 | /* todo: find a better way */ 6 | height: calc(100vh - 240px); 7 | 8 | .CodeMirror-scroll { 9 | padding-bottom: 0px; 10 | } 11 | } 12 | .editing-mode { 13 | cursor: pointer; 14 | color: ${(props) => props.theme.colors.text.yellow}; 15 | } 16 | `; 17 | 18 | export default StyledWrapper; 19 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/Sidebar/GoldenEdition/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const StyledWrapper = styled.div` 4 | color: ${(props) => props.theme.text}; 5 | .collection-options { 6 | svg { 7 | position: relative; 8 | top: -1px; 9 | } 10 | 11 | .label { 12 | cursor: pointer; 13 | &:hover { 14 | text-decoration: underline; 15 | } 16 | } 17 | } 18 | `; 19 | 20 | export default StyledWrapper; 21 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/Spinner/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const StyledWrapper = styled.div` 4 | .spinner { 5 | display: inline-block; 6 | width: 2rem; 7 | height: 2rem; 8 | vertical-align: text-bottom; 9 | border: 0.25em solid currentColor; 10 | border-right-color: transparent; 11 | border-radius: 50%; 12 | animation: spinner-border 0.75s linear infinite; 13 | } 14 | `; 15 | 16 | export default StyledWrapper; 17 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection/echo/echo plaintext.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: echo plaintext 3 | type: http 4 | seq: 2 5 | } 6 | 7 | post { 8 | url: {{host}}/api/echo/text 9 | body: text 10 | auth: none 11 | } 12 | 13 | body:text { 14 | hello 15 | } 16 | 17 | assert { 18 | res.status: eq 200 19 | } 20 | 21 | tests { 22 | test("should return plain text", function() { 23 | const data = res.getBody(); 24 | expect(res.getBody()).to.eql("hello"); 25 | }); 26 | 27 | } 28 | -------------------------------------------------------------------------------- /packages/bruno-cli/src/reporters/html.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | 4 | const makeHtmlOutput = async (results, outputPath) => { 5 | const resultsJson = JSON.stringify(results, null, 2); 6 | 7 | const reportPath = path.join(__dirname, 'html-template.html'); 8 | const template = fs.readFileSync(reportPath, 'utf8'); 9 | 10 | fs.writeFileSync(outputPath, template.replace('__RESULTS_JSON__', resultsJson)); 11 | }; 12 | 13 | module.exports = makeHtmlOutput; 14 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/CollectionSettings/Docs/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const StyledWrapper = styled.div` 4 | div.CodeMirror { 5 | /* todo: find a better way */ 6 | height: calc(100vh - 240px); 7 | 8 | .CodeMirror-scroll { 9 | padding-bottom: 0px; 10 | } 11 | } 12 | .editing-mode { 13 | cursor: pointer; 14 | color: ${(props) => props.theme.colors.text.yellow}; 15 | } 16 | `; 17 | 18 | export default StyledWrapper; 19 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/RequestPane/Auth/OAuth2/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const Wrapper = styled.div` 4 | label { 5 | font-size: 0.8125rem; 6 | } 7 | .single-line-editor-wrapper { 8 | max-width: 400px; 9 | padding: 0.15rem 0.4rem; 10 | border-radius: 3px; 11 | border: solid 1px ${(props) => props.theme.input.border}; 12 | background-color: ${(props) => props.theme.input.bg}; 13 | } 14 | `; 15 | 16 | export default Wrapper; 17 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/CollectionSettings/Auth/OAuth2/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const Wrapper = styled.div` 4 | label { 5 | font-size: 0.8125rem; 6 | } 7 | .single-line-editor-wrapper { 8 | max-width: 400px; 9 | padding: 0.15rem 0.4rem; 10 | border-radius: 3px; 11 | border: solid 1px ${(props) => props.theme.input.border}; 12 | background-color: ${(props) => props.theme.input.bg}; 13 | } 14 | `; 15 | 16 | export default Wrapper; 17 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/RequestPane/Auth/AwsV4Auth/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const Wrapper = styled.div` 4 | label { 5 | font-size: 0.8125rem; 6 | } 7 | 8 | .single-line-editor-wrapper { 9 | max-width: 400px; 10 | padding: 0.15rem 0.4rem; 11 | border-radius: 3px; 12 | border: solid 1px ${(props) => props.theme.input.border}; 13 | background-color: ${(props) => props.theme.input.bg}; 14 | } 15 | `; 16 | 17 | export default Wrapper; 18 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/RequestPane/Auth/BasicAuth/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const Wrapper = styled.div` 4 | label { 5 | font-size: 0.8125rem; 6 | } 7 | 8 | .single-line-editor-wrapper { 9 | max-width: 400px; 10 | padding: 0.15rem 0.4rem; 11 | border-radius: 3px; 12 | border: solid 1px ${(props) => props.theme.input.border}; 13 | background-color: ${(props) => props.theme.input.bg}; 14 | } 15 | `; 16 | 17 | export default Wrapper; 18 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/RequestPane/Auth/BearerAuth/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const Wrapper = styled.div` 4 | label { 5 | font-size: 0.8125rem; 6 | } 7 | 8 | .single-line-editor-wrapper { 9 | max-width: 400px; 10 | padding: 0.15rem 0.4rem; 11 | border-radius: 3px; 12 | border: solid 1px ${(props) => props.theme.input.border}; 13 | background-color: ${(props) => props.theme.input.bg}; 14 | } 15 | `; 16 | 17 | export default Wrapper; 18 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/RequestPane/Auth/DigestAuth/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const Wrapper = styled.div` 4 | label { 5 | font-size: 0.8125rem; 6 | } 7 | 8 | .single-line-editor-wrapper { 9 | max-width: 400px; 10 | padding: 0.15rem 0.4rem; 11 | border-radius: 3px; 12 | border: solid 1px ${(props) => props.theme.input.border}; 13 | background-color: ${(props) => props.theme.input.bg}; 14 | } 15 | `; 16 | 17 | export default Wrapper; 18 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/GenerateCodeItem/CodeView/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const StyledWrapper = styled.div` 4 | position: relative; 5 | 6 | .copy-to-clipboard { 7 | position: absolute; 8 | cursor: pointer; 9 | top: 10px; 10 | right: 10px; 11 | z-index: 10; 12 | opacity: 0.5; 13 | 14 | &:hover { 15 | opacity: 1; 16 | } 17 | } 18 | `; 19 | 20 | export default StyledWrapper; 21 | -------------------------------------------------------------------------------- /packages/bruno-electron/src/store/bruno-config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This modules stores the configs loaded from bruno.json 3 | */ 4 | 5 | const config = {}; 6 | 7 | // collectionUid is a hash based on the collection path) 8 | const getBrunoConfig = (collectionUid) => { 9 | return config[collectionUid] || {}; 10 | }; 11 | 12 | const setBrunoConfig = (collectionUid, brunoConfig) => { 13 | config[collectionUid] = brunoConfig; 14 | }; 15 | 16 | module.exports = { 17 | getBrunoConfig, 18 | setBrunoConfig 19 | }; 20 | -------------------------------------------------------------------------------- /packages/bruno-toml/tests/headers/unicode-in-header/request.json: -------------------------------------------------------------------------------- 1 | { 2 | "meta": { 3 | "name": "Get users", 4 | "type": "http", 5 | "seq": 1 6 | }, 7 | "http": { 8 | "method": "GET", 9 | "url": "https://reqres.in/api/users" 10 | }, 11 | "headers": [ 12 | { 13 | "name": "Content-Type", 14 | "value": "application/json", 15 | "enabled": true 16 | }, 17 | { 18 | "name": "🐶", 19 | "value": "🚀", 20 | "enabled": true 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/Sidebar/Collections/SelectCollection/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const StyledWrapper = styled.div` 4 | div.collection { 5 | padding: 4px 6px; 6 | padding-left: 8px; 7 | display: flex; 8 | align-items: center; 9 | border-radius: 3px; 10 | cursor: pointer; 11 | 12 | &:hover { 13 | background-color: ${(props) => props.theme.plainGrid.hoverBg}; 14 | } 15 | } 16 | `; 17 | 18 | export default StyledWrapper; 19 | -------------------------------------------------------------------------------- /packages/bruno-toml/tests/headers/empty-header/request.json: -------------------------------------------------------------------------------- 1 | { 2 | "meta": { 3 | "name": "Get users", 4 | "type": "http", 5 | "seq": 1 6 | }, 7 | "http": { 8 | "method": "GET", 9 | "url": "https://reqres.in/api/users" 10 | }, 11 | "headers": [ 12 | { 13 | "name": "Content-Type", 14 | "value": "application/json", 15 | "enabled": true 16 | }, 17 | { 18 | "name": "Empty-Header", 19 | "value": "", 20 | "enabled": true 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /packages/bruno-toml/tests/headers/simple-header/request.json: -------------------------------------------------------------------------------- 1 | { 2 | "meta": { 3 | "name": "Get users", 4 | "type": "http", 5 | "seq": 1 6 | }, 7 | "http": { 8 | "method": "GET", 9 | "url": "https://reqres.in/api/users" 10 | }, 11 | "headers": [ 12 | { 13 | "name": "Content-Type", 14 | "value": "application/json", 15 | "enabled": true 16 | }, 17 | { 18 | "name": "Cookie", 19 | "value": "foo=bar", 20 | "enabled": true 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/RequestPane/Auth/OAuth2/AuthorizationCode/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const Wrapper = styled.div` 4 | label { 5 | font-size: 0.8125rem; 6 | } 7 | .single-line-editor-wrapper { 8 | max-width: 400px; 9 | padding: 0.15rem 0.4rem; 10 | border-radius: 3px; 11 | border: solid 1px ${(props) => props.theme.input.border}; 12 | background-color: ${(props) => props.theme.input.bg}; 13 | } 14 | `; 15 | 16 | export default Wrapper; 17 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/RequestPane/Auth/OAuth2/ClientCredentials/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const Wrapper = styled.div` 4 | label { 5 | font-size: 0.8125rem; 6 | } 7 | .single-line-editor-wrapper { 8 | max-width: 400px; 9 | padding: 0.15rem 0.4rem; 10 | border-radius: 3px; 11 | border: solid 1px ${(props) => props.theme.input.border}; 12 | background-color: ${(props) => props.theme.input.bg}; 13 | } 14 | `; 15 | 16 | export default Wrapper; 17 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/RequestPane/Auth/OAuth2/PasswordCredentials/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const Wrapper = styled.div` 4 | label { 5 | font-size: 0.8125rem; 6 | } 7 | .single-line-editor-wrapper { 8 | max-width: 400px; 9 | padding: 0.15rem 0.4rem; 10 | border-radius: 3px; 11 | border: solid 1px ${(props) => props.theme.input.border}; 12 | background-color: ${(props) => props.theme.input.bg}; 13 | } 14 | `; 15 | 16 | export default Wrapper; 17 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/VariablesEditor/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const StyledWrapper = styled.div` 4 | table { 5 | thead, 6 | td { 7 | border: 1px solid ${(props) => props.theme.table.border}; 8 | 9 | li { 10 | background-color: ${(props) => props.theme.bg} !important; 11 | } 12 | } 13 | } 14 | 15 | .muted { 16 | color: ${(props) => props.theme.colors.text.muted}; 17 | } 18 | `; 19 | 20 | export default StyledWrapper; 21 | -------------------------------------------------------------------------------- /packages/bruno-toml/tests/headers/disabled-header/request.json: -------------------------------------------------------------------------------- 1 | { 2 | "meta": { 3 | "name": "Get users", 4 | "type": "http", 5 | "seq": 1 6 | }, 7 | "http": { 8 | "method": "GET", 9 | "url": "https://reqres.in/api/users" 10 | }, 11 | "headers": [ 12 | { 13 | "name": "Content-Type", 14 | "value": "application/json", 15 | "enabled": true 16 | }, 17 | { 18 | "name": "Cookie", 19 | "value": "foo=bar", 20 | "enabled": false 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /packages/bruno-toml/tests/headers/spaces-in-header/request.json: -------------------------------------------------------------------------------- 1 | { 2 | "meta": { 3 | "name": "Get users", 4 | "type": "http", 5 | "seq": 1 6 | }, 7 | "http": { 8 | "method": "GET", 9 | "url": "https://reqres.in/api/users" 10 | }, 11 | "headers": [ 12 | { 13 | "name": "Content-Type", 14 | "value": "application/json", 15 | "enabled": true 16 | }, 17 | { 18 | "name": "Spaces In Header", 19 | "value": "", 20 | "enabled": true 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/CollectionSettings/Auth/OAuth2/AuthorizationCode/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const Wrapper = styled.div` 4 | label { 5 | font-size: 0.8125rem; 6 | } 7 | .single-line-editor-wrapper { 8 | max-width: 400px; 9 | padding: 0.15rem 0.4rem; 10 | border-radius: 3px; 11 | border: solid 1px ${(props) => props.theme.input.border}; 12 | background-color: ${(props) => props.theme.input.bg}; 13 | } 14 | `; 15 | 16 | export default Wrapper; 17 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/CollectionSettings/Auth/OAuth2/ClientCredentials/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const Wrapper = styled.div` 4 | label { 5 | font-size: 0.8125rem; 6 | } 7 | .single-line-editor-wrapper { 8 | max-width: 400px; 9 | padding: 0.15rem 0.4rem; 10 | border-radius: 3px; 11 | border: solid 1px ${(props) => props.theme.input.border}; 12 | background-color: ${(props) => props.theme.input.bg}; 13 | } 14 | `; 15 | 16 | export default Wrapper; 17 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/CollectionSettings/Auth/OAuth2/PasswordCredentials/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const Wrapper = styled.div` 4 | label { 5 | font-size: 0.8125rem; 6 | } 7 | .single-line-editor-wrapper { 8 | max-width: 400px; 9 | padding: 0.15rem 0.4rem; 10 | border-radius: 3px; 11 | border: solid 1px ${(props) => props.theme.input.border}; 12 | background-color: ${(props) => props.theme.input.bg}; 13 | } 14 | `; 15 | 16 | export default Wrapper; 17 | -------------------------------------------------------------------------------- /packages/bruno-toml/tests/headers/reserved-header/request.json: -------------------------------------------------------------------------------- 1 | { 2 | "meta": { 3 | "name": "Get users", 4 | "type": "http", 5 | "seq": 1 6 | }, 7 | "http": { 8 | "method": "GET", 9 | "url": "https://reqres.in/api/users" 10 | }, 11 | "headers": [ 12 | { 13 | "name": "disabled", 14 | "value": "foo", 15 | "enabled": true 16 | }, 17 | { 18 | "name": "disabled-header-name", 19 | "value": "disabled-header-value", 20 | "enabled": false 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /packages/bruno-toml/tests/headers/duplicate-header/request.json: -------------------------------------------------------------------------------- 1 | { 2 | "meta": { 3 | "name": "Get users", 4 | "type": "http", 5 | "seq": 1 6 | }, 7 | "http": { 8 | "method": "GET", 9 | "url": "https://reqres.in/api/users" 10 | }, 11 | "headers": [ 12 | { 13 | "name": "Content-Type", 14 | "value": "application/json", 15 | "enabled": true 16 | }, 17 | { 18 | "name": "Content-Type", 19 | "value": "application/ld+json", 20 | "enabled": true 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /packages/bruno-lang/v1/src/env-vars-tag.js: -------------------------------------------------------------------------------- 1 | const { between, regex } = require('arcsecond'); 2 | const { each } = require('lodash'); 3 | const keyValLines = require('./key-val-lines'); 4 | 5 | const begin = regex(/^vars\s*\r?\n/); 6 | const end = regex(/^[\r?\n]*\/vars\s*[\r?\n]*/); 7 | 8 | const envVarsTag = between(begin)(end)(keyValLines).map(([variables]) => { 9 | each(variables, (variable) => { 10 | variable.type = 'text'; 11 | }); 12 | 13 | return { 14 | variables 15 | }; 16 | }); 17 | 18 | module.exports = envVarsTag; 19 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection/redirects/Disable Redirect.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: Disable Redirect 3 | type: http 4 | seq: 1 5 | } 6 | 7 | get { 8 | url: {{host}}/redirect-to-ping 9 | body: none 10 | auth: none 11 | } 12 | 13 | assert { 14 | res.status: 302 15 | } 16 | 17 | script:pre-request { 18 | req.setMaxRedirects(0); 19 | } 20 | 21 | tests { 22 | test("should disable redirect to ping", function() { 23 | const data = res.getBody(); 24 | expect(data).to.equal('Found. Redirecting to /ping'); 25 | }); 26 | } 27 | -------------------------------------------------------------------------------- /packages/bruno-toml/tests/headers/dotted-header/request.json: -------------------------------------------------------------------------------- 1 | { 2 | "meta": { 3 | "name": "Get users", 4 | "type": "http", 5 | "seq": 1 6 | }, 7 | "http": { 8 | "method": "GET", 9 | "url": "https://reqres.in/api/users" 10 | }, 11 | "headers": [ 12 | { 13 | "name": "Content-Type", 14 | "value": "application/json", 15 | "enabled": true 16 | }, 17 | { 18 | "name": "Dots.In.Header.Key", 19 | "value": "Dots.In.Header.Value", 20 | "enabled": true 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /packages/bruno-app/src/pages/Bruno/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const Wrapper = styled.div` 4 | display: flex; 5 | width: 100%; 6 | height: 100%; 7 | min-height: 100vh; 8 | max-height: 100vh; 9 | 10 | &.is-dragging { 11 | cursor: col-resize !important; 12 | } 13 | 14 | section.main { 15 | display: flex; 16 | 17 | section.request-pane, 18 | section.response-pane { 19 | } 20 | } 21 | 22 | .fw-600 { 23 | font-weight: 600; 24 | } 25 | `; 26 | 27 | export default Wrapper; 28 | -------------------------------------------------------------------------------- /packages/bruno-electron/src/preload.js: -------------------------------------------------------------------------------- 1 | const { ipcRenderer, contextBridge } = require('electron'); 2 | 3 | contextBridge.exposeInMainWorld('ipcRenderer', { 4 | invoke: (channel, ...args) => ipcRenderer.invoke(channel, ...args), 5 | on: (channel, handler) => { 6 | // Deliberately strip event as it includes `sender` 7 | const subscription = (event, ...args) => handler(...args); 8 | ipcRenderer.on(channel, subscription); 9 | 10 | return () => { 11 | ipcRenderer.removeListener(channel, subscription); 12 | }; 13 | } 14 | }); 15 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection/auth/bearer/via headers/Bearer Auth 200.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: Bearer Auth 200 3 | type: http 4 | seq: 1 5 | } 6 | 7 | get { 8 | url: {{host}}/api/auth/bearer/protected 9 | body: json 10 | auth: none 11 | } 12 | 13 | headers { 14 | Authorization: Bearer your_secret_token 15 | } 16 | 17 | vars:pre-request { 18 | a-c: foo 19 | } 20 | 21 | assert { 22 | res.status: 200 23 | res.body.message: Authentication successful 24 | } 25 | 26 | script:post-response { 27 | bru.setEnvVar("foo", "bar"); 28 | } 29 | -------------------------------------------------------------------------------- /packages/bruno-tests/src/auth/bearer.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | 4 | const authenticateToken = (req, res, next) => { 5 | const token = req.header('Authorization'); 6 | 7 | if (!token || token !== `Bearer your_secret_token`) { 8 | return res.status(401).json({ message: 'Unauthorized' }); 9 | } 10 | 11 | next(); 12 | }; 13 | 14 | router.get('/protected', authenticateToken, (req, res) => { 15 | res.status(200).json({ message: 'Authentication successful' }); 16 | }); 17 | 18 | module.exports = router; 19 | -------------------------------------------------------------------------------- /packages/bruno-common/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export const flattenObject = (obj: Record, parentKey: string = ''): Record => { 2 | return Object.entries(obj).reduce((acc: Record, [key, value]: [string, any]) => { 3 | const newKey = parentKey ? (Array.isArray(obj) ? `${parentKey}[${key}]` : `${parentKey}.${key}`) : key; 4 | if (typeof value === 'object' && value !== null) { 5 | Object.assign(acc, flattenObject(value, newKey)); 6 | } else { 7 | acc[newKey] = value; 8 | } 9 | return acc; 10 | }, {}); 11 | }; 12 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection_oauth2/auth/oauth2/password_credentials/token.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: token 3 | type: http 4 | seq: 1 5 | } 6 | 7 | post { 8 | url: 9 | body: none 10 | auth: oauth2 11 | } 12 | 13 | auth:oauth2 { 14 | grant_type: password 15 | access_token_url: {{password_credentials_access_token_url}} 16 | username: {{password_credentials_username}} 17 | password: {{password_credentials_password}} 18 | scope: 19 | } 20 | 21 | script:post-response { 22 | bru.setEnvVar('passwordCredentials_access_token', res.body.access_token); 23 | } 24 | -------------------------------------------------------------------------------- /packages/bruno-common/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES6", 4 | "esModuleInterop": true, 5 | "strict": true, 6 | "skipLibCheck": true, 7 | "jsx": "react", 8 | "module": "ESNext", 9 | "declaration": true, 10 | "declarationDir": "types", 11 | "sourceMap": true, 12 | "outDir": "dist", 13 | "moduleResolution": "node", 14 | "emitDeclarationOnly": true, 15 | "allowSyntheticDefaultImports": true, 16 | "forceConsistentCasingInFileNames": true 17 | }, 18 | "exclude": ["dist", "node_modules", "tests"] 19 | } 20 | -------------------------------------------------------------------------------- /packages/bruno-app/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | node_modules 5 | .pnp 6 | .pnp.js 7 | pnpm-lock.yaml 8 | package-lock.json 9 | yarn.lock 10 | 11 | # testing 12 | coverage 13 | 14 | # production 15 | build 16 | 17 | # misc 18 | .DS_Store 19 | *.pem 20 | 21 | # debug 22 | npm-debug.log* 23 | yarn-debug.log* 24 | yarn-error.log* 25 | 26 | # local env files 27 | .env.local 28 | .env.development.local 29 | .env.test.local 30 | .env.production.local 31 | 32 | # next.js 33 | .next/ 34 | out/ 35 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/Sidebar/Collections/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const Wrapper = styled.div` 4 | .collections-badge { 5 | margin-inline: 0.5rem; 6 | background-color: ${(props) => props.theme.sidebar.badge.bg}; 7 | border-radius: 5px; 8 | 9 | .caret { 10 | margin-left: 0.25rem; 11 | color: rgb(140, 140, 140); 12 | fill: rgb(140, 140, 140); 13 | } 14 | } 15 | 16 | span.close-icon { 17 | color: ${(props) => props.theme.colors.text.muted}; 18 | } 19 | `; 20 | 21 | export default Wrapper; 22 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/RequestPane/Auth/OAuth2/PasswordCredentials/inputsConfig.js: -------------------------------------------------------------------------------- 1 | const inputsConfig = [ 2 | { 3 | key: 'accessTokenUrl', 4 | label: 'Access Token URL' 5 | }, 6 | { 7 | key: 'username', 8 | label: 'Username' 9 | }, 10 | { 11 | key: 'password', 12 | label: 'Password' 13 | }, 14 | { 15 | key: 'clientId', 16 | label: 'Client ID' 17 | }, 18 | { 19 | key: 'clientSecret', 20 | label: 'Client Secret' 21 | }, 22 | { 23 | key: 'scope', 24 | label: 'Scope' 25 | } 26 | ]; 27 | 28 | export { inputsConfig }; 29 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/CollectionSettings/Auth/OAuth2/PasswordCredentials/inputsConfig.js: -------------------------------------------------------------------------------- 1 | const inputsConfig = [ 2 | { 3 | key: 'accessTokenUrl', 4 | label: 'Access Token URL' 5 | }, 6 | { 7 | key: 'username', 8 | label: 'Username' 9 | }, 10 | { 11 | key: 'password', 12 | label: 'Password' 13 | }, 14 | { 15 | key: 'clientId', 16 | label: 'Client ID' 17 | }, 18 | { 19 | key: 'clientSecret', 20 | label: 'Client Secret' 21 | }, 22 | { 23 | key: 'scope', 24 | label: 'Scope' 25 | } 26 | ]; 27 | 28 | export { inputsConfig }; 29 | -------------------------------------------------------------------------------- /packages/bruno-graphql-docs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "esModuleInterop": true, 4 | "strict": true, 5 | "skipLibCheck": true, 6 | "jsx": "react", 7 | "module": "ESNext", 8 | "declaration": true, 9 | "declarationDir": "types", 10 | "sourceMap": true, 11 | "outDir": "dist", 12 | "moduleResolution": "node", 13 | "emitDeclarationOnly": true, 14 | "allowSyntheticDefaultImports": true, 15 | "forceConsistentCasingInFileNames": true 16 | }, 17 | "exclude": [ 18 | "dist", 19 | "node_modules", 20 | "src/**/*.test.tsx" 21 | ], 22 | } -------------------------------------------------------------------------------- /packages/bruno-tests/src/auth/basic.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const basicAuth = require('express-basic-auth'); 4 | 5 | const users = { 6 | bruno: 'della' 7 | }; 8 | 9 | const basicAuthMiddleware = basicAuth({ 10 | users, 11 | challenge: true, // Sends a 401 Unauthorized response when authentication fails 12 | unauthorizedResponse: 'Unauthorized' 13 | }); 14 | 15 | router.post('/protected', basicAuthMiddleware, (req, res) => { 16 | res.status(200).json({ message: 'Authentication successful' }); 17 | }); 18 | 19 | module.exports = router; 20 | -------------------------------------------------------------------------------- /packages/bruno-query/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES6", 4 | "esModuleInterop": true, 5 | "strict": true, 6 | "skipLibCheck": true, 7 | "jsx": "react", 8 | "module": "ESNext", 9 | "declaration": true, 10 | "declarationDir": "types", 11 | "sourceMap": true, 12 | "outDir": "dist", 13 | "moduleResolution": "node", 14 | "emitDeclarationOnly": true, 15 | "allowSyntheticDefaultImports": true, 16 | "forceConsistentCasingInFileNames": true 17 | }, 18 | "exclude": [ 19 | "dist", 20 | "node_modules", 21 | "tests" 22 | ], 23 | } -------------------------------------------------------------------------------- /packages/bruno-app/jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "jsx": "react", 4 | "target": "es2017", 5 | "allowSyntheticDefaultImports": false, 6 | "baseUrl": "./", 7 | "paths": { 8 | "assets/*": ["src/assets/*"], 9 | "components/*": ["src/components/*"], 10 | "hooks/*": ["src/hooks/*"], 11 | "themes/*": ["src/themes/*"], 12 | "api/*": ["src/api/*"], 13 | "pageComponents/*": ["src/pageComponents/*"], 14 | "providers/*": ["src/providers/*"], 15 | "utils/*": ["src/utils/*"] 16 | } 17 | }, 18 | "exclude": ["node_modules", "dist"] 19 | } 20 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection_oauth2/auth/oauth2/client_credentials/token.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: token 3 | type: http 4 | seq: 1 5 | } 6 | 7 | post { 8 | url: 9 | body: none 10 | auth: oauth2 11 | } 12 | 13 | auth:oauth2 { 14 | grant_type: client_credentials 15 | access_token_url: {{client_credentials_access_token_url}} 16 | client_id: {{client_credentials_client_id}} 17 | client_secret: {{client_credentials_client_secret}} 18 | scope: {{client_credentials_scope}} 19 | } 20 | 21 | script:post-response { 22 | bru.setEnvVar('client_credentials_access_token', res.body.access_token); 23 | } 24 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/ResponsePane/Timeline/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const StyledWrapper = styled.div` 4 | .line { 5 | white-space: pre-line; 6 | word-wrap: break-word; 7 | word-break: break-all; 8 | font-family: Inter, sans-serif !important; 9 | 10 | .arrow { 11 | opacity: 0.5; 12 | } 13 | 14 | &.request { 15 | color: ${(props) => props.theme.colors.text.green}; 16 | } 17 | 18 | &.response { 19 | color: ${(props) => props.theme.colors.text.purple}; 20 | } 21 | } 22 | `; 23 | 24 | export default StyledWrapper; 25 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection/auth/basic/via script/Basic Auth 401.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: Basic Auth 401 3 | type: http 4 | seq: 2 5 | } 6 | 7 | post { 8 | url: {{host}}/api/auth/basic/protected 9 | body: json 10 | auth: none 11 | } 12 | 13 | assert { 14 | res.status: 401 15 | res.body: Unauthorized 16 | } 17 | 18 | script:pre-request { 19 | const username = "bruno"; 20 | const password = "invalid"; 21 | 22 | const authString = `${username}:${password}`; 23 | const encodedAuthString = require('btoa')(authString); 24 | 25 | req.setHeader("Authorization", `Basic ${encodedAuthString}`); 26 | } 27 | -------------------------------------------------------------------------------- /packages/bruno-app/src/providers/ReduxStore/middlewares/debug/middleware.js: -------------------------------------------------------------------------------- 1 | import { createListenerMiddleware } from '@reduxjs/toolkit'; 2 | 3 | const debugMiddleware = createListenerMiddleware(); 4 | 5 | debugMiddleware.startListening({ 6 | predicate: () => true, // it'll track every change 7 | effect: (action, listenerApi) => { 8 | console.debug('---redux action---'); 9 | console.debug('action', action.type); // which action did it 10 | console.debug('action.payload', action.payload); 11 | console.debug(listenerApi.getState()); // the updated store 12 | } 13 | }); 14 | 15 | export default debugMiddleware; 16 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/Welcome/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const StyledWrapper = styled.div` 4 | .heading { 5 | color: ${(props) => props.theme.welcome.heading}; 6 | font-size: 0.75rem; 7 | } 8 | 9 | .muted { 10 | color: ${(props) => props.theme.welcome.muted}; 11 | } 12 | 13 | .collection-options { 14 | cursor: pointer; 15 | 16 | svg { 17 | position: relative; 18 | top: -1px; 19 | } 20 | 21 | .label { 22 | &:hover { 23 | text-decoration: underline; 24 | } 25 | } 26 | } 27 | `; 28 | 29 | export default StyledWrapper; 30 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection/auth/basic/via script/Basic Auth 200.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: Basic Auth 200 3 | type: http 4 | seq: 1 5 | } 6 | 7 | post { 8 | url: {{host}}/api/auth/basic/protected 9 | body: json 10 | auth: none 11 | } 12 | 13 | assert { 14 | res.status: eq 200 15 | res.body.message: Authentication successful 16 | } 17 | 18 | script:pre-request { 19 | const username = "bruno"; 20 | const password = "della"; 21 | 22 | const authString = `${username}:${password}`; 23 | const encodedAuthString = require('btoa')(authString); 24 | 25 | req.setHeader("Authorization", `Basic ${encodedAuthString}`); 26 | } 27 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection/echo/echo xml parsed.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: echo xml parsed 3 | type: http 4 | seq: 3 5 | } 6 | 7 | post { 8 | url: {{host}}/api/echo/xml-parsed 9 | body: xml 10 | auth: none 11 | } 12 | 13 | body:xml { 14 | 15 | bruno 16 | 17 | } 18 | 19 | assert { 20 | res.status: eq 200 21 | } 22 | 23 | tests { 24 | test("should return parsed xml", function() { 25 | const data = res.getBody(); 26 | expect(res.getBody()).to.eql({ 27 | "hello": { 28 | "world": [ 29 | "bruno" 30 | ] 31 | } 32 | }); 33 | }); 34 | 35 | } 36 | -------------------------------------------------------------------------------- /packages/bruno-app/src/hooks/useLocalStorage/index.js: -------------------------------------------------------------------------------- 1 | import { useState, useEffect } from 'react'; 2 | 3 | export default function useLocalStorage(key, defaultValue) { 4 | const [value, setValue] = useState(() => { 5 | try { 6 | const saved = localStorage.getItem(key); 7 | if (saved !== null) { 8 | return JSON.parse(saved); 9 | } 10 | return defaultValue; 11 | } catch { 12 | return defaultValue; 13 | } 14 | }); 15 | 16 | useEffect(() => { 17 | const rawValue = JSON.stringify(value); 18 | localStorage.setItem(key, rawValue); 19 | }, [key, value]); 20 | 21 | return [value, setValue]; 22 | } 23 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/RequestPane/Auth/AuthMode/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const Wrapper = styled.div` 4 | font-size: 0.8125rem; 5 | 6 | .auth-mode-selector { 7 | background: transparent; 8 | 9 | .auth-mode-label { 10 | color: ${(props) => props.theme.colors.text.yellow}; 11 | } 12 | 13 | .dropdown-item { 14 | padding: 0.2rem 0.6rem !important; 15 | } 16 | 17 | .label-item { 18 | padding: 0.2rem 0.6rem !important; 19 | } 20 | } 21 | 22 | .caret { 23 | color: rgb(140, 140, 140); 24 | fill: rgb(140 140 140); 25 | } 26 | `; 27 | 28 | export default Wrapper; 29 | -------------------------------------------------------------------------------- /packages/bruno-graphql-docs/src/components/DocExplorer/Directive.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2021 GraphQL Contributors. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import React from 'react'; 9 | import { DirectiveNode } from 'graphql'; 10 | 11 | type DirectiveProps = { 12 | directive: DirectiveNode; 13 | }; 14 | 15 | export default function Directive({ directive }: DirectiveProps) { 16 | return ( 17 | 18 | {'@'} 19 | {directive.name.value} 20 | 21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/CollectionSettings/Auth/AuthMode/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const Wrapper = styled.div` 4 | font-size: 0.8125rem; 5 | 6 | .auth-mode-selector { 7 | background: transparent; 8 | 9 | .auth-mode-label { 10 | color: ${(props) => props.theme.colors.text.yellow}; 11 | } 12 | 13 | .dropdown-item { 14 | padding: 0.2rem 0.6rem !important; 15 | } 16 | 17 | .label-item { 18 | padding: 0.2rem 0.6rem !important; 19 | } 20 | } 21 | 22 | .caret { 23 | color: rgb(140, 140, 140); 24 | fill: rgb(140 140 140); 25 | } 26 | `; 27 | 28 | export default Wrapper; 29 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/RequestPane/Auth/OAuth2/AuthorizationCode/inputsConfig.js: -------------------------------------------------------------------------------- 1 | const inputsConfig = [ 2 | { 3 | key: 'callbackUrl', 4 | label: 'Callback URL' 5 | }, 6 | { 7 | key: 'authorizationUrl', 8 | label: 'Authorization URL' 9 | }, 10 | { 11 | key: 'accessTokenUrl', 12 | label: 'Access Token URL' 13 | }, 14 | { 15 | key: 'clientId', 16 | label: 'Client ID' 17 | }, 18 | { 19 | key: 'clientSecret', 20 | label: 'Client Secret' 21 | }, 22 | { 23 | key: 'scope', 24 | label: 'Scope' 25 | }, 26 | { 27 | key: 'state', 28 | label: 'State' 29 | } 30 | ]; 31 | 32 | export { inputsConfig }; 33 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/ResponsePane/ResponseTime/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import StyledWrapper from './StyledWrapper'; 3 | 4 | const ResponseTime = ({ duration }) => { 5 | let durationToDisplay = ''; 6 | 7 | if (duration > 1000) { 8 | // duration greater than a second 9 | let seconds = Math.floor(duration / 1000); 10 | let decimal = ((duration % 1000) / 1000) * 100; 11 | durationToDisplay = seconds + '.' + decimal.toFixed(0) + 's'; 12 | } else { 13 | durationToDisplay = duration + 'ms'; 14 | } 15 | 16 | return {durationToDisplay}; 17 | }; 18 | export default ResponseTime; 19 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/RequestPane/QueryUrl/HttpMethodSelector/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const Wrapper = styled.div` 4 | font-size: 0.8125rem; 5 | 6 | .dropdown { 7 | width: 100%; 8 | } 9 | 10 | .method-selector { 11 | border-radius: 3px; 12 | min-width: 90px; 13 | 14 | .tippy-box { 15 | max-width: 150px !important; 16 | min-width: 110px !important; 17 | } 18 | 19 | .dropdown-item { 20 | padding: 0.25rem 0.6rem !important; 21 | } 22 | } 23 | 24 | .caret { 25 | color: rgb(140, 140, 140); 26 | fill: rgb(140 140 140); 27 | } 28 | `; 29 | 30 | export default Wrapper; 31 | -------------------------------------------------------------------------------- /packages/bruno-js/src/interpolate-string.js: -------------------------------------------------------------------------------- 1 | const { interpolate } = require('@usebruno/common'); 2 | 3 | const interpolateString = ( 4 | str, 5 | { envVariables = {}, collectionVariables = {}, processEnvVars = {}, requestVariables = {} } 6 | ) => { 7 | if (!str || !str.length || typeof str !== 'string') { 8 | return str; 9 | } 10 | 11 | const combinedVars = { 12 | ...envVariables, 13 | ...requestVariables, 14 | ...collectionVariables, 15 | process: { 16 | env: { 17 | ...processEnvVars 18 | } 19 | } 20 | }; 21 | 22 | return interpolate(str, combinedVars); 23 | }; 24 | 25 | module.exports = { 26 | interpolateString 27 | }; 28 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/CollectionSettings/Auth/OAuth2/AuthorizationCode/inputsConfig.js: -------------------------------------------------------------------------------- 1 | const inputsConfig = [ 2 | { 3 | key: 'callbackUrl', 4 | label: 'Callback URL' 5 | }, 6 | { 7 | key: 'authorizationUrl', 8 | label: 'Authorization URL' 9 | }, 10 | { 11 | key: 'accessTokenUrl', 12 | label: 'Access Token URL' 13 | }, 14 | { 15 | key: 'clientId', 16 | label: 'Client ID' 17 | }, 18 | { 19 | key: 'clientSecret', 20 | label: 'Client Secret' 21 | }, 22 | { 23 | key: 'scope', 24 | label: 'Scope' 25 | }, 26 | { 27 | key: 'state', 28 | label: 'State' 29 | } 30 | ]; 31 | 32 | export { inputsConfig }; 33 | -------------------------------------------------------------------------------- /docs/publishing/publishing_cn.md: -------------------------------------------------------------------------------- 1 | [English](../../publishing.md) 2 | | [Türkçe](./publishing_tr.md) 3 | | [Deutsch](./publishing_de.md) 4 | | [Français](./publishing_fr.md) 5 | | [Português (BR)](./publishing_pt_br.md) 6 | | [বাংলা](./publishing_bn.md) 7 | | [Română](./publishing_ro.md) 8 | | [Polski](./publishing_pl.md) 9 | | **简体中文** 10 | | [正體中文](./publishing_zhtw.md) 11 | | [日本語](./publishing_ja.md) 12 | 13 | ### 将 Bruno 发布到新的包管理器 14 | 15 | 虽然我们的代码是开源的,每个人都可以使用,但我们恳请您在考虑在新的包管理器上发布之前与我们联系。作为 Bruno 的创建者,我拥有这个项目的 Bruno 商标并希望管理其发行。如果您希望看到它使用新的包管理器,请提交一个 GitHub issue。 16 | 17 | 虽然我们的大部分功能都是免费与开源的 (涵盖 REST 和 GraphQL APIs) ,但我们努力在开源原则和可持续性之间取得和谐的平衡 - https://github.com/usebruno/bruno/discussions/269 18 | -------------------------------------------------------------------------------- /docs/publishing/publishing_zhtw.md: -------------------------------------------------------------------------------- 1 | [English](../../publishing.md) 2 | | [Türkçe](./publishing_tr.md) 3 | | [Deutsch](./publishing_de.md) 4 | | [Français](./publishing_fr.md) 5 | | [Português (BR)](./publishing_pt_br.md) 6 | | [বাংলা](./publishing_bn.md) 7 | | [Română](./publishing_ro.md) 8 | | [Polski](./publishing_pl.md) 9 | | [简体中文](./publishing_cn.md) 10 | | **正體中文** 11 | | [日本語](./publishing_ja.md) 12 | 13 | ### 將 Bruno 發佈到新的套件管理器 14 | 15 | 雖然我們的程式碼是開源的並且可供所有人使用,但我們懇請您在考慮在新的套件管理器上發布之前與我們聯繫。作為 Bruno 的創建者,我擁有這個專案的 Bruno 商標並希望管理其發行。如果您希望看到 Bruno 使用新的套件管理器,請提出一個 GitHub issue。 16 | 17 | 雖然我們的大部分功能都是免費和開源(涵蓋 REST 和 GraphQL APIs),但我們努力在開源的原則和永續性之間,取得和諧的平衡 - https://github.com/usebruno/bruno/discussions/269 18 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/Dropdown/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Tippy from '@tippyjs/react'; 3 | import StyledWrapper from './StyledWrapper'; 4 | 5 | const Dropdown = ({ icon, children, onCreate, placement }) => { 6 | return ( 7 | 8 | 18 | {icon} 19 | 20 | 21 | ); 22 | }; 23 | 24 | export default Dropdown; 25 | -------------------------------------------------------------------------------- /packages/bruno-schema/src/utils/testUtils.js: -------------------------------------------------------------------------------- 1 | const { customAlphabet } = require('nanoid'); 2 | const { expect } = require('@jest/globals'); 3 | 4 | // a customized version of nanoid without using _ and - 5 | const uuid = () => { 6 | // https://github.com/ai/nanoid/blob/main/url-alphabet/index.js 7 | const urlAlphabet = 'useandom26T198340PX75pxJACKVERYMINDBUSHWOLFGQZbfghjklqvwyzrict'; 8 | const customNanoId = customAlphabet(urlAlphabet, 21); 9 | 10 | return customNanoId(); 11 | }; 12 | 13 | const validationErrorWithMessages = (...errors) => { 14 | return expect.objectContaining({ 15 | errors 16 | }); 17 | }; 18 | 19 | module.exports = { 20 | uuid, 21 | validationErrorWithMessages 22 | }; 23 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/ResponsePane/ResponseHeaders/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const Wrapper = styled.div` 4 | table { 5 | width: 100%; 6 | border-collapse: collapse; 7 | 8 | thead { 9 | color: #777777; 10 | font-size: 0.75rem; 11 | font-weight: 600; 12 | text-transform: uppercase; 13 | } 14 | 15 | td { 16 | padding: 6px 10px; 17 | 18 | &.value { 19 | word-break: break-all; 20 | } 21 | } 22 | 23 | tbody { 24 | tr:nth-child(odd) { 25 | background-color: ${(props) => props.theme.table.striped}; 26 | } 27 | } 28 | } 29 | `; 30 | 31 | export default Wrapper; 32 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/ResponsePane/ResponseSize/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import StyledWrapper from './StyledWrapper'; 3 | 4 | const ResponseSize = ({ size }) => { 5 | let sizeToDisplay = ''; 6 | 7 | if (size > 1024) { 8 | // size is greater than 1kb 9 | let kb = Math.floor(size / 1024); 10 | let decimal = Math.round(((size % 1024) / 1024).toFixed(2) * 100); 11 | sizeToDisplay = kb + '.' + decimal + 'KB'; 12 | } else { 13 | sizeToDisplay = size + 'B'; 14 | } 15 | 16 | return ( 17 | 18 | {sizeToDisplay} 19 | 20 | ); 21 | }; 22 | export default ResponseSize; 23 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection/string interpolation/env vars.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: env vars 3 | type: http 4 | seq: 2 5 | } 6 | 7 | post { 8 | url: {{host}}/api/echo/json 9 | body: json 10 | auth: none 11 | } 12 | 13 | auth:basic { 14 | username: asd 15 | password: j 16 | } 17 | 18 | auth:bearer { 19 | token: 20 | } 21 | 22 | body:json { 23 | { 24 | "envVar1": "{{env.var1}}", 25 | "envVar2": "{{env-var2}}" 26 | } 27 | } 28 | 29 | assert { 30 | res.status: eq 200 31 | } 32 | 33 | tests { 34 | test("should return json", function() { 35 | expect(res.getBody()).to.eql({ 36 | "envVar1": "envVar1", 37 | "envVar2": "envVar2" 38 | }); 39 | }); 40 | 41 | } 42 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection_oauth2/auth/oauth2/authorization_code/token with authorize.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: token with authorize 3 | type: http 4 | seq: 4 5 | } 6 | 7 | post { 8 | url: 9 | body: none 10 | auth: oauth2 11 | } 12 | 13 | auth:oauth2 { 14 | grant_type: authorization_code 15 | callback_url: {{authorization_code_callback_url}} 16 | authorization_url: {{authorization_code_authorize_url}} 17 | access_token_url: {{authorization_code_access_token_url}} 18 | client_id: {{client_id}} 19 | client_secret: {{client_secret}} 20 | scope: 21 | pkce: true 22 | } 23 | 24 | script:post-response { 25 | bru.setEnvVar('authorization_code_access_token', res.body.access_token); 26 | } 27 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection/string interpolation/process env vars.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: process env vars 3 | type: http 4 | seq: 4 5 | } 6 | 7 | post { 8 | url: {{host}}/api/echo/json 9 | body: json 10 | auth: none 11 | } 12 | 13 | auth:basic { 14 | username: asd 15 | password: j 16 | } 17 | 18 | auth:bearer { 19 | token: 20 | } 21 | 22 | body:json { 23 | { 24 | "bark": "{{bark}}", 25 | "bark2": "{{process.env.PROC_ENV_VAR}}" 26 | } 27 | } 28 | 29 | assert { 30 | res.status: eq 200 31 | } 32 | 33 | tests { 34 | test("should return json", function() { 35 | expect(res.getBody()).to.eql({ 36 | "bark": "woof", 37 | "bark2": "woof" 38 | }); 39 | }); 40 | 41 | } 42 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/ResponsePane/Overlay/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const StyledWrapper = styled.div` 4 | position: absolute; 5 | height: 100%; 6 | z-index: 1; 7 | background-color: ${(props) => props.theme.requestTabPanel.responseOverlayBg}; 8 | 9 | div.overlay { 10 | height: 100%; 11 | z-index: 9; 12 | display: flex; 13 | flex-direction: column; 14 | align-items: center; 15 | padding-top: 20%; 16 | overflow: hidden; 17 | text-align: center; 18 | 19 | .loading-icon { 20 | transform: scaleY(-1); 21 | animation: rotateCounterClockwise 1s linear infinite; 22 | } 23 | } 24 | `; 25 | 26 | export default StyledWrapper; 27 | -------------------------------------------------------------------------------- /packages/bruno-lang/v1/src/utils.js: -------------------------------------------------------------------------------- 1 | // safely parse json 2 | const safeParseJson = (json) => { 3 | try { 4 | return JSON.parse(json); 5 | } catch (e) { 6 | return null; 7 | } 8 | }; 9 | 10 | const indentString = (str) => { 11 | if (!str || !str.length) { 12 | return str || ''; 13 | } 14 | 15 | return str 16 | .split('\n') 17 | .map((line) => ' ' + line) 18 | .join('\n'); 19 | }; 20 | 21 | const outdentString = (str) => { 22 | if (!str || !str.length) { 23 | return str || ''; 24 | } 25 | 26 | return str 27 | .split('\n') 28 | .map((line) => line.replace(/^ /, '')) 29 | .join('\n'); 30 | }; 31 | 32 | module.exports = { 33 | safeParseJson, 34 | indentString, 35 | outdentString 36 | }; 37 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/RequestPane/RequestBody/RequestBodyMode/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const Wrapper = styled.div` 4 | font-size: 0.8125rem; 5 | 6 | .body-mode-selector { 7 | background: transparent; 8 | border-radius: 3px; 9 | 10 | .dropdown-item { 11 | padding: 0.2rem 0.6rem !important; 12 | padding-left: 1.5rem !important; 13 | } 14 | 15 | .label-item { 16 | padding: 0.2rem 0.6rem !important; 17 | } 18 | 19 | .selected-body-mode { 20 | color: ${(props) => props.theme.colors.text.yellow}; 21 | } 22 | } 23 | 24 | .caret { 25 | color: rgb(140, 140, 140); 26 | fill: rgb(140 140 140); 27 | } 28 | `; 29 | 30 | export default Wrapper; 31 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection/bruno.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1", 3 | "name": "bruno-testbench", 4 | "type": "collection", 5 | "proxy": { 6 | "enabled": false, 7 | "protocol": "http", 8 | "hostname": "{{proxyHostname}}", 9 | "port": 4000, 10 | "auth": { 11 | "enabled": false, 12 | "username": "anoop", 13 | "password": "password" 14 | }, 15 | "bypassProxy": "" 16 | }, 17 | "scripts": { 18 | "moduleWhitelist": ["crypto", "buffer"], 19 | "filesystemAccess": { 20 | "allow": true 21 | } 22 | }, 23 | "clientCertificates": { 24 | "enabled": true, 25 | "certs": [] 26 | }, 27 | "presets": { 28 | "requestType": "http", 29 | "requestUrl": "http://localhost:6000" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection/scripting/local modules/sum.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: sum 3 | type: http 4 | seq: 1 5 | } 6 | 7 | post { 8 | url: {{host}}/api/echo/json 9 | body: json 10 | auth: none 11 | } 12 | 13 | body:json { 14 | { 15 | "a": 1, 16 | "b": 2 17 | } 18 | } 19 | 20 | assert { 21 | res.status: eq 200 22 | } 23 | 24 | script:pre-request { 25 | const math = require("./lib/math"); 26 | 27 | const body = req.getBody(); 28 | body.sum = body.a + body.b; 29 | 30 | req.setBody(body); 31 | } 32 | 33 | tests { 34 | test("should return json", function() { 35 | const data = res.getBody(); 36 | expect(res.getBody()).to.eql({ 37 | "a": 1, 38 | "b": 2, 39 | "sum": 3 40 | }); 41 | }); 42 | } 43 | -------------------------------------------------------------------------------- /packages/bruno-lang/src/index.js: -------------------------------------------------------------------------------- 1 | const bruToJsonV2 = require('../v2/src/bruToJson'); 2 | const jsonToBruV2 = require('../v2/src/jsonToBru'); 3 | const bruToEnvJsonV2 = require('../v2/src/envToJson'); 4 | const envJsonToBruV2 = require('../v2/src/jsonToEnv'); 5 | const dotenvToJson = require('../v2/src/dotenvToJson'); 6 | 7 | const collectionBruToJson = require('../v2/src/collectionBruToJson'); 8 | const jsonToCollectionBru = require('../v2/src/jsonToCollectionBru'); 9 | 10 | // Todo: remove V2 suffixes 11 | // Changes will have to be made to the CLI and GUI 12 | 13 | module.exports = { 14 | bruToJsonV2, 15 | jsonToBruV2, 16 | bruToEnvJsonV2, 17 | envJsonToBruV2, 18 | 19 | collectionBruToJson, 20 | jsonToCollectionBru, 21 | 22 | dotenvToJson 23 | }; 24 | -------------------------------------------------------------------------------- /packages/bruno-lang/v2/tests/assert.spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This test file is used to test the text parser. 3 | */ 4 | const parser = require('../src/bruToJson'); 5 | 6 | describe('assert parser', () => { 7 | it('should parse assert statement', () => { 8 | const input = ` 9 | assert { 10 | res("data.airports").filter(a => a.code ==="BLR").name: "Bangalore International Airport" 11 | } 12 | `; 13 | 14 | const output = parser(input); 15 | const expected = { 16 | assertions: [ 17 | { 18 | name: 'res("data.airports").filter(a => a.code ==="BLR").name', 19 | value: '"Bangalore International Airport"', 20 | enabled: true 21 | } 22 | ] 23 | }; 24 | expect(output).toEqual(expected); 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection/echo/echo json.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: echo json 3 | type: http 4 | seq: 1 5 | } 6 | 7 | post { 8 | url: {{host}}/api/echo/json 9 | body: json 10 | auth: none 11 | } 12 | 13 | headers { 14 | foo: bar 15 | } 16 | 17 | auth:basic { 18 | username: asd 19 | password: j 20 | } 21 | 22 | auth:bearer { 23 | token: 24 | } 25 | 26 | body:json { 27 | { 28 | "hello": "bruno" 29 | } 30 | } 31 | 32 | assert { 33 | res.status: eq 200 34 | } 35 | 36 | script:pre-request { 37 | bru.setVar("foo", "foo-world-2"); 38 | } 39 | 40 | tests { 41 | test("should return json", function() { 42 | const data = res.getBody(); 43 | expect(res.getBody()).to.eql({ 44 | "hello": "bruno" 45 | }); 46 | }); 47 | 48 | } 49 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/Preferences/ProxySettings/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const StyledWrapper = styled.div` 4 | .settings-label { 5 | width: 80px; 6 | } 7 | 8 | .textbox { 9 | border: 1px solid #ccc; 10 | padding: 0.15rem 0.45rem; 11 | box-shadow: none; 12 | outline: none; 13 | transition: border-color ease-in-out 0.1s; 14 | border-radius: 3px; 15 | background-color: ${(props) => props.theme.modal.input.bg}; 16 | border: 1px solid ${(props) => props.theme.modal.input.border}; 17 | 18 | &:focus { 19 | border: solid 1px ${(props) => props.theme.modal.input.focusBorder} !important; 20 | outline: none !important; 21 | } 22 | } 23 | `; 24 | 25 | export default StyledWrapper; 26 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/RunnerResults/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const Wrapper = styled.div` 4 | .item-path { 5 | .link { 6 | color: ${(props) => props.theme.textLink}; 7 | } 8 | } 9 | .danger { 10 | color: ${(props) => props.theme.colors.text.danger}; 11 | } 12 | 13 | .test-summary { 14 | color: ${(props) => props.theme.tabs.active.border}; 15 | } 16 | 17 | /* test results */ 18 | .test-success { 19 | color: ${(props) => props.theme.colors.text.green}; 20 | } 21 | 22 | .test-failure { 23 | color: ${(props) => props.theme.colors.text.danger}; 24 | 25 | .error-message { 26 | color: ${(props) => props.theme.colors.text.muted}; 27 | } 28 | } 29 | `; 30 | 31 | export default Wrapper; 32 | -------------------------------------------------------------------------------- /docs/publishing/publishing_ja.md: -------------------------------------------------------------------------------- 1 | [English](../../publishing.md) 2 | | [Türkçe](./publishing_tr.md) 3 | | [Deutsch](./publishing_de.md) 4 | | [Français](./publishing_fr.md) 5 | | [Português (BR)](./publishing_pt_br.md) 6 | | [বাংলা](./publishing_bn.md) 7 | | [Română](./publishing_ro.md) 8 | | [Polski](./publishing_pl.md) 9 | | [简体中文](./publishing_cn.md) 10 | | [正體中文](./publishing_zhtw.md) 11 | | **日本語** 12 | 13 | ### Bruno を新しいパッケージマネージャに公開する場合の注意 14 | 15 | 私たちのソースコードはオープンソースで誰でも使用できますが、新しいパッケージマネージャで公開を検討する前に、私たちにご連絡ください。私は Bruno の製作者として、このプロジェクト「Bruno」の商標を保有しており、その配布を管理したいと考えています。もし新しいパッケージマネージャで Bruno を使いたい場合は、GitHub の issue を立ててください。 16 | 17 | 私たちの機能の大部分が無料でオープンソース(REST や GraphQL の API も含む)ですが、 18 | 私たちはオープンソースの原則と長期的な維持の間でよいバランスをとれるように努力しています- https://github.com/usebruno/bruno/discussions/269 19 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection_oauth2/auth/oauth2/authorization_code/github token with authorize.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: github token with authorize 3 | type: http 4 | seq: 1 5 | } 6 | 7 | post { 8 | url: 9 | body: none 10 | auth: oauth2 11 | } 12 | 13 | auth:oauth2 { 14 | grant_type: authorization_code 15 | callback_url: {{authorization_code_callback_url}} 16 | authorization_url: {{authorization_code_github_authorize_url}} 17 | access_token_url: {{authorization_code_github_access_token_url}} 18 | client_id: {{authorization_code_github_client_id}} 19 | client_secret: {{authorization_code_github_client_secret}} 20 | scope: repo,gist 21 | } 22 | 23 | script:post-response { 24 | bru.setEnvVar('github_access_token',res.body.split('access_token=')[1]?.split('&scope')[0]); 25 | } 26 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection_oauth2/auth/oauth2/authorization_code/google token with authorize.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: google token with authorize 3 | type: http 4 | seq: 4 5 | } 6 | 7 | post { 8 | url: 9 | body: none 10 | auth: oauth2 11 | } 12 | 13 | auth:oauth2 { 14 | grant_type: authorization_code 15 | callback_url: {{authorization_code_callback_url}} 16 | authorization_url: {{authorization_code_google_auth_url}} 17 | access_token_url: {{authorization_code_google_access_token_url}} 18 | client_id: {{authorization_code_google_client_id}} 19 | client_secret: {{authorization_code_google_client_secret}} 20 | scope: {{authorization_code_google_scope}} 21 | } 22 | 23 | script:post-response { 24 | bru.setEnvVar('authorization_code_access_token', res.body.access_token); 25 | } 26 | -------------------------------------------------------------------------------- /packages/bruno-lang/v1/src/inline-tag.js: -------------------------------------------------------------------------------- 1 | const { sequenceOf, str, regex, choice, endOfInput, everyCharUntil } = require('arcsecond'); 2 | 3 | const whitespace = regex(/^[ \t]*/); 4 | const newline = regex(/^\r?\n/); 5 | const newLineOrEndOfInput = choice([endOfInput, newline]); 6 | 7 | const inlineTag = sequenceOf([ 8 | choice([str('type'), str('name'), str('method'), str('url'), str('seq'), str('body-mode')]), 9 | whitespace, 10 | choice([newline, everyCharUntil(newLineOrEndOfInput)]) 11 | ]).map(([key, _, val]) => { 12 | if (val === '\n' || val === '\r\n') { 13 | val = ''; 14 | } 15 | 16 | if (key === 'body-mode') { 17 | return { 18 | body: { 19 | mode: val 20 | } 21 | }; 22 | } 23 | 24 | return { [key]: val }; 25 | }); 26 | 27 | module.exports = inlineTag; 28 | -------------------------------------------------------------------------------- /packages/bruno-graphql-docs/src/utility/debounce.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2021 GraphQL Contributors. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | /** 9 | * Provided a duration and a function, returns a new function which is called 10 | * `duration` milliseconds after the last call. 11 | */ 12 | export default function debounce any>(duration: number, fn: F) { 13 | let timeout: number | null; 14 | return function (this: any, ...args: Parameters) { 15 | if (timeout) { 16 | window.clearTimeout(timeout); 17 | } 18 | timeout = window.setTimeout(() => { 19 | timeout = null; 20 | fn.apply(this, args); 21 | }, duration); 22 | }; 23 | } 24 | -------------------------------------------------------------------------------- /packages/bruno-app/src/providers/Toaster/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Toaster } from 'react-hot-toast'; 3 | import { useTheme } from 'providers/Theme'; 4 | 5 | export const ToastContext = React.createContext(); 6 | 7 | export const ToastProvider = (props) => { 8 | const { storedTheme } = useTheme(); 9 | 10 | const toastOptions = { duration: 2000 }; 11 | if (storedTheme === 'dark') { 12 | toastOptions.style = { 13 | borderRadius: '10px', 14 | background: '#3d3d3d', 15 | color: '#fff' 16 | }; 17 | } 18 | 19 | return ( 20 | 21 | 22 |
{props.children}
23 |
24 | ); 25 | }; 26 | 27 | export default ToastProvider; 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | bun.lockb 5 | node_modules 6 | yarn.lock 7 | pnpm-lock.yaml 8 | .pnp 9 | .pnp.js 10 | bun.lockb 11 | bun.lock 12 | 13 | # testing 14 | coverage 15 | 16 | # production 17 | build 18 | chrome-extension 19 | chrome-extension.pem 20 | chrome-extension.crx 21 | bruno.zip 22 | *.zip 23 | 24 | # misc 25 | .DS_Store 26 | *.pem 27 | 28 | # debug 29 | npm-debug.log* 30 | yarn-debug.log* 31 | yarn-error.log* 32 | 33 | # local env files 34 | .env.local 35 | .env.development.local 36 | .env.test.local 37 | .env.production.local 38 | 39 | # next.js 40 | /renderer 41 | /renderer/.next/ 42 | /renderer/out/ 43 | /test-results/ 44 | /playwright-report/ 45 | /playwright/.cache/ 46 | 47 | #dev editor 48 | bruno.iml 49 | .idea -------------------------------------------------------------------------------- /packages/bruno-app/src/assets/github.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection_level_oauth2/collection.bru: -------------------------------------------------------------------------------- 1 | headers { 2 | check: again 3 | } 4 | 5 | auth { 6 | mode: oauth2 7 | } 8 | 9 | auth:oauth2 { 10 | grant_type: authorization_code 11 | callback_url: {{authorization_code_callback_url}} 12 | authorization_url: {{authorization_code_authorize_url}} 13 | access_token_url: {{authorization_code_access_token_url}} 14 | client_id: {{client_id}} 15 | client_secret: {{client_secret}} 16 | scope: 17 | pkce: true 18 | } 19 | 20 | script:post-response { 21 | if(req.getAuthMode() == 'oauth2' && res.body.access_token) { 22 | bru.setEnvVar('access_token_set_by_collection',res.body.access_token) 23 | } 24 | } 25 | 26 | docs { 27 | # bruno-testbench 🐶 28 | 29 | This is a test collection that I am using to test various functionalities around bruno 30 | } 31 | -------------------------------------------------------------------------------- /packages/bruno-graphql-docs/src/components/DocExplorer/types.ts: -------------------------------------------------------------------------------- 1 | import { MouseEvent } from 'react'; 2 | import { 3 | GraphQLField, 4 | GraphQLInputField, 5 | GraphQLArgument, 6 | GraphQLObjectType, 7 | GraphQLInterfaceType, 8 | GraphQLInputObjectType, 9 | GraphQLType, 10 | GraphQLNamedType 11 | } from 'graphql'; 12 | 13 | export type FieldType = GraphQLField<{}, {}, {}> | GraphQLInputField | GraphQLArgument; 14 | 15 | export type OnClickFieldFunction = ( 16 | field: FieldType, 17 | type?: GraphQLObjectType | GraphQLInterfaceType | GraphQLInputObjectType | GraphQLType, 18 | event?: MouseEvent 19 | ) => void; 20 | 21 | export type OnClickTypeFunction = (type: GraphQLNamedType, event?: MouseEvent) => void; 22 | 23 | export type OnClickFieldOrTypeFunction = OnClickFieldFunction | OnClickTypeFunction; 24 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/CollectionSettings/Presets/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const StyledWrapper = styled.div` 4 | .settings-label { 5 | width: 110px; 6 | } 7 | 8 | .textbox { 9 | border: 1px solid #ccc; 10 | padding: 0.15rem 0.45rem; 11 | box-shadow: none; 12 | border-radius: 0px; 13 | outline: none; 14 | box-shadow: none; 15 | transition: border-color ease-in-out 0.1s; 16 | border-radius: 3px; 17 | background-color: ${(props) => props.theme.modal.input.bg}; 18 | border: 1px solid ${(props) => props.theme.modal.input.border}; 19 | 20 | &:focus { 21 | border: solid 1px ${(props) => props.theme.modal.input.focusBorder} !important; 22 | outline: none !important; 23 | } 24 | } 25 | `; 26 | 27 | export default StyledWrapper; 28 | -------------------------------------------------------------------------------- /packages/bruno-tests/readme.md: -------------------------------------------------------------------------------- 1 | # bruno-tests 2 | 3 | This package is used to test the Bruno CLI. 4 | We have a collection that sits in the `collection` directory. 5 | 6 | ### Test Server 7 | 8 | This will start the server on port 80 which exposes endpoints that the collection will hit. 9 | 10 | ```bash 11 | # install node dependencies 12 | npm install 13 | 14 | # start server 15 | npm start 16 | ``` 17 | 18 | ### Run Bru CLI on Collection 19 | 20 | ```bash 21 | cd collection 22 | 23 | # run collection against local server 24 | node ../../bruno-cli/bin/bru.js run --env Local --output junit.xml --format junit 25 | 26 | # run collection against prod server hosted at https://testbench.usebruno.com 27 | node ../../bruno-cli/bin/bru.js run --env Prod --output junit.xml --format junit 28 | ``` 29 | 30 | ### License 31 | 32 | [MIT](LICENSE) 33 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/CollectionSettings/ProxySettings/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const StyledWrapper = styled.div` 4 | .settings-label { 5 | width: 80px; 6 | } 7 | 8 | .textbox { 9 | border: 1px solid #ccc; 10 | padding: 0.15rem 0.45rem; 11 | box-shadow: none; 12 | border-radius: 0px; 13 | outline: none; 14 | box-shadow: none; 15 | transition: border-color ease-in-out 0.1s; 16 | border-radius: 3px; 17 | background-color: ${(props) => props.theme.modal.input.bg}; 18 | border: 1px solid ${(props) => props.theme.modal.input.border}; 19 | 20 | &:focus { 21 | border: solid 1px ${(props) => props.theme.modal.input.focusBorder} !important; 22 | outline: none !important; 23 | } 24 | } 25 | `; 26 | 27 | export default StyledWrapper; 28 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/StopWatch/index.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react'; 2 | 3 | const StopWatch = ({ requestTimestamp }) => { 4 | const [milliseconds, setMilliseconds] = useState(0); 5 | 6 | const tickInterval = 200; 7 | const tick = () => { 8 | setMilliseconds(milliseconds + tickInterval); 9 | }; 10 | 11 | useEffect(() => { 12 | let timerID = setInterval(() => tick(), tickInterval); 13 | return () => { 14 | clearInterval(timerID); 15 | }; 16 | }); 17 | 18 | useEffect(() => { 19 | setMilliseconds(Date.now() - requestTimestamp); 20 | }, [requestTimestamp]); 21 | 22 | if (milliseconds < 1000) { 23 | return 'Loading...'; 24 | } 25 | 26 | let seconds = milliseconds / 1000; 27 | return {seconds.toFixed(1)}s; 28 | }; 29 | 30 | export default StopWatch; 31 | -------------------------------------------------------------------------------- /packages/bruno-js/src/test.js: -------------------------------------------------------------------------------- 1 | const Test = (__brunoTestResults, chai) => async (description, callback) => { 2 | try { 3 | await callback(); 4 | __brunoTestResults.addResult({ description, status: 'pass' }); 5 | } catch (error) { 6 | console.log(chai.AssertionError); 7 | if (error instanceof chai.AssertionError) { 8 | const { message, actual, expected } = error; 9 | __brunoTestResults.addResult({ 10 | description, 11 | status: 'fail', 12 | error: message, 13 | actual, 14 | expected 15 | }); 16 | } else { 17 | __brunoTestResults.addResult({ 18 | description, 19 | status: 'fail', 20 | error: error.message || 'An unexpected error occurred.' 21 | }); 22 | } 23 | console.log(error); 24 | } 25 | }; 26 | 27 | module.exports = Test; 28 | -------------------------------------------------------------------------------- /packages/bruno-tests/src/auth/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | 4 | const authBearer = require('./bearer'); 5 | const authBasic = require('./basic'); 6 | const authCookie = require('./cookie'); 7 | const authOAuth2PasswordCredentials = require('./oauth2/passwordCredentials'); 8 | const authOAuth2AuthorizationCode = require('./oauth2/authorizationCode'); 9 | const authOAuth2ClientCredentials = require('./oauth2/clientCredentials'); 10 | 11 | router.use('/oauth2/password_credentials', authOAuth2PasswordCredentials); 12 | router.use('/oauth2/authorization_code', authOAuth2AuthorizationCode); 13 | router.use('/oauth2/client_credentials', authOAuth2ClientCredentials); 14 | router.use('/bearer', authBearer); 15 | router.use('/basic', authBasic); 16 | router.use('/cookie', authCookie); 17 | 18 | module.exports = router; 19 | -------------------------------------------------------------------------------- /packages/bruno-cli/src/index.js: -------------------------------------------------------------------------------- 1 | const yargs = require('yargs'); 2 | const chalk = require('chalk'); 3 | 4 | const { CLI_EPILOGUE, CLI_VERSION } = require('./constants'); 5 | 6 | const printBanner = () => { 7 | console.log(chalk.yellow(`Bru CLI ${CLI_VERSION}`)); 8 | }; 9 | 10 | const run = async () => { 11 | const argLength = process.argv.length; 12 | const commandsToPrintBanner = ['--help', '-h']; 13 | 14 | if (argLength <= 2 || process.argv.find((arg) => commandsToPrintBanner.includes(arg))) { 15 | printBanner(); 16 | } 17 | 18 | const { argv } = yargs 19 | .strict() 20 | .commandDir('commands') 21 | .epilogue(CLI_EPILOGUE) 22 | .usage('Usage: $0 [options]') 23 | .demandCommand(1, "Woof!! Let's play with some APIs!!") 24 | .help('h') 25 | .alias('h', 'help'); 26 | }; 27 | 28 | module.exports = { 29 | run 30 | }; 31 | -------------------------------------------------------------------------------- /packages/bruno-js/src/bruno-response.js: -------------------------------------------------------------------------------- 1 | class BrunoResponse { 2 | constructor(res) { 3 | this.res = res; 4 | this.status = res ? res.status : null; 5 | this.statusText = res ? res.statusText : null; 6 | this.headers = res ? res.headers : null; 7 | this.body = res ? res.data : null; 8 | this.responseTime = res ? res.responseTime : null; 9 | } 10 | 11 | getStatus() { 12 | return this.res ? this.res.status : null; 13 | } 14 | 15 | getHeader(name) { 16 | return this.res && this.res.headers ? this.res.headers[name] : null; 17 | } 18 | 19 | getHeaders() { 20 | return this.res ? this.res.headers : null; 21 | } 22 | 23 | getBody() { 24 | return this.res ? this.res.data : null; 25 | } 26 | 27 | getResponseTime() { 28 | return this.res ? this.res.responseTime : null; 29 | } 30 | } 31 | 32 | module.exports = BrunoResponse; 33 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/RequestPane/GraphQLRequestPane/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const StyledWrapper = styled.div` 4 | div.tabs { 5 | div.tab { 6 | padding: 6px 0px; 7 | border: none; 8 | border-bottom: solid 2px transparent; 9 | margin-right: 1.25rem; 10 | color: var(--color-tab-inactive); 11 | cursor: pointer; 12 | 13 | &:focus, 14 | &:active, 15 | &:focus-within, 16 | &:focus-visible, 17 | &:target { 18 | outline: none !important; 19 | box-shadow: none !important; 20 | } 21 | 22 | &.active { 23 | color: ${(props) => props.theme.tabs.active.color} !important; 24 | border-bottom: solid 2px ${(props) => props.theme.tabs.active.border} !important; 25 | } 26 | } 27 | } 28 | `; 29 | 30 | export default StyledWrapper; 31 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/RequestPane/HttpRequestPane/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const StyledWrapper = styled.div` 4 | div.tabs { 5 | div.tab { 6 | padding: 6px 0px; 7 | border: none; 8 | border-bottom: solid 2px transparent; 9 | margin-right: 1.25rem; 10 | color: var(--color-tab-inactive); 11 | cursor: pointer; 12 | 13 | &:focus, 14 | &:active, 15 | &:focus-within, 16 | &:focus-visible, 17 | &:target { 18 | outline: none !important; 19 | box-shadow: none !important; 20 | } 21 | 22 | &.active { 23 | color: ${(props) => props.theme.tabs.active.color} !important; 24 | border-bottom: solid 2px ${(props) => props.theme.tabs.active.border} !important; 25 | } 26 | } 27 | } 28 | `; 29 | 30 | export default StyledWrapper; 31 | -------------------------------------------------------------------------------- /packages/bruno-graphql-docs/src/components/DocExplorer/MarkdownContent.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2021 GraphQL Contributors. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import React from 'react'; 9 | import MD from 'markdown-it'; 10 | 11 | type Maybe = T | null | undefined; 12 | 13 | const md = new MD({ 14 | // render urls as links, à la github-flavored markdown 15 | linkify: true 16 | }); 17 | 18 | type MarkdownContentProps = { 19 | markdown?: Maybe; 20 | className?: string; 21 | }; 22 | 23 | export default function MarkdownContent({ markdown, className }: MarkdownContentProps) { 24 | if (!markdown) { 25 | return
; 26 | } 27 | 28 | return
; 29 | } 30 | -------------------------------------------------------------------------------- /packages/bruno-electron/tests/network/authorize-user.spec.js: -------------------------------------------------------------------------------- 1 | const { matchesCallbackUrl } = require('../../src/ipc/network/authorize-user-in-window'); 2 | 3 | describe('matchesCallbackUrl', () => { 4 | const testCases = [ 5 | { url: 'https://random-url/endpoint', expected: false }, 6 | { url: 'https://random-url/endpoint?code=abcd', expected: false }, 7 | { url: 'https://callback.url/endpoint?code=abcd', expected: true }, 8 | { url: 'https://callback.url/endpoint/?code=abcd', expected: true }, 9 | { url: 'https://callback.url/random-endpoint/?code=abcd', expected: false } 10 | ]; 11 | 12 | it.each(testCases)('$url - should be $expected', ({ url, expected }) => { 13 | let callBackUrl = 'https://callback.url/endpoint'; 14 | 15 | let actual = matchesCallbackUrl(new URL(url), new URL(callBackUrl)); 16 | 17 | expect(actual).toBe(expected); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /packages/bruno-query/readme.md: -------------------------------------------------------------------------------- 1 | # bruno-query 2 | 3 | Bruno query with deep navigation, filter and map support 4 | 5 | Easy array navigation 6 | ```js 7 | get(data, 'customer.orders.items.amount') 8 | ``` 9 | Deep navigation .. double dots 10 | ```js 11 | get(data, '..items.amount') 12 | ``` 13 | Array indexing 14 | ```js 15 | get(data, '..items[0].amount') 16 | ``` 17 | Array filtering [?] with corresponding filter function 18 | ```js 19 | get(data, '..items[?].amount', i => i.amount > 20) 20 | ``` 21 | Array filtering [?] with simple object predicate, same as (i => i.id === 2 && i.amount === 20) 22 | ```js 23 | get(data, '..items[?]', { id: 2, amount: 20 }) 24 | ``` 25 | Array mapping [?] with corresponding mapper function 26 | ```js 27 | get(data, '..items[?].amount', i => i.amount + 10) 28 | ``` 29 | 30 | ### Publish to Npm Registry 31 | ```bash 32 | npm publish --access=public 33 | ``` 34 | -------------------------------------------------------------------------------- /packages/bruno-lang/v2/tests/index.spec.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const bruToJson = require('../src/bruToJson'); 4 | const jsonToBru = require('../src/jsonToBru'); 5 | 6 | describe('bruToJson', () => { 7 | it('should parse the bru file', () => { 8 | const input = fs.readFileSync(path.join(__dirname, 'fixtures', 'request.bru'), 'utf8'); 9 | const expected = require('./fixtures/request.json'); 10 | const output = bruToJson(input); 11 | 12 | expect(output).toEqual(expected); 13 | }); 14 | }); 15 | 16 | describe('jsonToBru', () => { 17 | it('should parse the json file', () => { 18 | const input = require('./fixtures/request.json'); 19 | const expected = fs.readFileSync(path.join(__dirname, 'fixtures', 'request.bru'), 'utf8'); 20 | const output = jsonToBru(input); 21 | 22 | expect(output).toEqual(expected); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /packages/bruno-js/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usebruno/js", 3 | "version": "0.12.0", 4 | "license": "MIT", 5 | "main": "src/index.js", 6 | "files": [ 7 | "src", 8 | "package.json" 9 | ], 10 | "peerDependencies": { 11 | "@n8n/vm2": "^3.9.23" 12 | }, 13 | "scripts": { 14 | "test": "jest --testPathIgnorePatterns test.js" 15 | }, 16 | "dependencies": { 17 | "@usebruno/common": "0.1.0", 18 | "@usebruno/query": "0.1.0", 19 | "ajv": "^8.12.0", 20 | "ajv-formats": "^2.1.1", 21 | "atob": "^2.1.2", 22 | "axios": "^1.5.1", 23 | "btoa": "^1.2.1", 24 | "chai": "^4.3.7", 25 | "chai-string": "^1.5.0", 26 | "crypto-js": "^4.1.1", 27 | "json-query": "^2.2.2", 28 | "lodash": "^4.17.21", 29 | "moment": "^2.29.4", 30 | "nanoid": "3.3.4", 31 | "node-fetch": "2.*", 32 | "node-vault": "^0.10.2", 33 | "uuid": "^9.0.0" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection/string interpolation/missing values.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: missing values 3 | type: http 4 | seq: 1 5 | } 6 | 7 | post { 8 | url: {{host}}/api/echo/json?foo={{undefinedVar}} 9 | body: json 10 | auth: none 11 | } 12 | 13 | query { 14 | foo: {{undefinedVar}} 15 | } 16 | 17 | auth:basic { 18 | username: asd 19 | password: j 20 | } 21 | 22 | auth:bearer { 23 | token: 24 | } 25 | 26 | body:json { 27 | { 28 | "hello": "{{undefinedVar2}}" 29 | } 30 | } 31 | 32 | assert { 33 | res.status: eq 200 34 | } 35 | 36 | tests { 37 | test("should return json", function() { 38 | const url = req.getUrl(); 39 | const query = url.split("?")[1]; 40 | expect(query).to.equal("foo={{undefinedVar}}"); 41 | 42 | const data = res.getBody(); 43 | expect(res.getBody()).to.eql({ 44 | "hello": "{{undefinedVar2}}" 45 | }); 46 | }); 47 | 48 | } 49 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | # Description 2 | 3 | 4 | 5 | ### Contribution Checklist: 6 | 7 | - [ ] **The pull request only addresses one issue or adds one feature.** 8 | - [ ] **The pull request does not introduce any breaking changes** 9 | - [ ] **I have added screenshots or gifs to help explain the change if applicable.** 10 | - [ ] **I have read the [contribution guidelines](https://github.com/usebruno/bruno/blob/main/contributing.md).** 11 | - [ ] **Create an issue and link to the pull request.** 12 | 13 | Note: Keeping the PR small and focused helps make it easier to review and merge. If you have multiple changes you want to make, please consider submitting them as separate pull requests. 14 | 15 | ### Publishing to New Package Managers 16 | 17 | Please see [here](../publishing.md) for more information. 18 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/ResponsePane/NetworkError/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const NetworkError = ({ onClose }) => { 4 | return ( 5 |
6 |
7 |
8 |
9 |

Network Error

10 |
11 |
12 |
13 |
14 | 20 |
21 |
22 | ); 23 | }; 24 | 25 | export default NetworkError; 26 | -------------------------------------------------------------------------------- /packages/bruno-lang/v2/tests/fixtures/collection.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | type: collection 3 | } 4 | 5 | headers { 6 | content-type: application/json 7 | Authorization: Bearer 123 8 | ~transaction-id: {{transactionId}} 9 | } 10 | 11 | auth { 12 | mode: none 13 | } 14 | 15 | auth:basic { 16 | username: john 17 | password: secret 18 | } 19 | 20 | auth:bearer { 21 | token: 123 22 | } 23 | 24 | auth:digest { 25 | username: john 26 | password: secret 27 | } 28 | 29 | vars:pre-request { 30 | departingDate: 2020-01-01 31 | ~returningDate: 2020-01-02 32 | } 33 | 34 | vars:post-response { 35 | ~transactionId: $res.body.transactionId 36 | } 37 | 38 | script:pre-request { 39 | console.log("In Collection pre Request Script"); 40 | } 41 | 42 | script:post-response { 43 | console.log("In Collection post Request Script"); 44 | } 45 | 46 | docs { 47 | This request needs auth token to be set in the headers. 48 | } 49 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/FeatureRequest.yaml: -------------------------------------------------------------------------------- 1 | name: Feature Request 2 | description: Suggest an idea for this project. 3 | labels: ['enhancement'] 4 | body: 5 | - type: checkboxes 6 | attributes: 7 | label: 'I have checked the following:' 8 | options: 9 | - label: I've searched existing issues and found nothing related to my issue. 10 | required: true 11 | - type: markdown 12 | attributes: 13 | value: | 14 | Suggest an idea for this project. 15 | - type: textarea 16 | attributes: 17 | label: Describe the feature you want to add 18 | description: A clear and concise description of the feature you want to be added. 19 | validations: 20 | required: true 21 | - type: textarea 22 | attributes: 23 | label: Mockups or Images of the feature 24 | description: Add some images to support your feature. 25 | validations: 26 | required: true 27 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/ResponsePane/ResponseClear/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { IconEraser } from '@tabler/icons'; 3 | import { useDispatch } from 'react-redux'; 4 | import StyledWrapper from './StyledWrapper'; 5 | import { responseCleared } from 'providers/ReduxStore/slices/collections/index'; 6 | 7 | const ResponseClear = ({ collection, item }) => { 8 | const dispatch = useDispatch(); 9 | 10 | const clearResponse = () => 11 | dispatch( 12 | responseCleared({ 13 | itemUid: item.uid, 14 | collectionUid: collection.uid, 15 | response: null 16 | }) 17 | ); 18 | 19 | return ( 20 | 21 | 24 | 25 | ); 26 | }; 27 | export default ResponseClear; 28 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/ResponsePane/StatusCode/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import classnames from 'classnames'; 3 | import statusCodePhraseMap from './get-status-code-phrase'; 4 | import StyledWrapper from './StyledWrapper'; 5 | 6 | // Todo: text-error class is not getting pulled in for 500 errors 7 | const StatusCode = ({ status }) => { 8 | const getTabClassname = (status) => { 9 | return classnames('ml-2', { 10 | 'text-ok': status >= 100 && status < 200, 11 | 'text-ok': status >= 200 && status < 300, 12 | 'text-error': status >= 300 && status < 400, 13 | 'text-error': status >= 400 && status < 500, 14 | 'text-error': status >= 500 && status < 600 15 | }); 16 | }; 17 | 18 | return ( 19 | 20 | {status} {statusCodePhraseMap[status]} 21 | 22 | ); 23 | }; 24 | export default StatusCode; 25 | -------------------------------------------------------------------------------- /packages/bruno-electron/src/ipc/notifications.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config(); 2 | const { ipcMain } = require('electron'); 3 | const fetch = require('node-fetch'); 4 | 5 | const registerNotificationsIpc = (mainWindow, watcher) => { 6 | ipcMain.handle('renderer:fetch-notifications', async () => { 7 | try { 8 | const notifications = await fetchNotifications(); 9 | return Promise.resolve(notifications); 10 | } catch (error) { 11 | return Promise.reject(error); 12 | } 13 | }); 14 | }; 15 | 16 | module.exports = registerNotificationsIpc; 17 | 18 | const fetchNotifications = async () => { 19 | try { 20 | let url = process.env.BRUNO_INFO_ENDPOINT || 'https://appinfo.usebruno.com'; 21 | const data = await fetch(url).then((res) => res.json()); 22 | 23 | return data?.notifications || []; 24 | } catch (error) { 25 | return Promise.reject('Error while fetching notifications!', error); 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /packages/bruno-query/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usebruno/query", 3 | "version": "0.1.0", 4 | "license" : "MIT", 5 | "main": "dist/cjs/index.js", 6 | "module": "dist/esm/index.js", 7 | "types": "dist/index.d.ts", 8 | "files": [ 9 | "dist", 10 | "src", 11 | "package.json" 12 | ], 13 | "scripts": { 14 | "clean": "rimraf dist", 15 | "test": "jest", 16 | "prebuild": "npm run clean", 17 | "build": "rollup -c", 18 | "prepack": "npm run test && npm run build" 19 | }, 20 | "devDependencies": { 21 | "@rollup/plugin-commonjs": "^23.0.2", 22 | "@rollup/plugin-node-resolve": "^15.0.1", 23 | "@rollup/plugin-typescript": "^9.0.2", 24 | "rollup": "3.2.5", 25 | "rollup-plugin-dts": "^5.0.0", 26 | "rollup-plugin-peer-deps-external": "^2.2.4", 27 | "rollup-plugin-terser": "^7.0.2", 28 | "typescript": "^4.8.4" 29 | }, 30 | "overrides": { 31 | "rollup": "3.2.5" 32 | } 33 | } -------------------------------------------------------------------------------- /packages/bruno-cli/tests/runner/prepare-request.spec.js: -------------------------------------------------------------------------------- 1 | const { describe, it, expect } = require('@jest/globals'); 2 | 3 | const prepareRequest = require('../../src/runner/prepare-request'); 4 | 5 | describe('prepare-request: prepareRequest', () => { 6 | describe('Decomments request body', () => { 7 | it('If request body is valid JSON', async () => { 8 | const body = { mode: 'json', json: '{\n"test": "{{someVar}}" // comment\n}' }; 9 | const expected = { test: '{{someVar}}' }; 10 | const result = prepareRequest({ body }); 11 | expect(result.data).toEqual(expected); 12 | }); 13 | 14 | it('If request body is not valid JSON', async () => { 15 | const body = { mode: 'json', json: '{\n"test": {{someVar}} // comment\n}' }; 16 | const expected = '{\n"test": {{someVar}} \n}'; 17 | const result = prepareRequest({ body }); 18 | expect(result.data).toEqual(expected); 19 | }); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/Preferences/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const StyledWrapper = styled.div` 4 | div.tabs { 5 | margin-top: -0.5rem; 6 | 7 | div.tab { 8 | padding: 6px 0px; 9 | border: none; 10 | border-bottom: solid 2px transparent; 11 | margin-right: 1.25rem; 12 | color: var(--color-tab-inactive); 13 | cursor: pointer; 14 | 15 | &:focus, 16 | &:active, 17 | &:focus-within, 18 | &:focus-visible, 19 | &:target { 20 | outline: none !important; 21 | box-shadow: none !important; 22 | } 23 | 24 | &.active { 25 | color: ${(props) => props.theme.tabs.active.color} !important; 26 | border-bottom: solid 2px ${(props) => props.theme.tabs.active.border} !important; 27 | } 28 | } 29 | } 30 | 31 | section.tab-panel { 32 | min-height: 300px; 33 | } 34 | `; 35 | 36 | export default StyledWrapper; 37 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection_oauth2/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usebruno/test-collection", 3 | "version": "0.0.1", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "@usebruno/test-collection", 9 | "version": "0.0.1", 10 | "dependencies": { 11 | "@faker-js/faker": "^8.4.0" 12 | } 13 | }, 14 | "node_modules/@faker-js/faker": { 15 | "version": "8.4.0", 16 | "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-8.4.0.tgz", 17 | "integrity": "sha512-htW87352wzUCdX1jyUQocUcmAaFqcR/w082EC8iP/gtkF0K+aKcBp0hR5Arb7dzR8tQ1TrhE9DNa5EbJELm84w==", 18 | "funding": [ 19 | { 20 | "type": "opencollective", 21 | "url": "https://opencollective.com/fakerjs" 22 | } 23 | ], 24 | "engines": { 25 | "node": "^14.17.0 || ^16.13.0 || >=18.0.0", 26 | "npm": ">=6.14.13" 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /packages/bruno-app/src/utils/codegenerator/auth.js: -------------------------------------------------------------------------------- 1 | import get from 'lodash/get'; 2 | 3 | export const getAuthHeaders = (collectionRootAuth, requestAuth) => { 4 | const auth = collectionRootAuth && ['inherit'].includes(requestAuth?.mode) ? collectionRootAuth : requestAuth; 5 | 6 | switch (auth.mode) { 7 | case 'basic': 8 | const username = get(auth, 'basic.username', ''); 9 | const password = get(auth, 'basic.password', ''); 10 | const basicToken = Buffer.from(`${username}:${password}`).toString('base64'); 11 | 12 | return [ 13 | { 14 | enabled: true, 15 | name: 'Authorization', 16 | value: `Basic ${basicToken}` 17 | } 18 | ]; 19 | case 'bearer': 20 | return [ 21 | { 22 | enabled: true, 23 | name: 'Authorization', 24 | value: `Bearer ${get(auth, 'bearer.token', '')}` 25 | } 26 | ]; 27 | default: 28 | return []; 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /packages/bruno-electron/src/store/window-state.js: -------------------------------------------------------------------------------- 1 | const Store = require('electron-store'); 2 | 3 | const DEFAULT_WINDOW_WIDTH = 1280; 4 | const DEFAULT_WINDOW_HEIGHT = 768; 5 | 6 | const DEFAULT_MAXIMIZED = false; 7 | 8 | class WindowStateStore { 9 | constructor() { 10 | this.store = new Store({ 11 | name: 'preferences', 12 | clearInvalidConfig: true 13 | }); 14 | } 15 | 16 | getBounds() { 17 | return ( 18 | this.store.get('window-bounds') || { 19 | x: 0, 20 | y: 0, 21 | width: DEFAULT_WINDOW_WIDTH, 22 | height: DEFAULT_WINDOW_HEIGHT 23 | } 24 | ); 25 | } 26 | 27 | setBounds(bounds) { 28 | this.store.set('window-bounds', bounds); 29 | } 30 | 31 | getMaximized() { 32 | return this.store.get('maximized') || DEFAULT_MAXIMIZED; 33 | } 34 | 35 | setMaximized(isMaximized) { 36 | this.store.set('maximized', isMaximized); 37 | } 38 | } 39 | 40 | module.exports = WindowStateStore; 41 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection_level_oauth2/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usebruno/test-collection", 3 | "version": "0.0.1", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "@usebruno/test-collection", 9 | "version": "0.0.1", 10 | "dependencies": { 11 | "@faker-js/faker": "^8.4.0" 12 | } 13 | }, 14 | "node_modules/@faker-js/faker": { 15 | "version": "8.4.0", 16 | "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-8.4.0.tgz", 17 | "integrity": "sha512-htW87352wzUCdX1jyUQocUcmAaFqcR/w082EC8iP/gtkF0K+aKcBp0hR5Arb7dzR8tQ1TrhE9DNa5EbJELm84w==", 18 | "funding": [ 19 | { 20 | "type": "opencollective", 21 | "url": "https://opencollective.com/fakerjs" 22 | } 23 | ], 24 | "engines": { 25 | "node": "^14.17.0 || ^16.13.0 || >=18.0.0", 26 | "npm": ">=6.14.13" 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /packages/bruno-common/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usebruno/common", 3 | "version": "0.1.0", 4 | "license": "MIT", 5 | "main": "dist/cjs/index.js", 6 | "module": "dist/esm/index.js", 7 | "types": "dist/index.d.ts", 8 | "files": [ 9 | "dist", 10 | "src", 11 | "package.json" 12 | ], 13 | "scripts": { 14 | "clean": "rimraf dist", 15 | "test": "jest", 16 | "test:watch": "jest --watch", 17 | "prebuild": "npm run clean", 18 | "build": "rollup -c", 19 | "prepack": "npm run test && npm run build" 20 | }, 21 | "devDependencies": { 22 | "@rollup/plugin-commonjs": "^23.0.2", 23 | "@rollup/plugin-node-resolve": "^15.0.1", 24 | "@rollup/plugin-typescript": "^9.0.2", 25 | "rollup": "3.2.5", 26 | "rollup-plugin-dts": "^5.0.0", 27 | "rollup-plugin-peer-deps-external": "^2.2.4", 28 | "rollup-plugin-terser": "^7.0.2", 29 | "typescript": "^4.8.4" 30 | }, 31 | "overrides": { 32 | "rollup": "3.2.5" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /packages/bruno-lang/v1/tests/bru-to-env-json.spec.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | 4 | const { bruToEnvJson } = require('../src'); 5 | 6 | describe('bruToEnvJson', () => { 7 | it('should parse .bru file contents', () => { 8 | const requestFile = fs.readFileSync(path.join(__dirname, 'fixtures', 'env.bru'), 'utf8'); 9 | const result = bruToEnvJson(requestFile); 10 | 11 | expect(result).toEqual({ 12 | variables: [ 13 | { 14 | enabled: true, 15 | name: 'host', 16 | value: 'https://www.google.com', 17 | type: 'text' 18 | }, 19 | { 20 | enabled: true, 21 | name: 'jwt', 22 | value: 'secret', 23 | type: 'text' 24 | }, 25 | { 26 | enabled: false, 27 | name: 'Content-type', 28 | value: 'application/json', 29 | type: 'text' 30 | } 31 | ] 32 | }); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /packages/bruno-electron/tests/network/prepare-request.spec.js: -------------------------------------------------------------------------------- 1 | const { describe, it, expect } = require('@jest/globals'); 2 | 3 | const prepareRequest = require('../../src/ipc/network/prepare-request'); 4 | 5 | describe('prepare-request: prepareRequest', () => { 6 | describe('Decomments request body', () => { 7 | it('If request body is valid JSON', async () => { 8 | const body = { mode: 'json', json: '{\n"test": "{{someVar}}" // comment\n}' }; 9 | const expected = { test: '{{someVar}}' }; 10 | const result = prepareRequest({ request: { body } }, {}); 11 | expect(result.data).toEqual(expected); 12 | }); 13 | 14 | it('If request body is not valid JSON', async () => { 15 | const body = { mode: 'json', json: '{\n"test": {{someVar}} // comment\n}' }; 16 | const expected = '{\n"test": {{someVar}} \n}'; 17 | const result = prepareRequest({ request: { body } }, {}); 18 | expect(result.data).toEqual(expected); 19 | }); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /packages/bruno-tests/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usebruno/tests", 3 | "version": "0.0.1", 4 | "description": "", 5 | "main": "src/index.js", 6 | "scripts": { 7 | "start": "node ." 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/usebruno/bruno-testbench.git" 12 | }, 13 | "keywords": [], 14 | "author": "", 15 | "license": "MIT", 16 | "bugs": { 17 | "url": "https://github.com/usebruno/bruno-testbench/issues" 18 | }, 19 | "homepage": "https://github.com/usebruno/bruno-testbench#readme", 20 | "dependencies": { 21 | "axios": "^1.5.1", 22 | "body-parser": "^1.20.0", 23 | "cookie-parser": "^1.4.6", 24 | "cors": "^2.8.5", 25 | "express": "^4.18.1", 26 | "express-basic-auth": "^1.2.1", 27 | "express-xml-bodyparser": "^0.3.0", 28 | "http-proxy": "^1.18.1", 29 | "js-yaml": "^4.1.0", 30 | "jsonwebtoken": "^9.0.2", 31 | "lodash": "^4.17.21", 32 | "multer": "^1.4.5-lts.1" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /packages/bruno-tests/collection/scripting/npm modules/fakerjs.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: fakerjs 3 | type: http 4 | seq: 1 5 | } 6 | 7 | post { 8 | url: {{host}}/api/echo/json 9 | body: json 10 | auth: none 11 | } 12 | 13 | body:json { 14 | { 15 | "hello": "bruno" 16 | } 17 | } 18 | 19 | assert { 20 | res.status: eq 200 21 | } 22 | 23 | script:pre-request { 24 | const { faker } = require('@faker-js/faker'); 25 | const uuid = faker.string.uuid(); 26 | 27 | const data = req.getBody(); 28 | data.uuid = uuid; 29 | 30 | req.setBody(data); 31 | } 32 | 33 | tests { 34 | test("should return json", function() { 35 | const data = res.getBody(); 36 | const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i; 37 | const isUUID = (inputString) => { 38 | return uuidRegex.test(inputString); 39 | }; 40 | 41 | expect(data.hello).to.equal("bruno"); 42 | expect(isUUID(data.uuid)).to.be.true; 43 | }); 44 | 45 | } 46 | -------------------------------------------------------------------------------- /packages/bruno-lang/v2/tests/script.spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This test file is used to test the text parser. 3 | */ 4 | const parser = require('../src/bruToJson'); 5 | 6 | describe('script parser', () => { 7 | it('should parse request script', () => { 8 | const input = ` 9 | script:pre-request { 10 | $req.setHeader('Content-Type', 'application/json'); 11 | } 12 | `; 13 | 14 | const output = parser(input); 15 | const expected = { 16 | script: { 17 | req: "$req.setHeader('Content-Type', 'application/json');" 18 | } 19 | }; 20 | expect(output).toEqual(expected); 21 | }); 22 | 23 | it('should parse response script', () => { 24 | const input = ` 25 | script:post-response { 26 | expect(response.status).to.equal(200); 27 | } 28 | `; 29 | 30 | const output = parser(input); 31 | const expected = { 32 | script: { 33 | res: 'expect(response.status).to.equal(200);' 34 | } 35 | }; 36 | expect(output).toEqual(expected); 37 | }); 38 | }); 39 | -------------------------------------------------------------------------------- /packages/bruno-app/src/providers/App/ConfirmAppClose/index.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react'; 2 | import { useDispatch } from 'react-redux'; 3 | import SaveRequestsModal from './SaveRequestsModal'; 4 | import { isElectron } from 'utils/common/platform'; 5 | 6 | const ConfirmAppClose = () => { 7 | const { ipcRenderer } = window; 8 | const [showConfirmClose, setShowConfirmClose] = useState(false); 9 | const dispatch = useDispatch(); 10 | 11 | useEffect(() => { 12 | if (!isElectron()) { 13 | return; 14 | } 15 | 16 | const clearListener = ipcRenderer.on('main:start-quit-flow', () => { 17 | setShowConfirmClose(true); 18 | }); 19 | 20 | return () => { 21 | clearListener(); 22 | }; 23 | }, [isElectron, ipcRenderer, dispatch, setShowConfirmClose]); 24 | 25 | if (!showConfirmClose) { 26 | return null; 27 | } 28 | 29 | return setShowConfirmClose(false)} />; 30 | }; 31 | 32 | export default ConfirmAppClose; 33 | -------------------------------------------------------------------------------- /packages/bruno-graphql-docs/src/components/DocExplorer/Argument.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2021 GraphQL Contributors. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import React from 'react'; 9 | import { GraphQLArgument } from 'graphql'; 10 | import TypeLink from './TypeLink'; 11 | import DefaultValue from './DefaultValue'; 12 | import { OnClickTypeFunction } from './types'; 13 | 14 | type ArgumentProps = { 15 | arg: GraphQLArgument; 16 | onClickType: OnClickTypeFunction; 17 | showDefaultValue?: boolean; 18 | }; 19 | 20 | export default function Argument({ arg, onClickType, showDefaultValue }: ArgumentProps) { 21 | return ( 22 | 23 | {arg.name} 24 | {': '} 25 | 26 | {showDefaultValue !== false && } 27 | 28 | ); 29 | } 30 | -------------------------------------------------------------------------------- /packages/bruno-app/src/utils/collections/search.js: -------------------------------------------------------------------------------- 1 | import { flattenItems, isItemARequest } from './index'; 2 | import filter from 'lodash/filter'; 3 | import find from 'lodash/find'; 4 | 5 | export const doesRequestMatchSearchText = (request, searchText = '') => { 6 | return request.name.toLowerCase().includes(searchText.toLowerCase()); 7 | }; 8 | 9 | export const doesFolderHaveItemsMatchSearchText = (item, searchText = '') => { 10 | let flattenedItems = flattenItems(item.items); 11 | let requestItems = filter(flattenedItems, (item) => isItemARequest(item)); 12 | 13 | return find(requestItems, (request) => doesRequestMatchSearchText(request, searchText)); 14 | }; 15 | 16 | export const doesCollectionHaveItemsMatchingSearchText = (collection, searchText = '') => { 17 | let flattenedItems = flattenItems(collection.items); 18 | let requestItems = filter(flattenedItems, (item) => isItemARequest(item)); 19 | 20 | return find(requestItems, (request) => doesRequestMatchSearchText(request, searchText)); 21 | }; 22 | -------------------------------------------------------------------------------- /packages/bruno-lang/v2/tests/collection.spec.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const collectionBruToJson = require('../src/collectionBruToJson'); 4 | const jsonToCollectionBru = require('../src/jsonToCollectionBru'); 5 | 6 | describe('collectionBruToJson', () => { 7 | it('should parse the collection bru file', () => { 8 | const input = fs.readFileSync(path.join(__dirname, 'fixtures', 'collection.bru'), 'utf8'); 9 | const expected = require('./fixtures/collection.json'); 10 | const output = collectionBruToJson(input); 11 | 12 | expect(output).toEqual(expected); 13 | }); 14 | }); 15 | 16 | describe('jsonToCollectionBru', () => { 17 | it('should convert the collection json to bru', () => { 18 | const input = require('./fixtures/collection.json'); 19 | const expected = fs.readFileSync(path.join(__dirname, 'fixtures', 'collection.bru'), 'utf8'); 20 | const output = jsonToCollectionBru(input); 21 | 22 | expect(output).toEqual(expected); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/RequestTabs/RequestTab/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const StyledWrapper = styled.div` 4 | .tab-label { 5 | overflow: hidden; 6 | } 7 | 8 | .tab-name { 9 | overflow: hidden; 10 | text-overflow: ellipsis; 11 | white-space: nowrap; 12 | } 13 | 14 | .close-icon-container { 15 | min-height: 20px; 16 | min-width: 24px; 17 | margin-left: 4px; 18 | border-radius: 3px; 19 | 20 | .close-icon { 21 | display: none; 22 | color: ${(props) => props.theme.requestTabs.icon.color}; 23 | width: 8px; 24 | padding-bottom: 6px; 25 | padding-top: 6px; 26 | } 27 | 28 | &:hover, 29 | &:hover .close-icon { 30 | color: ${(props) => props.theme.requestTabs.icon.hoverColor}; 31 | background-color: ${(props) => props.theme.requestTabs.icon.hoverBg}; 32 | } 33 | 34 | .has-changes-icon { 35 | height: 24px; 36 | } 37 | } 38 | `; 39 | 40 | export default StyledWrapper; 41 | -------------------------------------------------------------------------------- /packages/bruno-app/src/utils/common/error.js: -------------------------------------------------------------------------------- 1 | import toast from 'react-hot-toast'; 2 | 3 | // levels: 'warning, error' 4 | export class BrunoError extends Error { 5 | constructor(message, level) { 6 | super(message); 7 | this.name = 'BrunoError'; 8 | this.level = level || 'error'; 9 | } 10 | } 11 | 12 | export const parseError = (error, defaultErrorMsg = 'An error occurred') => { 13 | if (error instanceof BrunoError) { 14 | return error.message; 15 | } 16 | 17 | return error.message ? error.message : defaultErrorMsg; 18 | }; 19 | 20 | export const toastError = (error, defaultErrorMsg = 'An error occurred') => { 21 | let errorMsg = parseError(error, defaultErrorMsg); 22 | 23 | if (error instanceof BrunoError) { 24 | if (error.level === 'warning') { 25 | return toast(errorMsg, { 26 | icon: '⚠️', 27 | duration: 3000 28 | }); 29 | } 30 | return toast.error(errorMsg, { 31 | duration: 3000 32 | }); 33 | } 34 | 35 | return toast.error(errorMsg); 36 | }; 37 | -------------------------------------------------------------------------------- /packages/bruno-lang/v1/tests/env-json-to-bru.spec.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | 4 | const { envJsonToBru } = require('../src'); 5 | 6 | describe('envJsonToBru', () => { 7 | it('should convert json file into .bru file', () => { 8 | const env = { 9 | variables: [ 10 | { 11 | enabled: true, 12 | name: 'host', 13 | value: 'https://www.google.com', 14 | type: 'text' 15 | }, 16 | { 17 | enabled: true, 18 | name: 'jwt', 19 | value: 'secret', 20 | type: 'text' 21 | }, 22 | { 23 | enabled: false, 24 | name: 'Content-type', 25 | value: 'application/json', 26 | type: 'text' 27 | } 28 | ] 29 | }; 30 | 31 | const expectedBruFile = fs.readFileSync(path.join(__dirname, 'fixtures', 'env.bru'), 'utf8'); 32 | const actualBruFile = envJsonToBru(env); 33 | 34 | expect(expectedBruFile).toEqual(actualBruFile); 35 | }); 36 | }); 37 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/ResponsePane/ResponseHeaders/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import StyledWrapper from './StyledWrapper'; 3 | 4 | const ResponseHeaders = ({ headers }) => { 5 | const headersArray = typeof headers === 'object' ? Object.entries(headers) : []; 6 | 7 | return ( 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | {headersArray && headersArray.length 18 | ? headersArray.map((header, index) => { 19 | return ( 20 | 21 | 22 | 23 | 24 | ); 25 | }) 26 | : null} 27 | 28 |
NameValue
{header[0]}{header[1]}
29 |
30 | ); 31 | }; 32 | export default ResponseHeaders; 33 | -------------------------------------------------------------------------------- /docs/publishing/publishing_tr.md: -------------------------------------------------------------------------------- 1 | [English](../../publishing.md) 2 | | **Türkçe** 3 | | [Deutsch](./publishing_de.md) 4 | | [Français](./publishing_fr.md) 5 | | [Português (BR)](./publishing_pt_br.md) 6 | | [বাংলা](./publishing_bn.md) 7 | | [Română](./publishing_ro.md) 8 | | [Polski](./publishing_pl.md) 9 | | [简体中文](./publishing_cn.md) 10 | | [正體中文](./publishing_zhtw.md) 11 | | [日本語](./publishing_ja.md) 12 | 13 | ### Bruno'yu yeni bir paket yöneticisine yayınlama 14 | 15 | Kodumuz açık kaynak kodlu ve herkesin kullanımına açık olsa da, yeni paket yöneticilerinde yayınlamayı düşünmeden önce bize ulaşmanızı rica ediyoruz. Bruno'nun yaratıcısı olarak, bu proje için `Bruno` ticari markasına sahibim ve dağıtımını yönetmek istiyorum. Bruno'yu yeni bir paket yöneticisinde görmek istiyorsanız, lütfen bir GitHub sorunu oluşturun. 16 | 17 | Özelliklerimizin çoğu ücretsiz ve açık kaynak olsa da (REST ve GraphQL Apis'i kapsar), 18 | açık kaynak ilkeleri ile sürdürülebilirlik arasında uyumlu bir denge kurmaya çalışıyoruz - https://github.com/usebruno/bruno/discussions/269 19 | -------------------------------------------------------------------------------- /docs/publishing/publishing_bn.md: -------------------------------------------------------------------------------- 1 | [English](../../publishing.md) 2 | | [Türkçe](./publishing_tr.md) 3 | | [Deutsch](./publishing_de.md) 4 | | [Français](./publishing_fr.md) 5 | | [Português (BR)](./publishing_pt_br.md) 6 | | **বাংলা** 7 | | [Română](./publishing_ro.md) 8 | | [Polski](./publishing_pl.md) 9 | | [简体中文](./publishing_cn.md) 10 | | [正體中文](./publishing_zhtw.md) 11 | | [日本語](./publishing_ja.md) 12 | 13 | ### ব্রুনোকে নতুন প্যাকেজ ম্যানেজারে প্রকাশ করা 14 | 15 | যদিও আমাদের কোড ওপেন সোর্স এবং সবার ব্যবহারের জন্য উপলব্ধ, তবে আমরা নতুন প্যাকেজ ম্যানেজারে প্রকাশনা বিবেচনা করার আগে আমাদের সাথে যোগাযোগ করার জন্য অনুরোধ করি। ব্রুনোর স্রষ্টা হিসাবে, আমি এই প্রকল্পের জন্য `Bruno` ট্রেডমার্ক ধারণ করি এবং এর বিতরণ পরিচালনা করতে চাই। যদি আপনি একটি নতুন প্যাকেজ ম্যানেজারে ব্রুনো দেখতে চান, দয়া করে একটি GitHub ইস্যু তুলুন। 16 | 17 | যদিও আমাদের বেশিরভাগ বৈশিষ্ট্য বিনামূল্যে এবং ওপেন সোর্স (যা REST এবং GraphQL API গুলিকে কভার করে), আমরা ওপেন-সোর্স নীতি এবং স্থায়িত্বের মধ্যে একটি সুসঙ্গত ভারসাম্য বজায় রাখার জন্য চেষ্টা করি - https://github.com/usebruno/bruno/discussions/269 18 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/RequestPane/Vars/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import get from 'lodash/get'; 3 | import VarsTable from './VarsTable'; 4 | import StyledWrapper from './StyledWrapper'; 5 | 6 | const Vars = ({ item, collection }) => { 7 | const requestVars = item.draft ? get(item, 'draft.request.vars.req') : get(item, 'request.vars.req'); 8 | const responseVars = item.draft ? get(item, 'draft.request.vars.res') : get(item, 'request.vars.res'); 9 | 10 | return ( 11 | 12 |
13 |
Pre Request
14 | 15 |
16 |
17 |
Post Response
18 | 19 |
20 |
21 | ); 22 | }; 23 | 24 | export default Vars; 25 | -------------------------------------------------------------------------------- /docs/publishing/publishing_pl.md: -------------------------------------------------------------------------------- 1 | [English](../../publishing.md) 2 | | [Türkçe](./publishing_tr.md) 3 | | [Deutsch](./publishing_de.md) 4 | | [Français](./publishing_fr.md) 5 | | [Português (BR)](./publishing_pt_br.md) 6 | | [বাংলা](./publishing_bn.md) 7 | | [Română](./publishing_ro.md) 8 | | **Polski** 9 | | [简体中文](./publishing_cn.md) 10 | | [正體中文](./publishing_zhtw.md) 11 | | [日本語](./publishing_ja.md) 12 | 13 | ### Publikowanie Bruno w nowym menedżerze pakietów 14 | 15 | Chociaż nasz kod jest otwartoźródłowy i dostępny dla każdego do użytku, uprzejmie prosimy o kontakt z nami przed rozważeniem publikacji w nowych menedżerach pakietów. Jako twórca Bruno, posiadam znak towarowy `Bruno` dla tego projektu i chciałbym zarządzać jego dystrybucją. Jeśli chcesz zobaczyć Bruno w nowym menedżerze pakietów, proszę zgłoś problem na GitHubie. 16 | 17 | Chociaż większość naszych funkcji jest darmowa i otwartoźródłowa (co obejmuje REST i GraphQL Apis), 18 | staramy się osiągnąć harmonijny balans między zasadami open-source a zrównoważonym rozwojem - https://github.com/usebruno/bruno/discussions/269 19 | -------------------------------------------------------------------------------- /packages/bruno-app/src/utils/idb/index.js: -------------------------------------------------------------------------------- 1 | export const saveCollectionToIdb = (connection, collection) => { 2 | return new Promise((resolve, reject) => { 3 | connection 4 | .then((db) => { 5 | let tx = db.transaction(`collection`, 'readwrite'); 6 | let collectionStore = tx.objectStore('collection'); 7 | 8 | collectionStore.put(collection); 9 | 10 | resolve(collection); 11 | }) 12 | .catch((err) => reject(err)); 13 | }); 14 | }; 15 | 16 | export const getCollectionsFromIdb = (connection) => { 17 | return new Promise((resolve, reject) => { 18 | connection 19 | .then((db) => { 20 | let tx = db.transaction('collection'); 21 | let collectionStore = tx.objectStore('collection'); 22 | return collectionStore.getAll(); 23 | }) 24 | .then((collections) => { 25 | if (!Array.isArray(collections)) { 26 | return new Error('IDB Corrupted'); 27 | } 28 | 29 | return resolve(collections); 30 | }) 31 | .catch((err) => reject(err)); 32 | }); 33 | }; 34 | -------------------------------------------------------------------------------- /packages/bruno-electron/src/utils/filesystem.test.js: -------------------------------------------------------------------------------- 1 | const { sanitizeDirectoryName } = require('./filesystem.js'); 2 | 3 | describe('sanitizeDirectoryName', () => { 4 | it('should replace invalid characters with hyphens', () => { 5 | const input = '<>:"/\\|?*\x00-\x1F'; 6 | const expectedOutput = '---'; 7 | expect(sanitizeDirectoryName(input)).toEqual(expectedOutput); 8 | }); 9 | 10 | it('should not modify valid directory names', () => { 11 | const input = 'my-directory'; 12 | expect(sanitizeDirectoryName(input)).toEqual(input); 13 | }); 14 | 15 | it('should replace multiple invalid characters with a single hyphen', () => { 16 | const input = 'my<>invalid?directory'; 17 | const expectedOutput = 'my-invalid-directory'; 18 | expect(sanitizeDirectoryName(input)).toEqual(expectedOutput); 19 | }); 20 | 21 | it('should handle names with slashes', () => { 22 | const input = 'my/invalid/directory'; 23 | const expectedOutput = 'my-invalid-directory'; 24 | expect(sanitizeDirectoryName(input)).toEqual(expectedOutput); 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /packages/bruno-graphql-docs/src/components/DocExplorer/DefaultValue.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2021 GraphQL Contributors. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import React from 'react'; 9 | import { astFromValue, print, ValueNode } from 'graphql'; 10 | import { FieldType } from './types'; 11 | 12 | const printDefault = (ast?: ValueNode | null): string => { 13 | if (!ast) { 14 | return ''; 15 | } 16 | return print(ast); 17 | }; 18 | 19 | type DefaultValueProps = { 20 | field: FieldType; 21 | }; 22 | 23 | export default function DefaultValue({ field }: DefaultValueProps) { 24 | // field.defaultValue could be null or false, so be careful here! 25 | if ('defaultValue' in field && field.defaultValue !== undefined) { 26 | return ( 27 | 28 | {' = '} 29 | {printDefault(astFromValue(field.defaultValue, field.type))} 30 | 31 | ); 32 | } 33 | 34 | return null; 35 | } 36 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/ResponsePane/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const StyledWrapper = styled.div` 4 | div.tabs { 5 | div.tab { 6 | padding: 6px 0px; 7 | border: none; 8 | border-bottom: solid 2px transparent; 9 | margin-right: 1.25rem; 10 | color: var(--color-tab-inactive); 11 | cursor: pointer; 12 | 13 | &:focus, 14 | &:active, 15 | &:focus-within, 16 | &:focus-visible, 17 | &:target { 18 | outline: none !important; 19 | box-shadow: none !important; 20 | } 21 | 22 | &.active { 23 | color: ${(props) => props.theme.tabs.active.color} !important; 24 | border-bottom: solid 2px ${(props) => props.theme.tabs.active.border} !important; 25 | } 26 | } 27 | } 28 | 29 | .some-tests-failed { 30 | color: ${(props) => props.theme.colors.text.danger} !important; 31 | } 32 | 33 | .all-tests-passed { 34 | color: ${(props) => props.theme.colors.text.green} !important; 35 | } 36 | `; 37 | 38 | export default StyledWrapper; 39 | -------------------------------------------------------------------------------- /packages/bruno-electron/tests/network/index.spec.js: -------------------------------------------------------------------------------- 1 | // damn jest throws an error when no tests are found in a file 2 | // --passWithNoTests doesn't work 3 | 4 | describe('dummy test', () => { 5 | it('should pass', () => { 6 | expect(true).toBe(true); 7 | }); 8 | }); 9 | 10 | // todo: fix this failing test 11 | // const { configureRequest } = require('../../src/ipc/network/index'); 12 | 13 | // describe('index: configureRequest', () => { 14 | // it("Should add 'http://' to the URL if no protocol is specified", async () => { 15 | // const request = { method: 'GET', url: 'test-domain', body: {} }; 16 | // await configureRequest(null, request, null, null, null, null); 17 | // expect(request.url).toEqual('http://test-domain'); 18 | // }); 19 | 20 | // it("Should NOT add 'http://' to the URL if a protocol is specified", async () => { 21 | // const request = { method: 'GET', url: 'ftp://test-domain', body: {} }; 22 | // await configureRequest(null, request, null, null, null, null); 23 | // expect(request.url).toEqual('ftp://test-domain'); 24 | // }); 25 | // }); 26 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/RequestMethod/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import classnames from 'classnames'; 3 | import StyledWrapper from './StyledWrapper'; 4 | 5 | const RequestMethod = ({ item }) => { 6 | if (!['http-request', 'graphql-request'].includes(item.type)) { 7 | return null; 8 | } 9 | 10 | const getClassname = (method = '') => { 11 | method = method.toLocaleLowerCase(); 12 | return classnames('mr-1', { 13 | 'method-get': method === 'get', 14 | 'method-post': method === 'post', 15 | 'method-put': method === 'put', 16 | 'method-delete': method === 'delete', 17 | 'method-patch': method === 'patch', 18 | 'method-head': method === 'head', 19 | 'method-options': method == 'options' 20 | }); 21 | }; 22 | 23 | return ( 24 | 25 |
26 | {item.request.method} 27 |
28 |
29 | ); 30 | }; 31 | 32 | export default RequestMethod; 33 | -------------------------------------------------------------------------------- /packages/bruno-app/src/providers/ReduxStore/index.js: -------------------------------------------------------------------------------- 1 | import getConfig from 'next/config'; 2 | import { configureStore } from '@reduxjs/toolkit'; 3 | import tasksMiddleware from './middlewares/tasks/middleware'; 4 | import debugMiddleware from './middlewares/debug/middleware'; 5 | import appReducer from './slices/app'; 6 | import collectionsReducer from './slices/collections'; 7 | import tabsReducer from './slices/tabs'; 8 | import notificationsReducer from './slices/notifications'; 9 | 10 | const { publicRuntimeConfig } = getConfig(); 11 | const isDevEnv = () => { 12 | return publicRuntimeConfig.ENV === 'dev'; 13 | }; 14 | 15 | let middleware = [tasksMiddleware.middleware]; 16 | if (isDevEnv()) { 17 | middleware = [...middleware, debugMiddleware.middleware]; 18 | } 19 | 20 | export const store = configureStore({ 21 | reducer: { 22 | app: appReducer, 23 | collections: collectionsReducer, 24 | tabs: tabsReducer, 25 | notifications: notificationsReducer 26 | }, 27 | middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(middleware) 28 | }); 29 | 30 | export default store; 31 | -------------------------------------------------------------------------------- /packages/bruno-lang/v2/src/jsonToEnv.js: -------------------------------------------------------------------------------- 1 | const _ = require('lodash'); 2 | 3 | const envToJson = (json) => { 4 | const variables = _.get(json, 'variables', []); 5 | const vars = variables 6 | .filter((variable) => !variable.secret) 7 | .map((variable) => { 8 | const { name, value, enabled } = variable; 9 | const prefix = enabled ? '' : '~'; 10 | return ` ${prefix}${name}: ${value}`; 11 | }); 12 | 13 | const secretVars = variables 14 | .filter((variable) => variable.secret) 15 | .map((variable) => { 16 | const { name, enabled } = variable; 17 | const prefix = enabled ? '' : '~'; 18 | return ` ${prefix}${name}`; 19 | }); 20 | 21 | if (!variables || !variables.length) { 22 | return `vars { 23 | } 24 | `; 25 | } 26 | 27 | let output = ''; 28 | if (vars.length) { 29 | output += `vars { 30 | ${vars.join('\n')} 31 | } 32 | `; 33 | } 34 | 35 | if (secretVars.length) { 36 | output += `vars:secret [ 37 | ${secretVars.join(',\n')} 38 | ] 39 | `; 40 | } 41 | 42 | return output; 43 | }; 44 | 45 | module.exports = envToJson; 46 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/RunnerResults/ResponsePane/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const StyledWrapper = styled.div` 4 | div.tabs { 5 | div.tab { 6 | padding: 6px 0px; 7 | border: none; 8 | border-bottom: solid 2px transparent; 9 | margin-right: 1.25rem; 10 | color: var(--color-tab-inactive); 11 | cursor: pointer; 12 | 13 | &:focus, 14 | &:active, 15 | &:focus-within, 16 | &:focus-visible, 17 | &:target { 18 | outline: none !important; 19 | box-shadow: none !important; 20 | } 21 | 22 | &.active { 23 | color: ${(props) => props.theme.tabs.active.color} !important; 24 | border-bottom: solid 2px ${(props) => props.theme.tabs.active.border} !important; 25 | } 26 | } 27 | } 28 | 29 | .some-tests-failed { 30 | color: ${(props) => props.theme.colors.text.danger} !important; 31 | } 32 | 33 | .all-tests-passed { 34 | color: ${(props) => props.theme.colors.text.green} !important; 35 | } 36 | `; 37 | 38 | export default StyledWrapper; 39 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/RequestMethod/StyledWrapper.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const Wrapper = styled.div` 4 | font-size: 0.6875rem; 5 | display: flex; 6 | align-self: stretch; 7 | align-items: center; 8 | min-width: 34px; 9 | flex-shrink: 0; 10 | 11 | span { 12 | position: relative; 13 | top: 1px; 14 | } 15 | 16 | .method-get { 17 | color: ${(props) => props.theme.request.methods.get}; 18 | } 19 | .method-post { 20 | color: ${(props) => props.theme.request.methods.post}; 21 | } 22 | .method-put { 23 | color: ${(props) => props.theme.request.methods.put}; 24 | } 25 | .method-delete { 26 | color: ${(props) => props.theme.request.methods.delete}; 27 | } 28 | .method-patch { 29 | color: ${(props) => props.theme.request.methods.patch}; 30 | } 31 | .method-options { 32 | color: ${(props) => props.theme.request.methods.options}; 33 | } 34 | .method-head { 35 | color: ${(props) => props.theme.request.methods.head}; 36 | } 37 | `; 38 | 39 | export default Wrapper; 40 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/Toast/index.js: -------------------------------------------------------------------------------- 1 | import React, { useEffect } from 'react'; 2 | import StyledWrapper from './StyledWrapper'; 3 | import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; 4 | import { faTimes } from '@fortawesome/free-solid-svg-icons'; 5 | 6 | const ToastContent = ({ type, text, handleClose }) => ( 7 |
8 |
{text}
9 |
10 | 11 |
12 |
13 | ); 14 | 15 | const Toast = ({ text, type, duration, handleClose }) => { 16 | let lifetime = duration ? duration : 3000; 17 | 18 | useEffect(() => { 19 | if (text) { 20 | setTimeout(handleClose, lifetime); 21 | } 22 | }, [text]); 23 | 24 | return ( 25 | 26 |
27 | 28 |
29 |
30 | ); 31 | }; 32 | 33 | export default Toast; 34 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/MarkDown/index.jsx: -------------------------------------------------------------------------------- 1 | import MarkdownIt from 'markdown-it'; 2 | import StyledWrapper from './StyledWrapper'; 3 | import React from 'react'; 4 | 5 | const md = new MarkdownIt(); 6 | 7 | const Markdown = ({ onDoubleClick, content }) => { 8 | const handleOnClick = (event) => { 9 | const target = event.target; 10 | if (target.tagName === 'A') { 11 | event.preventDefault(); 12 | const href = target.getAttribute('href'); 13 | if (href) { 14 | window.open(href, '_blank'); 15 | return; 16 | } 17 | } 18 | }; 19 | 20 | const handleOnDoubleClick = (event) => { 21 | if (event.detail === 2) { 22 | onDoubleClick(); 23 | } 24 | }; 25 | 26 | const htmlFromMarkdown = md.render(content || ''); 27 | 28 | return ( 29 | 30 |
36 | 37 | ); 38 | }; 39 | 40 | export default Markdown; 41 | -------------------------------------------------------------------------------- /packages/bruno-graphql-docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usebruno/graphql-docs", 3 | "version": "0.1.0", 4 | "license" : "MIT", 5 | "main": "dist/cjs/index.js", 6 | "module": "dist/esm/index.js", 7 | "files": [ 8 | "dist", 9 | "package.json" 10 | ], 11 | "scripts": { 12 | "build": "rollup -c" 13 | }, 14 | "devDependencies": { 15 | "@rollup/plugin-commonjs": "^23.0.2", 16 | "@rollup/plugin-node-resolve": "^15.0.1", 17 | "@rollup/plugin-typescript": "^9.0.2", 18 | "@types/markdown-it": "^12.2.3", 19 | "@types/react": "^18.0.25", 20 | "graphql": "^16.6.0", 21 | "markdown-it": "^13.0.1", 22 | "postcss": "^8.4.18", 23 | "react": "18.2.0", 24 | "react-dom": "18.2.0", 25 | "rollup": "3.2.5", 26 | "rollup-plugin-dts": "^5.0.0", 27 | "rollup-plugin-peer-deps-external": "^2.2.4", 28 | "rollup-plugin-postcss": "^4.0.2", 29 | "rollup-plugin-terser": "^7.0.2", 30 | "typescript": "^4.8.4" 31 | }, 32 | "peerDependencies": { 33 | "graphql": "^16.6.0", 34 | "markdown-it": "^13.0.1" 35 | }, 36 | "overrides": { 37 | "rollup": "3.2.5" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /docs/publishing/publishing_de.md: -------------------------------------------------------------------------------- 1 | [English](../../publishing.md) 2 | | [Türkçe](./publishing_tr.md) 3 | | **Deutsch** 4 | | [Français](./publishing_fr.md) 5 | | [Português (BR)](./publishing_pt_br.md) 6 | | [বাংলা](./publishing_bn.md) 7 | | [Română](./publishing_ro.md) 8 | | [Polski](./publishing_pl.md) 9 | | [简体中文](./publishing_cn.md) 10 | | [正體中文](./publishing_zhtw.md) 11 | | [日本語](./publishing_ja.md) 12 | 13 | ### Veröffentlichung von Bruno über neue Paket-Manager 14 | 15 | Obwohl Bruno Open Source und für alle frei zugänglich ist, bitten wir dich Kontakt zu uns aufzunehmen, bevor du Bruno über weitere Paket-Manager veröffentlichst. 16 | Als Schöpfer von Bruno liegen alle Marktrechte von `Bruno` bei mir und ich möchte die volle Kontrolle über alle Verbreitungswege behalten. 17 | Falls Bruno über einen weiteren Paketmanager veröffentlicht werden soll, eröffne bitte ein GitHub-Issue. 18 | 19 | Während ein Großteil der Features kostenlos und Open Source ist (beinhaltet REST und GraphQL APIs), 20 | bemühen wir uns um ein harmonisches Gleichgewicht zwischen Open-Source-Prinzipien und Nachhaltigkeit - https://github.com/usebruno/bruno/discussions/269 21 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/ResponsePane/ResponseSave/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import StyledWrapper from './StyledWrapper'; 3 | import toast from 'react-hot-toast'; 4 | import get from 'lodash/get'; 5 | import { IconDownload } from '@tabler/icons'; 6 | 7 | const ResponseSave = ({ item }) => { 8 | const { ipcRenderer } = window; 9 | const response = item.response || {}; 10 | 11 | const saveResponseToFile = () => { 12 | return new Promise((resolve, reject) => { 13 | ipcRenderer 14 | .invoke('renderer:save-response-to-file', response, item.requestSent.url) 15 | .then(resolve) 16 | .catch((err) => { 17 | toast.error(get(err, 'error.message') || 'Something went wrong!'); 18 | reject(err); 19 | }); 20 | }); 21 | }; 22 | 23 | return ( 24 | 25 | 28 | 29 | ); 30 | }; 31 | export default ResponseSave; 32 | -------------------------------------------------------------------------------- /packages/bruno-app/public/theme/dark.js: -------------------------------------------------------------------------------- 1 | const darkTheme = { 2 | brand: '#546de5', 3 | text: 'rgb(52 52 52)', 4 | 'primary-text': '#ffffff', 5 | 'primary-theme': '#1e1e1e', 6 | 'secondary-text': '#929292', 7 | 'sidebar-collection-item-active-indent-border': '#d0d0d0', 8 | 'sidebar-collection-item-active-background': '#e1e1e1', 9 | 'sidebar-background': '#252526', 10 | 'sidebar-bottom-bg': '#68217a', 11 | 'request-dragbar-background': '#efefef', 12 | 'request-dragbar-background-active': 'rgb(200, 200, 200)', 13 | 'tab-inactive': 'rgb(155 155 155)', 14 | 'tab-active-border': '#546de5', 15 | 'layout-border': '#dedede', 16 | 'codemirror-border': '#efefef', 17 | 'codemirror-background': 'rgb(243, 243, 243)', 18 | 'text-link': '#1663bb', 19 | 'text-danger': 'rgb(185, 28, 28)', 20 | 'background-danger': '#dc3545', 21 | 'method-get': 'rgb(5, 150, 105)', 22 | 'method-post': '#8e44ad', 23 | 'method-delete': 'rgb(185, 28, 28)', 24 | 'method-patch': 'rgb(52 52 52)', 25 | 'method-options': 'rgb(52 52 52)', 26 | 'method-head': 'rgb(52 52 52)', 27 | 'table-stripe': '#f3f3f3' 28 | }; 29 | 30 | export default darkTheme; 31 | -------------------------------------------------------------------------------- /packages/bruno-electron/notarize.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config({ path: process.env.DOTENV_PATH }); 2 | const fs = require('fs'); 3 | const path = require('path'); 4 | const electron_notarize = require('electron-notarize'); 5 | 6 | const notarize = async function (params) { 7 | if (process.platform !== 'darwin') { 8 | return; 9 | } 10 | 11 | let appId = 'com.usebruno.app'; 12 | 13 | let appPath = path.join(params.appOutDir, `${params.packager.appInfo.productFilename}.app`); 14 | if (!fs.existsSync(appPath)) { 15 | console.error(`Cannot find application at: ${appPath}`); 16 | return; 17 | } 18 | 19 | console.log(`Notarizing ${appId} found at ${appPath} using Apple ID ${process.env.APPLE_ID}`); 20 | 21 | try { 22 | await electron_notarize.notarize({ 23 | appBundleId: appId, 24 | appPath: appPath, 25 | appleId: process.env.APPLE_ID, 26 | appleIdPassword: process.env.APPLE_ID_PASSWORD, 27 | ascProvider: 'W7LPPWA48L' 28 | }); 29 | } catch (error) { 30 | console.error(error); 31 | } 32 | 33 | console.log(`Done notarizing ${appId}`); 34 | }; 35 | 36 | module.exports = notarize; -------------------------------------------------------------------------------- /docs/publishing/publishing_fr.md: -------------------------------------------------------------------------------- 1 | [English](../../publishing.md) 2 | | [Türkçe](./publishing_tr.md) 3 | | [Deutsch](./publishing_de.md) 4 | | **Français** 5 | | [Português (BR)](./publishing_pt_br.md) 6 | | [বাংলা](./publishing_bn.md) 7 | | [Română](./publishing_ro.md) 8 | | [Polski](./publishing_pl.md) 9 | | [简体中文](./publishing_cn.md) 10 | | [正體中文](./publishing_zhtw.md) 11 | | [日本語](./publishing_ja.md) 12 | 13 | ### Publier Bruno dans un nouveau gestionnaire de paquets 14 | 15 | Bien que notre code soit open source et disponible pour tout le monde, nous vous remercions de nous contacter avant de considérer sa publication sur un nouveau gestionnaire de paquets. En tant que créateur de Bruno, je détiens la marque `Bruno` pour ce projet et j'aimerais gérer moi-même sa distribution. Si vous voyez Bruno sur un nouveau gestionnaire de paquets, merci de créer une _issue_ GitHub. 16 | 17 | Bien que la majorité de nos fonctionnalités soient gratuites et open source (ce qui couvre les APIs REST et GraphQL), nous nous efforçons de trouver un équilibre harmonieux entre les principes de l'open source et la pérennité - https://github.com/usebruno/bruno/discussions/269 18 | -------------------------------------------------------------------------------- /packages/bruno-app/src/components/Sidebar/Collections/SelectCollection/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Modal from 'components/Modal/index'; 3 | import { IconFiles } from '@tabler/icons'; 4 | import { useSelector } from 'react-redux'; 5 | import StyledWrapper from './StyledWrapper'; 6 | 7 | const SelectCollection = ({ onClose, onSelect, title }) => { 8 | const { collections } = useSelector((state) => state.collections); 9 | 10 | return ( 11 | 12 | 13 |
    14 | {collections && collections.length ? ( 15 | collections.map((c) => ( 16 |
    onSelect(c.uid)}> 17 | {c.name} 18 |
    19 | )) 20 | ) : ( 21 |
    No collections found
    22 | )} 23 |
24 |
25 |
26 | ); 27 | }; 28 | 29 | export default SelectCollection; 30 | -------------------------------------------------------------------------------- /packages/bruno-app/public/theme/light.js: -------------------------------------------------------------------------------- 1 | const lightTheme = { 2 | brand: '#546de5', 3 | text: 'rgb(52 52 52)', 4 | 'primary-text': 'rgb(52 52 52)', 5 | 'primary-theme': '#ffffff', 6 | 'secondary-text': '#929292', 7 | 'sidebar-collection-item-active-indent-border': '#d0d0d0', 8 | 'sidebar-collection-item-active-background': '#e1e1e1', 9 | 'sidebar-background': '#f3f3f3', 10 | 'sidebar-bottom-bg': '#f3f3f3', 11 | 'request-dragbar-background': '#efefef', 12 | 'request-dragbar-background-active': 'rgb(200, 200, 200)', 13 | 'tab-inactive': 'rgb(155 155 155)', 14 | 'tab-active-border': '#546de5', 15 | 'layout-border': '#dedede', 16 | 'codemirror-border': '#efefef', 17 | 'codemirror-background': 'rgb(243, 243, 243)', 18 | 'text-link': '#1663bb', 19 | 'text-danger': 'rgb(185, 28, 28)', 20 | 'background-danger': '#dc3545', 21 | 'method-get': 'rgb(5, 150, 105)', 22 | 'method-post': '#8e44ad', 23 | 'method-delete': 'rgb(185, 28, 28)', 24 | 'method-patch': 'rgb(52 52 52)', 25 | 'method-options': 'rgb(52 52 52)', 26 | 'method-head': 'rgb(52 52 52)', 27 | 'table-stripe': '#f3f3f3' 28 | }; 29 | 30 | export default lightTheme; 31 | -------------------------------------------------------------------------------- /docs/publishing/publishing_pt_br.md: -------------------------------------------------------------------------------- 1 | [English](../../publishing.md) 2 | | [Türkçe](./publishing_tr.md) 3 | | [Deutsch](./publishing_de.md) 4 | | [Français](./publishing_fr.md) 5 | | **Português (BR)** 6 | | [বাংলা](./publishing_bn.md) 7 | | [Română](./publishing_ro.md) 8 | | [Polski](./publishing_pl.md) 9 | | [简体中文](./publishing_cn.md) 10 | | [正體中文](./publishing_zhtw.md) 11 | | [日本語](./publishing_ja.md) 12 | 13 | ### Publicando Bruno em um novo gerenciador de pacotes 14 | 15 | Embora nosso código seja de código aberto e esteja disponível para todos usarem, pedimos gentilmente que entre em contato conosco antes de considerar a publicação em novos gerenciadores de pacotes. Como o criador da ferramenta, mantenho a marca registrada `Bruno` para este projeto e gostaria de gerenciar sua distribuição. Se deseja ver o Bruno em um novo gerenciador de pacotes, por favor, solicite através de uma issue no GitHub. 16 | 17 | Embora a maioria de nossas funcionalidades seja gratuita e de código aberto (o que abrange API's REST e GraphQL), buscamos alcançar um equilíbrio harmonioso entre os princípios de código aberto e sustentabilidade. - https://github.com/usebruno/bruno/discussions/269 18 | -------------------------------------------------------------------------------- /docs/publishing/publishing_ro.md: -------------------------------------------------------------------------------- 1 | [English](../../publishing.md) 2 | | [Türkçe](./publishing_tr.md) 3 | | [Deutsch](./publishing_de.md) 4 | | [Français](./publishing_fr.md) 5 | | [Português (BR)](./publishing_pt_br.md) 6 | | [বাংলা](./publishing_bn.md) 7 | | **Română** 8 | | [Polski](./publishing_pl.md) 9 | | [简体中文](./publishing_cn.md) 10 | | [正體中文](./publishing_zhtw.md) 11 | | [日本語](./publishing_ja.md) 12 | 13 | ### Publicarea lui Bruno la un gestionar de pachete nou 14 | 15 | Deși codul nostru este cu sursă deschisă și disponibil pentru utilizare pentru toată lumea, vă rugăm să ne contactați înainte de a considera publicarea pe gestionari de pachete noi. În calitate de creator al lui Bruno, dețin marca comercială `Bruno` pentru acest proiect și aș dori să gestionez distribuția acestuia. Dacă doriți să-l vedeți pe Bruno pe un gestionar de pachete nou, vă rugăm să creați un issue pe GitHub. 16 | 17 | În timp ce majoritatea funcțiilor noastre sunt gratuite și cu sursă deschisă (ceea ce acoperă API-uri REST și GraphQL), 18 | ne străduim să găsim un echilibru armonios între principiile de sursă deschisă și sustenabilitate - https://github.com/usebruno/bruno/discussions/269 19 | -------------------------------------------------------------------------------- /packages/bruno-cli/src/constants.js: -------------------------------------------------------------------------------- 1 | const { version } = require('../package.json'); 2 | 3 | const CLI_EPILOGUE = `Documentation: https://docs.usebruno.com (v${version})`; 4 | const CLI_VERSION = version; 5 | 6 | // Exit codes 7 | const EXIT_STATUS = { 8 | // One or more assertions, tests, or requests failed 9 | ERROR_FAILED_COLLECTION: 1, 10 | // The specified output dir does not exist 11 | ERROR_MISSING_OUTPUT_DIR: 2, 12 | // request chain caused an endless loop 13 | ERROR_INFINTE_LOOP: 3, 14 | // bru was called outside of a collection root 15 | ERROR_NOT_IN_COLLECTION: 4, 16 | // The specified file was not found 17 | ERROR_FILE_NOT_FOUND: 5, 18 | // The specified environment was not found 19 | ERROR_ENV_NOT_FOUND: 6, 20 | // Environment override not presented as string or object 21 | ERROR_MALFORMED_ENV_OVERRIDE: 7, 22 | // Environment overrides format incorrect 23 | ERROR_INCORRECT_ENV_OVERRIDE: 8, 24 | // Invalid output format requested 25 | ERROR_INCORRECT_OUTPUT_FORMAT: 9, 26 | // Everything else 27 | ERROR_GENERIC: 255, 28 | }; 29 | 30 | module.exports = { 31 | CLI_EPILOGUE, 32 | CLI_VERSION, 33 | EXIT_STATUS 34 | }; 35 | -------------------------------------------------------------------------------- /packages/bruno-lang/example/request.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "http-request", 3 | "name": "Send Bulk SMS", 4 | "request": { 5 | "method": "GET", 6 | "url": "https://api.textlocal.in/bulk_json?apiKey=secret=&numbers=998877665&message=hello&sender=600010", 7 | "params": [ 8 | { 9 | "name": "apiKey", 10 | "value": "secret", 11 | "enabled": true 12 | }, 13 | { 14 | "name": "numbers", 15 | "value": "998877665", 16 | "enabled": true 17 | }, 18 | { 19 | "name": "message", 20 | "value": "hello", 21 | "enabled": true 22 | }, 23 | { 24 | "name": "sender", 25 | "value": "600010", 26 | "enabled": true 27 | } 28 | ], 29 | "headers": [], 30 | "body": { 31 | "mode": "json", 32 | "json": "{\n apikey: \"secret\",\n numbers: \"+919988776655\",\n data: {\n sender: \"TXTLCL\",\n messages: [{\n numbers: \"+919988776655\",\n message: \"Hello World\"\n }]\n }\n}", 33 | "text": null, 34 | "xml": null, 35 | "multipartForm": null, 36 | "formUrlEncoded": null 37 | } 38 | } 39 | } --------------------------------------------------------------------------------