From c5a48acdaedb9a9f38cb6de46d804f781cdc97ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erdi=20K=C3=B6se?= Date: Fri, 4 Mar 2022 07:11:48 +0300 Subject: [PATCH 1/6] feat: Improve plugins install URL support --- package-lock.json | 271 ++++++++++++++++-- package.json | 2 + .../PluginManager/PluginInstallModal.tsx | 87 +++++- 3 files changed, 325 insertions(+), 35 deletions(-) diff --git a/package-lock.json b/package-lock.json index 86e4c9ed12..5f3dcd5dc2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33,6 +33,7 @@ "execa": "5.1.1", "fast-deep-equal": "3.1.3", "flat": "5.0.2", + "git-url-parse": "^11.6.0", "jsonpath-plus": "6.0.1", "lodash": "4.17.21", "loglevel": "1.8.0", @@ -64,8 +65,9 @@ "styled-components": "5.3.3", "tar": "6.1.11", "type-fest": "2.11.0", + "url-parse": "^1.5.10", "uuid": "8.3.2", - "vm2": "^3.9.6", + "vm2": "3.9.6", "web-vitals": "2.1.4", "worker-loader": "3.0.8", "yaml": "2.0.0-10", @@ -82,6 +84,7 @@ "@trivago/prettier-plugin-sort-imports": "3.1.0", "@types/dagre": "0.7.46", "@types/electron-devtools-installer": "2.2.0", + "@types/git-url-parse": "^9.0.1", "@types/jest": "27.0.1", "@types/luxon": "2.0.5", "@types/micromatch": "4.0.2", @@ -94,6 +97,7 @@ "@types/redux-logger": "3.0.9", "@types/shelljs": "0.8.9", "@types/styled-components": "5.1.12", + "@types/url-parse": "^1.4.8", "@types/uuid": "8.3.1", "@types/yargs": "17.0.2", "builder-util-runtime": "9.0.0-alpha.0", @@ -4959,6 +4963,12 @@ "@types/node": "*" } }, + "node_modules/@types/git-url-parse": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@types/git-url-parse/-/git-url-parse-9.0.1.tgz", + "integrity": "sha512-Zf9mY4Mz7N3Nyi341nUkOtgVUQn4j6NS4ndqEha/lOgEbTkHzpD7wZuRagYKzrXNtvawWfsrojoC1nhsQexvNA==", + "dev": true + }, "node_modules/@types/glob": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", @@ -5385,6 +5395,12 @@ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz", "integrity": "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==" }, + "node_modules/@types/url-parse": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/@types/url-parse/-/url-parse-1.4.8.tgz", + "integrity": "sha512-zqqcGKyNWgTLFBxmaexGUKQyWqeG7HjXj20EuQJSJWwXe54BjX0ihIo5cJB9yAQzH8dNugJ9GvkBYMjPXs/PJw==", + "dev": true + }, "node_modules/@types/uuid": { "version": "8.3.1", "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.1.tgz", @@ -7779,7 +7795,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, "dependencies": { "function-bind": "^1.1.1", "get-intrinsic": "^1.0.2" @@ -13274,6 +13289,14 @@ "node": ">=8" } }, + "node_modules/filter-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz", + "integrity": "sha1-mzERErxsYSehbgFsbF1/GeCAXFs=", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/finalhandler": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", @@ -13799,7 +13822,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "dev": true, "dependencies": { "function-bind": "^1.1.1", "has": "^1.0.3", @@ -13991,6 +14013,23 @@ "semver": "bin/semver.js" } }, + "node_modules/git-up": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/git-up/-/git-up-4.0.5.tgz", + "integrity": "sha512-YUvVDg/vX3d0syBsk/CKUTib0srcQME0JyHkL5BaYdwLsiCslPWmDSi8PUMo9pXYjrryMcmsCoCgsTpSCJEQaA==", + "dependencies": { + "is-ssh": "^1.3.0", + "parse-url": "^6.0.0" + } + }, + "node_modules/git-url-parse": { + "version": "11.6.0", + "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-11.6.0.tgz", + "integrity": "sha512-WWUxvJs5HsyHL6L08wOusa/IXYtMuCAhrMmnTjQPpBU0TTHyDhnOATNH3xNQz7YOQUsqIIPTGr4xiVti1Hsk5g==", + "dependencies": { + "git-up": "^4.0.0" + } + }, "node_modules/gitconfiglocal": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/gitconfiglocal/-/gitconfiglocal-1.0.0.tgz", @@ -14366,7 +14405,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -15956,6 +15994,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-ssh": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.3.3.tgz", + "integrity": "sha512-NKzJmQzJfEEma3w5cJNcUMxoXfDjz0Zj0eyCalHn2E6VOwlzjZo0yuO2fcBSf8zhFuVCL/82/r5gRcoi6aEPVQ==", + "dependencies": { + "protocols": "^1.1.0" + } + }, "node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -21940,7 +21986,6 @@ "version": "1.12.0", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -22717,6 +22762,78 @@ "node": ">= 0.10" } }, + "node_modules/parse-path": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/parse-path/-/parse-path-4.0.3.tgz", + "integrity": "sha512-9Cepbp2asKnWTJ9x2kpw6Fe8y9JDbqwahGCTvklzd/cEq5C5JC59x2Xb0Kx+x0QZ8bvNquGO8/BWP0cwBHzSAA==", + "dependencies": { + "is-ssh": "^1.3.0", + "protocols": "^1.4.0", + "qs": "^6.9.4", + "query-string": "^6.13.8" + } + }, + "node_modules/parse-path/node_modules/qs": { + "version": "6.10.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", + "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/parse-path/node_modules/query-string": { + "version": "6.14.1", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-6.14.1.tgz", + "integrity": "sha512-XDxAeVmpfu1/6IjyT/gXHOl+S0vQ9owggJ30hhWKdHAsNPOcasn5o9BW0eejZqL2e4vMjhAxoW3jVHcD6mbcYw==", + "dependencies": { + "decode-uri-component": "^0.2.0", + "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" + } + }, + "node_modules/parse-path/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": "sha1-ucczDHBChi9rFC3CdLvMWGbONUY=", + "engines": { + "node": ">=4" + } + }, + "node_modules/parse-url": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-6.0.0.tgz", + "integrity": "sha512-cYyojeX7yIIwuJzledIHeLUBVJ6COVLeT4eF+2P6aKVzwvgKQPndCBv3+yQ7pcWjqToYwaligxzSYNNmGoMAvw==", + "dependencies": { + "is-ssh": "^1.3.0", + "normalize-url": "^6.1.0", + "parse-path": "^4.0.0", + "protocols": "^1.4.0" + } + }, + "node_modules/parse-url/node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/parse5": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", @@ -24886,6 +25003,11 @@ "dev": true, "optional": true }, + "node_modules/protocols": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/protocols/-/protocols-1.4.8.tgz", + "integrity": "sha512-IgjKyaUSjsROSO8/D49Ab7hP8mJgTYcqApOqdPhLoPxAplXmkp+zRvsrSQjFn5by0rhm4VH0GAUELIPpx7B1yg==" + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -25037,8 +25159,7 @@ "node_modules/querystringify": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "dev": true + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" }, "node_modules/queue-microtask": { "version": "1.2.3", @@ -27294,8 +27415,7 @@ "node_modules/requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", - "dev": true + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" }, "node_modules/reselect": { "version": "4.1.5", @@ -28817,7 +28937,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, "dependencies": { "call-bind": "^1.0.0", "get-intrinsic": "^1.0.2", @@ -29325,6 +29444,14 @@ "node": "*" } }, + "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" + } + }, "node_modules/split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", @@ -32088,7 +32215,6 @@ "version": "1.5.10", "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", - "dev": true, "dependencies": { "querystringify": "^2.1.1", "requires-port": "^1.0.0" @@ -38204,6 +38330,12 @@ "@types/node": "*" } }, + "@types/git-url-parse": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@types/git-url-parse/-/git-url-parse-9.0.1.tgz", + "integrity": "sha512-Zf9mY4Mz7N3Nyi341nUkOtgVUQn4j6NS4ndqEha/lOgEbTkHzpD7wZuRagYKzrXNtvawWfsrojoC1nhsQexvNA==", + "dev": true + }, "@types/glob": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", @@ -38628,6 +38760,12 @@ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz", "integrity": "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==" }, + "@types/url-parse": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/@types/url-parse/-/url-parse-1.4.8.tgz", + "integrity": "sha512-zqqcGKyNWgTLFBxmaexGUKQyWqeG7HjXj20EuQJSJWwXe54BjX0ihIo5cJB9yAQzH8dNugJ9GvkBYMjPXs/PJw==", + "dev": true + }, "@types/uuid": { "version": "8.3.1", "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.1.tgz", @@ -40535,7 +40673,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, "requires": { "function-bind": "^1.1.1", "get-intrinsic": "^1.0.2" @@ -44810,6 +44947,11 @@ "to-regex-range": "^5.0.1" } }, + "filter-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz", + "integrity": "sha1-mzERErxsYSehbgFsbF1/GeCAXFs=" + }, "finalhandler": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", @@ -45223,7 +45365,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "dev": true, "requires": { "function-bind": "^1.1.1", "has": "^1.0.3", @@ -45364,6 +45505,23 @@ } } }, + "git-up": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/git-up/-/git-up-4.0.5.tgz", + "integrity": "sha512-YUvVDg/vX3d0syBsk/CKUTib0srcQME0JyHkL5BaYdwLsiCslPWmDSi8PUMo9pXYjrryMcmsCoCgsTpSCJEQaA==", + "requires": { + "is-ssh": "^1.3.0", + "parse-url": "^6.0.0" + } + }, + "git-url-parse": { + "version": "11.6.0", + "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-11.6.0.tgz", + "integrity": "sha512-WWUxvJs5HsyHL6L08wOusa/IXYtMuCAhrMmnTjQPpBU0TTHyDhnOATNH3xNQz7YOQUsqIIPTGr4xiVti1Hsk5g==", + "requires": { + "git-up": "^4.0.0" + } + }, "gitconfiglocal": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/gitconfiglocal/-/gitconfiglocal-1.0.0.tgz", @@ -45656,8 +45814,7 @@ "has-symbols": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" }, "has-tostringtag": { "version": "1.0.0", @@ -46818,6 +46975,14 @@ "integrity": "sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==", "dev": true }, + "is-ssh": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.3.3.tgz", + "integrity": "sha512-NKzJmQzJfEEma3w5cJNcUMxoXfDjz0Zj0eyCalHn2E6VOwlzjZo0yuO2fcBSf8zhFuVCL/82/r5gRcoi6aEPVQ==", + "requires": { + "protocols": "^1.1.0" + } + }, "is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -51472,8 +51637,7 @@ "object-inspect": { "version": "1.12.0", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", - "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==", - "dev": true + "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==" }, "object-is": { "version": "1.1.5", @@ -52032,6 +52196,61 @@ "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", "dev": true }, + "parse-path": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/parse-path/-/parse-path-4.0.3.tgz", + "integrity": "sha512-9Cepbp2asKnWTJ9x2kpw6Fe8y9JDbqwahGCTvklzd/cEq5C5JC59x2Xb0Kx+x0QZ8bvNquGO8/BWP0cwBHzSAA==", + "requires": { + "is-ssh": "^1.3.0", + "protocols": "^1.4.0", + "qs": "^6.9.4", + "query-string": "^6.13.8" + }, + "dependencies": { + "qs": { + "version": "6.10.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", + "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "requires": { + "side-channel": "^1.0.4" + } + }, + "query-string": { + "version": "6.14.1", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-6.14.1.tgz", + "integrity": "sha512-XDxAeVmpfu1/6IjyT/gXHOl+S0vQ9owggJ30hhWKdHAsNPOcasn5o9BW0eejZqL2e4vMjhAxoW3jVHcD6mbcYw==", + "requires": { + "decode-uri-component": "^0.2.0", + "filter-obj": "^1.1.0", + "split-on-first": "^1.0.0", + "strict-uri-encode": "^2.0.0" + } + }, + "strict-uri-encode": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", + "integrity": "sha1-ucczDHBChi9rFC3CdLvMWGbONUY=" + } + } + }, + "parse-url": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-6.0.0.tgz", + "integrity": "sha512-cYyojeX7yIIwuJzledIHeLUBVJ6COVLeT4eF+2P6aKVzwvgKQPndCBv3+yQ7pcWjqToYwaligxzSYNNmGoMAvw==", + "requires": { + "is-ssh": "^1.3.0", + "normalize-url": "^6.1.0", + "parse-path": "^4.0.0", + "protocols": "^1.4.0" + }, + "dependencies": { + "normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==" + } + } + }, "parse5": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", @@ -53809,6 +54028,11 @@ "dev": true, "optional": true }, + "protocols": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/protocols/-/protocols-1.4.8.tgz", + "integrity": "sha512-IgjKyaUSjsROSO8/D49Ab7hP8mJgTYcqApOqdPhLoPxAplXmkp+zRvsrSQjFn5by0rhm4VH0GAUELIPpx7B1yg==" + }, "proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -53938,8 +54162,7 @@ "querystringify": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "dev": true + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" }, "queue-microtask": { "version": "1.2.3", @@ -55592,8 +55815,7 @@ "requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", - "dev": true + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" }, "reselect": { "version": "4.1.5", @@ -56815,7 +57037,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, "requires": { "call-bind": "^1.0.0", "get-intrinsic": "^1.0.2", @@ -57243,6 +57464,11 @@ "through": "2" } }, + "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==" + }, "split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", @@ -59423,7 +59649,6 @@ "version": "1.5.10", "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", - "dev": true, "requires": { "querystringify": "^2.1.1", "requires-port": "^1.0.0" diff --git a/package.json b/package.json index f6a6bf6e1b..e083aac104 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "@trivago/prettier-plugin-sort-imports": "3.1.0", "@types/dagre": "0.7.46", "@types/electron-devtools-installer": "2.2.0", + "@types/git-url-parse": "9.0.1", "@types/jest": "27.0.1", "@types/luxon": "2.0.5", "@types/micromatch": "4.0.2", @@ -106,6 +107,7 @@ "execa": "5.1.1", "fast-deep-equal": "3.1.3", "flat": "5.0.2", + "git-url-parse": "11.6.0", "jsonpath-plus": "6.0.1", "lodash": "4.17.21", "loglevel": "1.8.0", diff --git a/src/components/organisms/PluginManager/PluginInstallModal.tsx b/src/components/organisms/PluginManager/PluginInstallModal.tsx index 3a21d2b610..ee56cb9342 100644 --- a/src/components/organisms/PluginManager/PluginInstallModal.tsx +++ b/src/components/organisms/PluginManager/PluginInstallModal.tsx @@ -1,8 +1,11 @@ import {ipcRenderer, shell} from 'electron'; -import React, {useState} from 'react'; +import React, {useEffect, useState} from 'react'; -import {Button, Input, Modal} from 'antd'; +import {Button, Form, Input, Modal} from 'antd'; +import {useForm} from 'antd/lib/form/Form'; + +import gitUrlParse from 'git-url-parse'; import {PLUGIN_DOCS_URL} from '@constants/constants'; import {DOWNLOAD_PLUGIN, DOWNLOAD_PLUGIN_RESULT} from '@constants/ipcEvents'; @@ -12,6 +15,8 @@ import {DownloadPluginResult, isDownloadPluginResult} from '@models/extension'; import {useAppDispatch} from '@redux/hooks'; import {addMultipleTemplates, addPlugin} from '@redux/reducers/extension'; +import {useFocus} from '@utils/hooks'; + import Colors from '@styles/Colors'; const downloadPlugin = (pluginUrl: string) => { @@ -35,11 +40,13 @@ const downloadPlugin = (pluginUrl: string) => { function PluginInstallModal(props: {isVisible: boolean; onClose: () => void}) { const dispatch = useAppDispatch(); const {isVisible, onClose} = props; - const [pluginUrl, setPluginUrl] = useState(''); + const [formValues, setFormValues] = useState({pluginUrl: ''}); const [errorMessage, setErrorMessage] = useState(); const [isDownloading, setIsDownloading] = useState(false); + const [createProjectForm] = useForm(); + const [inputRef, focus] = useFocus(); - const onClickDownload = async () => { + const download = async (pluginUrl: string) => { try { setIsDownloading(true); const downloadPluginResult = await downloadPlugin(pluginUrl); @@ -60,11 +67,57 @@ function PluginInstallModal(props: {isVisible: boolean; onClose: () => void}) { }; const close = () => { - setPluginUrl(''); + createProjectForm.setFields([ + { + name: 'pluginUrl', + value: '', + errors: [], + }, + ]); setIsDownloading(false); onClose(); }; + const handlePluginURLChange = async (url: string) => { + try { + const parsedURL = gitUrlParse(url); + if (!parsedURL.owner || !parsedURL.name) { + setErrorMessage('Please enter a valid git URL!'); + return; + } + if (!parsedURL.protocols.includes('https')) { + setErrorMessage('Currently we support only HTTPS protocol'); + return; + } + await download(`${parsedURL.protocol}://${parsedURL.resource}/${parsedURL.owner}/${parsedURL.name}`); + } catch (error: any) { + setErrorMessage(error.message); + } + }; + + const onFinish = async (values: {pluginUrl: string}) => { + setFormValues(values); + await handlePluginURLChange(values.pluginUrl); + }; + + useEffect(() => { + if (isVisible) { + focus(); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [isVisible]); + + useEffect(() => { + createProjectForm.setFields([ + { + name: 'pluginUrl', + value: formValues.pluginUrl, + errors: errorMessage ? [errorMessage] : [], + }, + ]); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [errorMessage]); + return ( void}) { , - , ]} @@ -85,12 +138,22 @@ function PluginInstallModal(props: {isVisible: boolean; onClose: () => void}) { See Plugin's documentation for more information.

- setPluginUrl(e.target.value)} /> - {errorMessage && ( -
-

{errorMessage}

-
- )} +
formValues}> + + + +
); } From 46f0abbf8849621b972c6e1619ca20db0fbfd367 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erdi=20K=C3=B6se?= Date: Fri, 4 Mar 2022 10:13:48 +0300 Subject: [PATCH 2/6] chore: change form name --- .../organisms/PluginManager/PluginInstallModal.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/organisms/PluginManager/PluginInstallModal.tsx b/src/components/organisms/PluginManager/PluginInstallModal.tsx index ee56cb9342..93f9411645 100644 --- a/src/components/organisms/PluginManager/PluginInstallModal.tsx +++ b/src/components/organisms/PluginManager/PluginInstallModal.tsx @@ -43,7 +43,7 @@ function PluginInstallModal(props: {isVisible: boolean; onClose: () => void}) { const [formValues, setFormValues] = useState({pluginUrl: ''}); const [errorMessage, setErrorMessage] = useState(); const [isDownloading, setIsDownloading] = useState(false); - const [createProjectForm] = useForm(); + const [pluginForm] = useForm(); const [inputRef, focus] = useFocus(); const download = async (pluginUrl: string) => { @@ -67,7 +67,7 @@ function PluginInstallModal(props: {isVisible: boolean; onClose: () => void}) { }; const close = () => { - createProjectForm.setFields([ + pluginForm.setFields([ { name: 'pluginUrl', value: '', @@ -108,7 +108,7 @@ function PluginInstallModal(props: {isVisible: boolean; onClose: () => void}) { }, [isVisible]); useEffect(() => { - createProjectForm.setFields([ + pluginForm.setFields([ { name: 'pluginUrl', value: formValues.pluginUrl, @@ -125,7 +125,7 @@ function PluginInstallModal(props: {isVisible: boolean; onClose: () => void}) { , - , ]} @@ -138,7 +138,7 @@ function PluginInstallModal(props: {isVisible: boolean; onClose: () => void}) { See Plugin's documentation for more information.

-
formValues}> + formValues}> Date: Sat, 5 Mar 2022 08:01:37 +0300 Subject: [PATCH 3/6] chore: support repository branches --- electron/extensions/downloadExtension.ts | 2 + electron/extensions/downloadExtensionEntry.ts | 2 +- electron/extensions/loadExtension.ts | 3 +- electron/pluginService.ts | 26 +++++++++++-- electron/utils.ts | 37 +++++++++++++------ package-lock.json | 2 +- package.json | 2 +- .../PluginManager/PluginInstallModal.tsx | 16 ++------ src/constants/tooltips.ts | 1 + 9 files changed, 59 insertions(+), 32 deletions(-) diff --git a/electron/extensions/downloadExtension.ts b/electron/extensions/downloadExtension.ts index 0dc8a905b9..2a7a62c1ae 100644 --- a/electron/extensions/downloadExtension.ts +++ b/electron/extensions/downloadExtension.ts @@ -30,6 +30,8 @@ async function downloadExtension( {skipEntryFileSave: true} ); + console.log('extensionEntry', extensionEntry); + const extensionFolderPath = makeExtensionFolderPath(extensionEntry); await createOrRecreateFolder(extensionFolderPath); diff --git a/electron/extensions/downloadExtensionEntry.ts b/electron/extensions/downloadExtensionEntry.ts index a635a6c902..43be56de95 100644 --- a/electron/extensions/downloadExtensionEntry.ts +++ b/electron/extensions/downloadExtensionEntry.ts @@ -47,7 +47,7 @@ async function downloadExtensionEntry( if (doesEntryFileExist) { await deleteFile(entryFilePath); } - await writeFile(entryFilePath, entryFileContent); + await writeFile(entryFilePath, JSON.stringify(parsedEntryFileContent)); return parsedEntryFileContent; } diff --git a/electron/extensions/loadExtension.ts b/electron/extensions/loadExtension.ts index c7bc887819..c8f1cdb50e 100644 --- a/electron/extensions/loadExtension.ts +++ b/electron/extensions/loadExtension.ts @@ -23,8 +23,9 @@ async function loadExtension( return undefined; } const entryFileContent = await readFile(entryFilePath); - const parsedEntryFileContent = parseEntryFileContent(entryFileContent); + let parsedEntryFileContent; try { + parsedEntryFileContent = parseEntryFileContent(entryFileContent); validateEntryFileContent(parsedEntryFileContent); } catch (e) { if (e instanceof Error) { diff --git a/electron/pluginService.ts b/electron/pluginService.ts index 16ca6b1902..0d26eb03bc 100644 --- a/electron/pluginService.ts +++ b/electron/pluginService.ts @@ -20,7 +20,9 @@ import {convertExtensionsToRecord, extractRepositoryOwnerAndNameFromUrl, makeExt const PLUGIN_ENTRY_FILE_NAME = 'package.json'; function transformPackageJsonToAnyPlugin(packageJson: PluginPackageJson, folderPath: string): AnyPlugin { - const {repositoryOwner, repositoryName} = extractRepositoryOwnerAndNameFromUrl(packageJson.repository); + const {repositoryOwner, repositoryName, repositoryBranch} = extractRepositoryOwnerAndNameFromUrl( + packageJson.repository + ); const plugin: AnyPlugin = { id: packageJson.monoklePlugin.id, name: packageJson.name, @@ -31,7 +33,7 @@ function transformPackageJsonToAnyPlugin(packageJson: PluginPackageJson, folderP repository: { owner: repositoryOwner, name: repositoryName, - branch: 'main', // TODO: handle the branch name + branch: repositoryBranch, // TODO: handle the branch name }, modules: packageJson.monoklePlugin.modules.map(module => { if (isTemplatePluginModule(module)) { @@ -60,7 +62,7 @@ export async function downloadPlugin( extensionTarballUrl: tarballUrl, entryFileName: 'package.json', entryFileUrl, - parseEntryFileContent: JSON.parse, + parseEntryFileContent: parseEntryFileContentHandler.bind(null, pluginUrl), validateEntryFileContent: validatePluginPackageJson, transformEntryFileContentToExtension: transformPackageJsonToAnyPlugin, makeExtensionFolderPath: () => { @@ -97,7 +99,14 @@ export async function updatePlugin( pluginsDir: string, userTempDir: string ): Promise | undefined> { - const repositoryUrl = `https://github.com/${plugin.repository.owner}/${plugin.repository.name}`; + let repositoryUrl; + + if (plugin.repository.branch) { + repositoryUrl = `https://github.com/${plugin.repository.owner}/${plugin.repository.name}/tree/${plugin.repository.branch}`; + } else { + repositoryUrl = `https://github.com/${plugin.repository.owner}/${plugin.repository.name}`; + } + const {entryFileUrl, folderPath} = makeExtensionDownloadData(repositoryUrl, PLUGIN_ENTRY_FILE_NAME, userTempDir); let tempPluginEntry: PluginPackageJson; try { @@ -114,6 +123,7 @@ export async function updatePlugin( } return; } + if (semver.lt(plugin.version, tempPluginEntry.version)) { try { const pluginExtension = await downloadPlugin(repositoryUrl, pluginsDir); @@ -128,3 +138,11 @@ export async function updatePlugin( } return undefined; } + +export const parseEntryFileContentHandler = (pluginUrl: string, entryFileContext: string) => { + const entryFile = JSON.parse(entryFileContext); + if (pluginUrl) { + entryFile.repository = pluginUrl; + } + return entryFile; +}; diff --git a/electron/utils.ts b/electron/utils.ts index 92ba1eb17f..dd06edea26 100644 --- a/electron/utils.ts +++ b/electron/utils.ts @@ -3,6 +3,7 @@ import {dialog} from 'electron'; import {AnyAction} from '@reduxjs/toolkit'; import {existsSync, mkdirSync, writeFileSync} from 'fs'; +import gitUrlParse from 'git-url-parse'; import _ from 'lodash'; import {machineIdSync} from 'node-machine-id'; import Nucleus from 'nucleus-nodejs'; @@ -18,7 +19,6 @@ import {loadResource} from '@redux/services'; import electronStore from '@utils/electronStore'; import {PROCESS_ENV} from '@utils/env'; -const GITHUB_URL = 'https://github.com'; const GITHUB_REPOSITORY_REGEX = /^https:\/\/github.com\/[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+/i; export function isValidRepositoryUrl(repositoryUrl: string) { @@ -27,14 +27,24 @@ export function isValidRepositoryUrl(repositoryUrl: string) { export function extractRepositoryOwnerAndNameFromUrl(pluginUrl: string) { if (!isValidRepositoryUrl(pluginUrl)) { - throw new Error('Invalid repository URL'); + throw new Error('Currently we support only Github as provider'); + } + const parsedURL = gitUrlParse(pluginUrl); + if (!parsedURL.owner || !parsedURL.name) { + throw new Error('Please enter a valid git URL!'); + } + if (!parsedURL.protocols.includes('https')) { + throw new Error('Currently we support only HTTPS protocol!'); + } + if (parsedURL.filepathtype && parsedURL.filepathtype !== 'tree') { + throw new Error('Please navigate main url of the branch!'); } - const repositoryPath = pluginUrl.split(`${GITHUB_URL}/`)[1]; - const [repositoryOwner, repositoryName] = repositoryPath.split('/'); - return { - repositoryOwner, - repositoryName, + repositoryOwner: parsedURL.owner, + repositoryName: parsedURL.name, + repositoryBranch: !parsedURL.filepathtype + ? 'main' + : `${parsedURL.ref}${parsedURL.filepath ? `/${parsedURL.filepath}` : ''}`, }; } @@ -43,10 +53,15 @@ export function makeExtensionDownloadData( extensionEntryFileName: string, downloadPath: string ) { - const {repositoryOwner, repositoryName} = extractRepositoryOwnerAndNameFromUrl(extensionRepositoryUrl); - const entryFileUrl = `https://raw.githubusercontent.com/${repositoryOwner}/${repositoryName}/main/${extensionEntryFileName}`; - const tarballUrl = `https://api.github.com/repos/${repositoryOwner}/${repositoryName}/tarball/main`; - const folderPath = path.join(downloadPath, `${repositoryOwner}-${repositoryName}`); + const {repositoryOwner, repositoryName, repositoryBranch} = + extractRepositoryOwnerAndNameFromUrl(extensionRepositoryUrl); + const entryFileUrl = `https://raw.githubusercontent.com/${repositoryOwner}/${repositoryName}/${repositoryBranch}/${extensionEntryFileName}`; + const tarballUrl = `https://api.github.com/repos/${repositoryOwner}/${repositoryName}/tarball/${repositoryBranch}`; + const folderPath = path.join( + downloadPath, + // @ts-ignore + `${repositoryOwner}-${repositoryName}-${repositoryBranch.replaceAll(path.sep, '-')}` + ); return {entryFileUrl, tarballUrl, folderPath}; } diff --git a/package-lock.json b/package-lock.json index 68f80f4b2a..3cc7fe6a3b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,7 +27,7 @@ "electron-devtools-installer": "3.2.0", "electron-log": "4.4.6", "electron-store": "8.0.1", - "electron-unhandled": "^4.0.0", + "electron-unhandled": "4.0.0", "electron-updater": "4.6.5", "es6-tween": "5.5.11", "execa": "5.1.1", diff --git a/package.json b/package.json index a04c3c9d2a..36754e855c 100644 --- a/package.json +++ b/package.json @@ -101,7 +101,7 @@ "electron-devtools-installer": "3.2.0", "electron-log": "4.4.6", "electron-store": "8.0.1", - "electron-unhandled": "^4.0.0", + "electron-unhandled": "4.0.0", "electron-updater": "4.6.5", "es6-tween": "5.5.11", "execa": "5.1.1", diff --git a/src/components/organisms/PluginManager/PluginInstallModal.tsx b/src/components/organisms/PluginManager/PluginInstallModal.tsx index 93f9411645..2a087aa42c 100644 --- a/src/components/organisms/PluginManager/PluginInstallModal.tsx +++ b/src/components/organisms/PluginManager/PluginInstallModal.tsx @@ -5,10 +5,9 @@ import React, {useEffect, useState} from 'react'; import {Button, Form, Input, Modal} from 'antd'; import {useForm} from 'antd/lib/form/Form'; -import gitUrlParse from 'git-url-parse'; - import {PLUGIN_DOCS_URL} from '@constants/constants'; import {DOWNLOAD_PLUGIN, DOWNLOAD_PLUGIN_RESULT} from '@constants/ipcEvents'; +import {PLUGIN_URL_INPUT_TOOLTIP} from '@constants/tooltips'; import {DownloadPluginResult, isDownloadPluginResult} from '@models/extension'; @@ -80,16 +79,7 @@ function PluginInstallModal(props: {isVisible: boolean; onClose: () => void}) { const handlePluginURLChange = async (url: string) => { try { - const parsedURL = gitUrlParse(url); - if (!parsedURL.owner || !parsedURL.name) { - setErrorMessage('Please enter a valid git URL!'); - return; - } - if (!parsedURL.protocols.includes('https')) { - setErrorMessage('Currently we support only HTTPS protocol'); - return; - } - await download(`${parsedURL.protocol}://${parsedURL.resource}/${parsedURL.owner}/${parsedURL.name}`); + await download(url); } catch (error: any) { setErrorMessage(error.message); } @@ -143,7 +133,7 @@ function PluginInstallModal(props: {isVisible: boolean; onClose: () => void}) { name="pluginUrl" label="URL" required - tooltip="pluginUrl" + tooltip={PLUGIN_URL_INPUT_TOOLTIP} rules={[ { required: true, diff --git a/src/constants/tooltips.ts b/src/constants/tooltips.ts index 5fc6d39847..63bdce0b04 100644 --- a/src/constants/tooltips.ts +++ b/src/constants/tooltips.ts @@ -60,3 +60,4 @@ export const NewResourceTooltip = `Create new resource (${KEY_CTRL_CMD} + N)`; export const NewPreviewConfigurationTooltip = 'Create a new Preview Configuration'; export const DisableEventTrackingTooltip = 'Disables collection of usage metrics'; export const DisableErrorReportingTooltip = 'Disables collection of error reports'; +export const PLUGIN_URL_INPUT_TOOLTIP = 'Enter the repository/branch url of the plugin you want to add!'; From 2c6e70ab121ed8fe8d672eab6356f00a20019fd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erdi=20K=C3=B6se?= Date: Sat, 5 Mar 2022 08:25:38 +0300 Subject: [PATCH 4/6] chore: delete logs and comments --- electron/extensions/downloadExtension.ts | 2 -- electron/pluginService.ts | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/electron/extensions/downloadExtension.ts b/electron/extensions/downloadExtension.ts index 2a7a62c1ae..0dc8a905b9 100644 --- a/electron/extensions/downloadExtension.ts +++ b/electron/extensions/downloadExtension.ts @@ -30,8 +30,6 @@ async function downloadExtension( {skipEntryFileSave: true} ); - console.log('extensionEntry', extensionEntry); - const extensionFolderPath = makeExtensionFolderPath(extensionEntry); await createOrRecreateFolder(extensionFolderPath); diff --git a/electron/pluginService.ts b/electron/pluginService.ts index 0d26eb03bc..86a3629077 100644 --- a/electron/pluginService.ts +++ b/electron/pluginService.ts @@ -33,7 +33,7 @@ function transformPackageJsonToAnyPlugin(packageJson: PluginPackageJson, folderP repository: { owner: repositoryOwner, name: repositoryName, - branch: repositoryBranch, // TODO: handle the branch name + branch: repositoryBranch, }, modules: packageJson.monoklePlugin.modules.map(module => { if (isTemplatePluginModule(module)) { From 1b02e480b0075a5e2060605dcb316d73167102fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erdi=20K=C3=B6se?= Date: Sun, 6 Mar 2022 04:54:12 +0300 Subject: [PATCH 5/6] chore: don't allow to save any extension if any json file is invalid --- electron/extensions/downloadExtension.ts | 22 +++++++++++++++++++++- electron/extensions/fileSystem.ts | 16 ++++++++++++++++ electron/extensions/loadExtension.ts | 5 ++--- electron/templateService.ts | 10 +++++++++- 4 files changed, 48 insertions(+), 5 deletions(-) diff --git a/electron/extensions/downloadExtension.ts b/electron/extensions/downloadExtension.ts index 0dc8a905b9..dac9354f5d 100644 --- a/electron/extensions/downloadExtension.ts +++ b/electron/extensions/downloadExtension.ts @@ -1,9 +1,11 @@ +import {readFileSync} from 'fs'; +import path from 'path'; import tar from 'tar'; import {downloadFile} from '@utils/http'; import downloadExtensionEntry from './downloadExtensionEntry'; -import {createOrRecreateFolder, deleteFile, doesPathExist} from './fileSystem'; +import {createOrRecreateFolder, deleteFile, deleteFolder, doesPathExist, getAllFiles} from './fileSystem'; import {DownloadExtensionOptions} from './types'; async function downloadExtension( @@ -50,7 +52,25 @@ async function downloadExtension( await deleteFile(tarballFilePath); + checkAllJSONFilesOfExtensionAreValid(extensionFolderPath); + return extension; } export default downloadExtension; + +export const checkAllJSONFilesOfExtensionAreValid = (folderPath: string) => { + const allFiles = getAllFiles(folderPath).filter(file => path.extname(file) === '.json'); + let currentFile: string = ''; + try { + allFiles.forEach(file => { + currentFile = file; + const fileData = readFileSync(file); + JSON.parse(fileData.toString()); + }); + } catch (error: any) { + deleteFolder(folderPath); + const paths: Array = currentFile.split(path.sep); + throw new Error(`[${paths[paths.length - 1]}]: ${error.message}`); + } +}; diff --git a/electron/extensions/fileSystem.ts b/electron/extensions/fileSystem.ts index 9946bf75b1..f775a85932 100644 --- a/electron/extensions/fileSystem.ts +++ b/electron/extensions/fileSystem.ts @@ -1,4 +1,5 @@ import fs, {promises} from 'fs'; +import { join, sep } from 'path'; import util from 'util'; export const doesPathExist = (path: string) => util.promisify(fs.exists)(path); @@ -14,3 +15,18 @@ export const deleteFile = (filePath: string) => promises.unlink(filePath); export const deleteFolder = (folderPath: string) => promises.rm(folderPath, {recursive: true}); export const readFile = (filePath: string) => promises.readFile(filePath, 'utf8'); export const writeFile = (filePath: string, fileContent: string) => promises.writeFile(filePath, fileContent, 'utf8'); + +export const getAllFiles = (dirPath: string, arrayOfFiles?: Array) => { + const files = fs.readdirSync(dirPath); + arrayOfFiles = arrayOfFiles || []; + + files.forEach((file: string) => { + if (fs.statSync(join(dirPath, file)).isDirectory()) { + arrayOfFiles = getAllFiles(join(dirPath, file), arrayOfFiles); + } else { + (>arrayOfFiles).push(join(dirPath, sep, file)); + } + }); + + return arrayOfFiles; +}; \ No newline at end of file diff --git a/electron/extensions/loadExtension.ts b/electron/extensions/loadExtension.ts index c8f1cdb50e..405cd80ca2 100644 --- a/electron/extensions/loadExtension.ts +++ b/electron/extensions/loadExtension.ts @@ -23,13 +23,12 @@ async function loadExtension( return undefined; } const entryFileContent = await readFile(entryFilePath); - let parsedEntryFileContent; + const parsedEntryFileContent = parseEntryFileContent(entryFileContent); try { - parsedEntryFileContent = parseEntryFileContent(entryFileContent); validateEntryFileContent(parsedEntryFileContent); } catch (e) { if (e instanceof Error) { - log.warn(`[LoadExtension]: Invalid ${entryFileName} in ${folderPath}: `, e.message); + log.warn(`[LoadExtension]: Invalid ${entryFileName} in ${folderPath}: `); } return undefined; } diff --git a/electron/templateService.ts b/electron/templateService.ts index f973d9fa93..8bdeea3a31 100644 --- a/electron/templateService.ts +++ b/electron/templateService.ts @@ -141,7 +141,7 @@ const makeLoadTemplateOptions = (folderPath: string) => { return { folderPath, entryFileName: TEMPLATE_ENTRY_FILE_NAME, - parseEntryFileContent: JSON.parse, + parseEntryFileContent: parseEntryFileContentHandler.bind(null), validateEntryFileContent: validateAnyTemplate, transformEntryFileContentToExtension: parseTemplate, }; @@ -307,3 +307,11 @@ export async function updateTemplatePack( } return undefined; } + +export const parseEntryFileContentHandler = (entryFileContent: any) => { + try { + return JSON.parse(entryFileContent); + } catch (error: any) { + log.error(`[${entryFileContent.name}]: ${error.message}`); + } +}; From dcb08aedb33c2dfaff1fe66489a23bf9a66ef3dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erdi=20K=C3=B6se?= Date: Sun, 6 Mar 2022 05:27:31 +0300 Subject: [PATCH 6/6] chore: add sample repository URLs --- .../PluginManager/PluginInstallModal.tsx | 17 ++++++++++++++--- src/constants/tooltips.ts | 1 - 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/components/organisms/PluginManager/PluginInstallModal.tsx b/src/components/organisms/PluginManager/PluginInstallModal.tsx index 2a087aa42c..e47d0bb0c5 100644 --- a/src/components/organisms/PluginManager/PluginInstallModal.tsx +++ b/src/components/organisms/PluginManager/PluginInstallModal.tsx @@ -7,7 +7,6 @@ import {useForm} from 'antd/lib/form/Form'; import {PLUGIN_DOCS_URL} from '@constants/constants'; import {DOWNLOAD_PLUGIN, DOWNLOAD_PLUGIN_RESULT} from '@constants/ipcEvents'; -import {PLUGIN_URL_INPUT_TOOLTIP} from '@constants/tooltips'; import {DownloadPluginResult, isDownloadPluginResult} from '@models/extension'; @@ -133,7 +132,16 @@ function PluginInstallModal(props: {isVisible: boolean; onClose: () => void}) { name="pluginUrl" label="URL" required - tooltip={PLUGIN_URL_INPUT_TOOLTIP} + tooltip={{ + title: ( +
+
Enter the repository/branch url of the plugin you want to add! ie:
+
https://github.com/kubeshop/monokle-default-templates-plugin,
+
https://github.com/kubeshop/monokle-default-templates-plugin/tree/test
+
+ ), + overlayInnerStyle: {width: '500px'}, + }} rules={[ { required: true, @@ -141,7 +149,10 @@ function PluginInstallModal(props: {isVisible: boolean; onClose: () => void}) { }, ]} > - +
diff --git a/src/constants/tooltips.ts b/src/constants/tooltips.ts index 63bdce0b04..5fc6d39847 100644 --- a/src/constants/tooltips.ts +++ b/src/constants/tooltips.ts @@ -60,4 +60,3 @@ export const NewResourceTooltip = `Create new resource (${KEY_CTRL_CMD} + N)`; export const NewPreviewConfigurationTooltip = 'Create a new Preview Configuration'; export const DisableEventTrackingTooltip = 'Disables collection of usage metrics'; export const DisableErrorReportingTooltip = 'Disables collection of error reports'; -export const PLUGIN_URL_INPUT_TOOLTIP = 'Enter the repository/branch url of the plugin you want to add!';