mirror of
https://github.com/usebruno/bruno.git
synced 2024-11-25 17:33:28 +01:00
Merge branch 'main' into enhancement/collection-dropdown
This commit is contained in:
commit
7617ae12cb
328
package-lock.json
generated
328
package-lock.json
generated
@ -1826,37 +1826,6 @@
|
||||
"integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@codemirror/language": {
|
||||
"version": "0.20.2",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/language/-/language-0.20.2.tgz",
|
||||
"integrity": "sha512-WB3Bnuusw0xhVvhBocieYKwJm04SOk5bPoOEYksVHKHcGHFOaYaw+eZVxR4gIqMMcGzOIUil0FsCmFk8yrhHpw==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@codemirror/state": "^0.20.0",
|
||||
"@codemirror/view": "^0.20.0",
|
||||
"@lezer/common": "^0.16.0",
|
||||
"@lezer/highlight": "^0.16.0",
|
||||
"@lezer/lr": "^0.16.0",
|
||||
"style-mod": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/state": {
|
||||
"version": "0.20.1",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/state/-/state-0.20.1.tgz",
|
||||
"integrity": "sha512-ms0tlV5A02OK0pFvTtSUGMLkoarzh1F8mr6jy1cD7ucSC2X/VLHtQCxfhdSEGqTYlQF2hoZtmLv+amqhdgbwjQ==",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/@codemirror/view": {
|
||||
"version": "0.20.7",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-0.20.7.tgz",
|
||||
"integrity": "sha512-pqEPCb9QFTOtHgAH5XU/oVy9UR/Anj6r+tG5CRmkNVcqSKEPmBU05WtN/jxJCFZBXf6HumzWC9ydE4qstO3TxQ==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@codemirror/state": "^0.20.0",
|
||||
"style-mod": "^4.0.0",
|
||||
"w3c-keyname": "^2.2.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@develar/schema-utils": {
|
||||
"version": "2.6.5",
|
||||
"resolved": "https://registry.npmjs.org/@develar/schema-utils/-/schema-utils-2.6.5.tgz",
|
||||
@ -2961,30 +2930,6 @@
|
||||
"@jridgewell/sourcemap-codec": "1.4.14"
|
||||
}
|
||||
},
|
||||
"node_modules/@lezer/common": {
|
||||
"version": "0.16.1",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/common/-/common-0.16.1.tgz",
|
||||
"integrity": "sha512-qPmG7YTZ6lATyTOAWf8vXE+iRrt1NJd4cm2nJHK+v7X9TsOF6+HtuU/ctaZy2RCrluxDb89hI6KWQ5LfQGQWuA==",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/@lezer/highlight": {
|
||||
"version": "0.16.0",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-0.16.0.tgz",
|
||||
"integrity": "sha512-iE5f4flHlJ1g1clOStvXNLbORJoiW4Kytso6ubfYzHnaNo/eo5SKhxs4wv/rtvwZQeZrK3we8S9SyA7OGOoRKQ==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@lezer/common": "^0.16.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@lezer/lr": {
|
||||
"version": "0.16.3",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-0.16.3.tgz",
|
||||
"integrity": "sha512-pau7um4eAw94BEuuShUIeQDTf3k4Wt6oIUOYxMmkZgDHdqtIcxWND4LRxi8nI9KuT4I1bXQv67BCapkxt7Ywqw==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@lezer/common": "^0.16.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@malept/cross-spawn-promise": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz",
|
||||
@ -4839,39 +4784,6 @@
|
||||
"node": ">=10.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/autoprefixer": {
|
||||
"version": "10.4.13",
|
||||
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.13.tgz",
|
||||
"integrity": "sha512-49vKpMqcZYsJjwotvt4+h/BCjJVnhGwcLpDt5xkcaOG3eLrG/HUYLagrihYsQ+qrIBgIzX1Rw7a6L8I/ZA1Atg==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/postcss/"
|
||||
},
|
||||
{
|
||||
"type": "tidelift",
|
||||
"url": "https://tidelift.com/funding/github/npm/autoprefixer"
|
||||
}
|
||||
],
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"browserslist": "^4.21.4",
|
||||
"caniuse-lite": "^1.0.30001426",
|
||||
"fraction.js": "^4.2.0",
|
||||
"normalize-range": "^0.1.2",
|
||||
"picocolors": "^1.0.0",
|
||||
"postcss-value-parser": "^4.2.0"
|
||||
},
|
||||
"bin": {
|
||||
"autoprefixer": "bin/autoprefixer"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^10 || ^12 || >=14"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"postcss": "^8.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/aws-sign2": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
|
||||
@ -5300,6 +5212,7 @@
|
||||
"version": "4.21.4",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz",
|
||||
"integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
@ -7338,7 +7251,8 @@
|
||||
"node_modules/electron-to-chromium": {
|
||||
"version": "1.4.284",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz",
|
||||
"integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA=="
|
||||
"integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/electron-util": {
|
||||
"version": "0.17.2",
|
||||
@ -8140,19 +8054,6 @@
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/fraction.js": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz",
|
||||
"integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": "*"
|
||||
},
|
||||
"funding": {
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/infusion"
|
||||
}
|
||||
},
|
||||
"node_modules/fresh": {
|
||||
"version": "0.5.2",
|
||||
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
|
||||
@ -8643,18 +8544,6 @@
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/graphql-ws": {
|
||||
"version": "5.11.2",
|
||||
"resolved": "https://registry.npmjs.org/graphql-ws/-/graphql-ws-5.11.2.tgz",
|
||||
"integrity": "sha512-4EiZ3/UXYcjm+xFGP544/yW1+DVI8ZpKASFbzrV5EDTFWJp0ZvLl4Dy2fSZAzz9imKp5pZMIcjB0x/H69Pv/6w==",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"graphql": ">=0.11 <=16"
|
||||
}
|
||||
},
|
||||
"node_modules/handlebars": {
|
||||
"version": "4.7.8",
|
||||
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz",
|
||||
@ -11641,7 +11530,8 @@
|
||||
"node_modules/node-releases": {
|
||||
"version": "2.0.8",
|
||||
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.8.tgz",
|
||||
"integrity": "sha512-dFSmB8fFHEH/s81Xi+Y/15DQY6VHW81nXRj86EMSL3lmuTmK1e+aT4wrFCkTbm+gSwkw4KpX+rT/pMM2c1mF+A=="
|
||||
"integrity": "sha512-dFSmB8fFHEH/s81Xi+Y/15DQY6VHW81nXRj86EMSL3lmuTmK1e+aT4wrFCkTbm+gSwkw4KpX+rT/pMM2c1mF+A==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/normalize-package-data": {
|
||||
"version": "2.5.0",
|
||||
@ -11678,15 +11568,6 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/normalize-range": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz",
|
||||
"integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/normalize-url": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz",
|
||||
@ -13626,7 +13507,8 @@
|
||||
"node_modules/react-is": {
|
||||
"version": "18.2.0",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
|
||||
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
|
||||
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/react-redux": {
|
||||
"version": "7.2.9",
|
||||
@ -15018,12 +14900,6 @@
|
||||
"webpack": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/style-mod": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.0.0.tgz",
|
||||
"integrity": "sha512-OPhtyEjyyN9x3nhPsu76f52yUGXiZcgvsrFVtvTkyGRQJ0XK+GPc6ov1z+lRpbeabka+MYEQxOYRnt5nF30aMw==",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/styled-components": {
|
||||
"version": "5.3.6",
|
||||
"resolved": "https://registry.npmjs.org/styled-components/-/styled-components-5.3.6.tgz",
|
||||
@ -15954,6 +15830,7 @@
|
||||
"version": "1.0.10",
|
||||
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz",
|
||||
"integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
@ -16236,12 +16113,6 @@
|
||||
"resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.2.tgz",
|
||||
"integrity": "sha512-zHhCWatviizPIq9B7Vh9uvrH6x3sK8itC84HkamnBWoDFJtzBf7SWlpLCZUit72b3os45h6RWQNC9xHRDF8dRA=="
|
||||
},
|
||||
"node_modules/w3c-keyname": {
|
||||
"version": "2.2.6",
|
||||
"resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.6.tgz",
|
||||
"integrity": "sha512-f+fciywl1SJEniZHD6H+kUO8gOnwIr7f4ijKA6+ZvJFjeGi1r4PDLl53Ayud9O/rk64RqgoQine0feoeOU0kXg==",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/walker": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz",
|
||||
@ -18428,37 +18299,6 @@
|
||||
"integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==",
|
||||
"dev": true
|
||||
},
|
||||
"@codemirror/language": {
|
||||
"version": "0.20.2",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/language/-/language-0.20.2.tgz",
|
||||
"integrity": "sha512-WB3Bnuusw0xhVvhBocieYKwJm04SOk5bPoOEYksVHKHcGHFOaYaw+eZVxR4gIqMMcGzOIUil0FsCmFk8yrhHpw==",
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"@codemirror/state": "^0.20.0",
|
||||
"@codemirror/view": "^0.20.0",
|
||||
"@lezer/common": "^0.16.0",
|
||||
"@lezer/highlight": "^0.16.0",
|
||||
"@lezer/lr": "^0.16.0",
|
||||
"style-mod": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"@codemirror/state": {
|
||||
"version": "0.20.1",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/state/-/state-0.20.1.tgz",
|
||||
"integrity": "sha512-ms0tlV5A02OK0pFvTtSUGMLkoarzh1F8mr6jy1cD7ucSC2X/VLHtQCxfhdSEGqTYlQF2hoZtmLv+amqhdgbwjQ==",
|
||||
"peer": true
|
||||
},
|
||||
"@codemirror/view": {
|
||||
"version": "0.20.7",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-0.20.7.tgz",
|
||||
"integrity": "sha512-pqEPCb9QFTOtHgAH5XU/oVy9UR/Anj6r+tG5CRmkNVcqSKEPmBU05WtN/jxJCFZBXf6HumzWC9ydE4qstO3TxQ==",
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"@codemirror/state": "^0.20.0",
|
||||
"style-mod": "^4.0.0",
|
||||
"w3c-keyname": "^2.2.4"
|
||||
}
|
||||
},
|
||||
"@develar/schema-utils": {
|
||||
"version": "2.6.5",
|
||||
"resolved": "https://registry.npmjs.org/@develar/schema-utils/-/schema-utils-2.6.5.tgz",
|
||||
@ -19330,30 +19170,6 @@
|
||||
"@jridgewell/sourcemap-codec": "1.4.14"
|
||||
}
|
||||
},
|
||||
"@lezer/common": {
|
||||
"version": "0.16.1",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/common/-/common-0.16.1.tgz",
|
||||
"integrity": "sha512-qPmG7YTZ6lATyTOAWf8vXE+iRrt1NJd4cm2nJHK+v7X9TsOF6+HtuU/ctaZy2RCrluxDb89hI6KWQ5LfQGQWuA==",
|
||||
"peer": true
|
||||
},
|
||||
"@lezer/highlight": {
|
||||
"version": "0.16.0",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-0.16.0.tgz",
|
||||
"integrity": "sha512-iE5f4flHlJ1g1clOStvXNLbORJoiW4Kytso6ubfYzHnaNo/eo5SKhxs4wv/rtvwZQeZrK3we8S9SyA7OGOoRKQ==",
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"@lezer/common": "^0.16.0"
|
||||
}
|
||||
},
|
||||
"@lezer/lr": {
|
||||
"version": "0.16.3",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-0.16.3.tgz",
|
||||
"integrity": "sha512-pau7um4eAw94BEuuShUIeQDTf3k4Wt6oIUOYxMmkZgDHdqtIcxWND4LRxi8nI9KuT4I1bXQv67BCapkxt7Ywqw==",
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"@lezer/common": "^0.16.0"
|
||||
}
|
||||
},
|
||||
"@malept/cross-spawn-promise": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz",
|
||||
@ -19680,8 +19496,7 @@
|
||||
"@tabler/icons": {
|
||||
"version": "1.119.0",
|
||||
"resolved": "https://registry.npmjs.org/@tabler/icons/-/icons-1.119.0.tgz",
|
||||
"integrity": "sha512-Fk3Qq4w2SXcTjc/n1cuL5bccPkylrOMo7cYpQIf/yw6zP76LQV9dtLcHQUjFiUnaYuswR645CnURIhlafyAh9g==",
|
||||
"requires": {}
|
||||
"integrity": "sha512-Fk3Qq4w2SXcTjc/n1cuL5bccPkylrOMo7cYpQIf/yw6zP76LQV9dtLcHQUjFiUnaYuswR645CnURIhlafyAh9g=="
|
||||
},
|
||||
"@tauri-apps/cli": {
|
||||
"version": "1.2.2",
|
||||
@ -20302,8 +20117,7 @@
|
||||
}
|
||||
},
|
||||
"@usebruno/schema": {
|
||||
"version": "file:packages/bruno-schema",
|
||||
"requires": {}
|
||||
"version": "file:packages/bruno-schema"
|
||||
},
|
||||
"@usebruno/testbench": {
|
||||
"version": "file:packages/bruno-testbench",
|
||||
@ -20479,8 +20293,7 @@
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.2.0.tgz",
|
||||
"integrity": "sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
"dev": true
|
||||
},
|
||||
"@webpack-cli/info": {
|
||||
"version": "1.5.0",
|
||||
@ -20495,8 +20308,7 @@
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.7.0.tgz",
|
||||
"integrity": "sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
"dev": true
|
||||
},
|
||||
"@xtuc/ieee754": {
|
||||
"version": "1.2.0",
|
||||
@ -20601,8 +20413,7 @@
|
||||
"version": "3.5.2",
|
||||
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
|
||||
"integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
"dev": true
|
||||
},
|
||||
"amdefine": {
|
||||
"version": "0.0.8",
|
||||
@ -20935,20 +20746,6 @@
|
||||
"resolved": "https://registry.npmjs.org/atomically/-/atomically-1.7.0.tgz",
|
||||
"integrity": "sha512-Xcz9l0z7y9yQ9rdDaxlmaI4uJHf/T8g9hOEzJcsEqX2SjCj4J20uK7+ldkDHMbpJDK76wF7xEIgxc/vSlsfw5w=="
|
||||
},
|
||||
"autoprefixer": {
|
||||
"version": "10.4.13",
|
||||
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.13.tgz",
|
||||
"integrity": "sha512-49vKpMqcZYsJjwotvt4+h/BCjJVnhGwcLpDt5xkcaOG3eLrG/HUYLagrihYsQ+qrIBgIzX1Rw7a6L8I/ZA1Atg==",
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"browserslist": "^4.21.4",
|
||||
"caniuse-lite": "^1.0.30001426",
|
||||
"fraction.js": "^4.2.0",
|
||||
"normalize-range": "^0.1.2",
|
||||
"picocolors": "^1.0.0",
|
||||
"postcss-value-parser": "^4.2.0"
|
||||
}
|
||||
},
|
||||
"aws-sign2": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
|
||||
@ -21278,6 +21075,7 @@
|
||||
"version": "4.21.4",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz",
|
||||
"integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"caniuse-lite": "^1.0.30001400",
|
||||
"electron-to-chromium": "^1.4.251",
|
||||
@ -22213,8 +22011,7 @@
|
||||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.3.1.tgz",
|
||||
"integrity": "sha512-fBffmak0bPAnyqc/HO8C3n2sHrp9wcqQz6ES9koRF2/mLOVAx9zIQ3Y7R29sYCteTPqMCwns4WYQoCX91Xl3+w==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
"dev": true
|
||||
},
|
||||
"css-loader": {
|
||||
"version": "6.7.3",
|
||||
@ -22359,8 +22156,7 @@
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.1.0.tgz",
|
||||
"integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
"dev": true
|
||||
},
|
||||
"csso": {
|
||||
"version": "4.2.0",
|
||||
@ -22933,7 +22729,8 @@
|
||||
"electron-to-chromium": {
|
||||
"version": "1.4.284",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz",
|
||||
"integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA=="
|
||||
"integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==",
|
||||
"dev": true
|
||||
},
|
||||
"electron-util": {
|
||||
"version": "0.17.2",
|
||||
@ -23558,12 +23355,6 @@
|
||||
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
|
||||
"integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="
|
||||
},
|
||||
"fraction.js": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz",
|
||||
"integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==",
|
||||
"peer": true
|
||||
},
|
||||
"fresh": {
|
||||
"version": "0.5.2",
|
||||
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
|
||||
@ -23826,8 +23617,7 @@
|
||||
"goober": {
|
||||
"version": "2.1.11",
|
||||
"resolved": "https://registry.npmjs.org/goober/-/goober-2.1.11.tgz",
|
||||
"integrity": "sha512-5SS2lmxbhqH0u9ABEWq7WPU69a4i2pYcHeCxqaNq6Cw3mnrF0ghWNM4tEGid4dKy8XNIAUbuThuozDHHKJVh3A==",
|
||||
"requires": {}
|
||||
"integrity": "sha512-5SS2lmxbhqH0u9ABEWq7WPU69a4i2pYcHeCxqaNq6Cw3mnrF0ghWNM4tEGid4dKy8XNIAUbuThuozDHHKJVh3A=="
|
||||
},
|
||||
"got": {
|
||||
"version": "9.6.0",
|
||||
@ -23950,13 +23740,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"graphql-ws": {
|
||||
"version": "5.11.2",
|
||||
"resolved": "https://registry.npmjs.org/graphql-ws/-/graphql-ws-5.11.2.tgz",
|
||||
"integrity": "sha512-4EiZ3/UXYcjm+xFGP544/yW1+DVI8ZpKASFbzrV5EDTFWJp0ZvLl4Dy2fSZAzz9imKp5pZMIcjB0x/H69Pv/6w==",
|
||||
"peer": true,
|
||||
"requires": {}
|
||||
},
|
||||
"handlebars": {
|
||||
"version": "4.7.8",
|
||||
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz",
|
||||
@ -24307,8 +24090,7 @@
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz",
|
||||
"integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
"dev": true
|
||||
},
|
||||
"idb": {
|
||||
"version": "7.1.1",
|
||||
@ -25087,8 +24869,7 @@
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz",
|
||||
"integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
"dev": true
|
||||
},
|
||||
"jest-regex-util": {
|
||||
"version": "29.2.0",
|
||||
@ -25850,8 +25631,7 @@
|
||||
"meros": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/meros/-/meros-1.2.1.tgz",
|
||||
"integrity": "sha512-R2f/jxYqCAGI19KhAvaxSOxALBMkaXWH2a7rOyqQw+ZmizX5bKkEYWLzdhC+U82ZVVPVp6MCXe3EkVligh+12g==",
|
||||
"requires": {}
|
||||
"integrity": "sha512-R2f/jxYqCAGI19KhAvaxSOxALBMkaXWH2a7rOyqQw+ZmizX5bKkEYWLzdhC+U82ZVVPVp6MCXe3EkVligh+12g=="
|
||||
},
|
||||
"methods": {
|
||||
"version": "1.1.2",
|
||||
@ -26185,7 +25965,8 @@
|
||||
"node-releases": {
|
||||
"version": "2.0.8",
|
||||
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.8.tgz",
|
||||
"integrity": "sha512-dFSmB8fFHEH/s81Xi+Y/15DQY6VHW81nXRj86EMSL3lmuTmK1e+aT4wrFCkTbm+gSwkw4KpX+rT/pMM2c1mF+A=="
|
||||
"integrity": "sha512-dFSmB8fFHEH/s81Xi+Y/15DQY6VHW81nXRj86EMSL3lmuTmK1e+aT4wrFCkTbm+gSwkw4KpX+rT/pMM2c1mF+A==",
|
||||
"dev": true
|
||||
},
|
||||
"normalize-package-data": {
|
||||
"version": "2.5.0",
|
||||
@ -26218,12 +25999,6 @@
|
||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="
|
||||
},
|
||||
"normalize-range": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz",
|
||||
"integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==",
|
||||
"peer": true
|
||||
},
|
||||
"normalize-url": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz",
|
||||
@ -26886,29 +26661,25 @@
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz",
|
||||
"integrity": "sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
"dev": true
|
||||
},
|
||||
"postcss-discard-duplicates": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz",
|
||||
"integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
"dev": true
|
||||
},
|
||||
"postcss-discard-empty": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz",
|
||||
"integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
"dev": true
|
||||
},
|
||||
"postcss-discard-overridden": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz",
|
||||
"integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
"dev": true
|
||||
},
|
||||
"postcss-js": {
|
||||
"version": "3.0.3",
|
||||
@ -27010,8 +26781,7 @@
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz",
|
||||
"integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
"dev": true
|
||||
},
|
||||
"postcss-modules-local-by-default": {
|
||||
"version": "4.0.0",
|
||||
@ -27054,8 +26824,7 @@
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz",
|
||||
"integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
"dev": true
|
||||
},
|
||||
"postcss-normalize-display-values": {
|
||||
"version": "5.1.0",
|
||||
@ -27576,13 +27345,13 @@
|
||||
"react-inspector": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/react-inspector/-/react-inspector-6.0.2.tgz",
|
||||
"integrity": "sha512-x+b7LxhmHXjHoU/VrFAzw5iutsILRoYyDq97EDYdFpPLcvqtEzk4ZSZSQjnFPbr5T57tLXnHcqFYoN1pI6u8uQ==",
|
||||
"requires": {}
|
||||
"integrity": "sha512-x+b7LxhmHXjHoU/VrFAzw5iutsILRoYyDq97EDYdFpPLcvqtEzk4ZSZSQjnFPbr5T57tLXnHcqFYoN1pI6u8uQ=="
|
||||
},
|
||||
"react-is": {
|
||||
"version": "18.2.0",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
|
||||
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
|
||||
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==",
|
||||
"dev": true
|
||||
},
|
||||
"react-redux": {
|
||||
"version": "7.2.9",
|
||||
@ -27769,8 +27538,7 @@
|
||||
"redux-thunk": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.2.tgz",
|
||||
"integrity": "sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==",
|
||||
"requires": {}
|
||||
"integrity": "sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q=="
|
||||
},
|
||||
"regenerate": {
|
||||
"version": "1.4.2",
|
||||
@ -28072,8 +27840,7 @@
|
||||
"version": "2.2.4",
|
||||
"resolved": "https://registry.npmjs.org/rollup-plugin-peer-deps-external/-/rollup-plugin-peer-deps-external-2.2.4.tgz",
|
||||
"integrity": "sha512-AWdukIM1+k5JDdAqV/Cxd+nejvno2FVLVeZ74NKggm3Q5s9cbbcOgUPGdbxPi4BXu7xGaZ8HG12F+thImYu/0g==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
"dev": true
|
||||
},
|
||||
"rollup-plugin-postcss": {
|
||||
"version": "4.0.2",
|
||||
@ -28686,14 +28453,7 @@
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.1.tgz",
|
||||
"integrity": "sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"style-mod": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.0.0.tgz",
|
||||
"integrity": "sha512-OPhtyEjyyN9x3nhPsu76f52yUGXiZcgvsrFVtvTkyGRQJ0XK+GPc6ov1z+lRpbeabka+MYEQxOYRnt5nF30aMw==",
|
||||
"peer": true
|
||||
"dev": true
|
||||
},
|
||||
"styled-components": {
|
||||
"version": "5.3.6",
|
||||
@ -28730,8 +28490,7 @@
|
||||
"styled-jsx": {
|
||||
"version": "5.0.7",
|
||||
"resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.0.7.tgz",
|
||||
"integrity": "sha512-b3sUzamS086YLRuvnaDigdAewz1/EFYlHpYBP5mZovKEdQQOIIYq8lApylub3HHZ6xFjV051kkGU7cudJmrXEA==",
|
||||
"requires": {}
|
||||
"integrity": "sha512-b3sUzamS086YLRuvnaDigdAewz1/EFYlHpYBP5mZovKEdQQOIIYq8lApylub3HHZ6xFjV051kkGU7cudJmrXEA=="
|
||||
},
|
||||
"stylehacks": {
|
||||
"version": "5.1.1",
|
||||
@ -29380,6 +29139,7 @@
|
||||
"version": "1.0.10",
|
||||
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz",
|
||||
"integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"escalade": "^3.1.1",
|
||||
"picocolors": "^1.0.0"
|
||||
@ -29468,8 +29228,7 @@
|
||||
"use-sync-external-store": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
|
||||
"integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==",
|
||||
"requires": {}
|
||||
"integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA=="
|
||||
},
|
||||
"utf8-byte-length": {
|
||||
"version": "1.0.4",
|
||||
@ -29602,12 +29361,6 @@
|
||||
"resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.2.tgz",
|
||||
"integrity": "sha512-zHhCWatviizPIq9B7Vh9uvrH6x3sK8itC84HkamnBWoDFJtzBf7SWlpLCZUit72b3os45h6RWQNC9xHRDF8dRA=="
|
||||
},
|
||||
"w3c-keyname": {
|
||||
"version": "2.2.6",
|
||||
"resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.6.tgz",
|
||||
"integrity": "sha512-f+fciywl1SJEniZHD6H+kUO8gOnwIr7f4ijKA6+ZvJFjeGi1r4PDLl53Ayud9O/rk64RqgoQine0feoeOU0kXg==",
|
||||
"peer": true
|
||||
},
|
||||
"walker": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz",
|
||||
@ -29688,8 +29441,7 @@
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz",
|
||||
"integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
"dev": true
|
||||
},
|
||||
"schema-utils": {
|
||||
"version": "3.1.1",
|
||||
|
@ -17,7 +17,7 @@ const CopyEnvironment = ({ collection, environment, onClose }) => {
|
||||
},
|
||||
validationSchema: Yup.object({
|
||||
name: Yup.string()
|
||||
.min(1, 'must be atleast 1 characters')
|
||||
.min(1, 'must be at least 1 character')
|
||||
.max(50, 'must be 50 characters or less')
|
||||
.required('name is required')
|
||||
}),
|
||||
|
@ -17,7 +17,7 @@ const CreateEnvironment = ({ collection, onClose }) => {
|
||||
},
|
||||
validationSchema: Yup.object({
|
||||
name: Yup.string()
|
||||
.min(1, 'must be atleast 1 characters')
|
||||
.min(1, 'must be at least 1 character')
|
||||
.max(50, 'must be 50 characters or less')
|
||||
.required('name is required')
|
||||
}),
|
||||
|
@ -17,7 +17,7 @@ const RenameEnvironment = ({ onClose, environment, collection }) => {
|
||||
},
|
||||
validationSchema: Yup.object({
|
||||
name: Yup.string()
|
||||
.min(1, 'must be atleast 1 characters')
|
||||
.min(1, 'must be at least 1 character')
|
||||
.max(50, 'must be 50 characters or less')
|
||||
.required('name is required')
|
||||
}),
|
||||
|
@ -22,6 +22,7 @@ const Wrapper = styled.div`
|
||||
justify-content: center;
|
||||
overflow-y: auto;
|
||||
z-index: 10;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.bruno-modal-card {
|
||||
|
@ -61,19 +61,20 @@ const Modal = ({
|
||||
children,
|
||||
confirmDisabled,
|
||||
hideCancel,
|
||||
hideFooter
|
||||
hideFooter,
|
||||
closeModalFadeTimeout = 500
|
||||
}) => {
|
||||
const [isClosing, setIsClosing] = useState(false);
|
||||
const escFunction = (event) => {
|
||||
const escKeyCode = 27;
|
||||
if (event.keyCode === escKeyCode) {
|
||||
closeModal();
|
||||
closeModal({ type: 'esc' });
|
||||
}
|
||||
};
|
||||
|
||||
const closeModal = () => {
|
||||
const closeModal = (args) => {
|
||||
setIsClosing(true);
|
||||
setTimeout(() => handleCancel(), 500);
|
||||
setTimeout(() => handleCancel(args), closeModalFadeTimeout);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
@ -94,12 +95,12 @@ const Modal = ({
|
||||
return (
|
||||
<StyledWrapper className={classes}>
|
||||
<div className={`bruno-modal-card modal-${size}`}>
|
||||
<ModalHeader title={title} handleCancel={() => closeModal()} />
|
||||
<ModalHeader title={title} handleCancel={() => closeModal({ type: 'icon' })} />
|
||||
<ModalContent>{children}</ModalContent>
|
||||
<ModalFooter
|
||||
confirmText={confirmText}
|
||||
cancelText={cancelText}
|
||||
handleCancel={() => closeModal()}
|
||||
handleCancel={() => closeModal({ type: 'button' })}
|
||||
handleSubmit={handleConfirm}
|
||||
confirmDisabled={confirmDisabled}
|
||||
hideCancel={hideCancel}
|
||||
@ -108,7 +109,12 @@ const Modal = ({
|
||||
</div>
|
||||
|
||||
{/* Clicking on backdrop closes the modal */}
|
||||
<div className="bruno-modal-backdrop" onClick={() => closeModal()} />
|
||||
<div
|
||||
className="bruno-modal-backdrop"
|
||||
onClick={() => {
|
||||
closeModal({ type: 'backdrop' });
|
||||
}}
|
||||
/>
|
||||
</StyledWrapper>
|
||||
);
|
||||
};
|
||||
|
@ -20,7 +20,7 @@ const Auth = ({ item, collection }) => {
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledWrapper className="w-full">
|
||||
<StyledWrapper className="w-full mt-1">
|
||||
<div className="flex flex-grow justify-start items-center">
|
||||
<AuthMode item={item} collection={collection} />
|
||||
</div>
|
||||
|
@ -40,7 +40,7 @@ const GraphQLRequestPane = ({ item, collection, leftPaneWidth, onSchemaLoad, tog
|
||||
loadSchema,
|
||||
isLoading: isSchemaLoading,
|
||||
error: schemaError
|
||||
} = useGraphqlSchema(url, environment, request, collection.collectionVariables);
|
||||
} = useGraphqlSchema(url, environment, request, collection);
|
||||
|
||||
const loadGqlSchema = () => {
|
||||
if (!isSchemaLoading) {
|
||||
|
@ -6,7 +6,7 @@ import { simpleHash } from 'utils/common';
|
||||
|
||||
const schemaHashPrefix = 'bruno.graphqlSchema';
|
||||
|
||||
const useGraphqlSchema = (endpoint, environment, request, collectionVariables) => {
|
||||
const useGraphqlSchema = (endpoint, environment, request, collection) => {
|
||||
const localStorageKey = `${schemaHashPrefix}.${simpleHash(endpoint)}`;
|
||||
const [error, setError] = useState(null);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
@ -25,7 +25,7 @@ const useGraphqlSchema = (endpoint, environment, request, collectionVariables) =
|
||||
|
||||
const loadSchema = () => {
|
||||
setIsLoading(true);
|
||||
fetchGqlSchema(endpoint, environment, request, collectionVariables)
|
||||
fetchGqlSchema(endpoint, environment, request, collection)
|
||||
.then((res) => res.data)
|
||||
.then((s) => {
|
||||
if (s && s.data) {
|
||||
|
@ -32,6 +32,50 @@ const Wrapper = styled.div`
|
||||
position: relative;
|
||||
top: 1px;
|
||||
}
|
||||
|
||||
.tooltip {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.tooltip:hover .tooltiptext {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.tooltiptext {
|
||||
visibility: hidden;
|
||||
width: auto;
|
||||
background-color: ${(props) => props.theme.requestTabs.active.bg};
|
||||
color: ${(props) => props.theme.text};
|
||||
text-align: center;
|
||||
border-radius: 4px;
|
||||
padding: 4px 8px;
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
bottom: 34px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.tooltiptext::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 50%;
|
||||
margin-left: -4px;
|
||||
border-width: 4px;
|
||||
border-style: solid;
|
||||
border-color: ${(props) => props.theme.requestTabs.active.bg} transparent transparent transparent;
|
||||
}
|
||||
|
||||
.shortcut {
|
||||
font-size: 0.625rem;
|
||||
}
|
||||
`;
|
||||
|
||||
export default Wrapper;
|
||||
|
@ -5,8 +5,9 @@ import { requestUrlChanged, updateRequestMethod } from 'providers/ReduxStore/sli
|
||||
import { saveRequest } from 'providers/ReduxStore/slices/collections/actions';
|
||||
import HttpMethodSelector from './HttpMethodSelector';
|
||||
import { useTheme } from 'providers/Theme';
|
||||
import SendIcon from 'components/Icons/Send';
|
||||
import { IconDeviceFloppy, IconArrowRight } from '@tabler/icons';
|
||||
import SingleLineEditor from 'components/SingleLineEditor';
|
||||
import { isMacOS } from 'utils/common/platform';
|
||||
import StyledWrapper from './StyledWrapper';
|
||||
|
||||
const QueryUrl = ({ item, collection, handleRun }) => {
|
||||
@ -14,6 +15,8 @@ const QueryUrl = ({ item, collection, handleRun }) => {
|
||||
const dispatch = useDispatch();
|
||||
const method = item.draft ? get(item, 'draft.request.method') : get(item, 'request.method');
|
||||
const url = item.draft ? get(item, 'draft.request.url') : get(item, 'request.url');
|
||||
const isMac = isMacOS();
|
||||
const saveShortcut = isMac ? 'Cmd + S' : 'Ctrl + S';
|
||||
|
||||
const [methodSelectorWidth, setMethodSelectorWidth] = useState(90);
|
||||
|
||||
@ -22,7 +25,10 @@ const QueryUrl = ({ item, collection, handleRun }) => {
|
||||
setMethodSelectorWidth(el.offsetWidth);
|
||||
}, [method]);
|
||||
|
||||
const onSave = () => dispatch(saveRequest(item.uid, collection.uid));
|
||||
const onSave = () => {
|
||||
dispatch(saveRequest(item.uid, collection.uid));
|
||||
};
|
||||
|
||||
const onUrlChange = (value) => {
|
||||
dispatch(
|
||||
requestUrlChanged({
|
||||
@ -65,7 +71,25 @@ const QueryUrl = ({ item, collection, handleRun }) => {
|
||||
collection={collection}
|
||||
/>
|
||||
<div className="flex items-center h-full mr-2 cursor-pointer" id="send-request" onClick={handleRun}>
|
||||
<SendIcon color={theme.requestTabPanel.url.icon} width={22} />
|
||||
<div
|
||||
className="tooltip mr-3"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
if (!item.draft) return;
|
||||
onSave();
|
||||
}}
|
||||
>
|
||||
<IconDeviceFloppy
|
||||
color={item.draft ? theme.colors.text.yellow : theme.requestTabs.icon.color}
|
||||
strokeWidth={1.5}
|
||||
size={22}
|
||||
className={`${item.draft ? 'cursor-pointer' : 'cursor-default'}`}
|
||||
/>
|
||||
<span className="tooltiptext text-xs">
|
||||
Save <span className="shortcut">({saveShortcut})</span>
|
||||
</span>
|
||||
</div>
|
||||
<IconArrowRight color={theme.requestTabPanel.url.icon} strokeWidth={1.5} size={22} />
|
||||
</div>
|
||||
</div>
|
||||
</StyledWrapper>
|
||||
|
@ -0,0 +1,30 @@
|
||||
import React from 'react';
|
||||
import Modal from 'components/Modal';
|
||||
|
||||
const ConfirmRequestClose = ({ onCancel, onCloseWithoutSave, onSaveAndClose }) => {
|
||||
const _handleCancel = ({ type }) => {
|
||||
if (type === 'button') {
|
||||
return onCloseWithoutSave();
|
||||
}
|
||||
|
||||
return onCancel();
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
size="sm"
|
||||
title="Unsaved changes"
|
||||
confirmText="Save and Close"
|
||||
cancelText="Close without saving"
|
||||
handleConfirm={onSaveAndClose}
|
||||
handleCancel={_handleCancel}
|
||||
disableEscapeKey={true}
|
||||
disableCloseOnOutsideClick={true}
|
||||
closeModalFadeTimeout={150}
|
||||
>
|
||||
<div className="font-normal">You have unsaved changes in you request.</div>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default ConfirmRequestClose;
|
@ -1,10 +1,13 @@
|
||||
import React from 'react';
|
||||
import React, { useState } from 'react';
|
||||
import get from 'lodash/get';
|
||||
import { closeTabs } from 'providers/ReduxStore/slices/tabs';
|
||||
import { saveRequest } from 'providers/ReduxStore/slices/collections/actions';
|
||||
import { deleteRequestDraft } from 'providers/ReduxStore/slices/collections';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { findItemInCollection } from 'utils/collections';
|
||||
import StyledWrapper from './StyledWrapper';
|
||||
import RequestTabNotFound from './RequestTabNotFound';
|
||||
import ConfirmRequestClose from './ConfirmRequestClose';
|
||||
import SpecialTab from './SpecialTab';
|
||||
import { useTheme } from 'providers/Theme';
|
||||
import darkTheme from 'themes/dark';
|
||||
@ -13,6 +16,7 @@ import lightTheme from 'themes/light';
|
||||
const RequestTab = ({ tab, collection }) => {
|
||||
const dispatch = useDispatch();
|
||||
const { storedTheme } = useTheme();
|
||||
const [showConfirmClose, setShowConfirmClose] = useState(false);
|
||||
|
||||
const handleCloseClick = (event) => {
|
||||
event.stopPropagation();
|
||||
@ -86,6 +90,39 @@ const RequestTab = ({ tab, collection }) => {
|
||||
|
||||
return (
|
||||
<StyledWrapper className="flex items-center justify-between tab-container px-1">
|
||||
{showConfirmClose && (
|
||||
<ConfirmRequestClose
|
||||
onCancel={() => setShowConfirmClose(false)}
|
||||
onCloseWithoutSave={() => {
|
||||
dispatch(
|
||||
deleteRequestDraft({
|
||||
itemUid: item.uid,
|
||||
collectionUid: collection.uid
|
||||
})
|
||||
);
|
||||
dispatch(
|
||||
closeTabs({
|
||||
tabUids: [tab.uid]
|
||||
})
|
||||
);
|
||||
setShowConfirmClose(false);
|
||||
}}
|
||||
onSaveAndClose={() => {
|
||||
dispatch(saveRequest(item.uid, collection.uid))
|
||||
.then(() => {
|
||||
dispatch(
|
||||
closeTabs({
|
||||
tabUids: [tab.uid]
|
||||
})
|
||||
);
|
||||
setShowConfirmClose(false);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log('err', err);
|
||||
});
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<div className="flex items-baseline tab-label pl-2">
|
||||
<span className="tab-method uppercase" style={{ color: getMethodColor(method), fontSize: 12 }}>
|
||||
{method}
|
||||
@ -94,7 +131,14 @@ const RequestTab = ({ tab, collection }) => {
|
||||
{item.name}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex px-2 close-icon-container" onClick={(e) => handleCloseClick(e)}>
|
||||
<div
|
||||
className="flex px-2 close-icon-container"
|
||||
onClick={(e) => {
|
||||
if (!item.draft) return handleCloseClick(e);
|
||||
|
||||
setShowConfirmClose(true);
|
||||
}}
|
||||
>
|
||||
{!item.draft ? (
|
||||
<svg focusable="false" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512" className="close-icon">
|
||||
<path
|
||||
|
@ -1,6 +1,11 @@
|
||||
import styled from 'styled-components';
|
||||
|
||||
const StyledWrapper = styled.div`
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
height: 100vh;
|
||||
background-color: ${(props) => props.theme.requestTabPanel.responseOverlayBg};
|
||||
|
||||
div.overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
@ -14,6 +19,11 @@ const StyledWrapper = styled.div`
|
||||
padding-top: 20%;
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
|
||||
.loading-icon {
|
||||
transform: scaleY(-1);
|
||||
animation: rotateCounterClockwise 1s linear infinite;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
|
@ -13,17 +13,17 @@ const ResponseLoadingOverlay = ({ item, collection }) => {
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledWrapper className="mt-4 px-3 w-full">
|
||||
<StyledWrapper className="px-3 w-full">
|
||||
<div className="overlay">
|
||||
<div style={{ marginBottom: 15, fontSize: 26 }}>
|
||||
<div style={{ display: 'inline-block', fontSize: 24, marginLeft: 5, marginRight: 5 }}>
|
||||
<div style={{ display: 'inline-block', fontSize: 20, marginLeft: 5, marginRight: 5 }}>
|
||||
<StopWatch />
|
||||
</div>
|
||||
</div>
|
||||
<IconRefresh size={24} className="animate-spin" />
|
||||
<IconRefresh size={24} className="loading-icon" />
|
||||
<button
|
||||
onClick={handleCancelRequest}
|
||||
className="mt-4 uppercase btn-md rounded btn-secondary ease-linear transition-all duration-150"
|
||||
className="mt-4 uppercase btn-sm rounded btn-secondary ease-linear transition-all duration-150"
|
||||
type="button"
|
||||
>
|
||||
Cancel Request
|
||||
|
@ -16,7 +16,7 @@ const TestResults = ({ results, assertionResults }) => {
|
||||
|
||||
return (
|
||||
<StyledWrapper className="flex flex-col px-3">
|
||||
<div className="py-2 font-medium test-summary">
|
||||
<div className="pb-2 font-medium test-summary">
|
||||
Tests ({results.length}/{results.length}), Passed: {passedTests.length}, Failed: {failedTests.length}
|
||||
</div>
|
||||
<ul className="">
|
||||
|
@ -61,15 +61,15 @@ const ResponsePane = ({ rightPaneWidth, item, collection }) => {
|
||||
}
|
||||
};
|
||||
|
||||
if (isLoading) {
|
||||
if (isLoading && !item.response) {
|
||||
return (
|
||||
<StyledWrapper className="flex h-full relative">
|
||||
<StyledWrapper className="flex flex-col h-full relative">
|
||||
<Overlay item={item} collection={collection} />
|
||||
</StyledWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
if (response.state !== 'success') {
|
||||
if (!item.response) {
|
||||
return (
|
||||
<StyledWrapper className="flex h-full relative">
|
||||
<Placeholder />
|
||||
@ -115,7 +115,10 @@ const ResponsePane = ({ rightPaneWidth, item, collection }) => {
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
<section className="flex flex-grow">{getTabPanel(focusedTab.responsePaneTab)}</section>
|
||||
<section className={`flex flex-grow ${focusedTab.responsePaneTab === 'response' ? '' : 'mt-4'}`}>
|
||||
{isLoading ? <Overlay item={item} collection={collection} /> : null}
|
||||
{getTabPanel(focusedTab.responsePaneTab)}
|
||||
</section>
|
||||
</StyledWrapper>
|
||||
);
|
||||
};
|
||||
|
@ -18,7 +18,7 @@ const CloneCollectionItem = ({ collection, item, onClose }) => {
|
||||
},
|
||||
validationSchema: Yup.object({
|
||||
name: Yup.string()
|
||||
.min(1, 'must be atleast 1 characters')
|
||||
.min(1, 'must be at least 1 character')
|
||||
.max(50, 'must be 50 characters or less')
|
||||
.required('name is required')
|
||||
}),
|
||||
|
@ -17,7 +17,7 @@ const RenameCollectionItem = ({ collection, item, onClose }) => {
|
||||
},
|
||||
validationSchema: Yup.object({
|
||||
name: Yup.string()
|
||||
.min(1, 'must be atleast 1 characters')
|
||||
.min(1, 'must be at least 1 character')
|
||||
.max(50, 'must be 50 characters or less')
|
||||
.required('name is required')
|
||||
}),
|
||||
|
@ -16,7 +16,7 @@ const RenameCollection = ({ collection, onClose }) => {
|
||||
},
|
||||
validationSchema: Yup.object({
|
||||
name: Yup.string()
|
||||
.min(1, 'must be atleast 1 characters')
|
||||
.min(1, 'must be at least 1 character')
|
||||
.max(50, 'must be 50 characters or less')
|
||||
.required('name is required')
|
||||
}),
|
||||
|
@ -21,11 +21,11 @@ const CreateCollection = ({ onClose }) => {
|
||||
},
|
||||
validationSchema: Yup.object({
|
||||
collectionName: Yup.string()
|
||||
.min(1, 'must be atleast 1 characters')
|
||||
.min(1, 'must be at least 1 character')
|
||||
.max(50, 'must be 50 characters or less')
|
||||
.required('collection name is required'),
|
||||
collectionFolderName: Yup.string()
|
||||
.min(1, 'must be atleast 1 characters')
|
||||
.min(1, 'must be at least 1 character')
|
||||
.max(50, 'must be 50 characters or less')
|
||||
.matches(/^[\w\-. ]+$/, 'Folder name contains invalid characters')
|
||||
.required('folder name is required'),
|
||||
|
@ -16,7 +16,7 @@ const ImportCollectionLocation = ({ onClose, handleSubmit, collectionName }) =>
|
||||
},
|
||||
validationSchema: Yup.object({
|
||||
collectionLocation: Yup.string()
|
||||
.min(1, 'must be atleast 1 characters')
|
||||
.min(1, 'must be at least 1 character')
|
||||
.max(500, 'must be 500 characters or less')
|
||||
.required('name is required')
|
||||
}),
|
||||
|
@ -16,7 +16,7 @@ const NewFolder = ({ collection, item, onClose }) => {
|
||||
},
|
||||
validationSchema: Yup.object({
|
||||
folderName: Yup.string()
|
||||
.min(1, 'must be atleast 1 characters')
|
||||
.min(1, 'must be at least 1 character')
|
||||
.required('name is required')
|
||||
.test({
|
||||
name: 'folderName',
|
||||
|
@ -25,7 +25,7 @@ const NewRequest = ({ collection, item, isEphemeral, onClose }) => {
|
||||
},
|
||||
validationSchema: Yup.object({
|
||||
requestName: Yup.string()
|
||||
.min(1, 'must be atleast 1 characters')
|
||||
.min(1, 'must be at least 1 character')
|
||||
.required('name is required')
|
||||
.test({
|
||||
name: 'requestName',
|
||||
|
@ -18,6 +18,7 @@ const TitleBar = () => {
|
||||
const [importCollectionModalOpen, setImportCollectionModalOpen] = useState(false);
|
||||
const [importCollectionLocationModalOpen, setImportCollectionLocationModalOpen] = useState(false);
|
||||
const dispatch = useDispatch();
|
||||
const { ipcRenderer } = window;
|
||||
|
||||
const handleImportCollection = (collection) => {
|
||||
setImportedCollection(collection);
|
||||
@ -50,6 +51,10 @@ const TitleBar = () => {
|
||||
);
|
||||
};
|
||||
|
||||
const openDevTools = () => {
|
||||
ipcRenderer.invoke('renderer:open-devtools');
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledWrapper className="px-2 py-2">
|
||||
{createCollectionModalOpen ? <CreateCollection onClose={() => setCreateCollectionModalOpen(false)} /> : null}
|
||||
@ -104,6 +109,15 @@ const TitleBar = () => {
|
||||
>
|
||||
Import Collection
|
||||
</div>
|
||||
<div
|
||||
className="dropdown-item"
|
||||
onClick={(e) => {
|
||||
menuDropdownTippyRef.current.hide();
|
||||
openDevTools();
|
||||
}}
|
||||
>
|
||||
Devtools
|
||||
</div>
|
||||
</Dropdown>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -105,7 +105,7 @@ const Sidebar = () => {
|
||||
Star
|
||||
</GitHubButton>
|
||||
</div>
|
||||
<div className="flex flex-grow items-center justify-end text-xs mr-2">v0.21.0</div>
|
||||
<div className="flex flex-grow items-center justify-end text-xs mr-2">v0.21.1</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -129,6 +129,24 @@ const GlobalStyle = createGlobalStyle`
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes rotateClockwise {
|
||||
0% {
|
||||
transform: scaleY(-1) rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: scaleY(-1) rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes rotateCounterClockwise {
|
||||
0% {
|
||||
transform: scaleY(-1) rotate(360deg);
|
||||
}
|
||||
100% {
|
||||
transform: scaleY(-1) rotate(0deg);
|
||||
}
|
||||
}
|
||||
|
||||
// codemirror
|
||||
.CodeMirror {
|
||||
.cm-variable-valid {
|
||||
|
@ -82,8 +82,12 @@ export const saveRequest = (itemUid, collectionUid) => (dispatch, getState) => {
|
||||
itemSchema
|
||||
.validate(itemToSave)
|
||||
.then(() => ipcRenderer.invoke('renderer:save-request', item.pathname, itemToSave))
|
||||
.then(() => toast.success('Request saved successfully'))
|
||||
.then(resolve)
|
||||
.catch(reject);
|
||||
.catch((err) => {
|
||||
toast.error('Failed to save request!');
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -258,6 +258,17 @@ export const collectionsSlice = createSlice({
|
||||
}
|
||||
}
|
||||
},
|
||||
deleteRequestDraft: (state, action) => {
|
||||
const collection = findCollectionByUid(state.collections, action.payload.collectionUid);
|
||||
|
||||
if (collection) {
|
||||
const item = findItemInCollection(collection, action.payload.itemUid);
|
||||
|
||||
if (item && item.draft) {
|
||||
item.draft = null;
|
||||
}
|
||||
}
|
||||
},
|
||||
newEphemeralHttpRequest: (state, action) => {
|
||||
const collection = findCollectionByUid(state.collections, action.payload.collectionUid);
|
||||
|
||||
@ -1103,7 +1114,6 @@ export const collectionsSlice = createSlice({
|
||||
const { cancelTokenUid } = action.payload;
|
||||
item.requestUid = requestUid;
|
||||
item.requestState = 'queued';
|
||||
item.response = null;
|
||||
item.cancelTokenUid = cancelTokenUid;
|
||||
}
|
||||
|
||||
@ -1224,6 +1234,7 @@ export const {
|
||||
requestCancelled,
|
||||
responseReceived,
|
||||
saveRequest,
|
||||
deleteRequestDraft,
|
||||
newEphemeralHttpRequest,
|
||||
collectionClicked,
|
||||
collectionFolderClicked,
|
||||
|
@ -53,3 +53,9 @@ body::-webkit-scrollbar-thumb,
|
||||
background-color: #cdcdcd;
|
||||
border-radius: 5rem;
|
||||
}
|
||||
|
||||
/* making all the checkboxes and radios bigger */
|
||||
input[type='checkbox'],
|
||||
input[type='radio'] {
|
||||
transform: scale(1.25);
|
||||
}
|
||||
|
@ -109,7 +109,8 @@ const darkTheme = {
|
||||
responseSendIcon: '#555',
|
||||
responseStatus: '#ccc',
|
||||
responseOk: '#8cd656',
|
||||
responseError: '#f06f57'
|
||||
responseError: '#f06f57',
|
||||
responseOverlayBg: 'rgba(30, 30, 30, 0.6)'
|
||||
},
|
||||
|
||||
collection: {
|
||||
|
@ -109,7 +109,8 @@ const lightTheme = {
|
||||
responseSendIcon: 'rgb(209, 213, 219)',
|
||||
responseStatus: 'rgb(117 117 117)',
|
||||
responseOk: '#047857',
|
||||
responseError: 'rgb(185, 28, 28)'
|
||||
responseError: 'rgb(185, 28, 28)',
|
||||
responseOverlayBg: 'rgba(255, 255, 255, 0.6)'
|
||||
},
|
||||
|
||||
collection: {
|
||||
|
@ -41,3 +41,10 @@ export const isWindowsOS = () => {
|
||||
|
||||
return osFamily.includes('windows');
|
||||
};
|
||||
|
||||
export const isMacOS = () => {
|
||||
const os = platform.os;
|
||||
const osFamily = os.family.toLowerCase();
|
||||
|
||||
return osFamily.includes('os x');
|
||||
};
|
||||
|
@ -29,14 +29,11 @@ const sendHttpRequest = async (item, collection, environment, collectionVariable
|
||||
});
|
||||
};
|
||||
|
||||
export const fetchGqlSchema = async (endpoint, environment, request, collectionVariables) => {
|
||||
export const fetchGqlSchema = async (endpoint, environment, request, collection) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const { ipcRenderer } = window;
|
||||
|
||||
ipcRenderer
|
||||
.invoke('fetch-gql-schema', endpoint, environment, request, collectionVariables)
|
||||
.then(resolve)
|
||||
.catch(reject);
|
||||
ipcRenderer.invoke('fetch-gql-schema', endpoint, environment, request, collection).then(resolve).catch(reject);
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "v0.21.0",
|
||||
"version": "v0.21.1",
|
||||
"name": "bruno",
|
||||
"description": "Opensource API Client for Exploring and Testing APIs",
|
||||
"homepage": "https://www.usebruno.com",
|
||||
|
@ -24,7 +24,10 @@ const template = [
|
||||
{ role: 'cut' },
|
||||
{ role: 'copy' },
|
||||
{ role: 'paste' },
|
||||
{ role: 'selectAll' }
|
||||
{ role: 'selectAll' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'hide' },
|
||||
{ role: 'hideOthers' }
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -2,8 +2,8 @@ const _ = require('lodash');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const chokidar = require('chokidar');
|
||||
const { hasBruExtension, writeFile } = require('../utils/filesystem');
|
||||
const { bruToEnvJson, envJsonToBru, bruToJson, jsonToBru } = require('../bru');
|
||||
const { hasBruExtension } = require('../utils/filesystem');
|
||||
const { bruToEnvJson, bruToJson } = require('../bru');
|
||||
const { dotenvToJson } = require('@usebruno/lang');
|
||||
|
||||
const { uuid } = require('../utils/common');
|
||||
@ -15,13 +15,6 @@ const EnvironmentSecretsStore = require('../store/env-secrets');
|
||||
|
||||
const environmentSecretsStore = new EnvironmentSecretsStore();
|
||||
|
||||
const isJsonEnvironmentConfig = (pathname, collectionPath) => {
|
||||
const dirname = path.dirname(pathname);
|
||||
const basename = path.basename(pathname);
|
||||
|
||||
return dirname === collectionPath && basename === 'environments.json';
|
||||
};
|
||||
|
||||
const isDotEnvFile = (pathname, collectionPath) => {
|
||||
const dirname = path.dirname(pathname);
|
||||
const basename = path.basename(pathname);
|
||||
@ -198,32 +191,6 @@ const add = async (win, pathname, collectionUid, collectionPath) => {
|
||||
}
|
||||
}
|
||||
|
||||
if (isJsonEnvironmentConfig(pathname, collectionPath)) {
|
||||
try {
|
||||
const dirname = path.dirname(pathname);
|
||||
const bruContent = fs.readFileSync(pathname, 'utf8');
|
||||
|
||||
const jsonData = JSON.parse(bruContent);
|
||||
|
||||
const envDirectory = path.join(dirname, 'environments');
|
||||
if (!fs.existsSync(envDirectory)) {
|
||||
fs.mkdirSync(envDirectory);
|
||||
}
|
||||
|
||||
for (const env of jsonData) {
|
||||
const bruEnvFilename = path.join(envDirectory, `${env.name}.bru`);
|
||||
const bruContent = envJsonToBru(env);
|
||||
await writeFile(bruEnvFilename, bruContent);
|
||||
}
|
||||
|
||||
await fs.unlinkSync(pathname);
|
||||
} catch (err) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (isBruEnvironmentConfig(pathname, collectionPath)) {
|
||||
return addEnvironmentFile(win, pathname, collectionUid, collectionPath);
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
const _ = require('lodash');
|
||||
const { bruToJsonV2, jsonToBruV2, bruToEnvJsonV2, envJsonToBruV2 } = require('@usebruno/lang');
|
||||
const { each } = require('lodash');
|
||||
|
||||
const bruToEnvJson = (bru) => {
|
||||
try {
|
||||
@ -10,7 +9,7 @@ const bruToEnvJson = (bru) => {
|
||||
// this need to be evaluated and safely removed
|
||||
// i don't see it being used in schema validation
|
||||
if (json && json.variables && json.variables.length) {
|
||||
each(json.variables, (v) => (v.type = 'text'));
|
||||
_.each(json.variables, (v) => (v.type = 'text'));
|
||||
}
|
||||
|
||||
return json;
|
||||
|
@ -9,6 +9,7 @@ const LastOpenedCollections = require('./store/last-opened-collections');
|
||||
const registerNetworkIpc = require('./ipc/network');
|
||||
const registerCollectionsIpc = require('./ipc/collection');
|
||||
const Watcher = require('./app/watcher');
|
||||
const { loadWindowState, saveWindowState } = require('./utils/window');
|
||||
|
||||
const lastOpenedCollections = new LastOpenedCollections();
|
||||
|
||||
@ -27,9 +28,13 @@ let watcher;
|
||||
|
||||
// Prepare the renderer once the app is ready
|
||||
app.on('ready', async () => {
|
||||
const { x, y, width, height } = loadWindowState();
|
||||
|
||||
mainWindow = new BrowserWindow({
|
||||
width: 1280,
|
||||
height: 768,
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
webPreferences: {
|
||||
nodeIntegration: true,
|
||||
contextIsolation: true,
|
||||
@ -54,6 +59,9 @@ app.on('ready', async () => {
|
||||
mainWindow.loadURL(url);
|
||||
watcher = new Watcher();
|
||||
|
||||
mainWindow.on('resize', () => saveWindowState(mainWindow));
|
||||
mainWindow.on('move', () => saveWindowState(mainWindow));
|
||||
|
||||
mainWindow.webContents.on('new-window', function (e, url) {
|
||||
e.preventDefault();
|
||||
require('electron').shell.openExternal(url);
|
||||
|
@ -486,6 +486,10 @@ const registerRendererEventHandlers = (mainWindow, watcher, lastOpenedCollection
|
||||
return Promise.reject(error);
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle('renderer:open-devtools', async () => {
|
||||
mainWindow.webContents.openDevTools();
|
||||
});
|
||||
};
|
||||
|
||||
const registerMainEventHandlers = (mainWindow, watcher, lastOpenedCollections) => {
|
||||
|
@ -469,7 +469,7 @@ const registerNetworkIpc = (mainWindow) => {
|
||||
});
|
||||
});
|
||||
|
||||
ipcMain.handle('fetch-gql-schema', async (event, endpoint, environment, request, collectionVariables) => {
|
||||
ipcMain.handle('fetch-gql-schema', async (event, endpoint, environment, request, collection) => {
|
||||
try {
|
||||
const envVars = getEnvVars(environment);
|
||||
const preparedRequest = prepareGqlIntrospectionRequest(endpoint, envVars, request);
|
||||
@ -483,7 +483,8 @@ const registerNetworkIpc = (mainWindow) => {
|
||||
});
|
||||
}
|
||||
|
||||
interpolateVars(preparedRequest, envVars, collectionVariables);
|
||||
const processEnvVars = getProcessEnvVars(collection.uid);
|
||||
interpolateVars(preparedRequest, envVars, collection.collectionVariables, processEnvVars);
|
||||
|
||||
const response = await axios(preparedRequest);
|
||||
|
||||
|
@ -1,16 +1,12 @@
|
||||
const Mustache = require('mustache');
|
||||
const Handlebars = require('handlebars');
|
||||
const { getIntrospectionQuery } = require('graphql');
|
||||
const { get } = require('lodash');
|
||||
|
||||
// override the default escape function to prevent escaping
|
||||
Mustache.escape = function (value) {
|
||||
return value;
|
||||
};
|
||||
|
||||
const prepareGqlIntrospectionRequest = (endpoint, envVars, request) => {
|
||||
if (endpoint && endpoint.length) {
|
||||
endpoint = Mustache.render(endpoint, envVars);
|
||||
endpoint = Handlebars.compile(endpoint, { noEscape: true })(envVars);
|
||||
}
|
||||
|
||||
const introspectionQuery = getIntrospectionQuery();
|
||||
const queryParams = {
|
||||
query: introspectionQuery
|
||||
@ -20,6 +16,7 @@ const prepareGqlIntrospectionRequest = (endpoint, envVars, request) => {
|
||||
method: 'POST',
|
||||
url: endpoint,
|
||||
headers: {
|
||||
...mapHeaders(request.headers),
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
@ -42,4 +39,10 @@ const prepareGqlIntrospectionRequest = (endpoint, envVars, request) => {
|
||||
return axiosRequest;
|
||||
};
|
||||
|
||||
const mapHeaders = (headers) => {
|
||||
const entries = headers.filter((header) => header.enabled).map(({ name, value }) => [name, value]);
|
||||
|
||||
return Object.fromEntries(entries);
|
||||
};
|
||||
|
||||
module.exports = prepareGqlIntrospectionRequest;
|
||||
|
31
packages/bruno-electron/src/store/window-state.js
Normal file
31
packages/bruno-electron/src/store/window-state.js
Normal file
@ -0,0 +1,31 @@
|
||||
const _ = require('lodash');
|
||||
const Store = require('electron-store');
|
||||
|
||||
const DEFAULT_WINDOW_WIDTH = 1280;
|
||||
const DEFAULT_WINDOW_HEIGHT = 768;
|
||||
|
||||
class WindowStateStore {
|
||||
constructor() {
|
||||
this.store = new Store({
|
||||
name: 'preferences',
|
||||
clearInvalidConfig: true
|
||||
});
|
||||
}
|
||||
|
||||
getBounds() {
|
||||
return (
|
||||
this.store.get('window-bounds') || {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: DEFAULT_WINDOW_WIDTH,
|
||||
height: DEFAULT_WINDOW_HEIGHT
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
setBounds(bounds) {
|
||||
this.store.set('window-bounds', bounds);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = WindowStateStore;
|
53
packages/bruno-electron/src/utils/window.js
Normal file
53
packages/bruno-electron/src/utils/window.js
Normal file
@ -0,0 +1,53 @@
|
||||
const { screen } = require('electron');
|
||||
const WindowStateStore = require('../store/window-state');
|
||||
|
||||
const windowStateStore = new WindowStateStore();
|
||||
|
||||
const DEFAULT_WINDOW_WIDTH = 1280;
|
||||
const DEFAULT_WINDOW_HEIGHT = 768;
|
||||
|
||||
const loadWindowState = () => {
|
||||
const bounds = windowStateStore.getBounds();
|
||||
|
||||
const positionValid = isPositionValid(bounds);
|
||||
const sizeValid = isSizeValid(bounds);
|
||||
|
||||
return {
|
||||
x: bounds.x && positionValid ? bounds.x : undefined,
|
||||
y: bounds.y && positionValid ? bounds.y : undefined,
|
||||
width: bounds.width && sizeValid ? bounds.width : DEFAULT_WINDOW_WIDTH,
|
||||
height: bounds.height && sizeValid ? bounds.height : DEFAULT_WINDOW_HEIGHT
|
||||
};
|
||||
};
|
||||
|
||||
const saveWindowState = (window) => {
|
||||
const bounds = window.getBounds();
|
||||
|
||||
windowStateStore.setBounds(bounds);
|
||||
};
|
||||
|
||||
const isPositionValid = (bounds) => {
|
||||
const area = getArea(bounds);
|
||||
|
||||
return (
|
||||
bounds.x >= area.x &&
|
||||
bounds.y >= area.y &&
|
||||
bounds.x + bounds.width <= area.x + area.width &&
|
||||
bounds.y + bounds.height <= area.y + area.height
|
||||
);
|
||||
};
|
||||
|
||||
const isSizeValid = (bounds) => {
|
||||
const area = getArea(bounds);
|
||||
|
||||
return bounds.width <= area.width && bounds.height <= area.height;
|
||||
};
|
||||
|
||||
const getArea = (bounds) => {
|
||||
return screen.getDisplayMatching(bounds).workArea;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
loadWindowState,
|
||||
saveWindowState
|
||||
};
|
@ -268,7 +268,7 @@ class AssertRuntime {
|
||||
expect(lhs).to.endWith(rhs);
|
||||
break;
|
||||
case 'between':
|
||||
const [min, max] = value.split(',');
|
||||
const [min, max] = rhs;
|
||||
expect(lhs).to.be.within(min, max);
|
||||
break;
|
||||
case 'isEmpty':
|
||||
|
273
packages/bruno-lang/v2/src/collectionBruToJson.js
Normal file
273
packages/bruno-lang/v2/src/collectionBruToJson.js
Normal file
@ -0,0 +1,273 @@
|
||||
const ohm = require('ohm-js');
|
||||
const _ = require('lodash');
|
||||
const { outdentString } = require('../../v1/src/utils');
|
||||
|
||||
const grammar = ohm.grammar(`Bru {
|
||||
BruFile = (meta | query | headers | auth | auths | vars | script | tests | docs)*
|
||||
auths = authbasic | authbearer
|
||||
|
||||
nl = "\\r"? "\\n"
|
||||
st = " " | "\\t"
|
||||
stnl = st | nl
|
||||
tagend = nl "}"
|
||||
optionalnl = ~tagend nl
|
||||
keychar = ~(tagend | st | nl | ":") any
|
||||
valuechar = ~(nl | tagend) any
|
||||
|
||||
// Dictionary Blocks
|
||||
dictionary = st* "{" pairlist? tagend
|
||||
pairlist = optionalnl* pair (~tagend stnl* pair)* (~tagend space)*
|
||||
pair = st* key st* ":" st* value st*
|
||||
key = keychar*
|
||||
value = valuechar*
|
||||
|
||||
// Text Blocks
|
||||
textblock = textline (~tagend nl textline)*
|
||||
textline = textchar*
|
||||
textchar = ~nl any
|
||||
|
||||
meta = "meta" dictionary
|
||||
|
||||
auth = "auth" dictionary
|
||||
|
||||
headers = "headers" dictionary
|
||||
|
||||
query = "query" dictionary
|
||||
|
||||
vars = varsreq | varsres
|
||||
varsreq = "vars:pre-request" dictionary
|
||||
varsres = "vars:post-response" dictionary
|
||||
|
||||
authbasic = "auth:basic" dictionary
|
||||
authbearer = "auth:bearer" dictionary
|
||||
|
||||
script = scriptreq | scriptres
|
||||
scriptreq = "script:pre-request" st* "{" nl* textblock tagend
|
||||
scriptres = "script:post-response" st* "{" nl* textblock tagend
|
||||
tests = "tests" st* "{" nl* textblock tagend
|
||||
docs = "docs" st* "{" nl* textblock tagend
|
||||
}`);
|
||||
|
||||
const mapPairListToKeyValPairs = (pairList = [], parseEnabled = true) => {
|
||||
if (!pairList.length) {
|
||||
return [];
|
||||
}
|
||||
return _.map(pairList[0], (pair) => {
|
||||
let name = _.keys(pair)[0];
|
||||
let value = pair[name];
|
||||
|
||||
if (!parseEnabled) {
|
||||
return {
|
||||
name,
|
||||
value
|
||||
};
|
||||
}
|
||||
|
||||
let enabled = true;
|
||||
if (name && name.length && name.charAt(0) === '~') {
|
||||
name = name.slice(1);
|
||||
enabled = false;
|
||||
}
|
||||
|
||||
return {
|
||||
name,
|
||||
value,
|
||||
enabled
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
const concatArrays = (objValue, srcValue) => {
|
||||
if (_.isArray(objValue) && _.isArray(srcValue)) {
|
||||
return objValue.concat(srcValue);
|
||||
}
|
||||
};
|
||||
|
||||
const mapPairListToKeyValPair = (pairList = []) => {
|
||||
if (!pairList || !pairList.length) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return _.merge({}, ...pairList[0]);
|
||||
};
|
||||
|
||||
const sem = grammar.createSemantics().addAttribute('ast', {
|
||||
BruFile(tags) {
|
||||
if (!tags || !tags.ast || !tags.ast.length) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return _.reduce(
|
||||
tags.ast,
|
||||
(result, item) => {
|
||||
return _.mergeWith(result, item, concatArrays);
|
||||
},
|
||||
{}
|
||||
);
|
||||
},
|
||||
dictionary(_1, _2, pairlist, _3) {
|
||||
return pairlist.ast;
|
||||
},
|
||||
pairlist(_1, pair, _2, rest, _3) {
|
||||
return [pair.ast, ...rest.ast];
|
||||
},
|
||||
pair(_1, key, _2, _3, _4, value, _5) {
|
||||
let res = {};
|
||||
res[key.ast] = value.ast ? value.ast.trim() : '';
|
||||
return res;
|
||||
},
|
||||
key(chars) {
|
||||
return chars.sourceString ? chars.sourceString.trim() : '';
|
||||
},
|
||||
value(chars) {
|
||||
return chars.sourceString ? chars.sourceString.trim() : '';
|
||||
},
|
||||
textblock(line, _1, rest) {
|
||||
return [line.ast, ...rest.ast].join('\n');
|
||||
},
|
||||
textline(chars) {
|
||||
return chars.sourceString;
|
||||
},
|
||||
textchar(char) {
|
||||
return char.sourceString;
|
||||
},
|
||||
nl(_1, _2) {
|
||||
return '';
|
||||
},
|
||||
st(_) {
|
||||
return '';
|
||||
},
|
||||
tagend(_1, _2) {
|
||||
return '';
|
||||
},
|
||||
_iter(...elements) {
|
||||
return elements.map((e) => e.ast);
|
||||
},
|
||||
meta(_1, dictionary) {
|
||||
let meta = mapPairListToKeyValPair(dictionary.ast) || {};
|
||||
|
||||
meta.type = 'collection';
|
||||
|
||||
return {
|
||||
meta
|
||||
};
|
||||
},
|
||||
auth(_1, dictionary) {
|
||||
let auth = mapPairListToKeyValPair(dictionary.ast) || {};
|
||||
|
||||
return {
|
||||
auth: {
|
||||
mode: auth ? auth.mode : 'none'
|
||||
}
|
||||
};
|
||||
},
|
||||
query(_1, dictionary) {
|
||||
return {
|
||||
query: mapPairListToKeyValPairs(dictionary.ast)
|
||||
};
|
||||
},
|
||||
headers(_1, dictionary) {
|
||||
return {
|
||||
headers: mapPairListToKeyValPairs(dictionary.ast)
|
||||
};
|
||||
},
|
||||
authbasic(_1, dictionary) {
|
||||
const auth = mapPairListToKeyValPairs(dictionary.ast, false);
|
||||
const usernameKey = _.find(auth, { name: 'username' });
|
||||
const passwordKey = _.find(auth, { name: 'password' });
|
||||
const username = usernameKey ? usernameKey.value : '';
|
||||
const password = passwordKey ? passwordKey.value : '';
|
||||
return {
|
||||
auth: {
|
||||
basic: {
|
||||
username,
|
||||
password
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
authbearer(_1, dictionary) {
|
||||
const auth = mapPairListToKeyValPairs(dictionary.ast, false);
|
||||
const tokenKey = _.find(auth, { name: 'token' });
|
||||
const token = tokenKey ? tokenKey.value : '';
|
||||
return {
|
||||
auth: {
|
||||
bearer: {
|
||||
token
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
varsreq(_1, dictionary) {
|
||||
const vars = mapPairListToKeyValPairs(dictionary.ast);
|
||||
_.each(vars, (v) => {
|
||||
let name = v.name;
|
||||
if (name && name.length && name.charAt(0) === '@') {
|
||||
v.name = name.slice(1);
|
||||
v.local = true;
|
||||
} else {
|
||||
v.local = false;
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
vars: {
|
||||
req: vars
|
||||
}
|
||||
};
|
||||
},
|
||||
varsres(_1, dictionary) {
|
||||
const vars = mapPairListToKeyValPairs(dictionary.ast);
|
||||
_.each(vars, (v) => {
|
||||
let name = v.name;
|
||||
if (name && name.length && name.charAt(0) === '@') {
|
||||
v.name = name.slice(1);
|
||||
v.local = true;
|
||||
} else {
|
||||
v.local = false;
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
vars: {
|
||||
res: vars
|
||||
}
|
||||
};
|
||||
},
|
||||
scriptreq(_1, _2, _3, _4, textblock, _5) {
|
||||
return {
|
||||
script: {
|
||||
req: outdentString(textblock.sourceString)
|
||||
}
|
||||
};
|
||||
},
|
||||
scriptres(_1, _2, _3, _4, textblock, _5) {
|
||||
return {
|
||||
script: {
|
||||
res: outdentString(textblock.sourceString)
|
||||
}
|
||||
};
|
||||
},
|
||||
tests(_1, _2, _3, _4, textblock, _5) {
|
||||
return {
|
||||
tests: outdentString(textblock.sourceString)
|
||||
};
|
||||
},
|
||||
docs(_1, _2, _3, _4, textblock, _5) {
|
||||
return {
|
||||
docs: outdentString(textblock.sourceString)
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
const parser = (input) => {
|
||||
const match = grammar.match(input);
|
||||
|
||||
if (match.succeeded()) {
|
||||
return sem(match).ast;
|
||||
} else {
|
||||
throw new Error(match.message);
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = parser;
|
185
packages/bruno-lang/v2/src/jsonToCollectionBru.js
Normal file
185
packages/bruno-lang/v2/src/jsonToCollectionBru.js
Normal file
@ -0,0 +1,185 @@
|
||||
const _ = require('lodash');
|
||||
|
||||
const { indentString } = require('../../v1/src/utils');
|
||||
|
||||
const enabled = (items = []) => items.filter((item) => item.enabled);
|
||||
const disabled = (items = []) => items.filter((item) => !item.enabled);
|
||||
|
||||
// remove the last line if two new lines are found
|
||||
const stripLastLine = (text) => {
|
||||
if (!text || !text.length) return text;
|
||||
|
||||
return text.replace(/(\r?\n)$/, '');
|
||||
};
|
||||
|
||||
const jsonToBru = (json) => {
|
||||
const { meta, query, headers, auth, script, tests, vars, docs } = json;
|
||||
|
||||
let bru = '';
|
||||
|
||||
if (meta) {
|
||||
bru += 'meta {\n';
|
||||
for (const key in meta) {
|
||||
bru += ` ${key}: ${meta[key]}\n`;
|
||||
}
|
||||
bru += '}\n\n';
|
||||
}
|
||||
|
||||
if (query && query.length) {
|
||||
bru += 'query {';
|
||||
if (enabled(query).length) {
|
||||
bru += `\n${indentString(
|
||||
enabled(query)
|
||||
.map((item) => `${item.name}: ${item.value}`)
|
||||
.join('\n')
|
||||
)}`;
|
||||
}
|
||||
|
||||
if (disabled(query).length) {
|
||||
bru += `\n${indentString(
|
||||
disabled(query)
|
||||
.map((item) => `~${item.name}: ${item.value}`)
|
||||
.join('\n')
|
||||
)}`;
|
||||
}
|
||||
|
||||
bru += '\n}\n\n';
|
||||
}
|
||||
|
||||
if (headers && headers.length) {
|
||||
bru += 'headers {';
|
||||
if (enabled(headers).length) {
|
||||
bru += `\n${indentString(
|
||||
enabled(headers)
|
||||
.map((item) => `${item.name}: ${item.value}`)
|
||||
.join('\n')
|
||||
)}`;
|
||||
}
|
||||
|
||||
if (disabled(headers).length) {
|
||||
bru += `\n${indentString(
|
||||
disabled(headers)
|
||||
.map((item) => `~${item.name}: ${item.value}`)
|
||||
.join('\n')
|
||||
)}`;
|
||||
}
|
||||
|
||||
bru += '\n}\n\n';
|
||||
}
|
||||
|
||||
if (auth && auth.mode) {
|
||||
bru += `auth {
|
||||
${indentString(`mode: ${auth.mode}`)}
|
||||
}
|
||||
|
||||
`;
|
||||
}
|
||||
|
||||
if (auth && auth.basic) {
|
||||
bru += `auth:basic {
|
||||
${indentString(`username: ${auth.basic.username}`)}
|
||||
${indentString(`password: ${auth.basic.password}`)}
|
||||
}
|
||||
|
||||
`;
|
||||
}
|
||||
|
||||
if (auth && auth.bearer) {
|
||||
bru += `auth:bearer {
|
||||
${indentString(`token: ${auth.bearer.token}`)}
|
||||
}
|
||||
|
||||
`;
|
||||
}
|
||||
|
||||
let reqvars = _.get(vars, 'req');
|
||||
let resvars = _.get(vars, 'res');
|
||||
if (reqvars && reqvars.length) {
|
||||
const varsEnabled = _.filter(reqvars, (v) => v.enabled && !v.local);
|
||||
const varsDisabled = _.filter(reqvars, (v) => !v.enabled && !v.local);
|
||||
const varsLocalEnabled = _.filter(reqvars, (v) => v.enabled && v.local);
|
||||
const varsLocalDisabled = _.filter(reqvars, (v) => !v.enabled && v.local);
|
||||
|
||||
bru += `vars:pre-request {`;
|
||||
|
||||
if (varsEnabled.length) {
|
||||
bru += `\n${indentString(varsEnabled.map((item) => `${item.name}: ${item.value}`).join('\n'))}`;
|
||||
}
|
||||
|
||||
if (varsLocalEnabled.length) {
|
||||
bru += `\n${indentString(varsLocalEnabled.map((item) => `@${item.name}: ${item.value}`).join('\n'))}`;
|
||||
}
|
||||
|
||||
if (varsDisabled.length) {
|
||||
bru += `\n${indentString(varsDisabled.map((item) => `~${item.name}: ${item.value}`).join('\n'))}`;
|
||||
}
|
||||
|
||||
if (varsLocalDisabled.length) {
|
||||
bru += `\n${indentString(varsLocalDisabled.map((item) => `~@${item.name}: ${item.value}`).join('\n'))}`;
|
||||
}
|
||||
|
||||
bru += '\n}\n\n';
|
||||
}
|
||||
if (resvars && resvars.length) {
|
||||
const varsEnabled = _.filter(resvars, (v) => v.enabled && !v.local);
|
||||
const varsDisabled = _.filter(resvars, (v) => !v.enabled && !v.local);
|
||||
const varsLocalEnabled = _.filter(resvars, (v) => v.enabled && v.local);
|
||||
const varsLocalDisabled = _.filter(resvars, (v) => !v.enabled && v.local);
|
||||
|
||||
bru += `vars:post-response {`;
|
||||
|
||||
if (varsEnabled.length) {
|
||||
bru += `\n${indentString(varsEnabled.map((item) => `${item.name}: ${item.value}`).join('\n'))}`;
|
||||
}
|
||||
|
||||
if (varsLocalEnabled.length) {
|
||||
bru += `\n${indentString(varsLocalEnabled.map((item) => `@${item.name}: ${item.value}`).join('\n'))}`;
|
||||
}
|
||||
|
||||
if (varsDisabled.length) {
|
||||
bru += `\n${indentString(varsDisabled.map((item) => `~${item.name}: ${item.value}`).join('\n'))}`;
|
||||
}
|
||||
|
||||
if (varsLocalDisabled.length) {
|
||||
bru += `\n${indentString(varsLocalDisabled.map((item) => `~@${item.name}: ${item.value}`).join('\n'))}`;
|
||||
}
|
||||
|
||||
bru += '\n}\n\n';
|
||||
}
|
||||
|
||||
if (script && script.req && script.req.length) {
|
||||
bru += `script:pre-request {
|
||||
${indentString(script.req)}
|
||||
}
|
||||
|
||||
`;
|
||||
}
|
||||
|
||||
if (script && script.res && script.res.length) {
|
||||
bru += `script:post-response {
|
||||
${indentString(script.res)}
|
||||
}
|
||||
|
||||
`;
|
||||
}
|
||||
|
||||
if (tests && tests.length) {
|
||||
bru += `tests {
|
||||
${indentString(tests)}
|
||||
}
|
||||
|
||||
`;
|
||||
}
|
||||
|
||||
if (docs && docs.length) {
|
||||
bru += `docs {
|
||||
${indentString(docs)}
|
||||
}
|
||||
|
||||
`;
|
||||
}
|
||||
|
||||
return stripLastLine(bru);
|
||||
};
|
||||
|
||||
module.exports = jsonToBru;
|
24
packages/bruno-lang/v2/tests/collection.spec.js
Normal file
24
packages/bruno-lang/v2/tests/collection.spec.js
Normal file
@ -0,0 +1,24 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const collectionBruToJson = require('../src/collectionBruToJson');
|
||||
const jsonToCollectionBru = require('../src/jsonToCollectionBru');
|
||||
|
||||
describe('collectionBruToJson', () => {
|
||||
it('should parse the collection bru file', () => {
|
||||
const input = fs.readFileSync(path.join(__dirname, 'fixtures', 'collection.bru'), 'utf8');
|
||||
const expected = require('./fixtures/collection.json');
|
||||
const output = collectionBruToJson(input);
|
||||
|
||||
expect(output).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('jsonToCollectionBru', () => {
|
||||
it('should convert the collection json to bru', () => {
|
||||
const input = require('./fixtures/collection.json');
|
||||
const expected = fs.readFileSync(path.join(__dirname, 'fixtures', 'collection.bru'), 'utf8');
|
||||
const output = jsonToCollectionBru(input);
|
||||
|
||||
expect(output).toEqual(expected);
|
||||
});
|
||||
});
|
43
packages/bruno-lang/v2/tests/fixtures/collection.bru
vendored
Normal file
43
packages/bruno-lang/v2/tests/fixtures/collection.bru
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
meta {
|
||||
type: collection
|
||||
}
|
||||
|
||||
headers {
|
||||
content-type: application/json
|
||||
Authorization: Bearer 123
|
||||
~transaction-id: {{transactionId}}
|
||||
}
|
||||
|
||||
auth {
|
||||
mode: none
|
||||
}
|
||||
|
||||
auth:basic {
|
||||
username: john
|
||||
password: secret
|
||||
}
|
||||
|
||||
auth:bearer {
|
||||
token: 123
|
||||
}
|
||||
|
||||
vars:pre-request {
|
||||
departingDate: 2020-01-01
|
||||
~returningDate: 2020-01-02
|
||||
}
|
||||
|
||||
vars:post-response {
|
||||
~transactionId: $res.body.transactionId
|
||||
}
|
||||
|
||||
script:pre-request {
|
||||
console.log("In Collection pre Request Script");
|
||||
}
|
||||
|
||||
script:post-response {
|
||||
console.log("In Collection post Request Script");
|
||||
}
|
||||
|
||||
docs {
|
||||
This request needs auth token to be set in the headers.
|
||||
}
|
61
packages/bruno-lang/v2/tests/fixtures/collection.json
vendored
Normal file
61
packages/bruno-lang/v2/tests/fixtures/collection.json
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
{
|
||||
"meta": {
|
||||
"type": "collection"
|
||||
},
|
||||
"headers": [
|
||||
{
|
||||
"name": "content-type",
|
||||
"value": "application/json",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"name": "Authorization",
|
||||
"value": "Bearer 123",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"name": "transaction-id",
|
||||
"value": "{{transactionId}}",
|
||||
"enabled": false
|
||||
}
|
||||
],
|
||||
"auth": {
|
||||
"mode": "none",
|
||||
"basic": {
|
||||
"username": "john",
|
||||
"password": "secret"
|
||||
},
|
||||
"bearer": {
|
||||
"token": "123"
|
||||
}
|
||||
},
|
||||
"vars": {
|
||||
"req": [
|
||||
{
|
||||
"name": "departingDate",
|
||||
"value": "2020-01-01",
|
||||
"enabled": true,
|
||||
"local": false
|
||||
},
|
||||
{
|
||||
"name": "returningDate",
|
||||
"value": "2020-01-02",
|
||||
"enabled": false,
|
||||
"local": false
|
||||
}
|
||||
],
|
||||
"res": [
|
||||
{
|
||||
"name": "transactionId",
|
||||
"value": "$res.body.transactionId",
|
||||
"enabled": false,
|
||||
"local": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"script": {
|
||||
"req": "console.log(\"In Collection pre Request Script\");",
|
||||
"res": "console.log(\"In Collection post Request Script\");"
|
||||
},
|
||||
"docs": "This request needs auth token to be set in the headers."
|
||||
}
|
@ -123,7 +123,7 @@ const itemSchema = Yup.object({
|
||||
uid: uidSchema,
|
||||
type: Yup.string().oneOf(['http-request', 'graphql-request', 'folder']).required('type is required'),
|
||||
seq: Yup.number().min(1),
|
||||
name: Yup.string().min(1, 'name must be atleast 1 characters').required('name is required'),
|
||||
name: Yup.string().min(1, 'name must be at least 1 character').required('name is required'),
|
||||
request: requestSchema.when('type', {
|
||||
is: (type) => ['http-request', 'graphql-request'].includes(type),
|
||||
then: (schema) => schema.required('request is required when item-type is request')
|
||||
@ -138,7 +138,7 @@ const itemSchema = Yup.object({
|
||||
const collectionSchema = Yup.object({
|
||||
version: Yup.string().oneOf(['1']).required('version is required'),
|
||||
uid: uidSchema,
|
||||
name: Yup.string().min(1, 'name must be atleast 1 characters').required('name is required'),
|
||||
name: Yup.string().min(1, 'name must be at least 1 character').required('name is required'),
|
||||
items: Yup.array().of(itemSchema),
|
||||
activeEnvironmentUid: Yup.string()
|
||||
.length(21, 'activeEnvironmentUid must be 21 characters in length')
|
||||
|
@ -34,7 +34,7 @@ describe('Item Schema Validation', () => {
|
||||
|
||||
return Promise.all([
|
||||
expect(itemSchema.validate(item)).rejects.toEqual(
|
||||
validationErrorWithMessages('name must be atleast 1 characters')
|
||||
validationErrorWithMessages('name must be at least 1 character')
|
||||
)
|
||||
]);
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user