diff --git a/package-lock.json b/package-lock.json index ade21b12..a1e84508 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5588,13 +5588,6 @@ "version": "1.12.0", "license": "MIT" }, - "node_modules/axios": { - "version": "0.26.1", - "license": "MIT", - "dependencies": { - "follow-redirects": "^1.14.8" - } - }, "node_modules/babel-jest": { "version": "29.3.1", "dev": true, @@ -6248,11 +6241,13 @@ } }, "node_modules/call-bind": { - "version": "1.0.2", - "license": "MIT", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", + "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.1", + "set-function-length": "^1.1.1" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -7327,12 +7322,27 @@ "dev": true, "license": "MIT" }, + "node_modules/define-data-property": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", + "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "dependencies": { + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/define-properties": { - "version": "1.1.4", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dev": true, - "license": "MIT", "optional": true, "dependencies": { + "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" }, @@ -8680,8 +8690,12 @@ } }, "node_modules/function-bind": { - "version": "1.1.1", - "license": "MIT" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/generic-names": { "version": "4.0.0", @@ -8722,12 +8736,14 @@ } }, "node_modules/get-intrinsic": { - "version": "1.1.3", - "license": "MIT", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", + "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -8956,6 +8972,17 @@ "csstype": "^3.0.10" } }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/got": { "version": "9.6.0", "dev": true, @@ -9172,9 +9199,7 @@ }, "node_modules/has-property-descriptors": { "version": "1.0.0", - "dev": true, "license": "MIT", - "optional": true, "dependencies": { "get-intrinsic": "^1.1.1" }, @@ -9182,6 +9207,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-symbols": { "version": "1.0.3", "license": "MIT", @@ -9220,6 +9256,17 @@ "node": ">=0.10.0" } }, + "node_modules/hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/he": { "version": "1.2.0", "dev": true, @@ -11938,8 +11985,9 @@ } }, "node_modules/object-inspect": { - "version": "1.12.3", - "license": "MIT", + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -12225,14 +12273,6 @@ "xml2js": "^0.4.5" } }, - "node_modules/parse-curl": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/parse-curl/-/parse-curl-0.2.6.tgz", - "integrity": "sha512-ENhXeIxG4A6wFvYSU87b0o3Tp6U+Wup069GYhXCn0ZP/E7evfvomTSM/MeEOs3QTyuye+u2r7fFRj6nX0q9kQA==", - "dependencies": { - "shellwords": "^0.1.0" - } - }, "node_modules/parse-headers": { "version": "2.0.5", "dev": true, @@ -14617,6 +14657,20 @@ "dev": true, "license": "ISC" }, + "node_modules/set-function-length": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", + "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "dependencies": { + "define-data-property": "^1.1.1", + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/set-value": { "version": "4.1.0", "funding": [ @@ -14671,11 +14725,6 @@ "node": ">=8" } }, - "node_modules/shellwords": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", - "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==" - }, "node_modules/side-channel": { "version": "1.0.4", "license": "MIT", @@ -14921,6 +14970,14 @@ "node": ">=10.0.0" } }, + "node_modules/strict-uri-encode": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", + "integrity": "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==", + "engines": { + "node": ">=4" + } + }, "node_modules/string_decoder": { "version": "1.1.1", "license": "MIT", @@ -16041,6 +16098,15 @@ "punycode": "^2.1.0" } }, + "node_modules/url": { + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.3.tgz", + "integrity": "sha512-6hxOLGfZASQK/cijlZnZJTq8OXAkt/3YGfQX45vvMYXpZoo8NdWZcY73K108Jf759lS1Bv/8wXnHDTSz17dSRw==", + "dependencies": { + "punycode": "^1.4.1", + "qs": "^6.11.2" + } + }, "node_modules/url-parse": { "version": "1.5.10", "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", @@ -16061,6 +16127,25 @@ "node": ">=4" } }, + "node_modules/url/node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==" + }, + "node_modules/url/node_modules/qs": { + "version": "6.11.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz", + "integrity": "sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/use-sync-external-store": { "version": "1.2.0", "license": "MIT", @@ -16584,7 +16669,8 @@ }, "node_modules/yargs-parser": { "version": "21.1.1", - "license": "ISC", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "engines": { "node": ">=12" } @@ -16637,10 +16723,11 @@ "@tippyjs/react": "^4.2.6", "@usebruno/graphql-docs": "0.1.0", "@usebruno/schema": "0.6.0", - "axios": "^0.26.0", + "axios": "^1.5.1", "classnames": "^2.3.1", "codemirror": "^5.65.2", "codemirror-graphql": "^1.2.5", + "cookie": "^0.6.0", "escape-html": "^1.0.3", "file-dialog": "^0.0.8", "file-saver": "^2.0.5", @@ -16653,17 +16740,18 @@ "httpsnippet": "^3.0.1", "idb": "^7.0.0", "immer": "^9.0.15", + "jsesc": "^3.0.2", "know-your-http-well": "^0.5.0", "lodash": "^4.17.21", "markdown-it": "^13.0.2", "mousetrap": "^1.6.5", "nanoid": "3.3.4", "next": "12.3.3", - "parse-curl": "^0.2.6", "path": "^0.12.7", "platform": "^1.3.6", "posthog-node": "^2.1.0", "qs": "^6.11.0", + "query-string": "^7.0.1", "react": "18.2.0", "react-dnd": "^16.0.1", "react-dnd-html5-backend": "^16.0.1", @@ -16676,7 +16764,9 @@ "sass": "^1.46.0", "styled-components": "^5.3.3", "tailwindcss": "^2.2.19", + "url": "^0.11.3", "xml-formatter": "^3.5.0", + "yargs-parser": "^21.1.1", "yup": "^0.32.11" }, "devDependencies": { @@ -16702,6 +16792,32 @@ "version": "2.0.1", "license": "Python-2.0" }, + "packages/bruno-app/node_modules/axios": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.0.tgz", + "integrity": "sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg==", + "dependencies": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "packages/bruno-app/node_modules/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "engines": { + "node": ">= 0.6" + } + }, + "packages/bruno-app/node_modules/decode-uri-component": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", + "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", + "engines": { + "node": ">=0.10" + } + }, "packages/bruno-app/node_modules/entities": { "version": "3.0.1", "license": "BSD-2-Clause", @@ -16712,6 +16828,25 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "packages/bruno-app/node_modules/filter-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz", + "integrity": "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "packages/bruno-app/node_modules/jsesc": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, "packages/bruno-app/node_modules/markdown-it": { "version": "13.0.2", "license": "MIT", @@ -16726,6 +16861,31 @@ "markdown-it": "bin/markdown-it.js" } }, + "packages/bruno-app/node_modules/query-string": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-7.1.3.tgz", + "integrity": "sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==", + "dependencies": { + "decode-uri-component": "^0.2.2", + "filter-obj": "^1.1.0", + "split-on-first": "^1.0.0", + "strict-uri-encode": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "packages/bruno-app/node_modules/split-on-first": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", + "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==", + "engines": { + "node": ">=6" + } + }, "packages/bruno-cli": { "name": "@usebruno/cli", "version": "1.0.0", @@ -16820,7 +16980,7 @@ }, "packages/bruno-electron": { "name": "bruno", - "version": "v1.0.1", + "version": "v1.1.0", "dependencies": { "@aws-sdk/credential-providers": "^3.425.0", "@usebruno/js": "0.9.1", @@ -17055,7 +17215,7 @@ "@usebruno/query": "0.1.0", "ajv": "^8.12.0", "atob": "^2.1.2", - "axios": "^0.26.0", + "axios": "^1.5.1", "btoa": "^1.2.1", "chai": "^4.3.7", "chai-string": "^1.5.0", @@ -17087,6 +17247,16 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "packages/bruno-js/node_modules/axios": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.0.tgz", + "integrity": "sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg==", + "dependencies": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "packages/bruno-js/node_modules/json-schema-traverse": { "version": "1.0.0", "license": "MIT" @@ -20738,11 +20908,12 @@ "@tippyjs/react": "^4.2.6", "@usebruno/graphql-docs": "0.1.0", "@usebruno/schema": "0.6.0", - "axios": "^0.26.0", + "axios": "^1.5.1", "babel-loader": "^8.2.3", "classnames": "^2.3.1", "codemirror": "^5.65.2", "codemirror-graphql": "^1.2.5", + "cookie": "^0.6.0", "cross-env": "^7.0.3", "css-loader": "^6.5.1", "escape-html": "^1.0.3", @@ -20760,6 +20931,7 @@ "httpsnippet": "^3.0.1", "idb": "^7.0.0", "immer": "^9.0.15", + "jsesc": "^3.0.2", "know-your-http-well": "^0.5.0", "lodash": "^4.17.21", "markdown-it": "^13.0.2", @@ -20767,12 +20939,12 @@ "mousetrap": "^1.6.5", "nanoid": "3.3.4", "next": "12.3.3", - "parse-curl": "^0.2.6", "path": "^0.12.7", "platform": "^1.3.6", "posthog-node": "^2.1.0", "prettier": "^2.7.1", "qs": "^6.11.0", + "query-string": "^7.0.1", "react": "18.2.0", "react-dnd": "^16.0.1", "react-dnd-html5-backend": "^16.0.1", @@ -20786,18 +20958,50 @@ "style-loader": "^3.3.1", "styled-components": "^5.3.3", "tailwindcss": "^2.2.19", + "url": "^0.11.3", "webpack": "^5.64.4", "webpack-cli": "^4.9.1", "xml-formatter": "^3.5.0", + "yargs-parser": "*", "yup": "^0.32.11" }, "dependencies": { "argparse": { "version": "2.0.1" }, + "axios": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.0.tgz", + "integrity": "sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg==", + "requires": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==" + }, + "decode-uri-component": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", + "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==" + }, "entities": { "version": "3.0.1" }, + "filter-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz", + "integrity": "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==" + }, + "jsesc": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==" + }, "markdown-it": { "version": "13.0.2", "requires": { @@ -20807,6 +21011,22 @@ "mdurl": "^1.0.1", "uc.micro": "^1.0.5" } + }, + "query-string": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-7.1.3.tgz", + "integrity": "sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==", + "requires": { + "decode-uri-component": "^0.2.2", + "filter-obj": "^1.1.0", + "split-on-first": "^1.0.0", + "strict-uri-encode": "^2.0.0" + } + }, + "split-on-first": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", + "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==" } } }, @@ -20913,7 +21133,7 @@ "@usebruno/query": "0.1.0", "ajv": "^8.12.0", "atob": "^2.1.2", - "axios": "^0.26.0", + "axios": "^1.5.1", "btoa": "^1.2.1", "chai": "^4.3.7", "chai-string": "^1.5.0", @@ -20937,6 +21157,16 @@ "uri-js": "^4.2.2" } }, + "axios": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.0.tgz", + "integrity": "sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg==", + "requires": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "json-schema-traverse": { "version": "1.0.0" }, @@ -21472,12 +21702,6 @@ "aws4": { "version": "1.12.0" }, - "axios": { - "version": "0.26.1", - "requires": { - "follow-redirects": "^1.14.8" - } - }, "babel-jest": { "version": "29.3.1", "dev": true, @@ -22041,10 +22265,13 @@ } }, "call-bind": { - "version": "1.0.2", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", + "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.1", + "set-function-length": "^1.1.1" } }, "callsites": { @@ -22704,11 +22931,24 @@ "version": "1.1.3", "dev": true }, + "define-data-property": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", + "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "requires": { + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + } + }, "define-properties": { - "version": "1.1.4", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dev": true, "optional": true, "requires": { + "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" } @@ -23601,7 +23841,9 @@ "optional": true }, "function-bind": { - "version": "1.1.1" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" }, "generic-names": { "version": "4.0.0", @@ -23627,11 +23869,14 @@ "version": "2.0.0" }, "get-intrinsic": { - "version": "1.1.3", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", + "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" } }, "get-own-enumerable-property-symbols": { @@ -23780,6 +24025,14 @@ "version": "2.1.11", "requires": {} }, + "gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "requires": { + "get-intrinsic": "^1.1.3" + } + }, "got": { "version": "9.6.0", "dev": true, @@ -23924,12 +24177,15 @@ }, "has-property-descriptors": { "version": "1.0.0", - "dev": true, - "optional": true, "requires": { "get-intrinsic": "^1.1.1" } }, + "has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==" + }, "has-symbols": { "version": "1.0.3" }, @@ -23951,6 +24207,14 @@ } } }, + "hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "requires": { + "function-bind": "^1.1.2" + } + }, "he": { "version": "1.2.0", "dev": true @@ -25657,7 +25921,9 @@ "version": "2.2.0" }, "object-inspect": { - "version": "1.12.3" + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==" }, "object-keys": { "version": "1.1.1", @@ -25830,14 +26096,6 @@ "xml2js": "^0.4.5" } }, - "parse-curl": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/parse-curl/-/parse-curl-0.2.6.tgz", - "integrity": "sha512-ENhXeIxG4A6wFvYSU87b0o3Tp6U+Wup069GYhXCn0ZP/E7evfvomTSM/MeEOs3QTyuye+u2r7fFRj6nX0q9kQA==", - "requires": { - "shellwords": "^0.1.0" - } - }, "parse-headers": { "version": "2.0.5", "dev": true @@ -27325,6 +27583,17 @@ "version": "2.0.0", "dev": true }, + "set-function-length": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", + "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "requires": { + "define-data-property": "^1.1.1", + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + } + }, "set-value": { "version": "4.1.0", "requires": { @@ -27356,11 +27625,6 @@ "version": "3.0.0", "dev": true }, - "shellwords": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", - "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==" - }, "side-channel": { "version": "1.0.4", "requires": { @@ -27537,6 +27801,11 @@ "streamsearch": { "version": "1.1.0" }, + "strict-uri-encode": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", + "integrity": "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==" + }, "string_decoder": { "version": "1.1.1", "requires": { @@ -28237,6 +28506,30 @@ "punycode": "^2.1.0" } }, + "url": { + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.3.tgz", + "integrity": "sha512-6hxOLGfZASQK/cijlZnZJTq8OXAkt/3YGfQX45vvMYXpZoo8NdWZcY73K108Jf759lS1Bv/8wXnHDTSz17dSRw==", + "requires": { + "punycode": "^1.4.1", + "qs": "^6.11.2" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==" + }, + "qs": { + "version": "6.11.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz", + "integrity": "sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==", + "requires": { + "side-channel": "^1.0.4" + } + } + } + }, "url-parse": { "version": "1.5.10", "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", @@ -28586,7 +28879,9 @@ } }, "yargs-parser": { - "version": "21.1.1" + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==" }, "yauzl": { "version": "2.10.0", diff --git a/packages/bruno-app/package.json b/packages/bruno-app/package.json index 77ff96b6..d5ba0b1a 100644 --- a/packages/bruno-app/package.json +++ b/packages/bruno-app/package.json @@ -20,10 +20,11 @@ "@tippyjs/react": "^4.2.6", "@usebruno/graphql-docs": "0.1.0", "@usebruno/schema": "0.6.0", - "axios": "^0.26.0", + "axios": "^1.5.1", "classnames": "^2.3.1", "codemirror": "^5.65.2", "codemirror-graphql": "^1.2.5", + "cookie": "^0.6.0", "escape-html": "^1.0.3", "file-dialog": "^0.0.8", "file-saver": "^2.0.5", @@ -36,17 +37,18 @@ "httpsnippet": "^3.0.1", "idb": "^7.0.0", "immer": "^9.0.15", + "jsesc": "^3.0.2", "know-your-http-well": "^0.5.0", "lodash": "^4.17.21", "markdown-it": "^13.0.2", "mousetrap": "^1.6.5", "nanoid": "3.3.4", "next": "12.3.3", - "parse-curl": "^0.2.6", "path": "^0.12.7", "platform": "^1.3.6", "posthog-node": "^2.1.0", "qs": "^6.11.0", + "query-string": "^7.0.1", "react": "18.2.0", "react-dnd": "^16.0.1", "react-dnd-html5-backend": "^16.0.1", @@ -59,7 +61,9 @@ "sass": "^1.46.0", "styled-components": "^5.3.3", "tailwindcss": "^2.2.19", + "url": "^0.11.3", "xml-formatter": "^3.5.0", + "yargs-parser": "^21.1.1", "yup": "^0.32.11" }, "devDependencies": { diff --git a/packages/bruno-app/src/utils/common/codemirror.js b/packages/bruno-app/src/utils/common/codemirror.js index 6074dbdc..4be4dc47 100644 --- a/packages/bruno-app/src/utils/common/codemirror.js +++ b/packages/bruno-app/src/utils/common/codemirror.js @@ -1,5 +1,4 @@ import get from 'lodash/get'; -import isString from 'lodash/isString'; let CodeMirror; const SERVER_RENDERED = typeof navigator === 'undefined' || global['PREVENT_CODEMIRROR_RENDER'] === true; diff --git a/packages/bruno-app/src/utils/common/index.js b/packages/bruno-app/src/utils/common/index.js index 992ec233..be698243 100644 --- a/packages/bruno-app/src/utils/common/index.js +++ b/packages/bruno-app/src/utils/common/index.js @@ -94,3 +94,15 @@ export const getContentType = (headers) => { return ''; }; + +export const startsWith = (str, search) => { + if (!str || !str.length || typeof str !== 'string') { + return false; + } + + if (!search || !search.length || typeof search !== 'string') { + return false; + } + + return str.substr(0, search.length) === search; +}; diff --git a/packages/bruno-app/src/utils/common/index.spec.js b/packages/bruno-app/src/utils/common/index.spec.js index 6d52ed1a..3484fac9 100644 --- a/packages/bruno-app/src/utils/common/index.spec.js +++ b/packages/bruno-app/src/utils/common/index.spec.js @@ -1,6 +1,6 @@ const { describe, it, expect } = require('@jest/globals'); -import { normalizeFileName } from './index'; +import { normalizeFileName, startsWith } from './index'; describe('common utils', () => { describe('normalizeFileName', () => { @@ -16,4 +16,37 @@ describe('common utils', () => { expect(normalizeFileName('foo\\bar\\')).toBe('foo-bar-'); }); }); + + describe('startsWith', () => { + it('should return false if str is not a string', () => { + expect(startsWith(null, 'foo')).toBe(false); + expect(startsWith(undefined, 'foo')).toBe(false); + expect(startsWith(123, 'foo')).toBe(false); + expect(startsWith({}, 'foo')).toBe(false); + expect(startsWith([], 'foo')).toBe(false); + }); + + it('should return false if search is not a string', () => { + expect(startsWith('foo', null)).toBe(false); + expect(startsWith('foo', undefined)).toBe(false); + expect(startsWith('foo', 123)).toBe(false); + expect(startsWith('foo', {})).toBe(false); + expect(startsWith('foo', [])).toBe(false); + }); + + it('should return false if str does not start with search', () => { + expect(startsWith('foo', 'bar')).toBe(false); + expect(startsWith('foo', 'baz')).toBe(false); + expect(startsWith('foo', 'bar')).toBe(false); + expect(startsWith('foo', 'baz')).toBe(false); + expect(startsWith('foo', 'bar')).toBe(false); + expect(startsWith('foo', 'baz')).toBe(false); + }); + + it('should return true if str starts with search', () => { + expect(startsWith('foo', 'f')).toBe(true); + expect(startsWith('foo', 'fo')).toBe(true); + expect(startsWith('foo', 'foo')).toBe(true); + }); + }); }); diff --git a/packages/bruno-app/src/utils/curl/curl-to-json.js b/packages/bruno-app/src/utils/curl/curl-to-json.js new file mode 100644 index 00000000..8313e0a7 --- /dev/null +++ b/packages/bruno-app/src/utils/curl/curl-to-json.js @@ -0,0 +1,169 @@ +/** + * Copyright (c) 2014-2016 Nick Carneiro + * https://github.com/curlconverter/curlconverter + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import parseCurlCommand from './parse-curl'; +import * as querystring from 'query-string'; +import * as jsesc from 'jsesc'; + +function getContentType(headers = {}) { + const contentType = Object.keys(headers).find((key) => key.toLowerCase() === 'content-type'); + + return contentType ? headers[contentType] : null; +} + +function repr(value, isKey) { + return isKey ? "'" + jsesc(value, { quotes: 'single' }) + "'" : value; +} + +function getQueries(request) { + const queries = {}; + for (const paramName in request.query) { + const rawValue = request.query[paramName]; + let paramValue; + if (Array.isArray(rawValue)) { + paramValue = rawValue.map(repr); + } else { + paramValue = repr(rawValue); + } + queries[repr(paramName)] = paramValue; + } + + return queries; +} + +function getDataString(request) { + if (typeof request.data === 'number') { + request.data = request.data.toString(); + } + + const contentType = getContentType(request.headers); + + if (contentType && contentType.includes('application/json')) { + return { data: request.data.toString() }; + } + + const parsedQueryString = querystring.parse(request.data, { sort: false }); + const keyCount = Object.keys(parsedQueryString).length; + const singleKeyOnly = keyCount === 1 && !parsedQueryString[Object.keys(parsedQueryString)[0]]; + const singularData = request.isDataBinary || singleKeyOnly; + if (singularData) { + const data = {}; + data[repr(request.data)] = ''; + return { data: data }; + } else { + return getMultipleDataString(request, parsedQueryString); + } +} + +function getMultipleDataString(request, parsedQueryString) { + const data = {}; + + for (const key in parsedQueryString) { + const value = parsedQueryString[key]; + if (Array.isArray(value)) { + data[repr(key)] = value; + } else { + data[repr(key)] = repr(value); + } + } + + return { data: data }; +} + +function getFilesString(request) { + const data = {}; + + data.files = {}; + data.data = {}; + + for (const multipartKey in request.multipartUploads) { + const multipartValue = request.multipartUploads[multipartKey]; + if (multipartValue.startsWith('@')) { + const fileName = multipartValue.slice(1); + data.files[repr(multipartKey)] = repr(fileName); + } else { + data.data[repr(multipartKey)] = repr(multipartValue); + } + } + + if (Object.keys(data.files).length === 0) { + delete data.files; + } + + if (Object.keys(data.data).length === 0) { + delete data.data; + } + + return data; +} + +const curlToJson = (curlCommand) => { + const request = parseCurlCommand(curlCommand); + + const requestJson = {}; + + // curl automatically prepends 'http' if the scheme is missing, but python fails and returns an error + // we tack it on here to mimic curl + if (!request.url.match(/https?:/)) { + request.url = 'http://' + request.url; + } + if (!request.urlWithoutQuery.match(/https?:/)) { + request.urlWithoutQuery = 'http://' + request.urlWithoutQuery; + } + + requestJson.url = request.urlWithoutQuery.replace(/\/$/, ''); + requestJson.raw_url = request.url; + requestJson.method = request.method; + + if (request.cookies) { + const cookies = {}; + for (const cookieName in request.cookies) { + cookies[repr(cookieName)] = repr(request.cookies[cookieName]); + } + + requestJson.cookies = cookies; + } + + if (request.headers) { + const headers = {}; + for (const headerName in request.headers) { + headers[repr(headerName)] = repr(request.headers[headerName]); + } + + requestJson.headers = headers; + } + + if (request.query) { + requestJson.queries = getQueries(request); + } + + if (typeof request.data === 'string' || typeof request.data === 'number') { + Object.assign(requestJson, getDataString(request)); + } else if (request.multipartUploads) { + Object.assign(requestJson, getFilesString(request)); + } + + if (request.insecure) { + requestJson.insecure = false; + } + + if (request.auth) { + const splitAuth = request.auth.split(':'); + const user = splitAuth[0] || ''; + const password = splitAuth[1] || ''; + + requestJson.auth = { + user: repr(user), + password: repr(password) + }; + } + + return Object.keys(requestJson).length ? requestJson : {}; +}; + +export default curlToJson; diff --git a/packages/bruno-app/src/utils/curl/curl-to-json.spec.js b/packages/bruno-app/src/utils/curl/curl-to-json.spec.js new file mode 100644 index 00000000..bf7d836d --- /dev/null +++ b/packages/bruno-app/src/utils/curl/curl-to-json.spec.js @@ -0,0 +1,62 @@ +const { describe, it, expect } = require('@jest/globals'); + +import curlToJson from './curl-to-json'; + +describe('curlToJson', () => { + it('should return a parse a simple curl command', () => { + const curlCommand = 'curl https://www.usebruno.com'; + const result = curlToJson(curlCommand); + + expect(result).toEqual({ + url: 'https://www.usebruno.com', + raw_url: 'https://www.usebruno.com', + method: 'get' + }); + }); + + it('should return a parse a curl command with headers', () => { + const curlCommand = `curl https://www.usebruno.com + -H 'Accept: application/json, text/plain, */*' + -H 'Accept-Language: en-US,en;q=0.9,hi;q=0.8' + `; + + const result = curlToJson(curlCommand); + + expect(result).toEqual({ + url: 'https://www.usebruno.com', + raw_url: 'https://www.usebruno.com', + method: 'get', + headers: { + Accept: 'application/json, text/plain, */*', + 'Accept-Language': 'en-US,en;q=0.9,hi;q=0.8' + } + }); + }); + + it('should return a parse a curl with a post body', () => { + const curlCommand = `curl 'https://www.usebruno.com' + -H 'Accept: application/json, text/plain, */*' + -H 'Accept-Language: en-US,en;q=0.9,hi;q=0.8' + -H 'Content-Type: application/json;charset=utf-8' + -H 'Origin: https://www.usebruno.com' + -H 'Referer: https://www.usebruno.com/' + --data-raw '{"email":"test@usebruno.com","password":"test"}' + `; + + const result = curlToJson(curlCommand); + + expect(result).toEqual({ + url: '%27https://www.usebruno.com%27', + raw_url: "'https://www.usebruno.com'", + method: 'post', + headers: { + Accept: 'application/json, text/plain, */*', + 'Accept-Language': 'en-US,en;q=0.9,hi;q=0.8', + 'Content-Type': 'application/json;charset=utf-8', + Origin: 'https://www.usebruno.com', + Referer: 'https://www.usebruno.com/' + }, + data: '{"email":"test@usebruno.com","password":"test"}' + }); + }); +}); diff --git a/packages/bruno-app/src/utils/curl/index.js b/packages/bruno-app/src/utils/curl/index.js index 30080e46..ecaf582c 100644 --- a/packages/bruno-app/src/utils/curl/index.js +++ b/packages/bruno-app/src/utils/curl/index.js @@ -1,18 +1,29 @@ -import * as parse from 'parse-curl'; -import { BrunoError } from 'utils/common/error'; -import { parseQueryParams } from 'utils/url'; +import { forOwn } from 'lodash'; +import { safeStringifyJSON } from 'utils/common'; +import curlToJson from './curl-to-json'; -export const getRequestFromCurlCommand = (command) => { +export const getRequestFromCurlCommand = (curlCommand) => { const parseFormData = (parsedBody) => { - parseQueryParams(parsedBody); - }; - try { - const request = parse(command); - const parsedHeader = request?.header; - const headers = - parsedHeader && Object.keys(parsedHeader).map((key) => ({ name: key, value: parsedHeader[key], enabled: true })); + const formData = []; + forOwn(parsedBody, (value, key) => { + formData.push({ name: key, value, enabled: true }); + }); - const contentType = headers?.find((h) => h.name.toLowerCase() === 'content-type'); + return formData; + }; + + try { + if (!curlCommand || typeof curlCommand !== 'string' || curlCommand.length === 0) { + return null; + } + + const request = curlToJson(curlCommand); + const parsedHeaders = request?.headers; + const headers = + parsedHeaders && + Object.keys(parsedHeaders).map((key) => ({ name: key, value: parsedHeaders[key], enabled: true })); + + const contentType = headers?.find((h) => h.name.toLowerCase() === 'content-type')?.value; const body = { mode: 'none', json: null, @@ -22,30 +33,25 @@ export const getRequestFromCurlCommand = (command) => { multipartForm: null, formUrlEncoded: null }; - const parsedBody = request?.body; - if (parsedBody && contentType) { - switch (contentType.value.toLowerCase()) { - case 'application/json': - body.mode = 'json'; - body.json = parsedBody; - break; - case 'text/xml': - body.mode = 'xml'; - body.xml = parsedBody; - break; - case 'application/x-www-form-urlencoded': - body.mode = 'formUrlEncoded'; - body.formUrlEncoded = parseFormData(parsedBody); - break; - case 'multipart/form-data': - body.mode = 'multipartForm'; - body.multipartForm = parsedBody; - break; - case 'text/plain': - default: - body.mode = 'text'; - body.text = parsedBody; - break; + const parsedBody = request.data; + if (parsedBody && contentType && typeof contentType === 'string') { + if (contentType.includes('application/json')) { + body.mode = 'json'; + body.json = safeStringifyJSON(parsedBody); + } else if (contentType.includes('text/xml')) { + body.mode = 'xml'; + body.xml = parsedBody; + } else if (contentType.includes('application/x-www-form-urlencoded')) { + body.mode = 'formUrlEncoded'; + console.log(parsedBody); + console.log(parseFormData(parsedBody)); + body.formUrlEncoded = parseFormData(parsedBody); + } else if (contentType.includes('multipart/form-data')) { + body.mode = 'multipartForm'; + body.multipartForm = parsedBody; + } else if (contentType.includes('text/plain')) { + body.mode = 'text'; + body.text = parsedBody; } } return { @@ -55,6 +61,7 @@ export const getRequestFromCurlCommand = (command) => { headers: headers }; } catch (error) { + console.error(error); return null; } }; diff --git a/packages/bruno-app/src/utils/curl/parse-curl.js b/packages/bruno-app/src/utils/curl/parse-curl.js new file mode 100644 index 00000000..b7f6572f --- /dev/null +++ b/packages/bruno-app/src/utils/curl/parse-curl.js @@ -0,0 +1,238 @@ +/** + * Copyright (c) 2014-2016 Nick Carneiro + * https://github.com/curlconverter/curlconverter + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import * as cookie from 'cookie'; +import * as URL from 'url'; +import * as querystring from 'query-string'; +import yargs from 'yargs-parser'; + +const parseCurlCommand = (curlCommand) => { + // Remove newlines (and from continuations) + curlCommand = curlCommand.replace(/\\\r|\\\n/g, ''); + + // Remove extra whitespace + curlCommand = curlCommand.replace(/\s+/g, ' '); + + // yargs parses -XPOST as separate arguments. just prescreen for it. + curlCommand = curlCommand.replace(/ -XPOST/, ' -X POST'); + curlCommand = curlCommand.replace(/ -XGET/, ' -X GET'); + curlCommand = curlCommand.replace(/ -XPUT/, ' -X PUT'); + curlCommand = curlCommand.replace(/ -XPATCH/, ' -X PATCH'); + curlCommand = curlCommand.replace(/ -XDELETE/, ' -X DELETE'); + curlCommand = curlCommand.replace(/ -XOPTIONS/, ' -X OPTIONS'); + // Safari adds `-Xnull` if is unable to determine the request type, it can be ignored + curlCommand = curlCommand.replace(/ -Xnull/, ' '); + curlCommand = curlCommand.trim(); + + const parsedArguments = yargs(curlCommand, { + boolean: ['I', 'head', 'compressed', 'L', 'k', 'silent', 's'], + alias: { + H: 'header', + A: 'user-agent' + } + }); + + let cookieString; + let cookies; + let url = parsedArguments._[1] || ''; + + // remove surrounding quotes if present + if (url && url.length) { + url = url.replace(/^['"]|['"]$/g, ''); + } + + // if url argument wasn't where we expected it, try to find it in the other arguments + if (!url) { + for (const argName in parsedArguments) { + if (typeof parsedArguments[argName] === 'string') { + if (parsedArguments[argName].indexOf('http') === 0 || parsedArguments[argName].indexOf('www.') === 0) { + url = parsedArguments[argName]; + } + } + } + } + + let headers; + + if (parsedArguments.header) { + if (!headers) { + headers = {}; + } + if (!Array.isArray(parsedArguments.header)) { + parsedArguments.header = [parsedArguments.header]; + } + parsedArguments.header.forEach((header) => { + if (header.indexOf('Cookie') !== -1) { + cookieString = header; + } else { + const components = header.split(/:(.*)/); + if (components[1]) { + headers[components[0]] = components[1].trim(); + } + } + }); + } + + if (parsedArguments['user-agent']) { + if (!headers) { + headers = {}; + } + headers['User-Agent'] = parsedArguments['user-agent']; + } + + if (parsedArguments.b) { + cookieString = parsedArguments.b; + } + if (parsedArguments.cookie) { + cookieString = parsedArguments.cookie; + } + let multipartUploads; + if (parsedArguments.F) { + multipartUploads = {}; + if (!Array.isArray(parsedArguments.F)) { + parsedArguments.F = [parsedArguments.F]; + } + parsedArguments.F.forEach((multipartArgument) => { + // input looks like key=value. value could be json or a file path prepended with an @ + const splitArguments = multipartArgument.split('=', 2); + const key = splitArguments[0]; + const value = splitArguments[1]; + multipartUploads[key] = value; + }); + } + if (cookieString) { + const cookieParseOptions = { + decode: function (s) { + return s; + } + }; + // separate out cookie headers into separate data structure + // note: cookie is case insensitive + cookies = cookie.parse(cookieString.replace(/^Cookie: /gi, ''), cookieParseOptions); + } + let method; + if (parsedArguments.X === 'POST') { + method = 'post'; + } else if (parsedArguments.X === 'PUT' || parsedArguments.T) { + method = 'put'; + } else if (parsedArguments.X === 'PATCH') { + method = 'patch'; + } else if (parsedArguments.X === 'DELETE') { + method = 'delete'; + } else if (parsedArguments.X === 'OPTIONS') { + method = 'options'; + } else if ( + (parsedArguments.d || + parsedArguments.data || + parsedArguments['data-ascii'] || + parsedArguments['data-binary'] || + parsedArguments['data-raw'] || + parsedArguments.F || + parsedArguments.form) && + !(parsedArguments.G || parsedArguments.get) + ) { + method = 'post'; + } else if (parsedArguments.I || parsedArguments.head) { + method = 'head'; + } else { + method = 'get'; + } + + const compressed = !!parsedArguments.compressed; + const urlObject = URL.parse(url || ''); + + // if GET request with data, convert data to query string + // NB: the -G flag does not change the http verb. It just moves the data into the url. + if (parsedArguments.G || parsedArguments.get) { + urlObject.query = urlObject.query ? urlObject.query : ''; + const option = 'd' in parsedArguments ? 'd' : 'data' in parsedArguments ? 'data' : null; + if (option) { + let urlQueryString = ''; + + if (url.indexOf('?') < 0) { + url += '?'; + } else { + urlQueryString += '&'; + } + + if (typeof parsedArguments[option] === 'object') { + urlQueryString += parsedArguments[option].join('&'); + } else { + urlQueryString += parsedArguments[option]; + } + urlObject.query += urlQueryString; + url += urlQueryString; + delete parsedArguments[option]; + } + } + if (urlObject.query && urlObject.query.endsWith('&')) { + urlObject.query = urlObject.query.slice(0, -1); + } + const query = querystring.parse(urlObject.query, { sort: false }); + for (const param in query) { + if (query[param] === null) { + query[param] = ''; + } + } + + urlObject.search = null; // Clean out the search/query portion. + const request = { + url: url, + urlWithoutQuery: URL.format(urlObject) + }; + if (compressed) { + request.compressed = true; + } + + if (Object.keys(query).length > 0) { + request.query = query; + } + if (headers) { + request.headers = headers; + } + request.method = method; + + if (cookies) { + request.cookies = cookies; + request.cookieString = cookieString.replace('Cookie: ', ''); + } + if (multipartUploads) { + request.multipartUploads = multipartUploads; + } + if (parsedArguments.data) { + request.data = parsedArguments.data; + } else if (parsedArguments['data-binary']) { + request.data = parsedArguments['data-binary']; + request.isDataBinary = true; + } else if (parsedArguments.d) { + request.data = parsedArguments.d; + } else if (parsedArguments['data-ascii']) { + request.data = parsedArguments['data-ascii']; + } else if (parsedArguments['data-raw']) { + request.data = parsedArguments['data-raw']; + request.isDataRaw = true; + } + + if (parsedArguments.u) { + request.auth = parsedArguments.u; + } + if (parsedArguments.user) { + request.auth = parsedArguments.user; + } + if (Array.isArray(request.data)) { + request.dataArray = request.data; + request.data = request.data.join('&'); + } + + if (parsedArguments.k || parsedArguments.insecure) { + request.insecure = true; + } + return request; +}; + +export default parseCurlCommand; diff --git a/packages/bruno-electron/src/index.js b/packages/bruno-electron/src/index.js index 602517b5..a65dc28c 100644 --- a/packages/bruno-electron/src/index.js +++ b/packages/bruno-electron/src/index.js @@ -14,16 +14,18 @@ const { loadWindowState, saveBounds, saveMaximized } = require('./utils/window') const lastOpenedCollections = new LastOpenedCollections(); +// Reference: https://content-security-policy.com/ const contentSecurityPolicy = [ - isDev ? "default-src 'self' 'unsafe-inline' 'unsafe-eval'" : "default-src 'self'", - "connect-src 'self' https://api.github.com/repos/usebruno/bruno", - "font-src 'self' https://fonts.gstatic.com", + "default-src 'self'", + "script-src * 'unsafe-inline' 'unsafe-eval'", + "connect-src 'self' api.github.com", + "font-src 'self' https:", "form-action 'none'", - "img-src 'self' blob: data:", - "style-src 'self' https://fonts.googleapis.com" + "img-src 'self' blob: data: https:", + "style-src 'self' 'unsafe-inline' https:" ]; -setContentSecurityPolicy(contentSecurityPolicy.join(';')); +setContentSecurityPolicy(contentSecurityPolicy.join(';') + ';'); const menu = Menu.buildFromTemplate(menuTemplate); Menu.setApplicationMenu(menu); diff --git a/packages/bruno-js/package.json b/packages/bruno-js/package.json index b6a83c07..1152beec 100644 --- a/packages/bruno-js/package.json +++ b/packages/bruno-js/package.json @@ -17,7 +17,7 @@ "@usebruno/query": "0.1.0", "ajv": "^8.12.0", "atob": "^2.1.2", - "axios": "^0.26.0", + "axios": "^1.5.1", "btoa": "^1.2.1", "chai": "^4.3.7", "chai-string": "^1.5.0",