diff --git a/packages/cli-repl/package-lock.json b/packages/cli-repl/package-lock.json index b26290fdb..183369f0c 100644 --- a/packages/cli-repl/package-lock.json +++ b/packages/cli-repl/package-lock.json @@ -18,19 +18,19 @@ "integrity": "sha512-0NqAC1IJE0S0+lL1SWFMxMkz1pKCNCjI4tr2Zx4LJSXxCLAdr6KyArnY+sno5m3yH9g737ygOyPABDsnXkpxiA==" }, "@babel/core": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.15.0.tgz", - "integrity": "sha512-tXtmTminrze5HEUPn/a0JtOzzfp0nk+UEXQ/tqIJo3WDGypl/2OFQEMll/zSFU8f/lfmfLXvTaORHF3cfXIQMw==", + "version": "7.15.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.15.5.tgz", + "integrity": "sha512-pYgXxiwAgQpgM1bNkZsDEq85f0ggXMA5L7c+o3tskGMh2BunCI9QUwB9Z4jpvXUOuMdyGKiGKQiRe11VS6Jzvg==", "requires": { "@babel/code-frame": "^7.14.5", - "@babel/generator": "^7.15.0", - "@babel/helper-compilation-targets": "^7.15.0", - "@babel/helper-module-transforms": "^7.15.0", - "@babel/helpers": "^7.14.8", - "@babel/parser": "^7.15.0", - "@babel/template": "^7.14.5", - "@babel/traverse": "^7.15.0", - "@babel/types": "^7.15.0", + "@babel/generator": "^7.15.4", + "@babel/helper-compilation-targets": "^7.15.4", + "@babel/helper-module-transforms": "^7.15.4", + "@babel/helpers": "^7.15.4", + "@babel/parser": "^7.15.5", + "@babel/template": "^7.15.4", + "@babel/traverse": "^7.15.4", + "@babel/types": "^7.15.4", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -40,9 +40,9 @@ }, "dependencies": { "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", "requires": { "ms": "2.1.2" } @@ -55,19 +55,19 @@ } }, "@babel/generator": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.15.0.tgz", - "integrity": "sha512-eKl4XdMrbpYvuB505KTta4AV9g+wWzmVBW69tX0H2NwKVKd2YJbKgyK6M8j/rgLbmHOYJn6rUklV677nOyJrEQ==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.15.4.tgz", + "integrity": "sha512-d3itta0tu+UayjEORPNz6e1T3FtvWlP5N4V5M+lhp/CxT4oAA7/NcScnpRyspUMLK6tu9MNHmQHxRykuN2R7hw==", "requires": { - "@babel/types": "^7.15.0", + "@babel/types": "^7.15.4", "jsesc": "^2.5.1", "source-map": "^0.5.0" } }, "@babel/helper-compilation-targets": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.15.0.tgz", - "integrity": "sha512-h+/9t0ncd4jfZ8wsdAsoIxSa61qhBYlycXiHWqJaQBCXAhDCMbPRSMTGnZIkkmt1u4ag+UQmuqcILwqKzZ4N2A==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.15.4.tgz", + "integrity": "sha512-rMWPCirulnPSe4d+gwdWXLfAXTTBj8M3guAf5xFQJ0nvFY7tfNAFnWdqaHegHlgDZOCT4qvhF3BYlSJag8yhqQ==", "requires": { "@babel/compat-data": "^7.15.0", "@babel/helper-validator-option": "^7.14.5", @@ -83,95 +83,95 @@ } }, "@babel/helper-function-name": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.14.5.tgz", - "integrity": "sha512-Gjna0AsXWfFvrAuX+VKcN/aNNWonizBj39yGwUzVDVTlMYJMK2Wp6xdpy72mfArFq5uK+NOuexfzZlzI1z9+AQ==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.15.4.tgz", + "integrity": "sha512-Z91cOMM4DseLIGOnog+Z8OI6YseR9bua+HpvLAQ2XayUGU+neTtX+97caALaLdyu53I/fjhbeCnWnRH1O3jFOw==", "requires": { - "@babel/helper-get-function-arity": "^7.14.5", - "@babel/template": "^7.14.5", - "@babel/types": "^7.14.5" + "@babel/helper-get-function-arity": "^7.15.4", + "@babel/template": "^7.15.4", + "@babel/types": "^7.15.4" } }, "@babel/helper-get-function-arity": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.14.5.tgz", - "integrity": "sha512-I1Db4Shst5lewOM4V+ZKJzQ0JGGaZ6VY1jYvMghRjqs6DWgxLCIyFt30GlnKkfUeFLpJt2vzbMVEXVSXlIFYUg==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.15.4.tgz", + "integrity": "sha512-1/AlxSF92CmGZzHnC515hm4SirTxtpDnLEJ0UyEMgTMZN+6bxXKg04dKhiRx5Enel+SUA1G1t5Ed/yQia0efrA==", "requires": { - "@babel/types": "^7.14.5" + "@babel/types": "^7.15.4" } }, "@babel/helper-hoist-variables": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.14.5.tgz", - "integrity": "sha512-R1PXiz31Uc0Vxy4OEOm07x0oSjKAdPPCh3tPivn/Eo8cvz6gveAeuyUUPB21Hoiif0uoPQSSdhIPS3352nvdyQ==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.15.4.tgz", + "integrity": "sha512-VTy085egb3jUGVK9ycIxQiPbquesq0HUQ+tPO0uv5mPEBZipk+5FkRKiWq5apuyTE9FUrjENB0rCf8y+n+UuhA==", "requires": { - "@babel/types": "^7.14.5" + "@babel/types": "^7.15.4" } }, "@babel/helper-member-expression-to-functions": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.15.0.tgz", - "integrity": "sha512-Jq8H8U2kYiafuj2xMTPQwkTBnEEdGKpT35lJEQsRRjnG0LW3neucsaMWLgKcwu3OHKNeYugfw+Z20BXBSEs2Lg==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.15.4.tgz", + "integrity": "sha512-cokOMkxC/BTyNP1AlY25HuBWM32iCEsLPI4BHDpJCHHm1FU2E7dKWWIXJgQgSFiu4lp8q3bL1BIKwqkSUviqtA==", "requires": { - "@babel/types": "^7.15.0" + "@babel/types": "^7.15.4" } }, "@babel/helper-module-imports": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.14.5.tgz", - "integrity": "sha512-SwrNHu5QWS84XlHwGYPDtCxcA0hrSlL2yhWYLgeOc0w7ccOl2qv4s/nARI0aYZW+bSwAL5CukeXA47B/1NKcnQ==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.15.4.tgz", + "integrity": "sha512-jeAHZbzUwdW/xHgHQ3QmWR4Jg6j15q4w/gCfwZvtqOxoo5DKtLHk8Bsf4c5RZRC7NmLEs+ohkdq8jFefuvIxAA==", "requires": { - "@babel/types": "^7.14.5" + "@babel/types": "^7.15.4" } }, "@babel/helper-module-transforms": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.15.0.tgz", - "integrity": "sha512-RkGiW5Rer7fpXv9m1B3iHIFDZdItnO2/BLfWVW/9q7+KqQSDY5kUfQEbzdXM1MVhJGcugKV7kRrNVzNxmk7NBg==", - "requires": { - "@babel/helper-module-imports": "^7.14.5", - "@babel/helper-replace-supers": "^7.15.0", - "@babel/helper-simple-access": "^7.14.8", - "@babel/helper-split-export-declaration": "^7.14.5", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.15.4.tgz", + "integrity": "sha512-9fHHSGE9zTC++KuXLZcB5FKgvlV83Ox+NLUmQTawovwlJ85+QMhk1CnVk406CQVj97LaWod6KVjl2Sfgw9Aktw==", + "requires": { + "@babel/helper-module-imports": "^7.15.4", + "@babel/helper-replace-supers": "^7.15.4", + "@babel/helper-simple-access": "^7.15.4", + "@babel/helper-split-export-declaration": "^7.15.4", "@babel/helper-validator-identifier": "^7.14.9", - "@babel/template": "^7.14.5", - "@babel/traverse": "^7.15.0", - "@babel/types": "^7.15.0" + "@babel/template": "^7.15.4", + "@babel/traverse": "^7.15.4", + "@babel/types": "^7.15.4" } }, "@babel/helper-optimise-call-expression": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.14.5.tgz", - "integrity": "sha512-IqiLIrODUOdnPU9/F8ib1Fx2ohlgDhxnIDU7OEVi+kAbEZcyiF7BLU8W6PfvPi9LzztjS7kcbzbmL7oG8kD6VA==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.15.4.tgz", + "integrity": "sha512-E/z9rfbAOt1vDW1DR7k4SzhzotVV5+qMciWV6LaG1g4jeFrkDlJedjtV4h0i4Q/ITnUu+Pk08M7fczsB9GXBDw==", "requires": { - "@babel/types": "^7.14.5" + "@babel/types": "^7.15.4" } }, "@babel/helper-replace-supers": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.15.0.tgz", - "integrity": "sha512-6O+eWrhx+HEra/uJnifCwhwMd6Bp5+ZfZeJwbqUTuqkhIT6YcRhiZCOOFChRypOIe0cV46kFrRBlm+t5vHCEaA==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.15.4.tgz", + "integrity": "sha512-/ztT6khaXF37MS47fufrKvIsiQkx1LBRvSJNzRqmbyeZnTwU9qBxXYLaaT/6KaxfKhjs2Wy8kG8ZdsFUuWBjzw==", "requires": { - "@babel/helper-member-expression-to-functions": "^7.15.0", - "@babel/helper-optimise-call-expression": "^7.14.5", - "@babel/traverse": "^7.15.0", - "@babel/types": "^7.15.0" + "@babel/helper-member-expression-to-functions": "^7.15.4", + "@babel/helper-optimise-call-expression": "^7.15.4", + "@babel/traverse": "^7.15.4", + "@babel/types": "^7.15.4" } }, "@babel/helper-simple-access": { - "version": "7.14.8", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.14.8.tgz", - "integrity": "sha512-TrFN4RHh9gnWEU+s7JloIho2T76GPwRHhdzOWLqTrMnlas8T9O7ec+oEDNsRXndOmru9ymH9DFrEOxpzPoSbdg==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.15.4.tgz", + "integrity": "sha512-UzazrDoIVOZZcTeHHEPYrr1MvTR/K+wgLg6MY6e1CJyaRhbibftF6fR2KU2sFRtI/nERUZR9fBd6aKgBlIBaPg==", "requires": { - "@babel/types": "^7.14.8" + "@babel/types": "^7.15.4" } }, "@babel/helper-split-export-declaration": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.14.5.tgz", - "integrity": "sha512-hprxVPu6e5Kdp2puZUmvOGjaLv9TCe58E/Fl6hRq4YiVQxIcNvuq6uTM2r1mT/oPskuS9CgR+I94sqAYv0NGKA==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.15.4.tgz", + "integrity": "sha512-HsFqhLDZ08DxCpBdEVtKmywj6PQbwnF6HHybur0MAnkAKnlS6uHkwnmRIkElB2Owpfb4xL4NwDmDLFubueDXsw==", "requires": { - "@babel/types": "^7.14.5" + "@babel/types": "^7.15.4" } }, "@babel/helper-validator-identifier": { @@ -185,13 +185,13 @@ "integrity": "sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow==" }, "@babel/helpers": { - "version": "7.15.3", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.15.3.tgz", - "integrity": "sha512-HwJiz52XaS96lX+28Tnbu31VeFSQJGOeKHJeaEPQlTl7PnlhFElWPj8tUXtqFIzeN86XxXoBr+WFAyK2PPVz6g==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.15.4.tgz", + "integrity": "sha512-V45u6dqEJ3w2rlryYYXf6i9rQ5YMNu4FLS6ngs8ikblhu2VdR1AqAd6aJjBzmf2Qzh6KOLqKHxEN9+TFbAkAVQ==", "requires": { - "@babel/template": "^7.14.5", - "@babel/traverse": "^7.15.0", - "@babel/types": "^7.15.0" + "@babel/template": "^7.15.4", + "@babel/traverse": "^7.15.4", + "@babel/types": "^7.15.4" } }, "@babel/highlight": { @@ -251,32 +251,32 @@ } }, "@babel/parser": { - "version": "7.15.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.15.3.tgz", - "integrity": "sha512-O0L6v/HvqbdJawj0iBEfVQMc3/6WP+AeOsovsIgBFyJaG+W2w7eqvZB7puddATmWuARlm1SX7DwxJ/JJUnDpEA==" + "version": "7.15.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.15.6.tgz", + "integrity": "sha512-S/TSCcsRuCkmpUuoWijua0Snt+f3ewU/8spLo+4AXJCZfT0bVCzLD5MuOKdrx0mlAptbKzn5AdgEIIKXxXkz9Q==" }, "@babel/template": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.14.5.tgz", - "integrity": "sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.15.4.tgz", + "integrity": "sha512-UgBAfEa1oGuYgDIPM2G+aHa4Nlo9Lh6mGD2bDBGMTbYnc38vulXPuC1MGjYILIEmlwl6Rd+BPR9ee3gm20CBtg==", "requires": { "@babel/code-frame": "^7.14.5", - "@babel/parser": "^7.14.5", - "@babel/types": "^7.14.5" + "@babel/parser": "^7.15.4", + "@babel/types": "^7.15.4" } }, "@babel/traverse": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.15.0.tgz", - "integrity": "sha512-392d8BN0C9eVxVWd8H6x9WfipgVH5IaIoLp23334Sc1vbKKWINnvwRpb4us0xtPaCumlwbTtIYNA0Dv/32sVFw==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.15.4.tgz", + "integrity": "sha512-W6lQD8l4rUbQR/vYgSuCAE75ADyyQvOpFVsvPPdkhf6lATXAsQIG9YdtOcu8BB1dZ0LKu+Zo3c1wEcbKeuhdlA==", "requires": { "@babel/code-frame": "^7.14.5", - "@babel/generator": "^7.15.0", - "@babel/helper-function-name": "^7.14.5", - "@babel/helper-hoist-variables": "^7.14.5", - "@babel/helper-split-export-declaration": "^7.14.5", - "@babel/parser": "^7.15.0", - "@babel/types": "^7.15.0", + "@babel/generator": "^7.15.4", + "@babel/helper-function-name": "^7.15.4", + "@babel/helper-hoist-variables": "^7.15.4", + "@babel/helper-split-export-declaration": "^7.15.4", + "@babel/parser": "^7.15.4", + "@babel/types": "^7.15.4", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -292,9 +292,9 @@ } }, "@babel/types": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz", - "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==", + "version": "7.15.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.6.tgz", + "integrity": "sha512-BPU+7QhqNjmWyDO0/vitH/CuhpV8ZmK1wpKva8nuyNF5MJfuRNWMc+hc14+u9xT93kvykMdncrJT19h74uB1Ig==", "requires": { "@babel/helper-validator-identifier": "^7.14.9", "to-fast-properties": "^2.0.0" @@ -322,9 +322,9 @@ "dev": true }, "@types/babel__core": { - "version": "7.1.15", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.15.tgz", - "integrity": "sha512-bxlMKPDbY8x5h6HBwVzEOk2C8fb6SLfYQ5Jw3uBYuYF1lfWk/kbLd81la82vrIkBb0l+JdmrZaDikPrNxpS/Ew==", + "version": "7.1.16", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.16.tgz", + "integrity": "sha512-EAEHtisTMM+KaKwfWdC3oyllIqswlznXCIVCt7/oRNrh+DhgT4UEBNC/jlADNjvw7UnfbcdkGQcPVZ1xYiLcrQ==", "dev": true, "requires": { "@babel/parser": "^7.1.0", @@ -335,18 +335,18 @@ } }, "@types/babel__generator": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.3.tgz", - "integrity": "sha512-/GWCmzJWqV7diQW54smJZzWbSFf4QYtF71WCKhcx6Ru/tFyQIY2eiiITcCAeuPbNSvT9YCGkVMqqvSk2Z0mXiA==", + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.2.tgz", + "integrity": "sha512-MdSJnBjl+bdwkLskZ3NGFp9YcXGx5ggLpQQPqtgakVhsWK0hTtNYhjpZLlWQTviGTvF8at+Bvli3jV7faPdgeQ==", "dev": true, "requires": { "@babel/types": "^7.0.0" } }, "@types/babel__template": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", - "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.0.tgz", + "integrity": "sha512-NTPErx4/FiPCGScH7foPyr+/1Dkzkni+rHiYHHoTjvwou7AQzJkNeD60A9CXRy+ZEN2B1bggmkTMCDb+Mv5k+A==", "dev": true, "requires": { "@babel/parser": "^7.1.0", @@ -354,9 +354,9 @@ } }, "@types/babel__traverse": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.14.2.tgz", - "integrity": "sha512-K2waXdXBi2302XUdcHcR1jCeU0LL4TD9HRs/gk0N2Xvrht+G/BfJa4QObBQZfhMdxiCpV3COl5Nfq4uKTeTnJA==", + "version": "7.11.1", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.11.1.tgz", + "integrity": "sha512-Vs0hm0vPahPMYi9tDjtP66llufgO3ST16WXaSTtDGEl9cewAl3AibmxWw6TINOqHPT9z0uABKAYjT9jNSg4npw==", "dev": true, "requires": { "@babel/types": "^7.3.0" @@ -559,15 +559,15 @@ } }, "browserslist": { - "version": "4.16.7", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.7.tgz", - "integrity": "sha512-7I4qVwqZltJ7j37wObBe3SoTz+nS8APaNcrBOlgoirb6/HbEU2XxW/LpUDTCngM6iauwFqmRTuOMfyKnFGY5JA==", + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.17.0.tgz", + "integrity": "sha512-g2BJ2a0nEYvEFQC208q8mVAhfNwpZ5Mu8BwgtCdZKO3qx98HChmeg448fPdUzld8aFmfLgVh7yymqV+q1lJZ5g==", "requires": { - "caniuse-lite": "^1.0.30001248", - "colorette": "^1.2.2", - "electron-to-chromium": "^1.3.793", + "caniuse-lite": "^1.0.30001254", + "colorette": "^1.3.0", + "electron-to-chromium": "^1.3.830", "escalade": "^3.1.1", - "node-releases": "^1.1.73" + "node-releases": "^1.1.75" } }, "bson": { @@ -588,9 +588,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001251", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001251.tgz", - "integrity": "sha512-HOe1r+9VkU4TFmnU70z+r7OLmtR+/chB1rdcJUeQlAinjEeb0cKL20tlAtOagNZhbrtLnCvV19B4FmF1rgzl6A==" + "version": "1.0.30001257", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001257.tgz", + "integrity": "sha512-JN49KplOgHSXpIsVSF+LUyhD8PUp6xPpAXeRrrcBh4KBeP7W864jHn6RvzJgDlrReyeVjMFJL3PLpPvKIxlIHA==" }, "chai-as-promised": { "version": "7.1.1", @@ -635,9 +635,9 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "colorette": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.3.0.tgz", - "integrity": "sha512-ecORCqbSFP7Wm8Y6lyqMJjexBQqXSF7SSeaTyGGphogUjBlFP9m9o08wy86HL2uB7fMTxtOUzLMk7ogKcxMg1w==" + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", + "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==" }, "component-type": { "version": "1.2.1", @@ -645,9 +645,9 @@ "integrity": "sha1-ikeQFwAjjk/DIml3EjAibyS0Fak=" }, "convert-source-map": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", - "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", "requires": { "safe-buffer": "~5.1.1" } @@ -673,9 +673,9 @@ } }, "electron-to-chromium": { - "version": "1.3.803", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.803.tgz", - "integrity": "sha512-tmRK9qB8Zs8eLMtTBp+w2zVS9MUe62gQQQHjYdAc5Zljam3ZIokNb+vZLPRz9RCREp6EFRwyhOFwbt1fEriQ2Q==" + "version": "1.3.836", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.836.tgz", + "integrity": "sha512-Ney3pHOJBWkG/AqYjrW0hr2AUCsao+2uvq9HUlRP8OlpSdk/zOHOUJP7eu0icDvePC9DlgffuelP4TnOJmMRUg==" }, "emphasize": { "version": "3.0.0", @@ -951,15 +951,15 @@ } }, "node-addon-api": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", - "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.1.0.tgz", + "integrity": "sha512-flmrDNB06LIl5lywUz7YlNGZH/5p0M7W28k8hzd9Lshtdh1wshD2Y+U4h9LD6KObOy1f+fEVdgprPrEymjM5uw==", "optional": true }, "node-releases": { - "version": "1.1.74", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.74.tgz", - "integrity": "sha512-caJBVempXZPepZoZAPCWRTNxYQ+xtG/KAi4ozTA5A+nJ7IU+kLQCbqaUjb5Rwy14M9upBWiQ4NutcmW04LJSRw==" + "version": "1.1.75", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.75.tgz", + "integrity": "sha512-Qe5OUajvqrqDSy6wrWFmMwfJ0jVgwiw4T3KqmbTcZ62qW0gQkheXYhcFM1+lOVcGUoRxcEcfyvFMAnDgaF1VWw==" }, "pretty-bytes": { "version": "5.3.0", diff --git a/packages/cli-repl/package.json b/packages/cli-repl/package.json index b53fad628..6789ddc7d 100644 --- a/packages/cli-repl/package.json +++ b/packages/cli-repl/package.json @@ -41,6 +41,7 @@ "dependencies": { "@babel/core": "^7.14.8", "@mongosh/autocomplete": "0.0.0-dev.0", + "@mongosh/editor": "0.0.0-dev.0", "@mongosh/errors": "0.0.0-dev.0", "@mongosh/history": "0.0.0-dev.0", "@mongosh/i18n": "0.0.0-dev.0", diff --git a/packages/cli-repl/src/cli-repl.ts b/packages/cli-repl/src/cli-repl.ts index a12128be7..075de8610 100644 --- a/packages/cli-repl/src/cli-repl.ts +++ b/packages/cli-repl/src/cli-repl.ts @@ -4,6 +4,7 @@ import i18n from '@mongosh/i18n'; import { bson, AutoEncryptionOptions } from '@mongosh/service-provider-core'; import { CliOptions, CliServiceProvider, MongoClientOptions } from '@mongosh/service-provider-server'; import { SnippetManager } from '@mongosh/snippet-manager'; +import { Editor } from '@mongosh/editor'; import Analytics from 'analytics-node'; import askpassword from 'askpassword'; import ConnectionString from 'mongodb-connection-string-url'; @@ -22,6 +23,7 @@ import { MongoshBus, CliUserConfig } from '@mongosh/types'; import { promises as fs } from 'fs'; import path from 'path'; import { promisify } from 'util'; +import { makeMultilineJSIntoSingleLine } from './js-multiline-to-singleline'; /** * Connecting text key. @@ -142,7 +144,7 @@ class CliRepl { /** * Setup CLI environment: serviceProvider, ShellEvaluator, log connection - * information, and finally start the repl. + * information, external editor, and finally start the repl. * * @param {string} driverUri - The driver URI. * @param {MongoClientOptions} driverOptions - The driver options. @@ -223,12 +225,21 @@ class CliRepl { let snippetManager: SnippetManager | undefined; if (this.config.snippetIndexSourceURLs !== '') { - snippetManager = new SnippetManager({ + snippetManager = SnippetManager.create({ installdir: this.shellHomeDirectory.roamingPath('snippets'), instanceState: this.mongoshRepl.runtimeState().instanceState }); } + Editor.create({ + input: this.input, + vscodeDir: this.shellHomeDirectory.rcPath('.vscode'), + tmpDir: this.shellHomeDirectory.localPath('editor'), + instanceState: this.mongoshRepl.runtimeState().instanceState, + makeMultilineJSIntoSingleLine: makeMultilineJSIntoSingleLine, // TODO: move to its own package + loadExternalCode: this.mongoshRepl.loadExternalCode.bind(this.mongoshRepl) + }); + const commandLineLoadFiles = this.cliOptions.fileNames ?? []; if (commandLineLoadFiles.length > 0 || this.cliOptions.eval !== undefined) { this.mongoshRepl.setIsInteractive(!!this.cliOptions.shell); diff --git a/packages/editor/.eslintignore b/packages/editor/.eslintignore new file mode 100644 index 000000000..491fc3597 --- /dev/null +++ b/packages/editor/.eslintignore @@ -0,0 +1,2 @@ +node_modules +lib diff --git a/packages/editor/.eslintrc.js b/packages/editor/.eslintrc.js new file mode 100644 index 000000000..4a958b44b --- /dev/null +++ b/packages/editor/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('../../config/eslintrc.base'); diff --git a/packages/editor/.gitignore b/packages/editor/.gitignore new file mode 100644 index 000000000..c3af85790 --- /dev/null +++ b/packages/editor/.gitignore @@ -0,0 +1 @@ +lib/ diff --git a/packages/editor/.npmignore b/packages/editor/.npmignore new file mode 100644 index 000000000..ef55c3b8a --- /dev/null +++ b/packages/editor/.npmignore @@ -0,0 +1,15 @@ +.DS_Store +.evergreen/ +.evergreen.yml +.gitignore +.jshintrc +.jsfmtrc +.travis.yml +.zuul.yml +azure-pipelines.yml +karma.conf.js +lerna.json +tsconfig.json +notices/ +src/ +test/ diff --git a/packages/editor/LICENSE b/packages/editor/LICENSE new file mode 100644 index 000000000..ad410e113 --- /dev/null +++ b/packages/editor/LICENSE @@ -0,0 +1,201 @@ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/packages/editor/README.md b/packages/editor/README.md new file mode 100644 index 000000000..c8c5d73ef --- /dev/null +++ b/packages/editor/README.md @@ -0,0 +1,9 @@ +# `@mongosh/editor` + +Package for [MongoDB Shell](https://github.com/mongodb-js/mongosh). + +### Installation + +```shell +npm install -S @mongosh/editor +``` diff --git a/packages/editor/package-lock.json b/packages/editor/package-lock.json new file mode 100644 index 000000000..38fe3692b --- /dev/null +++ b/packages/editor/package-lock.json @@ -0,0 +1,271 @@ +{ + "name": "@mongosh/editor", + "version": "0.0.0-dev.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@types/cross-spawn": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@types/cross-spawn/-/cross-spawn-6.0.2.tgz", + "integrity": "sha512-KuwNhp3eza+Rhu8IFI5HUXRP0LIhqH5cAjubUvGXXthh4YYBuP2ntwEX+Cz8GJoZUHlKo247wPWOfA9LYEq4cw==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/node": { + "version": "16.9.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.9.1.tgz", + "integrity": "sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g==", + "dev": true + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "config-chain": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", + "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", + "requires": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "editorconfig": { + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz", + "integrity": "sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==", + "requires": { + "commander": "^2.19.0", + "lru-cache": "^4.1.5", + "semver": "^5.6.0", + "sigmund": "^1.0.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "js-beautify": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.14.0.tgz", + "integrity": "sha512-yuck9KirNSCAwyNJbqW+BxJqJ0NLJ4PwBUzQQACl5O3qHMBXVkXb/rD0ilh/Lat/tn88zSZ+CAHOlk0DsY7GuQ==", + "requires": { + "config-chain": "^1.1.12", + "editorconfig": "^0.15.3", + "glob": "^7.1.3", + "nopt": "^5.0.0" + } + }, + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "nanoassert": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/nanoassert/-/nanoassert-1.1.0.tgz", + "integrity": "sha1-TzFS4JVA/eKMdvRLGbvNHVpCR40=", + "dev": true + }, + "nanobus": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/nanobus/-/nanobus-4.5.0.tgz", + "integrity": "sha512-7sBZo9wthqNJ7QXnfVXZL7fkKJLN55GLOdX+RyZT34UOvxxnFtJe/c7K0ZRLAKOvaY1xJThFFn0Usw2H9R6Frg==", + "dev": true, + "requires": { + "nanoassert": "^1.1.0", + "nanotiming": "^7.2.0", + "remove-array-items": "^1.0.0" + } + }, + "nanoscheduler": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/nanoscheduler/-/nanoscheduler-1.0.3.tgz", + "integrity": "sha512-jBbrF3qdU9321r8n9X7yu18DjP31Do2ItJm3mWrt90wJTrnDO+HXpoV7ftaUglAtjgj9s+OaCxGufbvx6pvbEQ==", + "dev": true, + "requires": { + "nanoassert": "^1.1.0" + } + }, + "nanotiming": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/nanotiming/-/nanotiming-7.3.1.tgz", + "integrity": "sha512-l3lC7v/PfOuRWQa8vV29Jo6TG10wHtnthLElFXs4Te4Aas57Fo4n1Q8LH9n+NDh9riOzTVvb2QNBhTS4JUKNjw==", + "dev": true, + "requires": { + "nanoassert": "^1.1.0", + "nanoscheduler": "^1.0.2" + } + }, + "nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "requires": { + "abbrev": "1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" + }, + "proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=" + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + }, + "remove-array-items": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/remove-array-items/-/remove-array-items-1.1.1.tgz", + "integrity": "sha512-MXW/jtHyl5F1PZI7NbpS8SOtympdLuF20aoWJT5lELR1p/HJDd5nqW8Eu9uLh/hCRY3FgvrIT5AwDCgBODklcA==", + "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" + }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=" + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "requires": { + "isexe": "^2.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + } + } +} diff --git a/packages/editor/package.json b/packages/editor/package.json new file mode 100644 index 000000000..60b75211b --- /dev/null +++ b/packages/editor/package.json @@ -0,0 +1,43 @@ +{ + "name": "@mongosh/editor", + "version": "0.0.0-dev.0", + "description": "MongoDB Shell External Editor", + "main": "./lib/index.js", + "repository": { + "type": "git", + "url": "git://github.com/mongodb-js/mongosh.git" + }, + "config": { + "unsafe-perm": true + }, + "scripts": { + "test": "mocha -r \"../../scripts/import-expansions.js\" --timeout 60000 -r ts-node/register \"./{src,lib}/**/*.spec.ts\"", + "test-ci": "node ../../scripts/run-if-package-requested.js npm test", + "lint": "eslint --report-unused-disable-directives \"./{src,test}/**/*.{js,ts,tsx}\"", + "check": "npm run lint && depcheck --skip-missing=true", + "compile-ts": "tsc -p tsconfig.json", + "prepublish": "npm run compile-ts" + }, + "license": "Apache-2.0", + "publishConfig": { + "access": "public" + }, + "engines": { + "node": ">=14.15.0" + }, + "mongosh": { + "unitTestsOnly": true + }, + "dependencies": { + "@mongosh/service-provider-core": "0.0.0-dev.0", + "@mongosh/shell-api": "0.0.0-dev.0", + "@mongosh/shell-evaluator": "0.0.0-dev.0", + "@mongosh/types": "0.0.0-dev.0", + "cross-spawn": "^7.0.3", + "js-beautify": "^1.14.0" + }, + "devDependencies": { + "@types/cross-spawn": "^6.0.2", + "nanobus": "^4.5.0" + } +} diff --git a/packages/editor/src/editor.spec.ts b/packages/editor/src/editor.spec.ts new file mode 100644 index 000000000..13f345e10 --- /dev/null +++ b/packages/editor/src/editor.spec.ts @@ -0,0 +1,205 @@ +import { bson } from '@mongosh/service-provider-core'; +import chai, { expect } from 'chai'; +import { Duplex, PassThrough } from 'stream'; +import Nanobus from 'nanobus'; +import path from 'path'; +import { promises as fs } from 'fs'; +import sinon from 'ts-sinon'; +import sinonChai from 'sinon-chai'; + +import { Editor } from './editor'; +import { eventually } from '../../../testing/eventually'; + +chai.use(sinonChai); + +describe('Editor', () => { + let input: Duplex; + let base: string; + let vscodeDir: string; + let tmpDir: string; + let contextObject: any; + let editor: Editor; + let makeEditor: () => Editor; + let busMessages: ({ ev: any, data?: any })[]; + let cmd: string | null; + let mockLoadExternalCodeResult: (...args: any[]) => { args: any[]; done: boolean }; + + beforeEach(() => { + input = new PassThrough(); + base = path.resolve(__dirname, '..', '..', '..', 'tmp', 'test', `${Date.now()}`, `${new bson.ObjectId()}`); + vscodeDir = path.join(base, '.vscode'); + tmpDir = path.join(base, 'editor'); + cmd = null; + contextObject = { + config: { + get(key: string): any { + switch (key) { + case 'editor': + return cmd; + default: + throw new Error(`Don’t know what to do with config key ${key}`); + } + } + }, + print: sinon.stub() + }; + mockLoadExternalCodeResult = function wrapper(...args: any[]) { + return { args, done: true }; + }; + + delete process.env.EDITOR; + + const messageBus = new Nanobus('mongosh-editor-test'); + busMessages = []; + + makeEditor = () => new Editor({ + input, + vscodeDir, + tmpDir, + instanceState: { + context: contextObject, + shellApi: contextObject, + registerPlugin: sinon.stub(), + messageBus + } as any, + makeMultilineJSIntoSingleLine: sinon.stub(), + loadExternalCode: (): any => mockLoadExternalCodeResult + }); + + editor = makeEditor(); + messageBus.on('*', (ev: any, data: any) => { + if (typeof data === 'number') { + busMessages.push({ ev }); + } else { + busMessages.push({ ev, data }); + } + }); + }); + + afterEach(async() => { + await eventually(async() => { + // This can fail when an index fetch is being written while we are removing + // the directory; hence, try again. + await fs.rmdir(tmpDir, { recursive: true }); + }); + }); + + it('_isVscodeApp returns true if command is code', () => { + const isVscodeApp = editor._isVscodeApp('code'); + expect(isVscodeApp).to.be.equal(true); + }); + + it('_isVscodeApp returns true if command is path to code', () => { + const isVscodeApp = editor._isVscodeApp('/usr/local/bin/code'); + expect(isVscodeApp).to.be.equal(true); + }); + + it('_isVscodeApp returns true if command is path to code on windows', () => { + const isVscodeApp = editor._isVscodeApp('C:\\Program Files\\Microsoft VS Code\\Code.exe'); + expect(isVscodeApp).to.be.equal(true); + }); + + it('_isVscodeApp returns false if command is nano', () => { + const isVscodeApp = editor._isVscodeApp('nano'); + expect(isVscodeApp).to.be.equal(false); + }); + + it('_isIdentifier returns false if a command is an empty find statement', () => { + const isIdentifier = editor._isIdentifier('db.test.find()'); + expect(isIdentifier).to.be.equal(false); + }); + + it('_isIdentifier returns false if a command is a find statement with a query', () => { + const isIdentifier = editor._isIdentifier("db.test.find({ name: 'lena' })"); + expect(isIdentifier).to.be.equal(false); + }); + + it('_isIdentifier returns true if a command is an identifier written with dots', () => { + const isIdentifier = editor._isIdentifier('db.test.find'); + expect(isIdentifier).to.be.equal(true); + }); + + it('_isIdentifier returns true if a command is an identifier written as an array and double quotes', () => { + const isIdentifier = editor._isIdentifier('db["test"]find'); + expect(isIdentifier).to.be.equal(true); + }); + + it('_isIdentifier returns true if a command is an identifier written as an array and single quotes', () => { + const isIdentifier = editor._isIdentifier("db['test']find"); + expect(isIdentifier).to.be.equal(true); + }); + + it('_isIdentifier returns true if it contains $', () => { + const isIdentifier = editor._isIdentifier('$something'); + expect(isIdentifier).to.be.equal(true); + }); + + it('_isIdentifier returns false for sum of numbers', () => { + const isIdentifier = editor._isIdentifier('1 + 2'); + expect(isIdentifier).to.be.equal(false); + }); + + it('_isIdentifier returns false for a class', () => { + const isIdentifier = editor._isIdentifier('class A {}'); + expect(isIdentifier).to.be.equal(false); + }); + + it('_isIdentifier returns true for a string', () => { + const isIdentifier = editor._isIdentifier('"some string"'); + expect(isIdentifier).to.be.equal(true); + }); + + it('_getEditor returns an editor value from process.env.EDITOR', async() => { + process.env.EDITOR = 'neweprocessditor'; + const editorName = await editor._getEditor(); + expect(editorName).to.be.equal(process.env.EDITOR); + }); + + it('_getEditor returns an editor value from the mongosh config', async() => { + cmd = 'newecmdditor'; + process.env.EDITOR = 'neweprocessditor'; + const editorName = await editor._getEditor(); + expect(editorName).to.be.equal(cmd); + }); + + it('runEditCommand returns an error for not existing editor', async() => { + try { + await editor.runEditCommand(''); + } catch (error) { + expect(error.message).to.include('Command failed with an error: please define an external editor'); + } + }); + + it('_getEditorContent returns function implementation', async() => { + const code = 'db.test.find'; + const content = await editor._getEditorContent(code); + expect(content).to.be.equal('function wrapper(...args) {\n return { args, done: true };\n }'); + }); + + it('_getEditorContent returns function', async() => { + const code = "function foo() { return 'a b'; }"; + const content = await editor._getEditorContent(code); + expect(content).to.be.equal(code); + }); + + it('_getEditorContent returns an unmodified statment', async() => { + const code = 'db.coll.find()'; + const content = await editor._getEditorContent(code); + expect(content).to.be.equal(code); + }); + + it('_getEditorContent returns the last opened content for the empty edit command', async() => { + editor._lastContent = 'db.test.find()'; + const content = await editor._getEditorContent(''); + expect(content).to.be.equal('db.test.find()'); + }); + + it('_getEditorContent returns a new content for not empty edit command', async() => { + editor._lastContent = 'db.coll.find()'; + const content = await editor._getEditorContent('1 + 1'); + expect(content).to.be.equal('1 + 1'); + }); + + // TODO: e2e or mock tests for _getExtension + // TODO: Write a node script that acts as an external editor and write e2e tests +}); diff --git a/packages/editor/src/editor.ts b/packages/editor/src/editor.ts new file mode 100644 index 000000000..5aa4c0b78 --- /dev/null +++ b/packages/editor/src/editor.ts @@ -0,0 +1,202 @@ +import * as path from 'path'; +import { once } from 'events'; +import { promises as fs } from 'fs'; +import { Readable } from 'stream'; +import spawn from 'cross-spawn'; + +import { bson } from '@mongosh/service-provider-core'; +import { signatures, ShellInstanceState, TypeSignature } from '@mongosh/shell-api'; +import { ShellResult } from '@mongosh/shell-evaluator'; + +import type { MongoshBus } from '@mongosh/types'; + +const beautify = require('js-beautify').js; + +export interface EditorOptions { + input: Readable; + vscodeDir: string; + tmpDir: string; + instanceState: ShellInstanceState; + makeMultilineJSIntoSingleLine: (code: string) => string; + loadExternalCode: (input: string, filename: string) => Promise; +} + +export class Editor { + _input: Readable; + _vscodeDir: string; + _tmpDir: string; + _instanceState: ShellInstanceState; + _makeMultilineJSIntoSingleLine: (code: string) => string; + _loadExternalCode: (input: string, filename: string) => Promise; + _lastContent: string; + print: (...args: any[]) => Promise; + + constructor({ input, vscodeDir, tmpDir, instanceState, makeMultilineJSIntoSingleLine, loadExternalCode }: EditorOptions) { + this._input = input; + this._vscodeDir = vscodeDir; + this._tmpDir = tmpDir; + this._instanceState = instanceState; + this._makeMultilineJSIntoSingleLine = makeMultilineJSIntoSingleLine; + this._loadExternalCode = loadExternalCode; + this._lastContent = ''; + this.print = instanceState.context.print; + + // Add edit command support to shell api. + const wrapperFn = (input: string) => { + return Object.assign(this.runEditCommand(input), { + [Symbol.for('@@mongosh.syntheticPromise')]: true + }); + }; + + wrapperFn.isDirectShellCommand = true; + wrapperFn.returnsPromise = true; + wrapperFn.acceptsRawInput = true; + (instanceState.shellApi as any).edit = instanceState.context.edit = wrapperFn; + (signatures.ShellApi.attributes as any).edit = { + type: 'function', + returnsPromise: true, + isDirectShellCommand: true, + acceptsRawInput: true + } as TypeSignature; + } + + static create(options: EditorOptions): Editor { + return new Editor(options); + } + + // In case of using VSCode as an external editor, + // detect whether the MongoDB extension is installed and open a .mongodb file. + // If not open a .js file instead. + async _getExtension(cmd: string): Promise { + if (!this._isVscodeApp(cmd)) { + return 'js'; + } + + try { + const extensions = await fs.readdir(path.join(this._vscodeDir, 'extensions')); + const hasMongodbExtension = !!extensions + .find((name) => name.includes('mongodb.mongodb-vscode')); + + this.messageBus.emit('mongosh-editor:read-vscode-extensions-done', { + vscodeDir: this._vscodeDir, + hasMongodbExtension + }); + + return hasMongodbExtension ? 'mongodb' : 'js'; + } catch (error) { + this.messageBus.emit('mongosh-editor:read-vscode-extensions-failed', { + action: 'mongosh-editor:read-vscode-extensions-failed', + error: (error as Error).message + }); + + return 'js'; + } + } + + async _getEditor(): Promise { + // Check for an external editor in the mongosh configuration. + let editor: string | null = await this._instanceState.shellApi.config.get('editor'); + + // Check for an external editor in the environment variable. + if (!editor && process.env.EDITOR) { + editor = process.env.EDITOR; + } + + return editor; + } + + async _createTempFile({ content, ext }: { content: string; ext: string }): Promise { + const tmpDoc = path.join(this._tmpDir, `edit-${new bson.ObjectId()}.${ext}`); + + // Create a temp file to store a content that is being edited. + await fs.mkdir(path.dirname(tmpDoc), { recursive: true, mode: 0o700 }); + await fs.writeFile(tmpDoc, beautify(content), { mode: 0o600 }); + + return tmpDoc; + } + + async _readAndDeleteTempFile(tmpDoc: string): Promise { + // Store the last opened content inside the class and delete a temp file. + this._lastContent = await fs.readFile(tmpDoc, 'utf8'); + await fs.unlink(tmpDoc); + // Transform a multi-line content to a single line. + return this._makeMultilineJSIntoSingleLine(this._lastContent); + } + + _isVscodeApp(cmd: string): boolean { + const regex = /^(.*)[\/\\]?[cC]ode(.exe)?$/; + return regex.test(cmd); + } + + _isIdentifier(code: string): boolean { + const regex = /^([^!#%&()*+,\-/\\^`{|}~]+)$/; + return regex.test(code); + } + + async _getEditorContent(code: string): Promise { + // If an empty edit command was called, return the last opened content. + if (!code) { + return this._lastContent; + } + + // If code is a statement return the original input string. + if (!this._isIdentifier(code)) { + return code; + } + + // If code is an identifier evaluate the string to see what the result is. + const evalResult = await this._loadExternalCode(code, '@(editor)'); + return evalResult.toString(); + } + + async runEditCommand(input: string): Promise { + await this.print('Opening an editor...'); + + const code = input.replace('edit', '').trim(); + const editor: string|null = await this._getEditor(); + + // If none of the above configurations are found return an error. + if (!editor) { + throw new Error('Command failed with an error: please define an external editor'); + } + + const content = await this._getEditorContent(code); + const ext = await this._getExtension(editor); + const tmpDoc = await this._createTempFile({ content, ext }); + + this.messageBus.emit('mongosh-editor:run-edit-command', { + tmpDoc, + editor, + code + }); + + const proc = spawn(editor, [tmpDoc], { stdio: 'inherit' }); + // Pause the parent readable stream to stop emitting data events + // and get a child the total control over the input. + this._input.pause(); + + try { + const [ exitCode ] = await once(proc, 'exit'); + + if (exitCode === 0) { + const result = await this._readAndDeleteTempFile(tmpDoc); + // Write a content from the editor to the parent readable stream. + this._input.unshift(result); + return; + } + + throw new Error(`Command '${code}' failed with an exit code ${exitCode}`); + } finally { + // Resume the parent readable stream to recive data events. + this._input.resume(); + + if (proc.exitCode === null && proc.signalCode === null) { + proc.kill(); // Not exited yet, i.e. this was interrupted. + } + } + } + + get messageBus(): MongoshBus { + return this._instanceState.messageBus; + } +} diff --git a/packages/editor/src/index.ts b/packages/editor/src/index.ts new file mode 100644 index 000000000..2f6832bfc --- /dev/null +++ b/packages/editor/src/index.ts @@ -0,0 +1 @@ +export { Editor } from './editor'; diff --git a/packages/editor/tsconfig.json b/packages/editor/tsconfig.json new file mode 100644 index 000000000..eff2d1418 --- /dev/null +++ b/packages/editor/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "../../config/tsconfig.base.json", + "compilerOptions": { + "outDir": "./lib", + "allowJs": true + }, + "include": [ + "./src/**/*" + ], + "exclude": [ + "./src/**/*.spec.*" + ] +} diff --git a/packages/editor/tsconfig.lint.json b/packages/editor/tsconfig.lint.json new file mode 100644 index 000000000..e797cf64f --- /dev/null +++ b/packages/editor/tsconfig.lint.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.json", + "include": [ + "./src/**/*", + "./test/**/*" + ], + "exclude": [] +} diff --git a/packages/java-shell/package-lock.json b/packages/java-shell/package-lock.json index b2dc42ab0..87a561648 100644 --- a/packages/java-shell/package-lock.json +++ b/packages/java-shell/package-lock.json @@ -85,9 +85,9 @@ } }, "available-typed-arrays": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.4.tgz", - "integrity": "sha512-SA5mXJWrId1TaQjfxUYghbqQ/hYioKmLJvPJyDuYRtXXenFNMjj4hSSt1Cf1xsuXSXrtxrVC5Ot4eU6cOtBDdA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", "dev": true }, "balanced-match": { @@ -392,9 +392,9 @@ "dev": true }, "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", "dev": true }, "create-ecdh": { @@ -573,22 +573,23 @@ } }, "es-abstract": { - "version": "1.18.5", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.5.tgz", - "integrity": "sha512-DDggyJLoS91CkJjgauM5c0yZMjiD1uK3KcaCeAmffGwZ+ODWzOkPN4QwRbsK5DOFf06fywmyLci3ZD8jLGhVYA==", + "version": "1.18.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.6.tgz", + "integrity": "sha512-kAeIT4cku5eNLNuUKhlmtuk1/TRZvQoYccn6TO0cSVdf1kzB0T7+dYuVK9MWM7l+/53W2Q8M7N2c6MQvhXFcUQ==", "dev": true, "requires": { "call-bind": "^1.0.2", "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", "get-intrinsic": "^1.1.1", + "get-symbol-description": "^1.0.0", "has": "^1.0.3", "has-symbols": "^1.0.2", "internal-slot": "^1.0.3", - "is-callable": "^1.2.3", + "is-callable": "^1.2.4", "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.3", - "is-string": "^1.0.6", + "is-regex": "^1.1.4", + "is-string": "^1.0.7", "object-inspect": "^1.11.0", "object-keys": "^1.1.1", "object.assign": "^4.1.2", @@ -625,9 +626,9 @@ } }, "fast-safe-stringify": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.8.tgz", - "integrity": "sha512-lXatBjf3WPjmWD6DpIZxkeSsCOwqI0maYMpgDlx8g4U2qi4lbjA9oH/HD2a87G+KfsUmo5WbJFmqBZlPxtptag==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", "dev": true }, "foreach": { @@ -665,6 +666,16 @@ "has-symbols": "^1.0.1" } }, + "get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + } + }, "glob": { "version": "7.1.7", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", @@ -700,6 +711,15 @@ "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", "dev": true }, + "has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.2" + } + }, "hash-base": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", @@ -818,27 +838,32 @@ } }, "is-arguments": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.0.tgz", - "integrity": "sha512-1Ij4lOMPl/xB5kBDn7I+b2ttPMKa8szhEIrXDuXQD/oe3HJLTLhqhgGspwgyGd6MOywBUqVvYicF72lkgDnIHg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", "dev": true, "requires": { - "call-bind": "^1.0.0" + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" } }, "is-bigint": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.2.tgz", - "integrity": "sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA==", - "dev": true + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "requires": { + "has-bigints": "^1.0.1" + } }, "is-boolean-object": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.1.tgz", - "integrity": "sha512-bXdQWkECBUIAcCkeH1unwJLIpZYaa5VvuygSyS/c2lf719mTKZDU5UdDRlpd01UjADgmW8RfqaP+mRaVPdr/Ng==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", "dev": true, "requires": { - "call-bind": "^1.0.2" + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" } }, "is-buffer": { @@ -848,31 +873,37 @@ "dev": true }, "is-callable": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", - "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", "dev": true }, "is-core-module": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.5.0.tgz", - "integrity": "sha512-TXCMSDsEHMEEZ6eCA8rwRDbLu55MRGmrctljsBX/2v1d9/GzqHOxW5c5oPSgrUt2vBFXebu9rGqckXGPWOlYpg==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.6.0.tgz", + "integrity": "sha512-wShG8vs60jKfPWpF2KZRaAtvt3a20OAn7+IJ6hLPECpSABLcKtFKTTI4ZtH5QcBruBHlq+WsdHWyz0BCZW7svQ==", "dev": true, "requires": { "has": "^1.0.3" } }, "is-date-object": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.4.tgz", - "integrity": "sha512-/b4ZVsG7Z5XVtIxs/h9W8nvfLgSAyKYdtGWQLbqy6jA1icmgjf8WCoTKgeS4wy5tYaPePouzFMANbnj94c2Z+A==", - "dev": true + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } }, "is-generator-function": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.9.tgz", - "integrity": "sha512-ZJ34p1uvIfptHCN7sFTjGibB9/oBg17sHqzDLfuwhvmN/qLVvIQXRQ8licZQ35WJ8KuEQt/etnnzQFI9C9Ue/A==", - "dev": true + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } }, "is-negative-zero": { "version": "2.0.1", @@ -881,26 +912,32 @@ "dev": true }, "is-number-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.5.tgz", - "integrity": "sha512-RU0lI/n95pMoUKu9v1BZP5MBcZuNSVJkMkAG2dJqC4z2GlkGUNeH68SuHuBKBD/XFe+LHZ+f9BKkLET60Niedw==", - "dev": true + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", + "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } }, "is-regex": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz", - "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "dev": true, "requires": { "call-bind": "^1.0.2", - "has-symbols": "^1.0.2" + "has-tostringtag": "^1.0.0" } }, "is-string": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.6.tgz", - "integrity": "sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w==", - "dev": true + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } }, "is-symbol": { "version": "1.0.4", @@ -912,16 +949,16 @@ } }, "is-typed-array": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.5.tgz", - "integrity": "sha512-S+GRDgJlR3PyEbsX/Fobd9cqpZBuvUS+8asRqYDMLCb2qMzt1oz5m5oxQCxOgUDxiWsOVNi4yaF+/uvdlHlYug==", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.8.tgz", + "integrity": "sha512-HqH41TNZq2fgtGT8WHVFVJhBVGuY3AnP3Q36K8JKXUxSxRgk/d+7NjmwG2vo2mYmXK8UYZKu0qH8bVP5gEisjA==", "dev": true, "requires": { - "available-typed-arrays": "^1.0.2", + "available-typed-arrays": "^1.0.5", "call-bind": "^1.0.2", - "es-abstract": "^1.18.0-next.2", + "es-abstract": "^1.18.5", "foreach": "^2.0.5", - "has-symbols": "^1.0.1" + "has-tostringtag": "^1.0.0" } }, "isarray": { @@ -1580,18 +1617,17 @@ } }, "which-typed-array": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.4.tgz", - "integrity": "sha512-49E0SpUe90cjpoc7BOJwyPHRqSAd12c10Qm2amdEZrJPCY2NDxaW01zHITrem+rnETY3dwrbH3UUrUwagfCYDA==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.7.tgz", + "integrity": "sha512-vjxaB4nfDqwKI0ws7wZpxIlde1XrLX5uB0ZjpfshgmapJMD7jJWhZI+yToJTqaFByF0eNBcYxbjmCzoRP7CfEw==", "dev": true, "requires": { - "available-typed-arrays": "^1.0.2", - "call-bind": "^1.0.0", - "es-abstract": "^1.18.0-next.1", + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-abstract": "^1.18.5", "foreach": "^2.0.5", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.1", - "is-typed-array": "^1.1.3" + "has-tostringtag": "^1.0.0", + "is-typed-array": "^1.1.7" } }, "wrappy": { diff --git a/packages/logging/package-lock.json b/packages/logging/package-lock.json new file mode 100644 index 000000000..150368ab0 --- /dev/null +++ b/packages/logging/package-lock.json @@ -0,0 +1,56 @@ +{ + "name": "@mongosh/logging", + "version": "0.0.0-dev.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + }, + "bson": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/bson/-/bson-4.5.2.tgz", + "integrity": "sha512-8CEMJpwc7qlQtrn2rney38jQSEeMar847lz0LyitwRmVknAW8iHXrzW4fTjHfyWm0E3sukyD/zppdH+QU1QefA==", + "requires": { + "buffer": "^5.6.0" + } + }, + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "mongodb-log-writer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/mongodb-log-writer/-/mongodb-log-writer-1.0.3.tgz", + "integrity": "sha512-l/ayAE/j0OpULyIke6T0bivks+RzzIIS1gnCOEYzX3V9xuFz1sGLDGQfWBZhhhA974N3VM0brdqYokx9pjQUzw==", + "requires": { + "bson": "^4.5.1" + } + }, + "mongodb-redact": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/mongodb-redact/-/mongodb-redact-0.2.2.tgz", + "integrity": "sha512-tmgDpSBymFtKggsLzpa0vDYaqh2wEXOswBZtJkXvbPKP0ThfPwoFYXtOukactU6WZsC4RYmpSPM4P6582FR/Xw==", + "requires": { + "lodash": "^4.17.15" + } + } + } +} diff --git a/packages/logging/src/setup-logger-and-telemetry.ts b/packages/logging/src/setup-logger-and-telemetry.ts index 72f77e7d0..fa028550e 100644 --- a/packages/logging/src/setup-logger-and-telemetry.ts +++ b/packages/logging/src/setup-logger-and-telemetry.ts @@ -29,7 +29,10 @@ import type { SpConnectHeartbeatSucceededEvent, SpResolveSrvErrorEvent, SpResolveSrvSucceededEvent, - SpMissingOptionalDependencyEvent + SpMissingOptionalDependencyEvent, + EditorRunEditCommandEvent, + EditorReadVscodeExtensionsDoneEvent, + EditorReadVscodeExtensionsFailedEvent } from '@mongosh/types'; import { inspect } from 'util'; import { MongoLogWriter, mongoLogId } from 'mongodb-log-writer'; @@ -414,4 +417,16 @@ export function setupLoggerAndTelemetry( error: ev?.error.message }); }); + + bus.on('mongosh-editor:run-edit-command', function(ev: EditorRunEditCommandEvent) { + log.error('MONGOSH-EDITOR', mongoLogId(1_000_000_042), 'editor', 'Open external editor', ev); + }); + + bus.on('mongosh-editor:read-vscode-extensions-done', function(ev: EditorReadVscodeExtensionsDoneEvent) { + log.error('MONGOSH-EDITOR', mongoLogId(1_000_000_043), 'editor', 'Reading vscode extensions from disc succeeded', ev); + }); + + bus.on('mongosh-editor:read-vscode-extensions-failed', function(ev: EditorReadVscodeExtensionsFailedEvent) { + log.error('MONGOSH-EDITOR', mongoLogId(1_000_000_044), 'editor', 'Reading vscode extensions from disc failed', ev); + }); } diff --git a/packages/service-provider-server/package-lock.json b/packages/service-provider-server/package-lock.json index 7f0d6cd63..71d4a1e7d 100644 --- a/packages/service-provider-server/package-lock.json +++ b/packages/service-provider-server/package-lock.json @@ -317,6 +317,17 @@ "denque": "^2.0.1", "mongodb-connection-string-url": "^2.0.0", "saslprep": "^1.0.3" + }, + "dependencies": { + "saslprep": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", + "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", + "optional": true, + "requires": { + "sparse-bitfield": "^3.0.3" + } + } } }, "mongodb-client-encryption": { diff --git a/packages/shell-api/src/aggregation-cursor.spec.ts b/packages/shell-api/src/aggregation-cursor.spec.ts index f31b23e46..a788448ee 100644 --- a/packages/shell-api/src/aggregation-cursor.spec.ts +++ b/packages/shell-api/src/aggregation-cursor.spec.ts @@ -30,6 +30,7 @@ describe('AggregationCursor', () => { apiVersions: ALL_API_VERSIONS, serverVersions: ALL_SERVER_VERSIONS, isDirectShellCommand: false, + acceptsRawInput: false, shellCommandCompleter: undefined }); }); diff --git a/packages/shell-api/src/bulk.spec.ts b/packages/shell-api/src/bulk.spec.ts index c36f34494..2d85aa233 100644 --- a/packages/shell-api/src/bulk.spec.ts +++ b/packages/shell-api/src/bulk.spec.ts @@ -42,6 +42,7 @@ describe('Bulk API', () => { apiVersions: [ 1, Infinity ], serverVersions: ALL_SERVER_VERSIONS, isDirectShellCommand: false, + acceptsRawInput: false, shellCommandCompleter: undefined }); }); @@ -244,6 +245,7 @@ describe('Bulk API', () => { apiVersions: [ 1, Infinity ], serverVersions: ALL_SERVER_VERSIONS, isDirectShellCommand: false, + acceptsRawInput: false, shellCommandCompleter: undefined }); }); diff --git a/packages/shell-api/src/change-stream-cursor.spec.ts b/packages/shell-api/src/change-stream-cursor.spec.ts index f8b5895bf..fe56e98e1 100644 --- a/packages/shell-api/src/change-stream-cursor.spec.ts +++ b/packages/shell-api/src/change-stream-cursor.spec.ts @@ -37,6 +37,7 @@ describe('ChangeStreamCursor', () => { apiVersions: ALL_API_VERSIONS, serverVersions: ALL_SERVER_VERSIONS, isDirectShellCommand: false, + acceptsRawInput: false, shellCommandCompleter: undefined }); }); diff --git a/packages/shell-api/src/collection.spec.ts b/packages/shell-api/src/collection.spec.ts index 0f43f2a80..09d093e23 100644 --- a/packages/shell-api/src/collection.spec.ts +++ b/packages/shell-api/src/collection.spec.ts @@ -47,6 +47,7 @@ describe('Collection', () => { apiVersions: [ 1, Infinity ], serverVersions: ALL_SERVER_VERSIONS, isDirectShellCommand: false, + acceptsRawInput: false, shellCommandCompleter: undefined }); }); diff --git a/packages/shell-api/src/cursor.spec.ts b/packages/shell-api/src/cursor.spec.ts index 09950b96d..9bc82f8e9 100644 --- a/packages/shell-api/src/cursor.spec.ts +++ b/packages/shell-api/src/cursor.spec.ts @@ -34,6 +34,7 @@ describe('Cursor', () => { apiVersions: ALL_API_VERSIONS, serverVersions: ALL_SERVER_VERSIONS, isDirectShellCommand: false, + acceptsRawInput: false, shellCommandCompleter: undefined }); }); diff --git a/packages/shell-api/src/database.spec.ts b/packages/shell-api/src/database.spec.ts index b085ae62c..d7b72164f 100644 --- a/packages/shell-api/src/database.spec.ts +++ b/packages/shell-api/src/database.spec.ts @@ -87,6 +87,7 @@ describe('Database', () => { apiVersions: [ 1, Infinity ], serverVersions: ALL_SERVER_VERSIONS, isDirectShellCommand: false, + acceptsRawInput: false, shellCommandCompleter: undefined }); }); diff --git a/packages/shell-api/src/decorators.ts b/packages/shell-api/src/decorators.ts index 9242fedbc..e70c36a5a 100644 --- a/packages/shell-api/src/decorators.ts +++ b/packages/shell-api/src/decorators.ts @@ -334,6 +334,7 @@ export interface TypeSignature { returnType?: string | TypeSignature; attributes?: { [key: string]: TypeSignature }; isDirectShellCommand?: boolean; + acceptsRawInput?: boolean; shellCommandCompleter?: ShellCommandCompleter; } @@ -378,6 +379,7 @@ type ClassSignature = { deprecated: boolean; platforms: ReplPlatform[]; isDirectShellCommand: boolean; + acceptsRawInput?: boolean; shellCommandCompleter?: ShellCommandCompleter; } }; @@ -440,6 +442,7 @@ function shellApiClassGeneric(constructor: Function, hasHelp: boolean): void { method.deprecated = method.deprecated || false; method.platforms = method.platforms || ALL_PLATFORMS; method.isDirectShellCommand = method.isDirectShellCommand || false; + method.acceptsRawInput = method.acceptsRawInput || false; method.shellCommandCompleter = method.shellCommandCompleter || undefined; classSignature.attributes[propertyName] = { @@ -452,6 +455,7 @@ function shellApiClassGeneric(constructor: Function, hasHelp: boolean): void { deprecated: method.deprecated, platforms: method.platforms, isDirectShellCommand: method.isDirectShellCommand, + acceptsRawInput: method.acceptsRawInput, shellCommandCompleter: method.shellCommandCompleter }; @@ -504,6 +508,7 @@ function shellApiClassGeneric(constructor: Function, hasHelp: boolean): void { deprecated: method.deprecated, platforms: method.platforms, isDirectShellCommand: method.isDirectShellCommand, + acceptsRawInput: method.acceptsRawInput, shellCommandCompleter: method.shellCommandCompleter }; diff --git a/packages/shell-api/src/explainable-cursor.spec.ts b/packages/shell-api/src/explainable-cursor.spec.ts index f388d72de..64cede211 100644 --- a/packages/shell-api/src/explainable-cursor.spec.ts +++ b/packages/shell-api/src/explainable-cursor.spec.ts @@ -27,6 +27,7 @@ describe('ExplainableCursor', () => { apiVersions: ALL_API_VERSIONS, serverVersions: ALL_SERVER_VERSIONS, isDirectShellCommand: false, + acceptsRawInput: false, shellCommandCompleter: undefined }); }); diff --git a/packages/shell-api/src/explainable.spec.ts b/packages/shell-api/src/explainable.spec.ts index d24b6c35e..1a8da2e91 100644 --- a/packages/shell-api/src/explainable.spec.ts +++ b/packages/shell-api/src/explainable.spec.ts @@ -34,6 +34,7 @@ describe('Explainable', () => { apiVersions: [ 1, Infinity ], serverVersions: ALL_SERVER_VERSIONS, isDirectShellCommand: false, + acceptsRawInput: false, shellCommandCompleter: undefined }); }); diff --git a/packages/shell-api/src/field-level-encryption.spec.ts b/packages/shell-api/src/field-level-encryption.spec.ts index e237fe682..d3f9c62f9 100644 --- a/packages/shell-api/src/field-level-encryption.spec.ts +++ b/packages/shell-api/src/field-level-encryption.spec.ts @@ -101,6 +101,7 @@ describe('Field Level Encryption', () => { apiVersions: [ 1, Infinity ], serverVersions: ALL_SERVER_VERSIONS, isDirectShellCommand: false, + acceptsRawInput: false, shellCommandCompleter: undefined }); expect(signatures.ClientEncryption.attributes.encrypt).to.deep.equal({ @@ -113,6 +114,7 @@ describe('Field Level Encryption', () => { apiVersions: ALL_API_VERSIONS, serverVersions: ALL_SERVER_VERSIONS, isDirectShellCommand: false, + acceptsRawInput: false, shellCommandCompleter: undefined }); }); diff --git a/packages/shell-api/src/mongo.spec.ts b/packages/shell-api/src/mongo.spec.ts index 3b007063a..18b1b41ec 100644 --- a/packages/shell-api/src/mongo.spec.ts +++ b/packages/shell-api/src/mongo.spec.ts @@ -51,6 +51,7 @@ describe('Mongo', () => { apiVersions: [ 1, Infinity ], serverVersions: ALL_SERVER_VERSIONS, isDirectShellCommand: false, + acceptsRawInput: false, shellCommandCompleter: undefined }); }); diff --git a/packages/shell-api/src/mongo.ts b/packages/shell-api/src/mongo.ts index 55805c8ba..575bb6038 100644 --- a/packages/shell-api/src/mongo.ts +++ b/packages/shell-api/src/mongo.ts @@ -181,7 +181,8 @@ export default class Mongo extends ShellApiClass { // about the fact that the behavior differs from the legacy shell here. if (e?.name === 'MongoServerSelectionError' && parentProvider.getRawClient()?.options?.tls && - !this._uri.match(/\b(ssl|tls)=/)) { + !this._uri.match(/\b(ssl|tls)=/) + ) { e.message += ' (is ?tls=true missing from the connection string?)'; } throw e; diff --git a/packages/shell-api/src/plan-cache.spec.ts b/packages/shell-api/src/plan-cache.spec.ts index e5c8f4c98..aec5f4b54 100644 --- a/packages/shell-api/src/plan-cache.spec.ts +++ b/packages/shell-api/src/plan-cache.spec.ts @@ -29,6 +29,7 @@ describe('PlanCache', () => { topologies: ALL_TOPOLOGIES, serverVersions: ['4.4.0', ServerVersions.latest], isDirectShellCommand: false, + acceptsRawInput: false, shellCommandCompleter: undefined }); }); diff --git a/packages/shell-api/src/replica-set.spec.ts b/packages/shell-api/src/replica-set.spec.ts index 0a8af55de..d11ce1582 100644 --- a/packages/shell-api/src/replica-set.spec.ts +++ b/packages/shell-api/src/replica-set.spec.ts @@ -58,6 +58,7 @@ describe('ReplicaSet', () => { apiVersions: ALL_API_VERSIONS, serverVersions: ALL_SERVER_VERSIONS, isDirectShellCommand: false, + acceptsRawInput: false, shellCommandCompleter: undefined }); }); diff --git a/packages/shell-api/src/session.spec.ts b/packages/shell-api/src/session.spec.ts index 31fb5698b..4dc111103 100644 --- a/packages/shell-api/src/session.spec.ts +++ b/packages/shell-api/src/session.spec.ts @@ -42,6 +42,7 @@ describe('Session', () => { apiVersions: ALL_API_VERSIONS, serverVersions: ALL_SERVER_VERSIONS, isDirectShellCommand: false, + acceptsRawInput: false, shellCommandCompleter: undefined }); }); diff --git a/packages/shell-api/src/shard.spec.ts b/packages/shell-api/src/shard.spec.ts index 34403ee51..3eb113ea2 100644 --- a/packages/shell-api/src/shard.spec.ts +++ b/packages/shell-api/src/shard.spec.ts @@ -41,6 +41,7 @@ describe('Shard', () => { apiVersions: [ 0, 0 ], serverVersions: ALL_SERVER_VERSIONS, isDirectShellCommand: false, + acceptsRawInput: false, shellCommandCompleter: undefined }); }); diff --git a/packages/shell-api/src/shell-api.spec.ts b/packages/shell-api/src/shell-api.spec.ts index 0969d2be9..b54eae7d4 100644 --- a/packages/shell-api/src/shell-api.spec.ts +++ b/packages/shell-api/src/shell-api.spec.ts @@ -43,6 +43,7 @@ describe('ShellApi', () => { apiVersions: ALL_API_VERSIONS, serverVersions: ALL_SERVER_VERSIONS, isDirectShellCommand: true, + acceptsRawInput: false, shellCommandCompleter: signatures.ShellApi.attributes.use.shellCommandCompleter }); expect(signatures.ShellApi.attributes.show).to.deep.equal({ @@ -55,6 +56,7 @@ describe('ShellApi', () => { apiVersions: ALL_API_VERSIONS, serverVersions: ALL_SERVER_VERSIONS, isDirectShellCommand: true, + acceptsRawInput: false, shellCommandCompleter: signatures.ShellApi.attributes.show.shellCommandCompleter }); expect(signatures.ShellApi.attributes.exit).to.deep.equal({ @@ -67,6 +69,7 @@ describe('ShellApi', () => { apiVersions: ALL_API_VERSIONS, serverVersions: ALL_SERVER_VERSIONS, isDirectShellCommand: true, + acceptsRawInput: false, shellCommandCompleter: undefined }); expect(signatures.ShellApi.attributes.it).to.deep.equal({ @@ -79,6 +82,7 @@ describe('ShellApi', () => { apiVersions: ALL_API_VERSIONS, serverVersions: ALL_SERVER_VERSIONS, isDirectShellCommand: true, + acceptsRawInput: false, shellCommandCompleter: undefined }); expect(signatures.ShellApi.attributes.print).to.deep.equal({ @@ -91,6 +95,7 @@ describe('ShellApi', () => { apiVersions: ALL_API_VERSIONS, serverVersions: ALL_SERVER_VERSIONS, isDirectShellCommand: false, + acceptsRawInput: false, shellCommandCompleter: undefined }); expect(signatures.ShellApi.attributes.printjson).to.deep.equal({ @@ -103,6 +108,7 @@ describe('ShellApi', () => { apiVersions: ALL_API_VERSIONS, serverVersions: ALL_SERVER_VERSIONS, isDirectShellCommand: false, + acceptsRawInput: false, shellCommandCompleter: undefined }); expect(signatures.ShellApi.attributes.sleep).to.deep.equal({ @@ -115,6 +121,7 @@ describe('ShellApi', () => { apiVersions: ALL_API_VERSIONS, serverVersions: ALL_SERVER_VERSIONS, isDirectShellCommand: false, + acceptsRawInput: false, shellCommandCompleter: undefined }); expect(signatures.ShellApi.attributes.cls).to.deep.equal({ @@ -127,6 +134,7 @@ describe('ShellApi', () => { apiVersions: ALL_API_VERSIONS, serverVersions: ALL_SERVER_VERSIONS, isDirectShellCommand: true, + acceptsRawInput: false, shellCommandCompleter: undefined }); expect(signatures.ShellApi.attributes.Mongo).to.deep.equal({ @@ -139,6 +147,7 @@ describe('ShellApi', () => { apiVersions: ALL_API_VERSIONS, serverVersions: ALL_SERVER_VERSIONS, isDirectShellCommand: false, + acceptsRawInput: false, shellCommandCompleter: undefined }); expect(signatures.ShellApi.attributes.connect).to.deep.equal({ @@ -151,6 +160,7 @@ describe('ShellApi', () => { apiVersions: ALL_API_VERSIONS, serverVersions: ALL_SERVER_VERSIONS, isDirectShellCommand: false, + acceptsRawInput: false, shellCommandCompleter: undefined }); }); @@ -730,8 +740,16 @@ describe('ShellApi', () => { it('will work with defaults', async() => { expect(await config.get('displayBatchSize')).to.equal(20); - expect((await toShellResult(config)).printable).to.deep.equal( - new Map([['displayBatchSize', 20], ['maxTimeMS', null], ['enableTelemetry', false]] as any)); + + const shellResult = await toShellResult(config); + const expectedResult = new Map([ + ['displayBatchSize', 20], + ['maxTimeMS', null], + ['enableTelemetry', false], + ['editor', null] + ] as any); + + expect(shellResult.printable).to.deep.equal(expectedResult); }); it('rejects setting all config keys', async() => { diff --git a/packages/shell-api/src/shell-instance-state.ts b/packages/shell-api/src/shell-instance-state.ts index 461c2a062..34313c1fd 100644 --- a/packages/shell-api/src/shell-instance-state.ts +++ b/packages/shell-api/src/shell-instance-state.ts @@ -346,7 +346,10 @@ export default class ShellInstanceState { const collectionNames = await this.currentDb._getCollectionNamesForCompletion(); return collectionNames.filter((name) => name.startsWith(collName)); } catch (err) { - if (err.code === ShellApiErrors.NotConnected || err.codeName === 'Unauthorized') { + if ( + err.code === ShellApiErrors.NotConnected || + err.codeName === 'Unauthorized' + ) { return []; } throw err; @@ -357,7 +360,10 @@ export default class ShellInstanceState { const dbNames = await this.currentDb._mongo._getDatabaseNamesForCompletion(); return dbNames.filter((name) => name.startsWith(dbName)); } catch (err) { - if (err.code === ShellApiErrors.NotConnected || err.codeName === 'Unauthorized') { + if ( + err.code === ShellApiErrors.NotConnected || + err.codeName === 'Unauthorized' + ) { return []; } throw err; diff --git a/packages/shell-evaluator/src/shell-evaluator.spec.ts b/packages/shell-evaluator/src/shell-evaluator.spec.ts index c11bf837c..a7efff30a 100644 --- a/packages/shell-evaluator/src/shell-evaluator.spec.ts +++ b/packages/shell-evaluator/src/shell-evaluator.spec.ts @@ -13,6 +13,7 @@ describe('ShellEvaluator', () => { let showSpy: any; let itSpy: any; let exitSpy: any; + let editSpy: any; let useSpy: any; const dontCallEval = () => { throw new Error('unreachable'); }; @@ -21,12 +22,14 @@ describe('ShellEvaluator', () => { showSpy = sinon.spy(); itSpy = sinon.spy(); exitSpy = sinon.spy(); + editSpy = sinon.spy(); internalStateMock = { messageBus: busMock, - shellApi: { use: useSpy, show: showSpy, it: itSpy, exit: exitSpy, quit: exitSpy } + shellApi: { use: useSpy, show: showSpy, it: itSpy, exit: exitSpy, quit: exitSpy, edit: editSpy } } as any; - for (const name of ['use', 'show', 'it', 'exit', 'quit']) { + for (const name of ['use', 'show', 'it', 'exit', 'quit', 'edit']) { internalStateMock.shellApi[name].isDirectShellCommand = true; + internalStateMock.shellApi[name].acceptsRawInput = (name === 'edit') ? true : false; } busMock = new EventEmitter(); @@ -84,6 +87,7 @@ describe('ShellEvaluator', () => { expect(originalEval.firstCall.args[1]).to.deep.equal({}); expect(originalEval.firstCall.args[2]).to.equal(''); }); + it('allows specifying custom result handlers', async() => { const shellEvaluator = new ShellEvaluator(internalStateMock, JSON.stringify); const originalEval = sinon.stub(); @@ -91,5 +95,10 @@ describe('ShellEvaluator', () => { const result = await shellEvaluator.customEval(originalEval, 'doSomething();', {}, ''); expect(result).to.equal('{"a":1}'); }); + + it('edit accepts raw input', async() => { + await shellEvaluator.customEval(dontCallEval, 'edit "1 2"', {}, ''); + expect(editSpy).to.have.been.calledWith('edit "1 2"'); + }); }); }); diff --git a/packages/shell-evaluator/src/shell-evaluator.ts b/packages/shell-evaluator/src/shell-evaluator.ts index 40a188d0a..5dfd2f0a4 100644 --- a/packages/shell-evaluator/src/shell-evaluator.ts +++ b/packages/shell-evaluator/src/shell-evaluator.ts @@ -32,10 +32,20 @@ class ShellEvaluator { * @param {Context} context - the execution context. * @param {String} filename */ + // eslint-disable-next-line complexity private async innerEval(originalEval: EvaluationFunction, input: string, context: object, filename: string): Promise { const { shellApi } = this.instanceState; const argv = input.trim().replace(/;$/, '').split(/\s+/g); const cmd = argv.shift() as keyof typeof shellApi; + + if ( + shellApi[cmd]?.isDirectShellCommand && + shellApi[cmd]?.acceptsRawInput && + !(argv[0] ?? '').startsWith('(') + ) { + return shellApi[cmd](input); + } + if (shellApi[cmd]?.isDirectShellCommand && !(argv[0] ?? '').startsWith('(')) { return shellApi[cmd](...argv); } diff --git a/packages/snippet-manager/src/snippet-manager.ts b/packages/snippet-manager/src/snippet-manager.ts index 5f47fbfcc..da34a6732 100644 --- a/packages/snippet-manager/src/snippet-manager.ts +++ b/packages/snippet-manager/src/snippet-manager.ts @@ -140,6 +140,10 @@ export class SnippetManager implements ShellPlugin { this.messageBus.emit('mongosh-snippets:loaded', { installdir }); } + static create(options: SnippetOptions): SnippetManager { + return new SnippetManager(options); + } + get messageBus(): MongoshBus { return this._instanceState.messageBus; } diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index 2dff8a306..abf057b4d 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -161,6 +161,27 @@ export interface SpMissingOptionalDependencyEvent { error: Error; } +export interface EditorRunEditCommandEvent { + tmpDoc: string; + editor: string; + code: string; +} + +export interface EditorRunEditCommandFailedEvent { + action: string; + error: string; +} + +export interface EditorReadVscodeExtensionsDoneEvent { + vscodeDir: string; + hasMongodbExtension: boolean; +} + +export interface EditorReadVscodeExtensionsFailedEvent { + action: string; + error: string; +} + export interface MongoshBusEventsMap { /** * Signals a connection to a MongoDB instance has been established @@ -333,6 +354,13 @@ export interface MongoshBusEventsMap { 'mongosh-sp:reset-connection-options': () => void; /** Signals that an optional dependency of the mongodb package is missing. */ 'mongosh-sp:missing-optional-dependency': (ev: SpMissingOptionalDependencyEvent) => void; + + /** Signals that open external editor command was called. */ + 'mongosh-editor:run-edit-command': (ev: EditorRunEditCommandEvent) => void; + /** Signals that reading vscode extensions from disc succeeded. */ + 'mongosh-editor:read-vscode-extensions-done': (ev: EditorReadVscodeExtensionsDoneEvent) => void; + /** Signals that reading vscode extensions from disc failed. */ + 'mongosh-editor:read-vscode-extensions-failed': (ev: EditorReadVscodeExtensionsFailedEvent) => void; } export interface MongoshBus { @@ -346,10 +374,11 @@ export class ShellUserConfig { displayBatchSize = 20; maxTimeMS: number | null = null; enableTelemetry = false; + editor: string | null = null; } export class ShellUserConfigValidator { - // eslint-disable-next-line @typescript-eslint/require-await + // eslint-disable-next-line complexity, @typescript-eslint/require-await static async validate(key: K, value: ShellUserConfig[K]): Promise { switch (key) { case 'displayBatchSize': @@ -367,6 +396,11 @@ export class ShellUserConfigValidator { return `${key} must be a boolean`; } return null; + case 'editor': + if (typeof value !== 'string' && value !== null) { + return `${key} must be a string or null`; + } + return null; default: return `${key} is not a known config option`; }