From 162efc02d536ec78e9cf5a8cfd63144f2610eafe Mon Sep 17 00:00:00 2001 From: Nick Mitchell Date: Mon, 10 Apr 2023 15:43:36 -0400 Subject: [PATCH] feat: remove need for babel This updates the way we prescan the plugins so as to remove any need for CJS modules. We can thus remove the last remaining use of babel. BREAKING CHANGE: this is a substantial change, and may introduce issues with plugins. It is unlikely, by it seems prudent to mark this as a major change. --- bin/switch-client.sh | 2 + package-lock.json | 318 ++++++++---------- package.json | 10 +- packages/builder/bin/compile.sh | 6 +- packages/builder/bin/prescan.sh | 24 +- .../dist/electron/builders/electron.js | 25 +- packages/builder/package.json | 6 - packages/core/src/core/command-tree.ts | 16 + packages/core/src/plugins/assembler.ts | 2 +- packages/core/src/plugins/path.ts | 2 +- packages/core/src/plugins/plugins.ts | 13 +- packages/core/src/plugins/preloader.ts | 7 +- packages/core/src/plugins/resolver.ts | 4 +- packages/core/src/plugins/scanner.ts | 217 ++++++------ packages/{builder => test}/bin/babel.sh | 0 packages/test/bin/runTest.sh | 3 + packages/test/package.json | 6 + packages/webpack/build.sh | 4 +- packages/webpack/headless-webpack.config.js | 15 +- packages/webpack/webpack.config.js | 2 +- plugins/plugin-bash-like/src/preload.ts | 10 +- .../src/components/Views/Confirm.tsx | 14 +- .../src/controller/alert.ts | 43 +-- .../src/controller/card.ts | 53 +-- .../src/controller/commentary.ts | 26 +- .../src/controller/confirm.ts | 83 +++-- .../src/controller/split.ts | 2 +- .../src/controller/user-settings.ts | 16 +- plugins/plugin-client-common/src/plugin.ts | 117 ++++++- .../src/lib/cmds/base64.ts | 6 +- .../src/lib/cmds/history/history.ts | 8 +- .../src/lib/cmds/replay.ts | 4 +- .../src/notebooks/vfs/index.ts | 3 +- plugins/plugin-s3/ibm/src/controller/bind.ts | 2 +- .../plugin-s3/ibm/src/controller/validate.ts | 2 +- plugins/plugin-s3/ibm/src/plugin.ts | 47 +-- plugins/plugin-s3/src/browse/index.ts | 8 +- .../plugin-s3/src/vfs/browser/forwarder.ts | 21 +- 38 files changed, 592 insertions(+), 555 deletions(-) rename packages/{builder => test}/bin/babel.sh (100%) diff --git a/bin/switch-client.sh b/bin/switch-client.sh index b430e5d34c1..ef41d4c87e4 100755 --- a/bin/switch-client.sh +++ b/bin/switch-client.sh @@ -19,6 +19,8 @@ set -e set -o pipefail +rm -f dist/electron/kui.min.js + SCRIPTDIR=$(cd $(dirname "$0") && pwd) cd "$SCRIPTDIR"/.. diff --git a/package-lock.json b/package-lock.json index 0c91be73cb3..b29025384cb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -64,12 +64,12 @@ } }, "node_modules/@ampproject/remapping": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", - "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", "dev": true, "dependencies": { - "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/gen-mapping": "^0.3.0", "@jridgewell/trace-mapping": "^0.3.9" }, "engines": { @@ -106,9 +106,9 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz", + "integrity": "sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==", "dev": true, "dependencies": { "@babel/highlight": "^7.18.6" @@ -118,30 +118,30 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.0.tgz", - "integrity": "sha512-gMuZsmsgxk/ENC3O/fRw5QY8A9/uxQbbCEypnLIiYYc/qVJtEV7ouxC3EllIIwNzMqAQee5tanFabWsUOutS7g==", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.4.tgz", + "integrity": "sha512-/DYyDpeCfaVinT40FPGdkkb+lYSKvsVuMjDAG7jPOWWiM1ibOaB9CXJAlc4d1QpP/U2q2P9jbrSlClKSErd55g==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.0.tgz", - "integrity": "sha512-PuxUbxcW6ZYe656yL3EAhpy7qXKq0DmYsrJLpbB8XrsCP9Nm+XCg9XFMb5vIDliPD7+U/+M+QJlH17XOcB7eXA==", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.4.tgz", + "integrity": "sha512-qt/YV149Jman/6AfmlxJ04LMIu8bMoyl3RB91yTFrxQmgbrSvQMy7cI8Q62FHx1t8wJ8B5fu0UDoLwHAhUo1QA==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.21.0", - "@babel/helper-compilation-targets": "^7.20.7", - "@babel/helper-module-transforms": "^7.21.0", + "@babel/code-frame": "^7.21.4", + "@babel/generator": "^7.21.4", + "@babel/helper-compilation-targets": "^7.21.4", + "@babel/helper-module-transforms": "^7.21.2", "@babel/helpers": "^7.21.0", - "@babel/parser": "^7.21.0", + "@babel/parser": "^7.21.4", "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.0", - "@babel/types": "^7.21.0", + "@babel/traverse": "^7.21.4", + "@babel/types": "^7.21.4", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -166,12 +166,12 @@ } }, "node_modules/@babel/generator": { - "version": "7.21.1", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.1.tgz", - "integrity": "sha512-1lT45bAYlQhFn/BHivJs43AiW2rg3/UbLyShGfF3C0KmHvO5fSghWd5kBJy30kpRRucGzXStvnnCFniCR2kXAA==", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.4.tgz", + "integrity": "sha512-NieM3pVIYW2SwGzKoqfPrQsf4xGs9M9AIG3ThppsSRmO+m7eQhmI6amajKMUeIO37wFfsvnvcxQFx6x6iqxDnA==", "dev": true, "dependencies": { - "@babel/types": "^7.21.0", + "@babel/types": "^7.21.4", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -180,28 +180,14 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz", - "integrity": "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.21.4.tgz", + "integrity": "sha512-Fa0tTuOXZ1iL8IeDFUWCzjZcn+sJGd9RZdH9esYVjEejGmzf+FFYQpMi/kZUk2kPy/q1H3/GPw7np8qar/stfg==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.20.5", - "@babel/helper-validator-option": "^7.18.6", + "@babel/compat-data": "^7.21.4", + "@babel/helper-validator-option": "^7.21.0", "browserslist": "^4.21.3", "lru-cache": "^5.1.1", "semver": "^6.3.0" @@ -257,21 +243,21 @@ } }, "node_modules/@babel/helper-module-imports": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", - "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.21.4.tgz", + "integrity": "sha512-orajc5T2PsRYUN3ZryCEFeMDYwyw09c/pZeaQEZPH0MpKzSvn3e0uXsDBu3k03VI+9DBiRo+l22BfKTpKwa/Wg==", "dev": true, "dependencies": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.21.4" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.0.tgz", - "integrity": "sha512-eD/JQ21IG2i1FraJnTMbUarAUkA7G988ofehG5MDCRXaUU91rEBJuCeSoou2Sk1y4RbLYXzqEg1QLwEmRU4qcQ==", + "version": "7.21.2", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz", + "integrity": "sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==", "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.18.9", @@ -280,8 +266,8 @@ "@babel/helper-split-export-declaration": "^7.18.6", "@babel/helper-validator-identifier": "^7.19.1", "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.0", - "@babel/types": "^7.21.0" + "@babel/traverse": "^7.21.2", + "@babel/types": "^7.21.2" }, "engines": { "node": ">=6.9.0" @@ -447,9 +433,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.21.1", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.1.tgz", - "integrity": "sha512-JzhBFpkuhBNYUY7qs+wTzNmyCWUHEaAFpQQD2YfU1rPL38/L43Wvid0fFkiOCnHvsGncRZgEPyGnltABLcVDTg==", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.4.tgz", + "integrity": "sha512-alVJj7k7zIxqBZ7BTRhz0IqJFxW1VJbm6N8JbcYhQ186df9ZBPbZBmWSqAMXwHGsCJdYks7z/voa3ibiS5bCIw==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -471,12 +457,12 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.20.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.20.11.tgz", - "integrity": "sha512-S8e1f7WQ7cimJQ51JkAaDrEtohVEitXjgCGAS2N8S31Y42E+kWwfSz83LYz57QdBm7q9diARVqanIaH2oVgQnw==", + "version": "7.21.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.21.2.tgz", + "integrity": "sha512-Cln+Yy04Gxua7iPdj6nOV96smLGjpElir5YwzF0LBPKoPlLDNJePNlrGGaybAJkd0zKRnOVXOgizSqPYMNYkzA==", "dev": true, "dependencies": { - "@babel/helper-module-transforms": "^7.20.11", + "@babel/helper-module-transforms": "^7.21.2", "@babel/helper-plugin-utils": "^7.20.2", "@babel/helper-simple-access": "^7.20.2" }, @@ -502,19 +488,19 @@ } }, "node_modules/@babel/traverse": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.0.tgz", - "integrity": "sha512-Xdt2P1H4LKTO8ApPfnO1KmzYMFpp7D/EinoXzLYN/cHcBNrVCAkAtGUcXnHXrl/VGktureU6fkQrHSBE2URfoA==", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.4.tgz", + "integrity": "sha512-eyKrRHKdyZxqDm+fV1iqL9UAHMoIg0nDaGqfIOd8rKH17m5snv7Gn4qgjBoFfLz9APvjFU/ICT00NVCv1Epp8Q==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.21.0", + "@babel/code-frame": "^7.21.4", + "@babel/generator": "^7.21.4", "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-function-name": "^7.21.0", "@babel/helper-hoist-variables": "^7.18.6", "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.21.0", - "@babel/types": "^7.21.0", + "@babel/parser": "^7.21.4", + "@babel/types": "^7.21.4", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -523,9 +509,9 @@ } }, "node_modules/@babel/types": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.0.tgz", - "integrity": "sha512-uR7NWq2VNFnDi7EYqiRz2Jv/VQIu38tu64Zy8TX2nQFQ6etJ9V/Rr2msW8BS132mum2rL645qpDrLtAJtVpuow==", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.4.tgz", + "integrity": "sha512-rU2oY501qDxE8Pyo7i/Orqma4ziCOrby0/9mvbDUGEfvZjb279Nk9k19e2fiCxHbRRpY2ZyrgW1eq22mvmOIzA==", "dev": true, "dependencies": { "@babel/helper-string-parser": "^7.19.4", @@ -825,13 +811,13 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", - "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", - "dev": true, + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", "dependencies": { - "@jridgewell/set-array": "^1.0.0", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" }, "engines": { "node": ">=6.0.0" @@ -862,19 +848,6 @@ "@jridgewell/trace-mapping": "^0.3.9" } }, - "node_modules/@jridgewell/source-map/node_modules/@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.14", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", @@ -17184,17 +17157,11 @@ "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "@babel/cli": "^7.20.7", - "@babel/core": "^7.20.12", - "@babel/plugin-transform-modules-commonjs": "^7.20.11", "@electron/rebuild": "^3.2.10", "@types/node": "^18.11.18", - "babel-plugin-dynamic-import-node-babel-7": "^2.0.7", - "babel-plugin-ignore-html-and-css-imports": "^0.0.2", "shelljs": "^0.8.5" }, "bin": { - "kui-babel": "bin/babel.sh", "kui-build-electron": "dist/electron/build.sh", "kui-build-headless": "dist/headless/build.sh", "kui-compile": "bin/compile.sh", @@ -17302,11 +17269,17 @@ "dev": true, "license": "Apache-2.0", "dependencies": { + "@babel/cli": "^7.20.7", + "@babel/core": "^7.20.12", + "@babel/plugin-transform-modules-commonjs": "^7.20.11", "@wdio/mocha-framework": "^7.26.0", + "babel-plugin-dynamic-import-node-babel-7": "^2.0.7", + "babel-plugin-ignore-html-and-css-imports": "^0.0.2", "mocha": "^10.2.0", "spectron": "starpit/spectron#7eebbebbf5346a1c488bb8f46506c881b6e25179" }, "bin": { + "kui-babel": "bin/babel.sh", "kui-test": "bin/runMochaLayers.sh" }, "devDependencies": { @@ -17656,12 +17629,12 @@ }, "dependencies": { "@ampproject/remapping": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", - "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", "dev": true, "requires": { - "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/gen-mapping": "^0.3.0", "@jridgewell/trace-mapping": "^0.3.9" } }, @@ -17683,36 +17656,36 @@ } }, "@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz", + "integrity": "sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==", "dev": true, "requires": { "@babel/highlight": "^7.18.6" } }, "@babel/compat-data": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.0.tgz", - "integrity": "sha512-gMuZsmsgxk/ENC3O/fRw5QY8A9/uxQbbCEypnLIiYYc/qVJtEV7ouxC3EllIIwNzMqAQee5tanFabWsUOutS7g==", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.4.tgz", + "integrity": "sha512-/DYyDpeCfaVinT40FPGdkkb+lYSKvsVuMjDAG7jPOWWiM1ibOaB9CXJAlc4d1QpP/U2q2P9jbrSlClKSErd55g==", "dev": true }, "@babel/core": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.0.tgz", - "integrity": "sha512-PuxUbxcW6ZYe656yL3EAhpy7qXKq0DmYsrJLpbB8XrsCP9Nm+XCg9XFMb5vIDliPD7+U/+M+QJlH17XOcB7eXA==", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.4.tgz", + "integrity": "sha512-qt/YV149Jman/6AfmlxJ04LMIu8bMoyl3RB91yTFrxQmgbrSvQMy7cI8Q62FHx1t8wJ8B5fu0UDoLwHAhUo1QA==", "dev": true, "requires": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.21.0", - "@babel/helper-compilation-targets": "^7.20.7", - "@babel/helper-module-transforms": "^7.21.0", + "@babel/code-frame": "^7.21.4", + "@babel/generator": "^7.21.4", + "@babel/helper-compilation-targets": "^7.21.4", + "@babel/helper-module-transforms": "^7.21.2", "@babel/helpers": "^7.21.0", - "@babel/parser": "^7.21.0", + "@babel/parser": "^7.21.4", "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.0", - "@babel/types": "^7.21.0", + "@babel/traverse": "^7.21.4", + "@babel/types": "^7.21.4", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -17729,38 +17702,25 @@ } }, "@babel/generator": { - "version": "7.21.1", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.1.tgz", - "integrity": "sha512-1lT45bAYlQhFn/BHivJs43AiW2rg3/UbLyShGfF3C0KmHvO5fSghWd5kBJy30kpRRucGzXStvnnCFniCR2kXAA==", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.4.tgz", + "integrity": "sha512-NieM3pVIYW2SwGzKoqfPrQsf4xGs9M9AIG3ThppsSRmO+m7eQhmI6amajKMUeIO37wFfsvnvcxQFx6x6iqxDnA==", "dev": true, "requires": { - "@babel/types": "^7.21.0", + "@babel/types": "^7.21.4", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" - }, - "dependencies": { - "@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, - "requires": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - } - } } }, "@babel/helper-compilation-targets": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz", - "integrity": "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.21.4.tgz", + "integrity": "sha512-Fa0tTuOXZ1iL8IeDFUWCzjZcn+sJGd9RZdH9esYVjEejGmzf+FFYQpMi/kZUk2kPy/q1H3/GPw7np8qar/stfg==", "dev": true, "requires": { - "@babel/compat-data": "^7.20.5", - "@babel/helper-validator-option": "^7.18.6", + "@babel/compat-data": "^7.21.4", + "@babel/helper-validator-option": "^7.21.0", "browserslist": "^4.21.3", "lru-cache": "^5.1.1", "semver": "^6.3.0" @@ -17800,18 +17760,18 @@ } }, "@babel/helper-module-imports": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", - "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.21.4.tgz", + "integrity": "sha512-orajc5T2PsRYUN3ZryCEFeMDYwyw09c/pZeaQEZPH0MpKzSvn3e0uXsDBu3k03VI+9DBiRo+l22BfKTpKwa/Wg==", "dev": true, "requires": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.21.4" } }, "@babel/helper-module-transforms": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.0.tgz", - "integrity": "sha512-eD/JQ21IG2i1FraJnTMbUarAUkA7G988ofehG5MDCRXaUU91rEBJuCeSoou2Sk1y4RbLYXzqEg1QLwEmRU4qcQ==", + "version": "7.21.2", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz", + "integrity": "sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==", "dev": true, "requires": { "@babel/helper-environment-visitor": "^7.18.9", @@ -17820,8 +17780,8 @@ "@babel/helper-split-export-declaration": "^7.18.6", "@babel/helper-validator-identifier": "^7.19.1", "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.0", - "@babel/types": "^7.21.0" + "@babel/traverse": "^7.21.2", + "@babel/types": "^7.21.2" } }, "@babel/helper-plugin-utils": { @@ -17947,9 +17907,9 @@ } }, "@babel/parser": { - "version": "7.21.1", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.1.tgz", - "integrity": "sha512-JzhBFpkuhBNYUY7qs+wTzNmyCWUHEaAFpQQD2YfU1rPL38/L43Wvid0fFkiOCnHvsGncRZgEPyGnltABLcVDTg==", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.4.tgz", + "integrity": "sha512-alVJj7k7zIxqBZ7BTRhz0IqJFxW1VJbm6N8JbcYhQ186df9ZBPbZBmWSqAMXwHGsCJdYks7z/voa3ibiS5bCIw==", "dev": true }, "@babel/plugin-syntax-dynamic-import": { @@ -17962,12 +17922,12 @@ } }, "@babel/plugin-transform-modules-commonjs": { - "version": "7.20.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.20.11.tgz", - "integrity": "sha512-S8e1f7WQ7cimJQ51JkAaDrEtohVEitXjgCGAS2N8S31Y42E+kWwfSz83LYz57QdBm7q9diARVqanIaH2oVgQnw==", + "version": "7.21.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.21.2.tgz", + "integrity": "sha512-Cln+Yy04Gxua7iPdj6nOV96smLGjpElir5YwzF0LBPKoPlLDNJePNlrGGaybAJkd0zKRnOVXOgizSqPYMNYkzA==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.20.11", + "@babel/helper-module-transforms": "^7.21.2", "@babel/helper-plugin-utils": "^7.20.2", "@babel/helper-simple-access": "^7.20.2" } @@ -17984,27 +17944,27 @@ } }, "@babel/traverse": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.0.tgz", - "integrity": "sha512-Xdt2P1H4LKTO8ApPfnO1KmzYMFpp7D/EinoXzLYN/cHcBNrVCAkAtGUcXnHXrl/VGktureU6fkQrHSBE2URfoA==", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.4.tgz", + "integrity": "sha512-eyKrRHKdyZxqDm+fV1iqL9UAHMoIg0nDaGqfIOd8rKH17m5snv7Gn4qgjBoFfLz9APvjFU/ICT00NVCv1Epp8Q==", "dev": true, "requires": { - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.21.0", + "@babel/code-frame": "^7.21.4", + "@babel/generator": "^7.21.4", "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-function-name": "^7.21.0", "@babel/helper-hoist-variables": "^7.18.6", "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.21.0", - "@babel/types": "^7.21.0", + "@babel/parser": "^7.21.4", + "@babel/types": "^7.21.4", "debug": "^4.1.0", "globals": "^11.1.0" } }, "@babel/types": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.0.tgz", - "integrity": "sha512-uR7NWq2VNFnDi7EYqiRz2Jv/VQIu38tu64Zy8TX2nQFQ6etJ9V/Rr2msW8BS132mum2rL645qpDrLtAJtVpuow==", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.4.tgz", + "integrity": "sha512-rU2oY501qDxE8Pyo7i/Orqma4ziCOrby0/9mvbDUGEfvZjb279Nk9k19e2fiCxHbRRpY2ZyrgW1eq22mvmOIzA==", "dev": true, "requires": { "@babel/helper-string-parser": "^7.19.4", @@ -18227,13 +18187,13 @@ } }, "@jridgewell/gen-mapping": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", - "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", - "dev": true, + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", "requires": { - "@jridgewell/set-array": "^1.0.0", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" } }, "@jridgewell/resolve-uri": { @@ -18253,18 +18213,6 @@ "requires": { "@jridgewell/gen-mapping": "^0.3.0", "@jridgewell/trace-mapping": "^0.3.9" - }, - "dependencies": { - "@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "requires": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - } - } } }, "@jridgewell/sourcemap-codec": { @@ -18289,13 +18237,8 @@ "@kui-shell/builder": { "version": "file:packages/builder", "requires": { - "@babel/cli": "^7.20.7", - "@babel/core": "^7.20.12", - "@babel/plugin-transform-modules-commonjs": "^7.20.11", "@electron/rebuild": "^3.2.10", "@types/node": "^18.11.18", - "babel-plugin-dynamic-import-node-babel-7": "^2.0.7", - "babel-plugin-ignore-html-and-css-imports": "^0.0.2", "shelljs": "^0.8.5" }, "dependencies": { @@ -18609,8 +18552,13 @@ "@kui-shell/test": { "version": "file:packages/test", "requires": { + "@babel/cli": "^7.20.7", + "@babel/core": "^7.20.12", + "@babel/plugin-transform-modules-commonjs": "^7.20.11", "@types/mocha": "^10.0.1", "@wdio/mocha-framework": "^7.26.0", + "babel-plugin-dynamic-import-node-babel-7": "^2.0.7", + "babel-plugin-ignore-html-and-css-imports": "^0.0.2", "mocha": "^10.2.0", "spectron": "starpit/spectron#7eebbebbf5346a1c488bb8f46506c881b6e25179" } diff --git a/package.json b/package.json index 00c4e320988..db0c9eb041d 100644 --- a/package.json +++ b/package.json @@ -33,15 +33,13 @@ "watch:browser": "concurrently -n COMPILE,WEBPACK --kill-others 'npm run watch:source' 'npm run watch:webpack'", "watch:browser:offline": "export IS_OFFLINE_CLIENT=true; concurrently -n COMPILE,WEBPACK --kill-others 'npm run watch:source' 'npm run watch:webpack'", "watch:electron": "bash -c \"npm run pty:electron && TARGET=electron-renderer npm run _watch\"", - "watch": "bash -c \"npm run kill; npm run compile && npm run link && concurrently -n COMPILE,WEBPACK --kill-others 'npm run watch:source' 'npm run watch:electron'\"", + "watch": "bash -c \"npm run kill; rm -f dist/headless/kui.min.js && npm run compile && npm run link && concurrently -n COMPILE,WEBPACK --kill-others 'npm run watch:source' 'npm run watch:electron'\"", "proxy": "export PORT=8081; npm run kill:proxy; export KUI_USE_HTTP=true; cd packages/proxy/app && npm install && ../../../tools/travis/proxy.sh ../../..", - "watch:source": "concurrently -n TYPESCRIPT,BABEL --kill-others 'tsc --build tsconfig.json --watch' 'WATCH=--watch npx kui-babel'", - "compile:prep": "touch node_modules/@kui-shell/prescan.json", + "watch:source": "concurrently -n TYPESCRIPT --kill-others 'tsc --build tsconfig.json --watch'", "compile:source:es6": "tsc --build tsconfig.json", - "compile:source": "npm run compile:prep && npm run compile:source:es6 && npx kui-babel", - "compile:prescan": "npx kui-prescan", + "compile:source": "npm run compile:source:es6", "compile:clean": "tsc --build tsconfig.json --clean", - "compile": "npm run compile:source && npm run compile:prescan", + "compile": "npm run compile:source && npx kui-prescan", "rebuild": "npm run compile:clean; npm run compile", "clean": "npm run compile:clean; rm -rf node_modules; for i in plugins/*; do rm -rf $i/node_modules; done; for i in packages/*; do rm -rf $i/node_modules; done", "purge": "npm run clean; rm -f package-lock.json", diff --git a/packages/builder/bin/compile.sh b/packages/builder/bin/compile.sh index b6cfc84cacb..7a8d21f014a 100755 --- a/packages/builder/bin/compile.sh +++ b/packages/builder/bin/compile.sh @@ -31,7 +31,7 @@ set -o pipefail SCRIPTDIR=$(cd $(dirname "$0") && pwd) -# for compile.js below; give it an absolute path +# these may no longer be needed, with the non-babel prescan? export CLIENT_HOME=${CLIENT_HOME-`pwd`} export PLUGIN_ROOT="$(cd "$TOPDIR" && pwd)/plugins" @@ -47,12 +47,10 @@ else # (produced by builder/lib/configure.js, but which cannot be run # until after we've compiled the source) mkdir -p ./node_modules/@kui-shell - touch ./node_modules/@kui-shell/prescan.json + echo "{}" > ./node_modules/@kui-shell/prescan.json # compile the source npx tsc -b ${1-.} - - npx kui-babel fi if [ ! -d node_modules/@kui-shell/build ]; then diff --git a/packages/builder/bin/prescan.sh b/packages/builder/bin/prescan.sh index b56258630cf..fce0524306b 100755 --- a/packages/builder/bin/prescan.sh +++ b/packages/builder/bin/prescan.sh @@ -23,7 +23,7 @@ SCRIPTDIR=$(cd $(dirname "$0") && pwd) # for compile.js below; give it an absolute path export CLIENT_HOME=${CLIENT_HOME-`pwd`} -export PLUGIN_ROOT="$(cd "$TOPDIR" && pwd)/plugins" +export PLUGIN_ROOT="$(cd "$CLIENT_HOME" && pwd)/plugins" # webpack.config.js may set this in its watcher to ask us to generate # the prescan in a specific location @@ -34,17 +34,27 @@ export KUI_PRESCAN # until after we've compiled the source) if [ -z "$KUI_PRESCAN" ]; then mkdir -p ./node_modules/@kui-shell - if [ ! -e ./node_modules/@kui-shell/prescan.json ]; then - touch ./node_modules/@kui-shell/prescan.json + if [ ! -s ./node_modules/@kui-shell/prescan.json ]; then + echo "{}" > ./node_modules/@kui-shell/prescan.json fi fi -# pre-compile plugin registry -if [ -f ./node_modules/@kui-shell/builder/dist/bin/compile.js ]; then - echo "compiling plugin registry $CLIENT_HOME to ${KUI_PRESCAN-default location}" - node ./node_modules/@kui-shell/builder/dist/bin/compile.js +echo "compiling plugin registry $CLIENT_HOME to ${KUI_PRESCAN-default location}" +MAIN=$(node -e "console.log(require(\"$CLIENT_HOME/package.json\").main)") +MAIN_PROXY=$(echo "$MAIN" | sed -E 's/\.min\.js/-proxy.min.js/') +if [ -f "$MAIN" ] +then KUI_HEADLESS=true node "$MAIN" -- kui internal scan +elif [ -f "$MAIN_PROXY" ] +then KUI_HEADLESS=true node "$MAIN_PROXY" -- kui internal scan +else echo "Deferring prescan" fi +# pre-compile plugin registry +#if [ -f ./node_modules/@kui-shell/builder/dist/bin/compile.js ]; then +# echo "compiling plugin registry $CLIENT_HOME to ${KUI_PRESCAN-default location}" +# node ./node_modules/@kui-shell/builder/dist/bin/compile.js +#fi + # generate the index.json in @kui-shell/client/notebooks/index.json if [ -d node_modules/@kui-shell/client/notebooks ]; then TGT=${KUI_PRESCAN_GUIDEBOOKS-node_modules/@kui-shell/build/client-guidebooks.json} diff --git a/packages/builder/dist/electron/builders/electron.js b/packages/builder/dist/electron/builders/electron.js index feb886a0b48..c6d0611076b 100644 --- a/packages/builder/dist/electron/builders/electron.js +++ b/packages/builder/dist/electron/builders/electron.js @@ -118,9 +118,9 @@ async function buildWebpack(buildPath, electronVersion, targetPlatform, targetAr KUI_BUILDER_HOME: `${CLIENT_HOME}/node_modules/@kui-shell/builder` }) - console.log('Building headless bundles via webpack') - asyncs.push( - new Promise((resolve, reject) => { + const buildHeadless = () => { + console.log('Building headless bundles via webpack') + return new Promise((resolve, reject) => { exec( `npx --no-install webpack-cli --mode=production --config "${CLIENT_HOME}/node_modules/@kui-shell/webpack/headless-webpack.config.js"`, { env }, @@ -135,7 +135,24 @@ async function buildWebpack(buildPath, electronVersion, targetPlatform, targetAr } ) }) - ) + } + + // generate prescan model; to do so we need a headless build + await buildHeadless() + await new Promise((resolve, reject) => { + exec(`npx --no-install kui-prescan`, { env, cwd: env.CLIENT_HOME }, (err, stdout, stderr) => { + console.log('stdout', stdout) + if (err) { + console.error(err) + reject(stderr) + } else { + resolve() + } + }) + }) + + // re-build headless now that we have the prescan + asyncs.push(buildHeadless()) console.log('Building electron bundles via webpack') asyncs.push( diff --git a/packages/builder/package.json b/packages/builder/package.json index 6eff7eac444..67646e94492 100644 --- a/packages/builder/package.json +++ b/packages/builder/package.json @@ -17,7 +17,6 @@ "kui-build-electron": "./dist/electron/build.sh", "kui-set-icon": "./bin/seticon.js", "kui-init": "./build/kui-dist-init.js", - "kui-babel": "./bin/babel.sh", "kui-compile": "./bin/compile.sh", "kui-prescan": "./bin/prescan.sh" }, @@ -26,13 +25,8 @@ "prepack": "chmod +x ./build/kui-dist-init.js" }, "dependencies": { - "@babel/cli": "^7.20.7", - "@babel/core": "^7.20.12", - "@babel/plugin-transform-modules-commonjs": "^7.20.11", "@electron/rebuild": "^3.2.10", "@types/node": "^18.11.18", - "babel-plugin-dynamic-import-node-babel-7": "^2.0.7", - "babel-plugin-ignore-html-and-css-imports": "^0.0.2", "shelljs": "^0.8.5" }, "kui": { diff --git a/packages/core/src/core/command-tree.ts b/packages/core/src/core/command-tree.ts index 3d54c0f1c6f..a6b85ce446c 100644 --- a/packages/core/src/core/command-tree.ts +++ b/packages/core/src/core/command-tree.ts @@ -582,6 +582,22 @@ export const read = async ( execOptions: ExecOptions, tryCatchalls = true ): Promise> => { + if (argv[0] === 'kui' && argv[1] === 'internal' && argv[2] === 'scan') { + // for bootstrapping the plugin registry + return { + eval: () => import('../plugins/assembler').then(_ => _.compile()).then(() => true as any as T), + subtree: undefined, + route: '/kui/internal/scan', + options: {}, + success: () => { + /* noop */ + }, + error: (a, b, c, err) => { + throw err + } + } + } + let cmd: false | CodedError | CommandHandlerWithEvents if (!noRetry) { diff --git a/packages/core/src/plugins/assembler.ts b/packages/core/src/plugins/assembler.ts index fd033b9287b..19174278a46 100644 --- a/packages/core/src/plugins/assembler.ts +++ b/packages/core/src/plugins/assembler.ts @@ -33,7 +33,7 @@ const debug = Debug('core/plugins/assembler') * model that represents user-installed plugins) * */ -const prescanned = (): string => require.resolve('@kui-shell/prescan') +const prescanned = (): string => join(process.env.CLIENT_HOME, 'node_modules/@kui-shell/prescan.json') /** * Serialize a `PrescanModel` to disk diff --git a/packages/core/src/plugins/path.ts b/packages/core/src/plugins/path.ts index 9e018f29772..6528c664a6a 100644 --- a/packages/core/src/plugins/path.ts +++ b/packages/core/src/plugins/path.ts @@ -22,7 +22,7 @@ * */ export function webpackPath(path: string) { - return path.replace(/^plugin-/, '').replace(/\/dist\/.*\.js$/, '') + return path.replace(/^plugin-/, '').replace(/\/mdist\/.*\.js$/, '') } /** diff --git a/packages/core/src/plugins/plugins.ts b/packages/core/src/plugins/plugins.ts index 099e2aeacc3..5298b4f055b 100644 --- a/packages/core/src/plugins/plugins.ts +++ b/packages/core/src/plugins/plugins.ts @@ -47,7 +47,7 @@ export const registrar: Record = {} let basePrescan: PrescanModel // without any user-installed plugins let prescan: PrescanModel try { - prescan = require('@kui-shell/prescan.json') as PrescanModel // the result of unify(basePrescan, userPrescan) + prescan = (require('@kui-shell/prescan.json') || {}) as PrescanModel // the result of unify(basePrescan, userPrescan) // populate the typeahead trie from prescan (in command-tree, we // register again for dynamic command registrations); but we need @@ -57,6 +57,17 @@ try { Object.keys(prescan.commandToPlugin).forEach(registerTypeahead) } } catch (err) { + prescan = { + docs: {}, + topological: {}, + flat: [], + overrides: {}, + usage: {}, + catchalls: [], + preloads: [], + themeSets: [], + commandToPlugin: {} + } debug(err) } export function prescanModel(): PrescanModel { diff --git a/packages/core/src/plugins/preloader.ts b/packages/core/src/plugins/preloader.ts index 8df457a8949..14704825e7d 100644 --- a/packages/core/src/plugins/preloader.ts +++ b/packages/core/src/plugins/preloader.ts @@ -18,8 +18,6 @@ import Debug from 'debug' const debug = Debug('core/plugins/preloader') debug('loading') -/* eslint-disable @typescript-eslint/camelcase */ - import { PrescanModel } from './prescan' import { Tab } from '../webapp/tab' @@ -68,8 +66,9 @@ class PreloaderRegistrarImpl extends ImplForPlugins implements PreloadRegistrar export default async (prescan: PrescanModel) => { debug('init') + const preloads = (prescan && prescan.preloads) || [] const jobs = Promise.all( - prescan.preloads.map(async module => { + preloads.map(async module => { // extends the capabilities of Kui try { debug('preloading capabilities.1 %s', module.path) @@ -104,7 +103,7 @@ export default async (prescan: PrescanModel) => { }) .then(() => Promise.all( - prescan.preloads.map(async module => { + preloads.map(async module => { // FIXME to support field-installed plugin paths try { debug('preloading misc %s', module.path) diff --git a/packages/core/src/plugins/resolver.ts b/packages/core/src/plugins/resolver.ts index 823c37c6940..05bbb28cbac 100644 --- a/packages/core/src/plugins/resolver.ts +++ b/packages/core/src/plugins/resolver.ts @@ -146,9 +146,9 @@ export const makeResolver = (prescan: PrescanModel, registrar: Record prescan.overrides[route] !== undefined, + isOverridden: (route: string): boolean => (prescan.overrides || {})[route] !== undefined, isAlpha: (route: string, plugin: string): boolean => - prescan.overrides[route] === undefined || prescan.overrides[route] === plugin, + prescan.overrides[route] === undefined || (prescan.overrides || {})[route] === plugin, resolveOne, diff --git a/packages/core/src/plugins/scanner.ts b/packages/core/src/plugins/scanner.ts index ec575e5e8a4..f71ed5b2471 100644 --- a/packages/core/src/plugins/scanner.ts +++ b/packages/core/src/plugins/scanner.ts @@ -16,9 +16,8 @@ import Debug from 'debug' const debug = Debug('core/plugins/scanner') -debug('loading') -import { dirname, join } from 'path' +import { join } from 'path' import { pluginRoot } from './plugins' import { PrescanModel, PrescanUsage } from './prescan' @@ -125,12 +124,22 @@ class CommandRegistrarForScan extends ImplForPlugins { * */ const loadPlugin = async (route: string, pluginPath: string, scanCache: ScanCache) => { - debug('loadPlugin %s', route) + debug('loadPlugin %s', route, pluginPath) // create a CommandRegistrar instance for this one plugin load const ctree = new CommandRegistrarForScan(route, scanCache) - const pluginLoaderRef: PluginRegistration | { default: PluginRegistration } = await import(pluginPath) + const pluginLoaderRef: PluginRegistration | { default: PluginRegistration } = /@kui-shell\/client/.test(pluginPath) + ? await import( + '@kui-shell/client' + + pluginPath.replace(/^.*node_modules\/@kui-shell\/client/, '').replace(/plugin\.js$/, '') + + 'plugin.js' + ) + : await import( + '@kui-shell/plugin-' + + pluginPath.replace(/^.*node_modules\/@kui-shell\/plugin-/, '').replace(/plugin\.js$/, '') + + 'plugin.js' + ) function isDirect(loader: PluginRegistration | { default: PluginRegistration }): loader is PluginRegistration { return typeof loader === 'function' } @@ -247,7 +256,7 @@ export const scanForModules = async (dir: string, quiet = false, filter: Filter const preloads: Record = {} const themeSets: ThemeSet[] = [] - const doScan = ({ + const doScan = async ({ modules, moduleDir, parentPath, @@ -262,134 +271,150 @@ export const scanForModules = async (dir: string, quiet = false, filter: Filter }) => { debug('doScan', modules) - modules.forEach(module => { - const modulePath = path.join(moduleDir, module) - const name = (parentPath ? `${parentPath}/` : '') + module - - try { - const themePath = path.join(modulePath, 'theme.json') - if (fs.existsSync(themePath)) { - const themeSet: ThemeSet = require(themePath) - const nThemes = !themeSet || !themeSet.themes ? 0 : themeSet.themes.length - if (nThemes > 0) { - // set these to have the latest apiVersion unless otherwise stated - // this decision will be serialized out to the prescan persisted model - themeSet.themes.forEach(_ => { - if (!_.apiVersion) { - _.apiVersion = defaultThemeApiVersion - } - }) + await Promise.all( + modules.map(async module => { + const modulePath = path.join(moduleDir, module) + const name = (parentPath ? `${parentPath}/` : '') + module + + try { + const themePath = path.join(modulePath, 'theme.json') + if (fs.existsSync(themePath)) { + const themeSet: ThemeSet = /@kui-shell\/client/.test(modulePath) + ? await import( + '@kui-shell/client' + + themePath.replace(/^.*node_modules\/@kui-shell\/client/, '').replace(/theme\.json$/, '') + + 'theme.json' + ) + : await import( + '@kui-shell/plugin-' + + themePath.replace(/^.*node_modules\/@kui-shell\/plugin-/, '').replace(/theme\.json$/, '') + + 'theme.json' + ) + const nThemes = !themeSet || !themeSet.themes ? 0 : themeSet.themes.length + if (nThemes > 0) { + // set these to have the latest apiVersion unless otherwise stated + // this decision will be serialized out to the prescan persisted model + themeSet.themes.forEach(_ => { + if (!_.apiVersion) { + _.apiVersion = defaultThemeApiVersion + } + }) - const msg = colors.bold(colors.rainbow('themes')) + colors.dim(` x${nThemes}`) - console.log(colors.green(' \u2713 ') + msg + '\t' + path.basename(module)) + const msg = colors.bold(colors.rainbow('themes')) + colors.dim(` x${nThemes}`) + console.log(colors.green(' \u2713 ') + msg + '\t' + path.basename(module)) - // add this plugin's themes onto the full list, across all plugins - themeSets.push({ themes: themeSet.themes, plugin: module }) + // add this plugin's themes onto the full list, across all plugins + themeSets.push({ themes: themeSet.themes, plugin: module }) + } } + } catch (err) { + console.error('Error registering theme', err) } - } catch (err) { - console.error('Error registering theme', err) - } - - if (module.charAt(0) === '@') { - // support for @owner/repo style modules; see shell issue #260 - return doScan({ - modules: fs.readdirSync(modulePath), - moduleDir: modulePath, - parentPath: module - }) - } - function lookFor(filename: string, destMap: Record, colorFn: (str: string) => string) { - const pluginPath = path.join(moduleDir, module, filename) - debug('lookFor', filename, pluginPath) - - /** report a successful find to the console */ - const ok = () => { - const parent = parentPath ? `${parentPath}/` : '' - console.log( - colors.green(' \u2713 ') + colorFn(filename.replace(/\..*$/, '')) + '\t' + parent + path.basename(module) - ) + if (module.charAt(0) === '@') { + // support for @owner/repo style modules; see shell issue #260 + return doScan({ + modules: fs.readdirSync(modulePath), + moduleDir: modulePath, + parentPath: module + }) } - if (fs.existsSync(pluginPath)) { - if (!quiet) { - debug('found', name) - ok() + async function lookFor(filename: string, destMap: Record, colorFn: (str: string) => string) { + const pluginPath = path.join(moduleDir, module, filename) + debug('lookFor', filename, pluginPath) + + /** report a successful find to the console */ + const ok = () => { + const parent = parentPath ? `${parentPath}/` : '' + console.log( + colors.green(' \u2713 ') + + colorFn(filename.replace(/\..*$/, '')) + + '\t' + + parent + + path.basename(module) + ) } - destMap[name] = pluginPath - } else { - const backupPluginPath = path.join(modulePath, 'dist', filename) - debug('lookFor2', filename, backupPluginPath) - if (fs.existsSync(backupPluginPath)) { + if (fs.existsSync(pluginPath)) { if (!quiet) { - debug('found2', name) + debug('found', name) ok() } - destMap[name] = backupPluginPath + destMap[name] = pluginPath } else { - // support for javascript-coded plugins (monorepo) - const backupPluginPath = path.join(modulePath, 'src/plugin', filename) - debug('lookFor3', filename, backupPluginPath) + const backupPluginPath = path.join(modulePath, 'mdist', filename) + debug('lookFor2', filename, backupPluginPath) if (fs.existsSync(backupPluginPath)) { if (!quiet) { - debug('found3', name) + debug('found2', name) ok() } destMap[name] = backupPluginPath } else { - // support for javascript-coded plugins (external client) - const backupPluginPath = path.join(modulePath, 'plugin', filename) - debug('lookFor4', filename, backupPluginPath) + // support for javascript-coded plugins (monorepo) + const backupPluginPath = path.join(modulePath, 'src/plugin', filename) + debug('lookFor3', filename, backupPluginPath) if (fs.existsSync(backupPluginPath)) { if (!quiet) { - debug('found4', name) + debug('found3', name) ok() } destMap[name] = backupPluginPath - // console.error('Skipping plugin, because it does not have a plugin.js', module) + } else { + // support for javascript-coded plugins (external client) + const backupPluginPath = path.join(modulePath, 'plugin', filename) + debug('lookFor4', filename, backupPluginPath) + + if (fs.existsSync(backupPluginPath)) { + if (!quiet) { + debug('found4', name) + ok() + } + destMap[name] = backupPluginPath + // console.error('Skipping plugin, because it does not have a plugin.js', module) + } } } } - } - if (fs.statSync(modulePath).isDirectory()) { - const subDirs = fs.readdirSync(modulePath).filter( - _ => - !/(^m?dist)|(bin)|(web)|(src)|(samples)|(i18n)|(tests)|(node_modules)$/.test(_) && - fs.existsSync(path.join(modulePath, _)) && // see https://github.com/kubernetes-sigs/kui/issues/7326 - fs.statSync(path.join(modulePath, _)).isDirectory() - ) - - if (subDirs.length > 0) { - doScan({ - modules: subDirs, - moduleDir: modulePath, - parentPath: module, - lookForPlugin: filename === 'plugin.js', - lookForPrescan: filename === 'preload.js' - }) + if (fs.statSync(modulePath).isDirectory()) { + const subDirs = fs.readdirSync(modulePath).filter( + _ => + !/(^m?dist)|(bin)|(web)|(src)|(samples)|(i18n)|(tests)|(node_modules)$/.test(_) && + fs.existsSync(path.join(modulePath, _)) && // see https://github.com/kubernetes-sigs/kui/issues/7326 + fs.statSync(path.join(modulePath, _)).isDirectory() + ) + + if (subDirs.length > 0) { + await doScan({ + modules: subDirs, + moduleDir: modulePath, + parentPath: module, + lookForPlugin: filename === 'plugin.js', + lookForPrescan: filename === 'preload.js' + }) + } } } - } - if (lookForPlugin) { - lookFor('plugin.js', plugins, colors.bold) - } + if (lookForPlugin) { + await lookFor('plugin.js', plugins, colors.bold) + } - if (lookForPrescan) { - lookFor('preload.js', preloads, colors.dim) - } - }) + if (lookForPrescan) { + await lookFor('preload.js', preloads, colors.dim) + } + }) + ) } // scan the app/plugins/modules directory const moduleDir = dir // path.join(dir, 'modules') debug('moduleDir', moduleDir) - doScan({ modules: fs.readdirSync(moduleDir).filter(filter), moduleDir }) + await doScan({ modules: fs.readdirSync(moduleDir).filter(filter), moduleDir }) return { plugins, preloads, themeSets } } catch (err) { @@ -419,7 +444,7 @@ async function clientHosted(opts: PrescanOptions) { * */ async function clientRequired() { - const topOfScan = dirname(require.resolve('@kui-shell/prescan.json')) + const topOfScan = join(process.env.CLIENT_HOME, 'node_modules/@kui-shell') debug('using clientRequired scan', topOfScan) return scanForModules(topOfScan, false, (filename: string) => /^plugin-/.test(filename) || /^client$/.test(filename)) } @@ -487,7 +512,7 @@ export const generatePrescanModel = async ( } return { - preloads: Object.keys(preloads).map(route => ({ + preloads: Object.keys(preloads || {}).map(route => ({ route, path: preloads[route] })), diff --git a/packages/builder/bin/babel.sh b/packages/test/bin/babel.sh similarity index 100% rename from packages/builder/bin/babel.sh rename to packages/test/bin/babel.sh diff --git a/packages/test/bin/runTest.sh b/packages/test/bin/runTest.sh index f500cbc488f..7e6234f2052 100755 --- a/packages/test/bin/runTest.sh +++ b/packages/test/bin/runTest.sh @@ -27,6 +27,9 @@ set -o pipefail SCRIPTDIR=$(cd $(dirname "$0") && pwd) +# sigh, for now, we still need to babel the files into CJS :( +(cd "$SCRIPTDIR"/../../.. && "$SCRIPTDIR"/babel.sh) + if [ -n "$LAYER" ]; then # user asked to run tests in just one specified layer, e.g. "07" diff --git a/packages/test/package.json b/packages/test/package.json index ebc23b7c585..d3f4f51b1f2 100644 --- a/packages/test/package.json +++ b/packages/test/package.json @@ -12,6 +12,7 @@ "test": "./bin/runMochaLayers.sh" }, "bin": { + "kui-babel": "./bin/babel.sh", "kui-test": "./bin/runMochaLayers.sh" }, "devDependencies": { @@ -20,6 +21,11 @@ "dependencies": { "@wdio/mocha-framework": "^7.26.0", "mocha": "^10.2.0", + "@babel/cli": "^7.20.7", + "@babel/core": "^7.20.12", + "@babel/plugin-transform-modules-commonjs": "^7.20.11", + "babel-plugin-dynamic-import-node-babel-7": "^2.0.7", + "babel-plugin-ignore-html-and-css-imports": "^0.0.2", "spectron": "starpit/spectron#7eebbebbf5346a1c488bb8f46506c881b6e25179" }, "kui": { diff --git a/packages/webpack/build.sh b/packages/webpack/build.sh index 7c41792d6d0..9cb7d10023e 100755 --- a/packages/webpack/build.sh +++ b/packages/webpack/build.sh @@ -73,7 +73,7 @@ function webpack { rm -f "$BUILDDIR"/*.js* if [ -z "$IS_OFFLINE_CLIENT" ]; then - echo "Buildinging Kui Headless bundles via webpack" + echo "Building Kui Headless bundles via webpack" KUI_LINK="$CLIENT_HOME"/node_modules/@kui-shell/proxy/kui if [ -L "$KUI_LINK" ]; then @@ -82,6 +82,8 @@ function webpack { RESTORE_KUI_LINK=true fi + NEEDS_KUI_PROXY=true npx --no-install webpack-cli --config ./node_modules/@kui-shell/webpack/headless-webpack.config.js --mode=$MODE + npx kui-prescan NEEDS_KUI_PROXY=true npx --no-install webpack-cli --config ./node_modules/@kui-shell/webpack/headless-webpack.config.js --mode=$MODE & fi diff --git a/packages/webpack/headless-webpack.config.js b/packages/webpack/headless-webpack.config.js index 038f3b34340..bec75b2a8a8 100644 --- a/packages/webpack/headless-webpack.config.js +++ b/packages/webpack/headless-webpack.config.js @@ -199,15 +199,12 @@ const config = ( extensions: ['.tsx', '.ts', '.js'] }, watchOptions: { - ignored: [ - '**/dist/headless/**', - '**/dist/webpack/**', - '**/dist/electron/**', - '**/*.d.ts', - '**/*.js.map', - '**/node_modules/**', - '**/clients/default/**' - ] + // here we ignore changes to any node_modules, except we want to + // trigger a webpack rebuild when either of these + // changes: @kui-shell/prescan.json + // or @kui-shell/build/client-guidebooks.json + // these files are generated by `npx kui-prescan` + ignored: /node_modules\/(?!@kui-shell\/(prescan\.json|build\/client-guidebooks\.json))/ }, optimization, module: { diff --git a/packages/webpack/webpack.config.js b/packages/webpack/webpack.config.js index 4b2bdb77bd8..11d2a111c29 100644 --- a/packages/webpack/webpack.config.js +++ b/packages/webpack/webpack.config.js @@ -158,7 +158,7 @@ if (process.env.WATCH) { // here, we are trying to be careful to avoid an infinite // loop: we re-generate prescan.json, which triggers a webpack // build, which triggers this script again... - 'export KUI_PRESCAN=$(mktemp); export KUI_PRESCAN_GUIDEBOOKS=$(mktemp); npx kui-prescan; if [ -n "$(diff $KUI_PRESCAN node_modules/@kui-shell/prescan.json)" ]; then mv $KUI_PRESCAN node_modules/@kui-shell/prescan.json; fi; if [ -n "$(diff $KUI_PRESCAN_GUIDEBOOKS node_modules/@kui-shell/build/client-guidebooks.json)" ]; then mv $KUI_PRESCAN_GUIDEBOOKS node_modules/@kui-shell/build/client-guidebooks.json; fi' + 'export KUI_PRESCAN=$(mktemp); export KUI_PRESCAN_GUIDEBOOKS=$(mktemp); npx kui-prescan; if [ -n "$(diff $KUI_PRESCAN node_modules/@kui-shell/prescan.json)" ]; then mv $KUI_PRESCAN node_modules/@kui-shell/prescan.json; fi; if [ -f node_modules/@kui-shell/build/client-guidebooks.json ] && [ -f $KUI_PRESCAN_GUIDEBOOKS ] && [ -n "$(diff $KUI_PRESCAN_GUIDEBOOKS node_modules/@kui-shell/build/client-guidebooks.json)" ]; then mv $KUI_PRESCAN_GUIDEBOOKS node_modules/@kui-shell/build/client-guidebooks.json; fi' ], blocking: false, parallel: true diff --git a/plugins/plugin-bash-like/src/preload.ts b/plugins/plugin-bash-like/src/preload.ts index 1bca40d6c82..fe461e6c3b4 100644 --- a/plugins/plugin-bash-like/src/preload.ts +++ b/plugins/plugin-bash-like/src/preload.ts @@ -17,9 +17,6 @@ import Debug from 'debug' import type { CapabilityRegistration, PreloadRegistrar } from '@kui-shell/core' -import registerPluginTabState from './tab-state' -import { preload as registerCatchAll } from './lib/cmds/catchall' - export const registerCapability: CapabilityRegistration = async (registrar: PreloadRegistrar) => { const { inBrowser, isHeadless, inProxy } = require('@kui-shell/core/mdist/api/Capabilities') @@ -42,6 +39,9 @@ export const registerCapability: CapabilityRegistration = async (registrar: Prel * */ export default async (registrar: PreloadRegistrar) => { - registerPluginTabState() - return registerCatchAll(registrar) + // registerPluginTabState() + await import('./tab-state').then(_ => _.default()) + + // register catch all + await import('./lib/cmds/catchall').then(_ => _.preload(registrar)) } diff --git a/plugins/plugin-client-common/src/components/Views/Confirm.tsx b/plugins/plugin-client-common/src/components/Views/Confirm.tsx index e034c45360b..f1178099f6b 100644 --- a/plugins/plugin-client-common/src/components/Views/Confirm.tsx +++ b/plugins/plugin-client-common/src/components/Views/Confirm.tsx @@ -21,8 +21,6 @@ import { i18n } from '@kui-shell/core/mdist/api/i18n' import { Tab as KuiTab } from '@kui-shell/core/mdist/api/Tab' import { eventChannelUnsafe } from '@kui-shell/core/mdist/api/Events' -const strings = i18n('plugin-core-support') - interface Props { /** tab uuid */ uuid: string @@ -87,6 +85,8 @@ export default class Confirm extends React.PureComponent @@ -96,17 +96,17 @@ export default class Confirm extends React.PureComponent -

{strings('aboutToExecute')}

+

{this.strings('aboutToExecute')}

{this.state.command}

-

{this.state.asking || strings('areYouSure')}

+

{this.state.asking || this.strings('areYouSure')}

) } diff --git a/plugins/plugin-client-common/src/controller/alert.ts b/plugins/plugin-client-common/src/controller/alert.ts index 7410700e079..46ba5b2edf8 100644 --- a/plugins/plugin-client-common/src/controller/alert.ts +++ b/plugins/plugin-client-common/src/controller/alert.ts @@ -14,48 +14,20 @@ * limitations under the License. */ -import type { Arguments, Registrar, ParsedOptions, UsageModel, ReactResponse } from '@kui-shell/core' - -import Alert from '../components/spi/Alert' +import type { Arguments, ParsedOptions, ReactResponse } from '@kui-shell/core' /** * alert command parsedOptions type */ -interface AlertOptions extends ParsedOptions { +export interface AlertOptions extends ParsedOptions { body: string } -/** - * alert command usage - */ -const usage: UsageModel = { - command: 'alert', - strict: 'alert', - example: 'alert [] [] [--body ]', - docs: 'Alert', - required: [ - { - name: 'type', - docs: 'info, success, warning, or error' - }, - { - name: 'title', - docs: 'alert title text' - } - ], - optional: [ - { - name: '--body', - docs: 'alert body text' - } - ] -} - /** * alert command handler * */ -async function doAlert(opts: Arguments): Promise { +export default async function doAlert(opts: Arguments): Promise { const argv = opts.argvNoOptions const option = opts.parsedOptions const type = argv[1] @@ -67,16 +39,9 @@ async function doAlert(opts: Arguments): Promise { ]) if (isSupportedToolbarTextType(type)) { + const { default: Alert } = await import('../components/spi/Alert') return { react: Alert({ alert: { type, title, body: option.body }, className: 'kui--terminal-alert' }) } } else { throw new UsageError(`alert type must be: 'info', 'success', 'warning' or 'error'.`) } } - -/** - * This plugin introduces the /alert command - * - */ -export default async (commandTree: Registrar) => { - commandTree.listen('/alert', doAlert, { usage }) -} diff --git a/plugins/plugin-client-common/src/controller/card.ts b/plugins/plugin-client-common/src/controller/card.ts index ee7a8b61973..c6b6c5f06a8 100644 --- a/plugins/plugin-client-common/src/controller/card.ts +++ b/plugins/plugin-client-common/src/controller/card.ts @@ -14,64 +14,33 @@ * limitations under the License. */ -import type { Arguments, Registrar, ParsedOptions, UsageModel, ReactResponse } from '@kui-shell/core' - -import card from '../components/spi/Card' -import fetchMarkdownFile from './fetch' +import type { Arguments, ParsedOptions, ReactResponse } from '@kui-shell/core' /** * card command parsedOptions type */ -interface CardOptions extends ParsedOptions { +export interface CardOptions extends ParsedOptions { title: string // icon: string filename: string f: string } -/** - * card command usage - */ -const usage: UsageModel = { - command: 'card', - strict: 'card', - example: 'card [] [--title ]', - docs: 'Card', - optional: [ - { - name: 'body', - docs: 'card body text' - }, - { - name: '--title', - docs: 'Content rendered inside the CardTitle' - }, - /* { - name: '--icon', - docs: 'Attribute that specifies the URL of the image to put on the card.' - }, */ - { - name: '-f', - docs: 'File that contains the texts' - }, - { - name: '--file', - docs: 'File that contains the texts' - } - ] -} - /** * card command handler * */ -async function doCard(opts: Arguments): Promise { +export default async function doCard(opts: Arguments): Promise { const argv = opts.argvNoOptions const option = opts.parsedOptions const { title /* , icon */ } = option + const { default: card } = await import('../components/spi/Card') + const filepath = option.filename || option.f if (filepath) { + const { default: fetchMarkdownFile } = await import('./fetch') + const { data } = await fetchMarkdownFile(filepath, opts) return { react: card({ title, children: data /*, icon */ }) } } else { @@ -83,11 +52,3 @@ async function doCard(opts: Arguments): Promise { } } } - -/** - * This plugin introduces the /card command - * - */ -export default async (commandTree: Registrar) => { - commandTree.listen('/card', doCard, { usage }) -} diff --git a/plugins/plugin-client-common/src/controller/commentary.ts b/plugins/plugin-client-common/src/controller/commentary.ts index 8ab7c21727d..ae2afcf512c 100644 --- a/plugins/plugin-client-common/src/controller/commentary.ts +++ b/plugins/plugin-client-common/src/controller/commentary.ts @@ -16,14 +16,12 @@ import { basename } from 'path' -import type { Arguments, CommentaryResponse, ParsedOptions, Registrar } from '@kui-shell/core' - -import fetchMarkdownFile, { join } from './fetch' +import type { Arguments, CommentaryResponse, ParsedOptions } from '@kui-shell/core' /** * commentary command parsedOptions type */ -type CommentaryOptions = ParsedOptions & +export type CommentaryOptions = ParsedOptions & Pick & { f: string file: string @@ -113,7 +111,7 @@ export async function setTabReadonly({ tab }: Arguments) { eventBus.emitWithTabId('/kui/tab/edit/unset', getPrimaryTabId(tab)) } -async function addComment(args: Arguments): Promise { +export async function addComment(args: Arguments): Promise { const { edit: _edit, header: _header, @@ -133,6 +131,8 @@ async function addComment(args: Arguments): Promise): Promise { - commandTree.listen( - '/confirm', - async ({ tab, argvNoOptions, parsedOptions, execOptions, REPL }) => { - const [{ i18n }, { ExecType }, { getPrimaryTabId }, { pexecInCurrentTab }, { eventChannelUnsafe }] = - await Promise.all([ - import('@kui-shell/core/mdist/api/i18n'), - import('@kui-shell/core/mdist/api/Command'), - import('@kui-shell/core/mdist/api/Tab'), - import('@kui-shell/core/mdist/api/Exec'), - import('@kui-shell/core/mdist/api/Events') - ]) - - const strings = i18n('plugin-core-support') - - return new Promise((resolve, reject) => { - const asking = parsedOptions.asking || strings('areYouSure') - const command = argvNoOptions[argvNoOptions.indexOf('confirm') + 1] - const { execUUID } = execOptions - - if (!command) { - throw new Error('Usage: confirm command line') - } - - const requestChannel = `/kui-shell/Confirm/v1/tab/${getPrimaryTabId(tab)}` - const responseChannel = `${requestChannel}/execUUID/${execUUID}/confirmed` - - const onConfirm = ({ confirmed }: { confirmed: boolean }) => { - if (!confirmed) { - reject(strings('operationCancelled')) - } else if (execOptions.type === ExecType.Nested) { - pexecInCurrentTab(command, tab).then(resolve, reject) - } else { - REPL.qexec(command, undefined, undefined, { tab }).then(resolve, reject) - } - } - - eventChannelUnsafe.once(responseChannel, onConfirm) - eventChannelUnsafe.emit(requestChannel, { command, asking, execUUID }) - }) - }, - { incognito: ['popup'] } - ) +export default async function confirm(args: Arguments) { + const { tab, argvNoOptions, parsedOptions, execOptions, REPL } = args + const [{ i18n }, { ExecType }, { getPrimaryTabId }, { pexecInCurrentTab }, { eventChannelUnsafe }] = + await Promise.all([ + import('@kui-shell/core/mdist/api/i18n'), + import('@kui-shell/core/mdist/api/Command'), + import('@kui-shell/core/mdist/api/Tab'), + import('@kui-shell/core/mdist/api/Exec'), + import('@kui-shell/core/mdist/api/Events') + ]) + + const strings = i18n('plugin-core-support') + + return new Promise((resolve, reject) => { + const asking = parsedOptions.asking || strings('areYouSure') + const command = argvNoOptions[argvNoOptions.indexOf('confirm') + 1] + const { execUUID } = execOptions + + if (!command) { + throw new Error('Usage: confirm command line') + } + + const requestChannel = `/kui-shell/Confirm/v1/tab/${getPrimaryTabId(tab)}` + const responseChannel = `${requestChannel}/execUUID/${execUUID}/confirmed` + + const onConfirm = ({ confirmed }: { confirmed: boolean }) => { + if (!confirmed) { + reject(strings('operationCancelled')) + } else if (execOptions.type === ExecType.Nested) { + pexecInCurrentTab(command, tab).then(resolve, reject) + } else { + REPL.qexec(command, undefined, undefined, { tab }).then(resolve, reject) + } + } + + eventChannelUnsafe.once(responseChannel, onConfirm) + eventChannelUnsafe.emit(requestChannel, { command, asking, execUUID }) + }) } diff --git a/plugins/plugin-client-common/src/controller/split.ts b/plugins/plugin-client-common/src/controller/split.ts index c298597d208..b58ce6f0951 100644 --- a/plugins/plugin-client-common/src/controller/split.ts +++ b/plugins/plugin-client-common/src/controller/split.ts @@ -17,7 +17,7 @@ import type { Arguments, ParsedOptions, TabLayoutModificationResponse, NewSplitRequest } from '@kui-shell/core' type Options = NewSplitRequest['options'] -type CommandLineOptions = ParsedOptions & Omit & { inverse: boolean } +export type CommandLineOptions = ParsedOptions & Omit & { inverse: boolean } /** For debugging, this returns the tab uuid of the current split */ export function debug(args: Arguments) { diff --git a/plugins/plugin-client-common/src/controller/user-settings.ts b/plugins/plugin-client-common/src/controller/user-settings.ts index 27619051fc4..85061a7c6f5 100644 --- a/plugins/plugin-client-common/src/controller/user-settings.ts +++ b/plugins/plugin-client-common/src/controller/user-settings.ts @@ -15,19 +15,18 @@ */ import type { CodedError, Registrar } from '@kui-shell/core' - -import KuiConfiguration from '../components/Client/KuiConfiguration' -import { get, reset, set, unset } from '../components/Client/UserSettings' - -const settings: (keyof KuiConfiguration)[] = ['prompt', '_for_testing_'] +import type KuiConfiguration from '../components/Client/KuiConfiguration' /** * This plugin introduces the /card command * */ -export default async (registrar: Registrar) => { +export default (registrar: Registrar) => { + const settings: (keyof KuiConfiguration)[] = ['prompt', '_for_testing_'] + /** Remove all user setting overrides */ registrar.listen('/kuiconfig/reset', async () => { + const { reset } = await import('../components/Client/UserSettings') await reset() return true }) @@ -35,6 +34,7 @@ export default async (registrar: Registrar) => { settings.forEach(setting => { /** Read out a given user setting override */ registrar.listen(`/kuiconfig/get/${setting}`, async () => { + const { get } = await import('../components/Client/UserSettings') const { i18n } = await import('@kui-shell/core/mdist/api/i18n') const strings = i18n('plugin-client-common/user-settings') @@ -52,24 +52,28 @@ export default async (registrar: Registrar) => { /** Update a given user setting override */ registrar.listen(`/kuiconfig/set/${setting}`, async args => { + const { set } = await import('../components/Client/UserSettings') await set(setting, args.argvNoOptions[3]) return true }) /** Does the given setting have a value? */ registrar.listen(`/kuiconfig/is/set/${setting}`, async () => { + const { get } = await import('../components/Client/UserSettings') const value = await get(setting) return value !== undefined }) /** Does the given setting not have a value? */ registrar.listen(`/kuiconfig/not/set/${setting}`, async () => { + const { get } = await import('../components/Client/UserSettings') const value = await get(setting) return value === undefined }) /** Remove a given user setting override */ registrar.listen(`/kuiconfig/unset/${setting}`, async () => { + const { unset } = await import('../components/Client/UserSettings') await unset(setting) return true }) diff --git a/plugins/plugin-client-common/src/plugin.ts b/plugins/plugin-client-common/src/plugin.ts index b7d6eab3cc6..c9f27fa31d3 100644 --- a/plugins/plugin-client-common/src/plugin.ts +++ b/plugins/plugin-client-common/src/plugin.ts @@ -14,18 +14,109 @@ * limitations under the License. */ -import type { Registrar } from '@kui-shell/core' - -export default async (registrar: Registrar) => { - await import('./controller/confirm').then(_ => _.default(registrar)) - await import('./controller/split').then(_ => { - registrar.listen('/split', _.default, { flags: { boolean: ['inverse'], alias: { split: ['s'] } } }) - registrar.listen('/split-debug', _.debug) - registrar.listen('/split-count', ({ tab }) => tab.splitCount()) - registrar.listen('/is-split', ({ tab }) => tab.hasSideBySideTerminals()) +import type { CodedError, KResponse, Registrar } from '@kui-shell/core' + +import type { CardOptions } from './controller/card' +import type { AlertOptions } from './controller/alert' +import type { CommentaryOptions } from './controller/commentary' +import type { CommandLineOptions as SplitOptions } from './controller/split' +import type KuiConfiguration from './components/Client/KuiConfiguration' + +function settings(registrar: Registrar) { + const settings: (keyof KuiConfiguration)[] = ['prompt', '_for_testing_'] + + /** Remove all user setting overrides */ + registrar.listen('/kuiconfig/reset', async () => { + const { reset } = await import('./components/Client/UserSettings') + await reset() + return true + }) + + settings.forEach(setting => { + /** Read out a given user setting override */ + registrar.listen(`/kuiconfig/get/${setting}`, async () => { + const { get } = await import('./components/Client/UserSettings') + const { i18n } = await import('@kui-shell/core/mdist/api/i18n') + const strings = i18n('plugin-client-common/user-settings') + + const value = await get(setting) + if (!value) { + const error: CodedError = new Error(strings('You have not specified a value for this setting')) + error.code = 404 + throw error + } else if (typeof value === 'string' || typeof value === 'boolean' || typeof value === 'number') { + return value + } else { + return value.toString() + } + }) + + /** Update a given user setting override */ + registrar.listen(`/kuiconfig/set/${setting}`, async args => { + const { set } = await import('./components/Client/UserSettings') + await set(setting, args.argvNoOptions[3]) + return true + }) + + /** Does the given setting have a value? */ + registrar.listen(`/kuiconfig/is/set/${setting}`, async () => { + const { get } = await import('./components/Client/UserSettings') + const value = await get(setting) + return value !== undefined + }) + + /** Does the given setting not have a value? */ + registrar.listen(`/kuiconfig/not/set/${setting}`, async () => { + const { get } = await import('./components/Client/UserSettings') + const value = await get(setting) + return value === undefined + }) + + /** Remove a given user setting override */ + registrar.listen(`/kuiconfig/unset/${setting}`, async () => { + const { unset } = await import('./components/Client/UserSettings') + await unset(setting) + return true + }) }) - await import('./controller/alert').then(_ => _.default(registrar)) - await import('./controller/card').then(_ => _.default(registrar)) - await import('./controller/commentary').then(_ => _.default(registrar)) - await import('./controller/user-settings').then(_ => _.default(registrar)) +} + +export default function registerPluginClientCommonControllers(registrar: Registrar) { + registrar.listen('/confirm', args => import('./controller/confirm').then(_ => _.default(args)), { + incognito: ['popup'] + }) + + registrar.listen('/split', args => import('./controller/split').then(_ => _.default(args)), { + flags: { boolean: ['inverse'], alias: { split: ['s'] } } + }) + registrar.listen('/split-debug', args => import('./controller/split').then(_ => _.debug(args))) + registrar.listen('/split-count', ({ tab }) => tab.splitCount()) + registrar.listen('/is-split', ({ tab }) => tab.hasSideBySideTerminals()) + + const flags = { + boolean: ['edit', 'header', 'preview', 'readonly', 'replace', 'simple'] + } + const commentaryFlags = { outputOnly: true, flags } + const hashFlags = { outputOnly: true, flags, noCoreRedirect: true } + const commentaryDelegateFlags = { outputOnly: true, needsUI: true } + registrar.listen('/alert', args => import('./controller/alert').then(_ => _.default(args))) + registrar.listen('/card', args => import('./controller/card').then(_ => _.default(args))) + + registrar.listen( + '/commentary', + args => import('./controller/commentary').then(_ => _.addComment(args)), + commentaryFlags + ) + registrar.listen( + '/#', + args => import('./controller/commentary').then(_ => _.addComment(args)), + hashFlags + ) + registrar.listen( + '/commentary/delegate', + args => import('./controller/commentary').then(_ => _.delegate(args)), + commentaryDelegateFlags + ) + + settings(registrar) } diff --git a/plugins/plugin-core-support/src/lib/cmds/base64.ts b/plugins/plugin-core-support/src/lib/cmds/base64.ts index 781459db800..04e13fe4970 100644 --- a/plugins/plugin-core-support/src/lib/cmds/base64.ts +++ b/plugins/plugin-core-support/src/lib/cmds/base64.ts @@ -17,8 +17,6 @@ import Debug from 'debug' import type { Registrar } from '@kui-shell/core' -const debug = Debug('plugins/core-support/base64') - /** * The command usage model * @@ -66,11 +64,11 @@ const breakout = (str: string, options) => { * */ export default (commandTree: Registrar) => { - debug('init') - commandTree.listen( '/base64', ({ argvNoOptions, parsedOptions: options }) => { + const debug = Debug('plugins/core-support/base64') + const str = argvNoOptions[1] debug('str', str, argvNoOptions) diff --git a/plugins/plugin-core-support/src/lib/cmds/history/history.ts b/plugins/plugin-core-support/src/lib/cmds/history/history.ts index f55d06586f3..47867694350 100644 --- a/plugins/plugin-core-support/src/lib/cmds/history/history.ts +++ b/plugins/plugin-core-support/src/lib/cmds/history/history.ts @@ -24,8 +24,6 @@ import Debug from 'debug' // the default number of history elements to show with import type { Arguments, Registrar, Row } from '@kui-shell/core' -const debug = Debug('plugins/core-support/history') - const DEFAULT_HISTORY_N = 20 const parseN = str => { @@ -73,6 +71,7 @@ const usage = { * */ const again = async ({ tab, REPL }: Arguments, N: number, historyEntry) => { + const debug = Debug('plugins/core-support/history') debug('again', N, historyEntry) const { History } = await import('@kui-shell/core/mdist/api/History') @@ -103,6 +102,7 @@ const showHistory = async ({ tab, argv, parsedOptions: options }) => { const history = await History(tab) if (options.c) { + const debug = Debug('plugins/core-support/history') debug('clearing command history') return history.wipe() } @@ -122,6 +122,7 @@ const showHistory = async ({ tab, argv, parsedOptions: options }) => { const endIdx = history.cursor - 1 const recent = history.slice(startIdx, endIdx) + const debug = Debug('plugins/core-support/history') debug('argv', argv) debug('Nargs', Nargs) debug('Nidx', Nidx) @@ -166,8 +167,6 @@ const showHistory = async ({ tab, argv, parsedOptions: options }) => { } export default (commandTree: Registrar) => { - debug('init') - commandTree.listen('/history', showHistory, { usage: usage.history }) @@ -180,6 +179,7 @@ export default (commandTree: Registrar) => { const { History } = await import('@kui-shell/core/mdist/api/History') const history = await History(args.tab) const N = args.argv[1] ? parseInt(args.argv[1], 10) : history.cursor - 2 // use the last command, if the user entered only "!!" + const debug = Debug('plugins/core-support/history') debug('againCmd', args.execOptions) return again(args, N, args.execOptions && args.execOptions.history) } diff --git a/plugins/plugin-core-support/src/lib/cmds/replay.ts b/plugins/plugin-core-support/src/lib/cmds/replay.ts index 6d76af075cc..00ba8749b89 100644 --- a/plugins/plugin-core-support/src/lib/cmds/replay.ts +++ b/plugins/plugin-core-support/src/lib/cmds/replay.ts @@ -17,8 +17,6 @@ import type { StatusStripeChangeEvent } from '@kui-shell/core/mdist/api/Events' import type { KResponse, ParsedOptions, Registrar } from '@kui-shell/core' -import { loadNotebook } from '@kui-shell/plugin-client-common/notebook' - /** For the Kui command registration: enforce one mandatory positional parameter */ // const required = [{ name: '', docs: 'path to saved snapshot' }] @@ -98,6 +96,8 @@ export default function (registrar: Registrar) { const cmdline = (filepath: string) => `commentary --readonly ${snippetBasePath} -f ${encodeComponent(filepath)}` + const { loadNotebook } = await import('@kui-shell/plugin-client-common/notebook') + await Promise.all([ parsedOptions.r ? REPL.pexec(cmdline(filepaths[0]), { noHistory: true }) : true, ...filepaths.slice(parsedOptions.r ? 1 : 0).map(async filepath => { diff --git a/plugins/plugin-core-support/src/notebooks/vfs/index.ts b/plugins/plugin-core-support/src/notebooks/vfs/index.ts index 17ae19631e6..0e5a708db2d 100644 --- a/plugins/plugin-core-support/src/notebooks/vfs/index.ts +++ b/plugins/plugin-core-support/src/notebooks/vfs/index.ts @@ -14,7 +14,8 @@ * limitations under the License. */ -import { TrieVFS, VFS, mount } from '@kui-shell/plugin-bash-like/fs' +import type { VFS } from '@kui-shell/plugin-bash-like/fs' +import { TrieVFS, mount } from '@kui-shell/plugin-bash-like/fs' type NotebookLeaf = TrieVFS.Leaf<{ srcFilepath: string }> // type NotebookEntry = TrieVFS.Directory | NotebookLeaf diff --git a/plugins/plugin-s3/ibm/src/controller/bind.ts b/plugins/plugin-s3/ibm/src/controller/bind.ts index ad22f07476d..1b96926ac52 100644 --- a/plugins/plugin-s3/ibm/src/controller/bind.ts +++ b/plugins/plugin-s3/ibm/src/controller/bind.ts @@ -88,7 +88,7 @@ async function createCredentials(instance: ServiceInstance, args: Arguments): Pr return bind(key, instance, args) } -interface Options extends ParsedOptions { +export interface Options extends ParsedOptions { 'cos-instance': string } diff --git a/plugins/plugin-s3/ibm/src/controller/validate.ts b/plugins/plugin-s3/ibm/src/controller/validate.ts index b1931327b8b..a83375b0525 100644 --- a/plugins/plugin-s3/ibm/src/controller/validate.ts +++ b/plugins/plugin-s3/ibm/src/controller/validate.ts @@ -24,7 +24,7 @@ import Config, { hasEndpoint, hasServiceInstanceName } from '../model/Config' const strings = i18n('plugin-s3', 'ibm') -interface Options extends ParsedOptions { +export interface Options extends ParsedOptions { output: 'name' 'cos-instance': string } diff --git a/plugins/plugin-s3/ibm/src/plugin.ts b/plugins/plugin-s3/ibm/src/plugin.ts index 11ac645806c..ca912364024 100644 --- a/plugins/plugin-s3/ibm/src/plugin.ts +++ b/plugins/plugin-s3/ibm/src/plugin.ts @@ -15,32 +15,37 @@ */ import { isEnabled } from '@kui-shell/plugin-s3' -import { CommandHandler, KResponse, ParsedOptions, Registrar, UsageModel } from '@kui-shell/core' +import type { KResponse, Registrar } from '@kui-shell/core' -function On(this: Registrar, command: string, handler: CommandHandler, usage?: UsageModel) { - ;['cos', 'cloud-object-storage'].forEach(cos => { - this.listen(`/ibmcloud/${cos}/${command}`, handler, usage ? { usage } : undefined) - }) -} +import type { Options as BindOptions } from './controller/bind' +import type { Options as ValidateOptions } from './controller/validate' export default async (registrar: Registrar) => { if (!isEnabled()) { return } - const on = On.bind(registrar) - - const [validateConfig, findServiceInstances, findAndBindCredentials, setEndpoint, defaultRegion] = await Promise.all([ - import('./controller/validate').then(_ => _.default), - import('./controller/find').then(_ => _.default), - import('./controller/bind').then(_ => _.default), - import('./controller/endpoint').then(_ => _.default), - import('./controller/defaultRegion').then(_ => _.default) - ]) - - on('service-instances', findServiceInstances) - on('bind', findAndBindCredentials) - on('endpoint', setEndpoint) - on('validate', validateConfig) - on('config/region/default', defaultRegion) + ;['cos', 'cloud-object-storage'].forEach(cos => { + registrar.listen(`/ibmcloud/${cos}/validate`, args => + import('./controller/validate').then(_ => _.default(args) as any) + ) + }) + ;['cos', 'cloud-object-storage'].forEach(cos => { + registrar.listen(`/ibmcloud/${cos}/service-instances`, args => + import('./controller/find').then(_ => _.default(args)) + ) + }) + ;['cos', 'cloud-object-storage'].forEach(cos => { + registrar.listen(`/ibmcloud/${cos}/bind`, args => + import('./controller/bind').then(_ => _.default(args) as unknown) + ) + }) + ;['cos', 'cloud-object-storage'].forEach(cos => { + registrar.listen(`/ibmcloud/${cos}/endpoint`, args => import('./controller/endpoint').then(_ => _.default(args))) + }) + ;['cos', 'cloud-object-storage'].forEach(cos => { + registrar.listen(`/ibmcloud/${cos}/config/region/default`, args => + import('./controller/defaultRegion').then(_ => _.default(args)) + ) + }) } diff --git a/plugins/plugin-s3/src/browse/index.ts b/plugins/plugin-s3/src/browse/index.ts index c215cdb2346..fdbe911a375 100644 --- a/plugins/plugin-s3/src/browse/index.ts +++ b/plugins/plugin-s3/src/browse/index.ts @@ -14,15 +14,15 @@ * limitations under the License. */ -import { Arguments, Registrar, encodeComponent } from '@kui-shell/core' - -const opts = { needsUI: true, width: 720, height: 900 } +import type { Arguments, Registrar } from '@kui-shell/core' function doBrowse(this: string, { REPL }: Arguments) { - return REPL.qexec(`ls ${encodeComponent(this)}`) + return REPL.qexec(`ls ${REPL.encodeComponent(this)}`) } export default async function (registrar: Registrar) { + const opts = { needsUI: true, width: 720, height: 900 } + registrar.listen('/browse/s3', doBrowse.bind('/s3'), opts) registrar.listen('/browse/cc', doBrowse.bind('/s3/aws/commoncrawl'), opts) registrar.listen('/browse/commoncrawl', doBrowse.bind('/s3/aws/commoncrawl'), opts) diff --git a/plugins/plugin-s3/src/vfs/browser/forwarder.ts b/plugins/plugin-s3/src/vfs/browser/forwarder.ts index fc0159a45fb..9bac55557da 100644 --- a/plugins/plugin-s3/src/vfs/browser/forwarder.ts +++ b/plugins/plugin-s3/src/vfs/browser/forwarder.ts @@ -14,16 +14,16 @@ * limitations under the License. */ -import { Registrar } from '@kui-shell/core' - -import { responderFor, vfsFor } from '../responders' +import type { Registrar } from '@kui-shell/core' export default function (registrar: Registrar) { registrar.listen( '/vfs-s3/cp', - args => { + async args => { const N = args.argvNoOptions.length + const { responderFor, vfsFor } = await import('../responders') + return responderFor(args).cp( args, args.argvNoOptions.slice(3, N - 5), @@ -40,13 +40,16 @@ export default function (registrar: Registrar) { ) registrar.listen( '/vfs-s3/rm', - args => responderFor(args).rm(args, args.argvNoOptions[3], args.argvNoOptions[4] === 'true'), + args => + import('../responders').then(_ => + _.responderFor(args).rm(args, args.argvNoOptions[3], args.argvNoOptions[4] === 'true') + ), { requiresLocal: true } ) registrar.listen( '/vfs-s3/rmdir', async args => { - await responderFor(args).rmdir(args, args.argvNoOptions[3]) + await import('../responders').then(_ => _.responderFor(args).rmdir(args, args.argvNoOptions[3])) return true }, { requiresLocal: true } @@ -54,7 +57,9 @@ export default function (registrar: Registrar) { registrar.listen( '/vfs-s3/fwrite', async args => { - await responderFor(args).fwrite(args, args.argvNoOptions[3], args.execOptions.data as string | Buffer) + await import('../responders').then(_ => + _.responderFor(args).fwrite(args, args.argvNoOptions[3], args.execOptions.data as string | Buffer) + ) return true }, { requiresLocal: true } @@ -62,7 +67,7 @@ export default function (registrar: Registrar) { registrar.listen( '/vfs-s3/mkdir', async args => { - await responderFor(args).mkdir(args, args.argvNoOptions[3]) + await import('../responders').then(_ => _.responderFor(args).mkdir(args, args.argvNoOptions[3])) return true }, { requiresLocal: true }