forked from extern/bruno
Merge branch 'main' into feature/get-supercharged
This commit is contained in:
commit
8300830a95
2
.github/workflows/unit-tests.yml
vendored
2
.github/workflows/unit-tests.yml
vendored
@ -21,3 +21,5 @@ jobs:
|
|||||||
run: npm run test --workspace=packages/bruno-schema
|
run: npm run test --workspace=packages/bruno-schema
|
||||||
- name: Test Package bruno-app
|
- name: Test Package bruno-app
|
||||||
run: npm run test --workspace=packages/bruno-app
|
run: npm run test --workspace=packages/bruno-app
|
||||||
|
- name: Test Package bruno-js
|
||||||
|
run: npm run test --workspace=packages/bruno-js
|
||||||
|
@ -23,25 +23,7 @@ You would need [Node v14.x or the latest LTS version](https://nodejs.org/en/) an
|
|||||||
|
|
||||||
### Lets start coding
|
### Lets start coding
|
||||||
|
|
||||||
```bash
|
Please reference [development.md](docs/development.md) for instructions on running the local development environment.
|
||||||
# clone and cd into bruno
|
|
||||||
# use Node 14.x, Npm 8.x
|
|
||||||
|
|
||||||
# Install deps (note that we use npm workspaces)
|
|
||||||
npm i
|
|
||||||
|
|
||||||
# run next app
|
|
||||||
npm run dev:web
|
|
||||||
|
|
||||||
# run electron app
|
|
||||||
# neededonly if you want to test changes related to electron app
|
|
||||||
# please note that both web and electron use the same code
|
|
||||||
# if it works in web, then it should also work in electron
|
|
||||||
npm run dev:electron
|
|
||||||
|
|
||||||
# open in browser
|
|
||||||
open http://localhost:3000
|
|
||||||
```
|
|
||||||
|
|
||||||
### Raising Pull Request
|
### Raising Pull Request
|
||||||
|
|
||||||
|
@ -1,40 +1,40 @@
|
|||||||
## development
|
## Development
|
||||||
|
|
||||||
Bruno is deing developed as a desktop app. You need to load the app by running the nextjs app in one terminal and then run the electron app in another terminal.
|
Bruno is deing developed as a desktop app. You need to load the app by running the nextjs app in one terminal and then run the electron app in another terminal.
|
||||||
|
|
||||||
### Dependencies
|
### Dependencies
|
||||||
* NodeJS v18
|
* NodeJS v18
|
||||||
|
|
||||||
###
|
### Local Development
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# use nodejs 18 version
|
# use nodejs 18 version
|
||||||
nvm use
|
nvm use
|
||||||
|
|
||||||
# install deps
|
# install deps
|
||||||
npm i
|
npm i --legacy-peer-deps
|
||||||
|
|
||||||
# run next app
|
# build graphql docs
|
||||||
npm run dev --workspace=packages/bruno-app
|
npm run build:graphql-docs
|
||||||
|
|
||||||
# run electron app
|
# run next app (terminal 1)
|
||||||
npm run dev --workspace=packages/bruno-electron
|
npm run dev:web
|
||||||
|
|
||||||
# build next app
|
# run electron app (terminal 2)
|
||||||
npm run build --workspace=packages/bruno-app
|
npm run dev:electron
|
||||||
```
|
```
|
||||||
|
|
||||||
### fix
|
### Troubleshooting
|
||||||
|
|
||||||
You might encounter a `Unsupported platform` error when you run `npm install`. To fix this, you will need to delete `node_modules` and `package-lock.json` and run `npm install`. This should install all the necessary packages needed to run the app.
|
You might encounter a `Unsupported platform` error when you run `npm install`. To fix this, you will need to delete `node_modules` and `package-lock.json` and run `npm install`. This should install all the necessary packages needed to run the app.
|
||||||
|
|
||||||
### testing
|
### Testing
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# bruno-schema
|
# bruno-schema
|
||||||
npm test --workspace=packages/bruno-schema
|
npm test --workspace=packages/bruno-schema
|
||||||
|
|
||||||
# bruno-lang
|
# bruno-lang
|
||||||
npm test --workspace=packages/bruno-schema
|
npm test --workspace=packages/bruno-lang
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import React, { useEffect, useState, forwardRef, useRef } from 'react';
|
import React, { useEffect, useState, forwardRef, useRef } from 'react';
|
||||||
import { findEnvironmentInCollection } from 'utils/collections';
|
import { findEnvironmentInCollection } from 'utils/collections';
|
||||||
|
import usePrevious from 'hooks/usePrevious';
|
||||||
import EnvironmentDetails from './EnvironmentDetails';
|
import EnvironmentDetails from './EnvironmentDetails';
|
||||||
import CreateEnvironment from '../CreateEnvironment/index';
|
import CreateEnvironment from '../CreateEnvironment/index';
|
||||||
import StyledWrapper from './StyledWrapper';
|
import StyledWrapper from './StyledWrapper';
|
||||||
@ -9,14 +10,36 @@ const EnvironmentList = ({ collection }) => {
|
|||||||
const [selectedEnvironment, setSelectedEnvironment] = useState(null);
|
const [selectedEnvironment, setSelectedEnvironment] = useState(null);
|
||||||
const [openCreateModal, setOpenCreateModal] = useState(false);
|
const [openCreateModal, setOpenCreateModal] = useState(false);
|
||||||
|
|
||||||
|
const envUids = environments ? environments.map((env) => env.uid) : [];
|
||||||
|
const prevEnvUids = usePrevious(envUids);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if(selectedEnvironment) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const environment = findEnvironmentInCollection(collection, collection.activeEnvironmentUid);
|
const environment = findEnvironmentInCollection(collection, collection.activeEnvironmentUid);
|
||||||
if(environment) {
|
if(environment) {
|
||||||
setSelectedEnvironment(environment);
|
setSelectedEnvironment(environment);
|
||||||
} else {
|
} else {
|
||||||
setSelectedEnvironment(environments && environments.length ? environments[0] : null);
|
setSelectedEnvironment(environments && environments.length ? environments[0] : null);
|
||||||
}
|
}
|
||||||
}, [collection, environments]);
|
}, [collection, environments, selectedEnvironment]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// check env add
|
||||||
|
if (prevEnvUids && prevEnvUids.length && envUids.length > prevEnvUids.length) {
|
||||||
|
const newEnv = environments.find((env) => !prevEnvUids.includes(env.uid));
|
||||||
|
if(newEnv){
|
||||||
|
setSelectedEnvironment(newEnv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check env delete
|
||||||
|
if (prevEnvUids && prevEnvUids.length && envUids.length < prevEnvUids.length) {
|
||||||
|
setSelectedEnvironment(environments && environments.length ? environments[0] : null);
|
||||||
|
}
|
||||||
|
}, [envUids, environments, prevEnvUids]);
|
||||||
|
|
||||||
if (!selectedEnvironment) {
|
if (!selectedEnvironment) {
|
||||||
return null;
|
return null;
|
||||||
@ -31,7 +54,11 @@ const EnvironmentList = ({ collection }) => {
|
|||||||
{environments &&
|
{environments &&
|
||||||
environments.length &&
|
environments.length &&
|
||||||
environments.map((env) => (
|
environments.map((env) => (
|
||||||
<div key={env.uid} className={selectedEnvironment.uid === env.uid ? 'environment-item active' : 'environment-item'} onClick={() => setSelectedEnvironment(env)}>
|
<div
|
||||||
|
key={env.uid}
|
||||||
|
className={selectedEnvironment.uid === env.uid ? 'environment-item active' : 'environment-item'}
|
||||||
|
onClick={() => setSelectedEnvironment(env)}
|
||||||
|
>
|
||||||
<span>{env.name}</span>
|
<span>{env.name}</span>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
@ -25,7 +25,7 @@ const NewFolder = ({ collection, item, onClose }) => {
|
|||||||
if(item && item.uid) {
|
if(item && item.uid) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return !(value.trim().toLowerCase().includes('environments'))
|
return value && !(value.trim().toLowerCase().includes('environments'))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}),
|
}),
|
||||||
|
@ -30,7 +30,7 @@ const NewRequest = ({ collection, item, isEphermal, onClose }) => {
|
|||||||
.test({
|
.test({
|
||||||
name: 'requestName',
|
name: 'requestName',
|
||||||
message: 'The request name "index" is reserved in bruno',
|
message: 'The request name "index" is reserved in bruno',
|
||||||
test: value => !(value.trim().toLowerCase().includes('index')),
|
test: value => value && !(value.trim().toLowerCase().includes('index')),
|
||||||
})
|
})
|
||||||
}),
|
}),
|
||||||
onSubmit: (values) => {
|
onSubmit: (values) => {
|
||||||
|
@ -117,7 +117,7 @@ const Sidebar = () => {
|
|||||||
</GitHubButton>
|
</GitHubButton>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-grow items-center justify-end text-xs mr-2">v0.9.3</div>
|
<div className="flex flex-grow items-center justify-end text-xs mr-2">v0.9.4</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
13
packages/bruno-app/src/hooks/usePrevious/index.js
Normal file
13
packages/bruno-app/src/hooks/usePrevious/index.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { useRef, useEffect } from 'react';
|
||||||
|
|
||||||
|
function usePrevious(value) {
|
||||||
|
const ref = useRef();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
ref.current = value; //assign the value of ref to the argument
|
||||||
|
},[value]); //this code will run when the value of 'value' changes
|
||||||
|
|
||||||
|
return ref.current; //in the end, return the current ref value.
|
||||||
|
}
|
||||||
|
|
||||||
|
export default usePrevious;
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@usebruno/cli",
|
"name": "@usebruno/cli",
|
||||||
"version": "0.2.1",
|
"version": "0.2.3",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
"bin": {
|
"bin": {
|
||||||
"bru": "./bin/bru.js"
|
"bru": "./bin/bru.js"
|
||||||
@ -12,7 +12,7 @@
|
|||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@usebruno/js": "0.1.1",
|
"@usebruno/js": "0.1.1",
|
||||||
"@usebruno/lang": "0.2.0",
|
"@usebruno/lang": "0.2.2",
|
||||||
"axios": "^1.3.2",
|
"axios": "^1.3.2",
|
||||||
"chai": "^4.3.7",
|
"chai": "^4.3.7",
|
||||||
"chalk": "^3.0.0",
|
"chalk": "^3.0.0",
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": "0.9.3",
|
"version": "0.9.4",
|
||||||
"name": "bruno",
|
"name": "bruno",
|
||||||
"description": "Opensource API Client",
|
"description": "Opensource API Client",
|
||||||
"homepage": "https://www.usebruno.com",
|
"homepage": "https://www.usebruno.com",
|
||||||
@ -14,8 +14,8 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@usebruno/js": "0.1.0",
|
"@usebruno/js": "0.1.0",
|
||||||
"@usebruno/lang": "0.1.0",
|
"@usebruno/lang": "0.2.2",
|
||||||
"@usebruno/schema": "0.1.0",
|
"@usebruno/schema": "0.3.1",
|
||||||
"axios": "^0.26.0",
|
"axios": "^0.26.0",
|
||||||
"chai": "^4.3.7",
|
"chai": "^4.3.7",
|
||||||
"chokidar": "^3.5.3",
|
"chokidar": "^3.5.3",
|
||||||
|
@ -18,7 +18,7 @@ const template = [
|
|||||||
submenu: [
|
submenu: [
|
||||||
{ role: 'undo'},
|
{ role: 'undo'},
|
||||||
{ role: 'redo'},
|
{ role: 'redo'},
|
||||||
{ role: 'separator'},
|
{ type: 'separator'},
|
||||||
{ role: 'cut'},
|
{ role: 'cut'},
|
||||||
{ role: 'copy'},
|
{ role: 'copy'},
|
||||||
{ role: 'paste'}
|
{ role: 'paste'}
|
||||||
@ -27,13 +27,12 @@ const template = [
|
|||||||
{
|
{
|
||||||
label: 'View',
|
label: 'View',
|
||||||
submenu: [
|
submenu: [
|
||||||
{ role: 'reload'},
|
|
||||||
{ role: 'toggledevtools'},
|
{ role: 'toggledevtools'},
|
||||||
{ role: 'separator'},
|
{ type: 'separator'},
|
||||||
{ role: 'resetzoom'},
|
{ role: 'resetzoom'},
|
||||||
{ role: 'zoomin'},
|
{ role: 'zoomin'},
|
||||||
{ role: 'zoomout'},
|
{ role: 'zoomout'},
|
||||||
{ role: 'separator'},
|
{ type: 'separator'},
|
||||||
{ role: 'togglefullscreen'}
|
{ role: 'togglefullscreen'}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@usebruno/lang",
|
"name": "@usebruno/lang",
|
||||||
"version": "0.2.0",
|
"version": "0.2.2",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
"files": [
|
"files": [
|
||||||
"src",
|
"src",
|
||||||
|
@ -57,11 +57,12 @@ const grammar = ohm.grammar(`Bru {
|
|||||||
|
|
||||||
meta = "meta" dictionary
|
meta = "meta" dictionary
|
||||||
|
|
||||||
http = get | post | put | delete | options | head | connect | trace
|
http = get | post | put | delete | patch | options | head | connect | trace
|
||||||
get = "get" dictionary
|
get = "get" dictionary
|
||||||
post = "post" dictionary
|
post = "post" dictionary
|
||||||
put = "put" dictionary
|
put = "put" dictionary
|
||||||
delete = "delete" dictionary
|
delete = "delete" dictionary
|
||||||
|
patch = "patch" dictionary
|
||||||
options = "options" dictionary
|
options = "options" dictionary
|
||||||
head = "head" dictionary
|
head = "head" dictionary
|
||||||
connect = "connect" dictionary
|
connect = "connect" dictionary
|
||||||
@ -237,6 +238,14 @@ const sem = grammar.createSemantics().addAttribute('ast', {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
patch(_1, dictionary) {
|
||||||
|
return {
|
||||||
|
http: {
|
||||||
|
method: 'patch',
|
||||||
|
...mapPairListToKeyValPair(dictionary.ast)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
options(_1, dictionary) {
|
options(_1, dictionary) {
|
||||||
return {
|
return {
|
||||||
http: {
|
http: {
|
||||||
|
@ -6,16 +6,18 @@ const grammar = ohm.grammar(`Bru {
|
|||||||
|
|
||||||
nl = "\\r"? "\\n"
|
nl = "\\r"? "\\n"
|
||||||
st = " " | "\\t"
|
st = " " | "\\t"
|
||||||
|
stnl = st | nl
|
||||||
tagend = nl "}"
|
tagend = nl "}"
|
||||||
validkey = ~(st | ":") any
|
optionalnl = ~tagend nl
|
||||||
validvalue = ~nl any
|
keychar = ~(tagend | st | nl | ":") any
|
||||||
|
valuechar = ~(nl | tagend) any
|
||||||
|
|
||||||
// Dictionary Blocks
|
// Dictionary Blocks
|
||||||
dictionary = st* "{" pairlist? tagend
|
dictionary = st* "{" pairlist? tagend
|
||||||
pairlist = nl* pair (~tagend nl pair)* (~tagend space)*
|
pairlist = optionalnl* pair (~tagend stnl* pair)* (~tagend space)*
|
||||||
pair = st* key st* ":" st* value? st*
|
pair = st* key st* ":" st* value st*
|
||||||
key = ~tagend validkey*
|
key = keychar*
|
||||||
value = ~tagend validvalue*
|
value = valuechar*
|
||||||
|
|
||||||
vars = "vars" dictionary
|
vars = "vars" dictionary
|
||||||
}`);
|
}`);
|
||||||
@ -68,7 +70,7 @@ const sem = grammar.createSemantics().addAttribute('ast', {
|
|||||||
},
|
},
|
||||||
pair(_1, key, _2, _3, _4, value, _5) {
|
pair(_1, key, _2, _3, _4, value, _5) {
|
||||||
let res = {};
|
let res = {};
|
||||||
res[key.ast] = _.get(value, 'ast[0]', '');
|
res[key.ast] = value.ast ? value.ast.trim() : '';
|
||||||
return res;
|
return res;
|
||||||
},
|
},
|
||||||
key(chars) {
|
key(chars) {
|
||||||
|
@ -85,4 +85,33 @@ vars {
|
|||||||
|
|
||||||
expect(output).toEqual(expected);
|
expect(output).toEqual(expected);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should parse vars with empty values", () => {
|
||||||
|
const input = `
|
||||||
|
vars {
|
||||||
|
url:
|
||||||
|
phone:
|
||||||
|
api-key:
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const output = parser(input);
|
||||||
|
const expected = {
|
||||||
|
"variables": [{
|
||||||
|
"name": "url",
|
||||||
|
"value": "",
|
||||||
|
"enabled" : true,
|
||||||
|
}, {
|
||||||
|
"name": "phone",
|
||||||
|
"value": "",
|
||||||
|
"enabled" : true,
|
||||||
|
}, {
|
||||||
|
"name": "api-key",
|
||||||
|
"value": "",
|
||||||
|
"enabled" : true,
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(output).toEqual(expected);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@usebruno/schema",
|
"name": "@usebruno/schema",
|
||||||
"version": "0.3.0",
|
"version": "0.3.1",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
"files": [
|
"files": [
|
||||||
"src",
|
"src",
|
||||||
|
Loading…
Reference in New Issue
Block a user