diff --git a/config/webpack.base.config.js b/config/webpack.base.config.js index 90058c95f..1c735837d 100644 --- a/config/webpack.base.config.js +++ b/config/webpack.base.config.js @@ -27,6 +27,21 @@ module.exports = { externals: { "node:crypto": "commonjs2 crypto", + // node-fetch https://github.com/node-fetch/node-fetch/blob/8b3320d2a7c07bce4afc6b2bf6c3bbddda85b01f/src/index.js#L9 + "node:buffer": "commonjs2 buffer", + "node:http": "commonjs2 http", + "node:https": "commonjs2 https", + "node:stream": "commonjs2 stream", + "node:zlib": "commonjs2 zlib", + "node:url": "commonjs2 url", + "node:util": "commonjs2 util", + "node:events": "commonjs2 events", + "node:net": "commonjs2 net", + // https://github.com/node-fetch/node-fetch/blob/8b3320d2a7c07bce4afc6b2bf6c3bbddda85b01f/test/main.js#L2 + "node:dns": "commonjs2 dns", + "node:fs": "commonjs2 fs", + "node:path": "commonjs2 path", + "node:vm": "commonjs2 vm", electron: "commonjs2 electron" // optional dep of the OIDC plugin }, diff --git a/configs/tsconfig-mongosh/tsconfig.common.json b/configs/tsconfig-mongosh/tsconfig.common.json index 40a63610c..ecca33737 100644 --- a/configs/tsconfig-mongosh/tsconfig.common.json +++ b/configs/tsconfig-mongosh/tsconfig.common.json @@ -2,6 +2,7 @@ "compilerOptions": { "esModuleInterop": true, "downlevelIteration": true, + "skipLibCheck": true, "sourceMap": true, "strict": true, diff --git a/package-lock.json b/package-lock.json index 62c965355..203676f13 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "packages/build", "packages/errors", "packages/history", + "packages/import-node-fetch", "packages/java-shell", "packages/js-multiline-to-singleline", "packages/types", @@ -5980,20 +5981,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@lerna/create/node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "optional": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/@lerna/create/node_modules/get-stream": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.0.tgz", @@ -7580,6 +7567,10 @@ "resolved": "packages/i18n", "link": true }, + "node_modules/@mongosh/import-node-fetch": { + "resolved": "packages/import-node-fetch", + "link": true + }, "node_modules/@mongosh/java-shell": { "resolved": "packages/java-shell", "link": true @@ -8000,21 +7991,6 @@ "node": ">=8" } }, - "node_modules/@nrwl/devkit/node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "optional": true, - "peer": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/@nrwl/devkit/node_modules/glob": { "version": "7.1.4", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", @@ -8331,20 +8307,6 @@ "node": ">=8" } }, - "node_modules/@nrwl/tao/node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "optional": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/@nrwl/tao/node_modules/glob": { "version": "7.1.4", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", @@ -10162,13 +10124,13 @@ "integrity": "sha512-q4jlIR71hUpWTnGhXWcakgkZeHa3CCjcQcnuzU8M891BAWA2jHiziiWEPEkdS5pFsz7H9HJiy8BrK7tBRNrY7A==" }, "node_modules/@types/node-fetch": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.4.tgz", - "integrity": "sha512-1ZX9fcN4Rvkvgv4E6PAY5WXUFWFcRWxZa3EW83UjycOB9ljJCedb2CupIP4RZMEwF/M3eTcCihbBRgwtGbg5Rg==", + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.11.tgz", + "integrity": "sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==", "dev": true, "dependencies": { "@types/node": "*", - "form-data": "^3.0.0" + "form-data": "^4.0.0" } }, "node_modules/@types/normalize-package-data": { @@ -15858,6 +15820,28 @@ "pend": "~1.2.0" } }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, "node_modules/figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", @@ -16164,10 +16148,10 @@ } }, "node_modules/form-data": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", - "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", - "dev": true, + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "devOptional": true, "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -16185,6 +16169,17 @@ "node": ">=0.4.x" } }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -20069,20 +20064,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/lerna/node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "optional": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/lerna/node_modules/get-stream": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.0.tgz", @@ -23090,10 +23071,28 @@ "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==" }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "engines": { + "node": ">=10.5.0" + } + }, "node_modules/node-fetch": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz", - "integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", "dependencies": { "whatwg-url": "^5.0.0" }, @@ -29483,6 +29482,14 @@ "defaults": "^1.0.3" } }, + "node_modules/web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "engines": { + "node": ">= 8" + } + }, "node_modules/webidl-conversions": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", @@ -30907,6 +30914,7 @@ "@mongosh/errors": "0.0.0-dev.0", "@mongosh/history": "0.0.0-dev.0", "@mongosh/i18n": "0.0.0-dev.0", + "@mongosh/import-node-fetch": "0.0.0-dev.0", "@mongosh/js-multiline-to-singleline": "0.0.0-dev.0", "@mongosh/logging": "0.0.0-dev.0", "@mongosh/service-provider-core": "0.0.0-dev.0", @@ -30950,7 +30958,6 @@ "eslint": "^7.25.0", "mongodb": "^6.3.0", "mongodb-crypt-library-dummy": "^1.0.2", - "node-fetch": "^2.6.1", "prettier": "^2.8.8", "webpack-merge": "^5.8.0" }, @@ -31011,7 +31018,7 @@ "lodash": "^4.17.21", "moment": "^2.29.1", "mongodb": "^6.3.0", - "node-fetch": "^2.6.1", + "node-fetch": "^3.3.2", "prettier": "^2.8.8", "rimraf": "^3.0.2" }, @@ -31019,6 +31026,33 @@ "node": ">=16.15.0" } }, + "packages/e2e-tests/node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "dev": true, + "engines": { + "node": ">= 12" + } + }, + "packages/e2e-tests/node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "dev": true, + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, "packages/editor": { "name": "@mongosh/editor", "version": "0.0.0-dev.0", @@ -31106,6 +31140,68 @@ "node": ">=14.15.1" } }, + "packages/import-esm": { + "name": "@mongosh/import-esm", + "version": "0.0.0-dev.0", + "extraneous": true, + "license": "Apache-2.0", + "devDependencies": { + "@mongodb-js/eslint-config-mongosh": "^1.0.0", + "@mongodb-js/prettier-config-devtools": "^1.0.1", + "@mongodb-js/tsconfig-mongosh": "^1.0.0", + "depcheck": "^1.4.3", + "eslint": "^7.25.0", + "node-fetch": "^3.3.2", + "prettier": "^2.8.8" + }, + "engines": { + "node": ">=14.15.1" + } + }, + "packages/import-node-fetch": { + "name": "@mongosh/import-node-fetch", + "version": "0.0.0-dev.0", + "license": "Apache-2.0", + "dependencies": { + "node-fetch": "^3.3.2" + }, + "devDependencies": { + "@mongodb-js/eslint-config-mongosh": "^1.0.0", + "@mongodb-js/prettier-config-devtools": "^1.0.1", + "@mongodb-js/tsconfig-mongosh": "^1.0.0", + "depcheck": "^1.4.3", + "eslint": "^7.25.0", + "prettier": "^2.8.8" + }, + "engines": { + "node": ">=14.15.1" + } + }, + "packages/import-node-fetch/node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "engines": { + "node": ">= 12" + } + }, + "packages/import-node-fetch/node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, "packages/java-shell": { "name": "@mongosh/java-shell", "version": "0.0.0-dev.0", @@ -31403,13 +31499,13 @@ "license": "Apache-2.0", "dependencies": { "@mongosh/errors": "0.0.0-dev.0", + "@mongosh/import-node-fetch": "0.0.0-dev.0", "@mongosh/shell-api": "0.0.0-dev.0", "@mongosh/types": "0.0.0-dev.0", "bson": "^6.2.0", "cross-spawn": "^7.0.3", "escape-string-regexp": "^4.0.0", "joi": "^17.4.0", - "node-fetch": "^2.6.1", "tar": "^6.1.15" }, "devDependencies": { @@ -31417,7 +31513,6 @@ "@mongodb-js/prettier-config-devtools": "^1.0.1", "@mongodb-js/tsconfig-mongosh": "^1.0.0", "@types/cross-spawn": "^6.0.2", - "@types/node-fetch": "^2.6.4", "@types/tar": "^4.0.4", "depcheck": "^1.4.3", "eslint": "^7.25.0", @@ -36274,17 +36369,6 @@ } } }, - "form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "optional": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - }, "get-stream": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.0.tgz", @@ -37758,6 +37842,7 @@ "@mongosh/errors": "0.0.0-dev.0", "@mongosh/history": "0.0.0-dev.0", "@mongosh/i18n": "0.0.0-dev.0", + "@mongosh/import-node-fetch": "0.0.0-dev.0", "@mongosh/js-multiline-to-singleline": "0.0.0-dev.0", "@mongosh/logging": "0.0.0-dev.0", "@mongosh/service-provider-core": "0.0.0-dev.0", @@ -37789,7 +37874,6 @@ "mongodb-crypt-library-dummy": "^1.0.2", "mongodb-crypt-library-version": "^1.0.3", "mongodb-log-writer": "^1.4.0", - "node-fetch": "^2.6.1", "numeral": "^2.0.6", "prettier": "^2.8.8", "pretty-repl": "^4.0.0", @@ -37846,10 +37930,29 @@ "lodash": "^4.17.21", "moment": "^2.29.1", "mongodb": "^6.3.0", - "node-fetch": "^2.6.1", + "node-fetch": "^3.3.2", "prettier": "^2.8.8", "rimraf": "^3.0.2", "strip-ansi": "^6.0.0" + }, + "dependencies": { + "data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "dev": true + }, + "node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "dev": true, + "requires": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + } + } } }, "@mongosh/editor": { @@ -37911,6 +38014,35 @@ "prettier": "^2.8.8" } }, + "@mongosh/import-node-fetch": { + "version": "file:packages/import-node-fetch", + "requires": { + "@mongodb-js/eslint-config-mongosh": "^1.0.0", + "@mongodb-js/prettier-config-devtools": "^1.0.1", + "@mongodb-js/tsconfig-mongosh": "^1.0.0", + "depcheck": "^1.4.3", + "eslint": "^7.25.0", + "node-fetch": "^3.3.2", + "prettier": "^2.8.8" + }, + "dependencies": { + "data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==" + }, + "node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "requires": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + } + } + } + }, "@mongosh/java-shell": { "version": "file:packages/java-shell", "requires": { @@ -38109,10 +38241,10 @@ "@mongodb-js/prettier-config-devtools": "^1.0.1", "@mongodb-js/tsconfig-mongosh": "^1.0.0", "@mongosh/errors": "0.0.0-dev.0", + "@mongosh/import-node-fetch": "0.0.0-dev.0", "@mongosh/shell-api": "0.0.0-dev.0", "@mongosh/types": "0.0.0-dev.0", "@types/cross-spawn": "^6.0.2", - "@types/node-fetch": "^2.6.4", "@types/tar": "^4.0.4", "bson": "^6.2.0", "cross-spawn": "^7.0.3", @@ -38121,7 +38253,6 @@ "eslint": "^7.25.0", "joi": "^17.4.0", "nanobus": "^4.5.0", - "node-fetch": "^2.6.1", "prettier": "^2.8.8", "tar": "^6.1.15" } @@ -38448,18 +38579,6 @@ "micromatch": "^4.0.4" } }, - "form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "optional": true, - "peer": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - }, "glob": { "version": "7.1.4", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", @@ -38703,17 +38822,6 @@ "micromatch": "^4.0.4" } }, - "form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "optional": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - }, "glob": { "version": "7.1.4", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", @@ -40180,13 +40288,13 @@ "integrity": "sha512-q4jlIR71hUpWTnGhXWcakgkZeHa3CCjcQcnuzU8M891BAWA2jHiziiWEPEkdS5pFsz7H9HJiy8BrK7tBRNrY7A==" }, "@types/node-fetch": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.4.tgz", - "integrity": "sha512-1ZX9fcN4Rvkvgv4E6PAY5WXUFWFcRWxZa3EW83UjycOB9ljJCedb2CupIP4RZMEwF/M3eTcCihbBRgwtGbg5Rg==", + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.11.tgz", + "integrity": "sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==", "dev": true, "requires": { "@types/node": "*", - "form-data": "^3.0.0" + "form-data": "^4.0.0" } }, "@types/normalize-package-data": { @@ -44662,6 +44770,15 @@ "pend": "~1.2.0" } }, + "fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "requires": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + } + }, "figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", @@ -44894,10 +45011,10 @@ "dev": true }, "form-data": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", - "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", - "dev": true, + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "devOptional": true, "requires": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -44909,6 +45026,14 @@ "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz", "integrity": "sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==" }, + "formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "requires": { + "fetch-blob": "^3.1.2" + } + }, "forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -47871,17 +47996,6 @@ } } }, - "form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "optional": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - }, "get-stream": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.0.tgz", @@ -50211,10 +50325,15 @@ "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==" }, + "node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==" + }, "node-fetch": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz", - "integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", "requires": { "whatwg-url": "^5.0.0" }, @@ -55121,6 +55240,11 @@ "defaults": "^1.0.3" } }, + "web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==" + }, "webidl-conversions": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", diff --git a/package.json b/package.json index d159f8666..13064d4d2 100644 --- a/package.json +++ b/package.json @@ -133,6 +133,7 @@ "packages/build", "packages/errors", "packages/history", + "packages/import-node-fetch", "packages/java-shell", "packages/js-multiline-to-singleline", "packages/types", diff --git a/packages/build/src/barque.ts b/packages/build/src/barque.ts index 0359620f9..6dd1c6eca 100644 --- a/packages/build/src/barque.ts +++ b/packages/build/src/barque.ts @@ -416,7 +416,7 @@ export class Barque { */ async extractLatestCurator(dest: string): Promise { const response = await fetch(LATEST_CURATOR); - if (response.ok) { + if (response.ok && response.body) { return pipeline(response.body, zlib.createGunzip(), tar.extract(dest)); } } diff --git a/packages/build/src/download-center/config.ts b/packages/build/src/download-center/config.ts index 1a2c54a63..16fd6250a 100644 --- a/packages/build/src/download-center/config.ts +++ b/packages/build/src/download-center/config.ts @@ -290,7 +290,7 @@ async function getHashes( let is4xxError = false; try { const response = await fetch(url); - if (!response.ok) { + if (!response.ok || !response.body) { is4xxError ||= response.status >= 400 && response.status < 500; throw new Error(`unexpected response ${response.statusText} for ${url}`); } diff --git a/packages/build/src/evergreen/rest-api.ts b/packages/build/src/evergreen/rest-api.ts index b564971fb..803526218 100644 --- a/packages/build/src/evergreen/rest-api.ts +++ b/packages/build/src/evergreen/rest-api.ts @@ -95,7 +95,7 @@ export class EvergreenApi { } - ${await response.text()}` ); } - return await response.json(); + return (await response.json()) as T; } private getApiHeaders(): Record { diff --git a/packages/build/src/packaging/download-manpage.ts b/packages/build/src/packaging/download-manpage.ts index ff967d48b..0fa00b63a 100644 --- a/packages/build/src/packaging/download-manpage.ts +++ b/packages/build/src/packaging/download-manpage.ts @@ -13,6 +13,9 @@ export async function downloadManpage( ) { await fs.mkdir(destination, { recursive: true }); const response = await fetch(url); + if (!response.ok || !response.body) { + throw new Error(`Unexpected response while fetching ${url}`); + } await promisify(pipeline)(response.body, tar.x({ cwd: destination })); await promisify(pipeline)( createReadStream(join(destination, basename(name, '.gz'))), diff --git a/packages/cli-repl/package.json b/packages/cli-repl/package.json index 5ca8ae5de..df67d72b9 100644 --- a/packages/cli-repl/package.json +++ b/packages/cli-repl/package.json @@ -64,6 +64,7 @@ "@mongosh/errors": "0.0.0-dev.0", "@mongosh/history": "0.0.0-dev.0", "@mongosh/i18n": "0.0.0-dev.0", + "@mongosh/import-node-fetch": "0.0.0-dev.0", "@mongosh/js-multiline-to-singleline": "0.0.0-dev.0", "@mongosh/logging": "0.0.0-dev.0", "@mongosh/service-provider-core": "0.0.0-dev.0", @@ -104,7 +105,6 @@ "depcheck": "^1.4.3", "eslint": "^7.25.0", "mongodb-crypt-library-dummy": "^1.0.2", - "node-fetch": "^2.6.1", "prettier": "^2.8.8", "webpack-merge": "^5.8.0" }, diff --git a/packages/cli-repl/src/cli-repl.spec.ts b/packages/cli-repl/src/cli-repl.spec.ts index c36e244ee..af2235202 100644 --- a/packages/cli-repl/src/cli-repl.spec.ts +++ b/packages/cli-repl/src/cli-repl.spec.ts @@ -477,7 +477,7 @@ describe('CliRepl', function () { expect(e.name).to.equal('MongoshWarning'); expect((e as any).code).to.equal(CliReplErrors.NodeVersionMismatch); } finally { - process.version = process.versions.node; + process.version = `v${process.versions.node}`; process.env.MONGOSH_SKIP_NODE_VERSION_CHECK = origVersionCheckEnvVar || ''; } @@ -1215,7 +1215,10 @@ describe('CliRepl', function () { it('does not emit warnings when connecting multiple times', async function () { await cliRepl.start(await testServer.connectionString(), {}); let warnings = 0; - const warningListener = () => warnings++; + const warningListener = (warning) => { + console.log('Unexpected warning', warning); + warnings++; + }; process.on('warning', warningListener); try { input.write( diff --git a/packages/cli-repl/src/update-notification-manager.ts b/packages/cli-repl/src/update-notification-manager.ts index 43531cdfb..762b8c3a4 100644 --- a/packages/cli-repl/src/update-notification-manager.ts +++ b/packages/cli-repl/src/update-notification-manager.ts @@ -1,10 +1,15 @@ import semver from 'semver'; import { promises as fs } from 'fs'; -import type { RequestInfo, RequestInit, Response } from 'node-fetch'; +import importNodeFetch from '@mongosh/import-node-fetch'; +import type { + RequestInfo, + RequestInit, + Response, +} from '@mongosh/import-node-fetch'; // 'http' is not supported in startup snapshots yet. const fetch = async (url: RequestInfo, init?: RequestInit): Promise => - await (await import('node-fetch')).default(url, init); + await (await importNodeFetch()).default(url, init); interface MongoshUpdateLocalFileContents { lastChecked?: number; @@ -97,7 +102,7 @@ export class UpdateNotificationManager { if (response.status === 304 /* Not Modified, i.e. ETag matched */) { response.body - .on('error', () => { + ?.once('error', () => { /* ignore response content and errors */ }) .resume(); @@ -106,14 +111,14 @@ export class UpdateNotificationManager { return; } - if (!response.ok) { + if (!response.ok || !response.body) { throw new Error( `Unexpected status code fetching ${updateURL}: ${response.status} ${response.statusText}` ); } - const jsonContents = await response.json(); - this.latestKnownMongoshVersion = (jsonContents?.versions as any[]) + const jsonContents = (await response.json()) as { versions?: any[] }; + this.latestKnownMongoshVersion = jsonContents?.versions ?.map((v: any) => v.version as string) ?.filter((v) => !semver.prerelease(v)) ?.sort(semver.rcompare)?.[0]; diff --git a/packages/e2e-tests/.depcheckrc b/packages/e2e-tests/.depcheckrc index 5922db46b..4468341a3 100644 --- a/packages/e2e-tests/.depcheckrc +++ b/packages/e2e-tests/.depcheckrc @@ -14,3 +14,10 @@ ignores: - eslint-config-mongodb-js ignore-patterns: - .eslintrc.js +parsers: + '**/*.mjs': + - 'es6' + '**/*.js': + - 'es6' + '**/*.ts': + - 'typescript' diff --git a/packages/e2e-tests/.eslintrc.js b/packages/e2e-tests/.eslintrc.js index 97657eb3c..37865c5ce 100644 --- a/packages/e2e-tests/.eslintrc.js +++ b/packages/e2e-tests/.eslintrc.js @@ -6,10 +6,12 @@ module.exports = { parserOptions: { tsconfigRootDir: fixCygwinPath(__dirname), project: ['./tsconfig-lint.json'], + sourceType: 'module', + ecmaVersion: 'latest', }, overrides: [ { - files: ['**/*.js', '**/*.ts'], + files: ['**/*.js', '**/*.mjs', '**/*.ts'], rules: { 'no-console': 0, }, diff --git a/packages/e2e-tests/package.json b/packages/e2e-tests/package.json index 7c0771633..20129a2aa 100644 --- a/packages/e2e-tests/package.json +++ b/packages/e2e-tests/package.json @@ -45,7 +45,7 @@ "lodash": "^4.17.21", "moment": "^2.29.1", "mongodb": "^6.3.0", - "node-fetch": "^2.6.1", + "node-fetch": "^3.3.2", "prettier": "^2.8.8", "rimraf": "^3.0.2" } diff --git a/packages/e2e-tests/test/e2e-oidc.spec.ts b/packages/e2e-tests/test/e2e-oidc.spec.ts index 44eac3b47..eb4bb93a2 100644 --- a/packages/e2e-tests/test/e2e-oidc.spec.ts +++ b/packages/e2e-tests/test/e2e-oidc.spec.ts @@ -23,7 +23,7 @@ describe('OIDC auth e2e', function () { const fetchBrowserFixture = `"${path.resolve( __dirname, 'fixtures', - 'curl.js' + 'curl.mjs' )}"`; skipIfEnvServerVersion('< 7.0'); diff --git a/packages/e2e-tests/test/fixtures/curl.js b/packages/e2e-tests/test/fixtures/curl.mjs similarity index 77% rename from packages/e2e-tests/test/fixtures/curl.js rename to packages/e2e-tests/test/fixtures/curl.mjs index ccb3a14c3..86fe29253 100755 --- a/packages/e2e-tests/test/fixtures/curl.js +++ b/packages/e2e-tests/test/fixtures/curl.mjs @@ -1,8 +1,8 @@ #!/usr/bin/env node 'use strict'; -const fetch = require('node-fetch'); +import fetch from 'node-fetch'; // fetch() an URL and ignore the response body -(async function() { +(async function () { (await fetch(process.argv[2])).body?.resume(); })().catch(err => { process.nextTick(() => { throw err; }); }); diff --git a/packages/import-node-fetch/.depcheckrc b/packages/import-node-fetch/.depcheckrc new file mode 100644 index 000000000..fe4bc51f9 --- /dev/null +++ b/packages/import-node-fetch/.depcheckrc @@ -0,0 +1,11 @@ +ignores: + - '@mongodb-js/eslint-config-mongosh' + - '@mongodb-js/tsconfig-mongosh' + - '@mongodb-js/prettier-config-devtools' + - '@typescript-eslint/parser' + - '@typescript-eslint/eslint-plugin' + - chai + - eslint-plugin-mocha + - eslint-config-mongodb-js +ignore-patterns: + - .eslintrc.js \ No newline at end of file diff --git a/packages/import-node-fetch/.eslintignore b/packages/import-node-fetch/.eslintignore new file mode 100644 index 000000000..491fc3597 --- /dev/null +++ b/packages/import-node-fetch/.eslintignore @@ -0,0 +1,2 @@ +node_modules +lib diff --git a/packages/import-node-fetch/.eslintrc.js b/packages/import-node-fetch/.eslintrc.js new file mode 100644 index 000000000..ffb213e29 --- /dev/null +++ b/packages/import-node-fetch/.eslintrc.js @@ -0,0 +1,10 @@ +const { fixCygwinPath } = require('@mongodb-js/eslint-config-mongosh/utils'); + +module.exports = { + root: true, + extends: ['@mongodb-js/eslint-config-mongosh'], + parserOptions: { + tsconfigRootDir: fixCygwinPath(__dirname), + project: ['./tsconfig-lint.json'], + }, +}; diff --git a/packages/import-node-fetch/.gitignore b/packages/import-node-fetch/.gitignore new file mode 100644 index 000000000..c3af85790 --- /dev/null +++ b/packages/import-node-fetch/.gitignore @@ -0,0 +1 @@ +lib/ diff --git a/packages/import-node-fetch/.npmignore b/packages/import-node-fetch/.npmignore new file mode 100644 index 000000000..ef55c3b8a --- /dev/null +++ b/packages/import-node-fetch/.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/import-node-fetch/.prettierignore b/packages/import-node-fetch/.prettierignore new file mode 100644 index 000000000..3cdee98d0 --- /dev/null +++ b/packages/import-node-fetch/.prettierignore @@ -0,0 +1,6 @@ +**/lib +**/dist +**/node_modules +**/test/fixtures +**/*.nocov* +**/*.wxs diff --git a/packages/import-node-fetch/.prettierrc.json b/packages/import-node-fetch/.prettierrc.json new file mode 100644 index 000000000..dfae21d04 --- /dev/null +++ b/packages/import-node-fetch/.prettierrc.json @@ -0,0 +1 @@ +"@mongodb-js/prettier-config-devtools" diff --git a/packages/import-node-fetch/LICENSE b/packages/import-node-fetch/LICENSE new file mode 100644 index 000000000..ad410e113 --- /dev/null +++ b/packages/import-node-fetch/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/import-node-fetch/README.md b/packages/import-node-fetch/README.md new file mode 100644 index 000000000..8569e0068 --- /dev/null +++ b/packages/import-node-fetch/README.md @@ -0,0 +1,9 @@ +# `@mongosh/import-node-fetch` + +Package for [MongoDB Shell](https://github.com/mongodb-js/mongosh). + +### Installation + +```shell +npm install -S @mongosh/import-node-fetch +``` diff --git a/packages/import-node-fetch/package.json b/packages/import-node-fetch/package.json new file mode 100644 index 000000000..9bcdc8215 --- /dev/null +++ b/packages/import-node-fetch/package.json @@ -0,0 +1,48 @@ +{ + "name": "@mongosh/import-node-fetch", + "version": "0.0.0-dev.0", + "description": "Wrapper for ESM module imports", + "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", + "test-coverage": "nyc --no-clean --cwd ../.. --reporter=none npm run test", + "test-ci-coverage": "nyc --no-clean --cwd ../.. --reporter=none npm run test-ci", + "eslint": "eslint", + "lint": "npm run eslint . && npm run prettier -- --check .", + "check": "npm run lint && npm run depcheck", + "depcheck": "depcheck", + "compile": "tsc -p tsconfig.json", + "prepublish": "npm run compile", + "prettier": "prettier", + "reformat": "npm run prettier -- --write . && npm run eslint --fix" + }, + "license": "Apache-2.0", + "publishConfig": { + "access": "public" + }, + "engines": { + "node": ">=14.15.1" + }, + "mongosh": { + "unitTestsOnly": true + }, + "dependencies": { + "node-fetch": "^3.3.2" + }, + "devDependencies": { + "@mongodb-js/eslint-config-mongosh": "^1.0.0", + "@mongodb-js/prettier-config-devtools": "^1.0.1", + "@mongodb-js/tsconfig-mongosh": "^1.0.0", + "depcheck": "^1.4.3", + "eslint": "^7.25.0", + "prettier": "^2.8.8" + } +} diff --git a/packages/import-node-fetch/src/global.d.ts b/packages/import-node-fetch/src/global.d.ts new file mode 100644 index 000000000..8cc7b7049 --- /dev/null +++ b/packages/import-node-fetch/src/global.d.ts @@ -0,0 +1 @@ +declare const __webpack_require__: unknown; diff --git a/packages/import-node-fetch/src/index.spec.ts b/packages/import-node-fetch/src/index.spec.ts new file mode 100644 index 000000000..15aa824e8 --- /dev/null +++ b/packages/import-node-fetch/src/index.spec.ts @@ -0,0 +1,23 @@ +import { expect } from 'chai'; +import importNodeFetch from './'; + +describe('import-node-fetch', function () { + it('Fails to import node-fetch normally', async function () { + let failed = false; + try { + await import('node-fetch'); + } catch (error) { + failed = true; + expect((error as Error).message).to.include('require() of ES Module'); + } + if (!failed) throw new Error('This was expected to fail'); + }); + + it('Imports node-fetch safely', async function () { + const fetch = await importNodeFetch(); + + expect(fetch).to.exist; + expect(fetch).to.haveOwnProperty('default'); + expect(fetch.default).to.be.a('function'); + }); +}); diff --git a/packages/import-node-fetch/src/index.ts b/packages/import-node-fetch/src/index.ts new file mode 100644 index 000000000..a871142eb --- /dev/null +++ b/packages/import-node-fetch/src/index.ts @@ -0,0 +1,33 @@ +// eslint-disable-next-line @typescript-eslint/consistent-type-imports +export type TNodeFetch = typeof import('node-fetch'); +export type { Request, Response, RequestInfo, RequestInit } from 'node-fetch'; + +export default async function importNodeFetch(): Promise { + // Node-fetch is an ESM module from 3.x + // Importing ESM modules to CommonJS is possible with a dynamic import. + // However, once this is transpiled with TS, `await import()` changes to `require()`, which fails to load + // the package at runtime. + // The alternative, to transpile with "moduleResolution": "NodeNext", is not always feasible. + // Use this function to safely import the node-fetch package + let module; + try { + module = await import('node-fetch'); + } catch (err: unknown) { + if ( + err && + typeof err === 'object' && + 'code' in err && + err.code === 'ERR_REQUIRE_ESM' && + typeof __webpack_require__ === 'undefined' + ) { + // This means that the import() above was transpiled to require() + // and that that require() called failed because it saw actual on-disk ESM. + // In this case, it should be safe to use eval'ed import(). + module = await eval(`import('node-fetch')`); + } else { + throw err; + } + } + + return module; +} diff --git a/packages/import-node-fetch/tsconfig-lint.json b/packages/import-node-fetch/tsconfig-lint.json new file mode 100644 index 000000000..981423b3e --- /dev/null +++ b/packages/import-node-fetch/tsconfig-lint.json @@ -0,0 +1,5 @@ +{ + "extends": "./tsconfig.json", + "include": ["**/*"], + "exclude": ["node_modules", "dist", "lib"] +} diff --git a/packages/import-node-fetch/tsconfig.json b/packages/import-node-fetch/tsconfig.json new file mode 100644 index 000000000..51ef57e2c --- /dev/null +++ b/packages/import-node-fetch/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "@mongodb-js/tsconfig-mongosh/tsconfig.common.json", + "compilerOptions": { + "outDir": "./lib", + "allowJs": true + }, + "include": ["src/**/*"], + "exclude": ["./src/**/*.spec.*"] +} diff --git a/packages/snippet-manager/package.json b/packages/snippet-manager/package.json index 9d3f29405..30a613f8c 100644 --- a/packages/snippet-manager/package.json +++ b/packages/snippet-manager/package.json @@ -36,13 +36,13 @@ }, "dependencies": { "@mongosh/errors": "0.0.0-dev.0", + "@mongosh/import-node-fetch": "0.0.0-dev.0", "@mongosh/shell-api": "0.0.0-dev.0", "@mongosh/types": "0.0.0-dev.0", "bson": "^6.2.0", "cross-spawn": "^7.0.3", "escape-string-regexp": "^4.0.0", "joi": "^17.4.0", - "node-fetch": "^2.6.1", "tar": "^6.1.15" }, "devDependencies": { @@ -50,7 +50,6 @@ "@mongodb-js/prettier-config-devtools": "^1.0.1", "@mongodb-js/tsconfig-mongosh": "^1.0.0", "@types/cross-spawn": "^6.0.2", - "@types/node-fetch": "^2.6.4", "@types/tar": "^4.0.4", "depcheck": "^1.4.3", "eslint": "^7.25.0", diff --git a/packages/snippet-manager/src/snippet-manager.ts b/packages/snippet-manager/src/snippet-manager.ts index 69cae4db9..ade98c74c 100644 --- a/packages/snippet-manager/src/snippet-manager.ts +++ b/packages/snippet-manager/src/snippet-manager.ts @@ -17,6 +17,8 @@ import tar from 'tar'; import zlib from 'zlib'; import bson from 'bson'; import joi from 'joi'; +import importNodeFetch from '@mongosh/import-node-fetch'; +import type { Response } from '@mongosh/import-node-fetch'; const pipeline = promisify(stream.pipeline); const brotliCompress = promisify(zlib.brotliCompress); const brotliDecompress = promisify(zlib.brotliDecompress); @@ -50,6 +52,12 @@ export interface SnippetIndexFile { sourceURL: string; } +interface NpmMetaDataResponse { + dist?: { + tarball?: string; + }; +} + const indexFileSchema = joi.object({ indexFileVersion: joi.number().integer().max(1).required(), @@ -185,9 +193,9 @@ export class SnippetManager implements ShellPlugin { return this._instanceState.messageBus; } - async fetch(url: string) { + async fetch(url: string): Promise { // 'http' is not supported in startup snapshots yet. - const fetch = await import('node-fetch'); + const fetch = await importNodeFetch(); return await fetch.default(url); } @@ -240,7 +248,9 @@ export class SnippetManager implements ShellPlugin { ); } interrupted.checkpoint(); - const npmTarballURL = (await npmMetadataResponse.json())?.dist?.tarball; + const npmTarballURL = ( + (await npmMetadataResponse.json()) as NpmMetaDataResponse + )?.dist?.tarball; if (!npmTarballURL) { this.messageBus.emit('mongosh-snippets:npm-download-failed', { npmMetadataURL, @@ -253,7 +263,7 @@ export class SnippetManager implements ShellPlugin { interrupted.checkpoint(); await this.print(`Downloading npm from ${npmTarballURL}...`); const npmTarball = await this.fetch(npmTarballURL); - if (!npmTarball.ok) { + if (!npmTarball.ok || !npmTarball.body) { this.messageBus.emit('mongosh-snippets:npm-download-failed', { npmMetadataURL, npmTarballURL, @@ -332,11 +342,12 @@ export class SnippetManager implements ShellPlugin { `The specified index file ${url} could not be read: ${repoRes.statusText}` ); } - const rawData = await repoRes.buffer(); + const arrayBuffer = await repoRes.arrayBuffer(); + const buffer = Buffer.from(arrayBuffer); let data; try { data = await unpackBSON>( - rawData + buffer ); } catch (err: any) { this.messageBus.emit('mongosh-snippets:fetch-index-error', {