From 97d8e2d88168825c778c7bb6177ce0250c554c40 Mon Sep 17 00:00:00 2001 From: Joe Lencioni Date: Fri, 7 Jun 2024 10:42:43 -0500 Subject: [PATCH 1/8] Install eslint I did this by running: ``` npm init @eslint/config@latest ``` --- eslint.config.mjs | 8 ++ package-lock.json | 354 +++++++++++++++------------------------------- package.json | 4 +- 3 files changed, 122 insertions(+), 244 deletions(-) create mode 100644 eslint.config.mjs diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000..2edbef8 --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,8 @@ +import globals from "globals"; +import pluginJs from "@eslint/js"; + + +export default [ + {languageOptions: { globals: globals.browser }}, + pluginJs.configs.recommended, +]; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 18d7aa6..b8d6125 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,7 +20,6 @@ "commander": "^4.0.1", "fb-watchman": "^2.0.1", "glob": "^7.1.6", - "globals": "^12.3.0", "lodash": "^4.17.15", "minimatch": "^3.0.4", "require-relative": "^0.8.7", @@ -40,8 +39,11 @@ "@babel/preset-env": "^7.7.6", "@babel/preset-flow": "^7.7.4", "@babel/preset-react": "^7.7.4", + "@eslint/js": "^9.4.0", "babel-jest": "^24.9.0", + "eslint": "^9.4.0", "flow-bin": "^0.113.0", + "globals": "^15.4.0", "jest": "^29.7.0", "mkdirp": "^0.5.1", "prettier": "^3.2.4", @@ -53,7 +55,6 @@ "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", "dev": true, - "peer": true, "engines": { "node": ">=0.10.0" } @@ -2019,7 +2020,6 @@ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", "dev": true, - "peer": true, "dependencies": { "eslint-visitor-keys": "^3.3.0" }, @@ -2035,7 +2035,6 @@ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, - "peer": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -2048,22 +2047,34 @@ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", "dev": true, - "peer": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, + "node_modules/@eslint/config-array": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.15.1.tgz", + "integrity": "sha512-K4gzNq+yymn/EVsXYmf+SBcBro8MTf+aXJZUphM96CdzUEr+ClGDvAbpmaEK+cGVigVXIgs9gNmvHAlrzzY5JQ==", + "dev": true, + "dependencies": { + "@eslint/object-schema": "^2.1.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", + "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", "dev": true, - "peer": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", + "espree": "^10.0.1", + "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", @@ -2071,7 +2082,7 @@ "strip-json-comments": "^3.1.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -2082,7 +2093,6 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -2095,16 +2105,12 @@ } }, "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", "dev": true, - "peer": true, - "dependencies": { - "type-fest": "^0.20.2" - }, "engines": { - "node": ">=8" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -2114,30 +2120,24 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "peer": true + "dev": true }, - "node_modules/@eslint/eslintrc/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "node_modules/@eslint/js": { + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.4.0.tgz", + "integrity": "sha512-fdI7VJjP3Rvc70lC4xkFXHB0fiPeojiL1PxVG6t1ZvXQrarj893PweuBTujxDUFk0Fxj4R7PIIAZ/aiiyZPZcg==", "dev": true, - "peer": true, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@eslint/js": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", - "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", + "node_modules/@eslint/object-schema": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.3.tgz", + "integrity": "sha512-HAbhAYKfsAC2EkTqve00ibWIZlaU74Z1EHwAjYr4PXF0YU2VEA1zSIKSSpKszRLRWwHzzRZXvK632u+uXzvsvw==", "dev": true, - "peer": true, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@gar/promisify": { @@ -2146,27 +2146,11 @@ "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", "optional": true }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", - "dev": true, - "peer": true, - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, - "peer": true, "engines": { "node": ">=12.22" }, @@ -2175,12 +2159,18 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", - "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", + "node_modules/@humanwhocodes/retry": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz", + "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==", "dev": true, - "peer": true + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", @@ -4163,7 +4153,6 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, - "peer": true, "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -4177,7 +4166,6 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, - "peer": true, "engines": { "node": ">= 8" } @@ -4187,7 +4175,6 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, - "peer": true, "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -4408,13 +4395,6 @@ "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", "dev": true }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true, - "peer": true - }, "node_modules/abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -4426,7 +4406,6 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", "dev": true, - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -4439,7 +4418,6 @@ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, - "peer": true, "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } @@ -4581,8 +4559,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "peer": true + "dev": true }, "node_modules/arr-diff": { "version": "4.0.0", @@ -5672,8 +5649,7 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true, - "peer": true + "dev": true }, "node_modules/deepmerge": { "version": "4.3.1", @@ -5760,19 +5736,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "peer": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/electron-to-chromium": { "version": "1.4.637", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.637.tgz", @@ -5949,42 +5912,37 @@ } }, "node_modules/eslint": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", - "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.4.0.tgz", + "integrity": "sha512-sjc7Y8cUD1IlwYcTS9qPSvGjAC8Ne9LctpxKKu3x/1IC9bnOg98Zy6GxEJUfr1NojMgVPlyANXYns8oE2c1TAA==", "dev": true, - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.56.0", - "@humanwhocodes/config-array": "^0.11.13", + "@eslint/config-array": "^0.15.1", + "@eslint/eslintrc": "^3.1.0", + "@eslint/js": "9.4.0", "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.3.0", "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", - "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", + "eslint-scope": "^8.0.1", + "eslint-visitor-keys": "^4.0.0", + "espree": "^10.0.1", "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", + "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", "lodash.merge": "^4.6.2", @@ -5998,7 +5956,7 @@ "eslint": "bin/eslint.js" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -6040,7 +5998,6 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -6057,7 +6014,6 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, - "peer": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -6073,7 +6029,6 @@ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "peer": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -6090,7 +6045,6 @@ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, - "peer": true, "dependencies": { "color-name": "~1.1.4" }, @@ -6102,15 +6056,13 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "peer": true + "dev": true }, "node_modules/eslint/node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, - "peer": true, "engines": { "node": ">=10" }, @@ -6119,30 +6071,28 @@ } }, "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.1.tgz", + "integrity": "sha512-pL8XjgP4ZOmmwfFE8mEhSxA7ZY4C+LWyqjQ3o4yWkkmD0qcMT9kkW3zWHOczhWcjTSgqycYAgwSlXvZltv65og==", "dev": true, - "peer": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", + "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", "dev": true, - "peer": true, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -6153,7 +6103,6 @@ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, - "peer": true, "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -6170,7 +6119,6 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, - "peer": true, "dependencies": { "is-glob": "^4.0.3" }, @@ -6178,28 +6126,11 @@ "node": ">=10.13.0" } }, - "node_modules/eslint/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "peer": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/eslint/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "peer": true, "engines": { "node": ">=8" } @@ -6208,15 +6139,13 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "peer": true + "dev": true }, "node_modules/eslint/node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, - "peer": true, "dependencies": { "p-locate": "^5.0.0" }, @@ -6232,7 +6161,6 @@ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, - "peer": true, "dependencies": { "yocto-queue": "^0.1.0" }, @@ -6248,7 +6176,6 @@ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, - "peer": true, "dependencies": { "p-limit": "^3.0.2" }, @@ -6264,7 +6191,6 @@ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, - "peer": true, "engines": { "node": ">=8" } @@ -6274,7 +6200,6 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, - "peer": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -6282,45 +6207,30 @@ "node": ">=8" } }, - "node_modules/eslint/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "peer": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.0.1.tgz", + "integrity": "sha512-MWkrWZbJsL2UwnjxTX3gG8FneachS/Mwg7tdGXce011sJd5b0JG54vat5KHnfSBODZ3Wvzd2WnjxyzsRoVv+ww==", "dev": true, - "peer": true, "dependencies": { - "acorn": "^8.9.0", + "acorn": "^8.11.3", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" + "eslint-visitor-keys": "^4.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", + "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", "dev": true, - "peer": true, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -6344,7 +6254,6 @@ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", "dev": true, - "peer": true, "dependencies": { "estraverse": "^5.1.0" }, @@ -6871,15 +6780,13 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true, - "peer": true + "dev": true }, "node_modules/fastq": { "version": "1.16.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.16.0.tgz", "integrity": "sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA==", "dev": true, - "peer": true, "dependencies": { "reusify": "^1.0.4" } @@ -6898,16 +6805,15 @@ "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==" }, "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, - "peer": true, "dependencies": { - "flat-cache": "^3.0.4" + "flat-cache": "^4.0.0" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16.0.0" } }, "node_modules/file-uri-to-path": { @@ -6940,26 +6846,23 @@ } }, "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, - "peer": true, "dependencies": { "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" + "keyv": "^4.5.4" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16" } }, "node_modules/flatted": { - "version": "3.2.9", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", - "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", - "dev": true, - "peer": true + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true }, "node_modules/flow-bin": { "version": "0.113.0", @@ -7220,14 +7123,12 @@ } }, "node_modules/globals": { - "version": "12.4.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", - "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", - "dependencies": { - "type-fest": "^0.8.1" - }, + "version": "15.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.4.0.tgz", + "integrity": "sha512-unnwvMZpv0eDUyjNyh9DH/yxUaRYrEjW/qK4QcdrHg3oO11igUQrCSgODHEqxlKg8v2CD2Sd7UkqqEBoz5U7TQ==", + "dev": true, "engines": { - "node": ">=8" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -7266,13 +7167,6 @@ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "devOptional": true }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true, - "peer": true - }, "node_modules/has-bigints": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", @@ -7493,11 +7387,10 @@ ] }, "node_modules/ignore": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", - "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", "dev": true, - "peer": true, "engines": { "node": ">= 4" } @@ -7507,7 +7400,6 @@ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, - "peer": true, "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -7878,7 +7770,6 @@ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true, - "peer": true, "engines": { "node": ">=8" } @@ -12325,7 +12216,6 @@ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, - "peer": true, "dependencies": { "argparse": "^2.0.1" }, @@ -12348,8 +12238,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true, - "peer": true + "dev": true }, "node_modules/json-parse-better-errors": { "version": "1.0.2", @@ -12372,8 +12261,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true, - "peer": true + "dev": true }, "node_modules/json5": { "version": "2.2.3", @@ -12391,7 +12279,6 @@ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, - "peer": true, "dependencies": { "json-buffer": "3.0.1" } @@ -12433,7 +12320,6 @@ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, - "peer": true, "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" @@ -12500,8 +12386,7 @@ "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true, - "peer": true + "dev": true }, "node_modules/logform": { "version": "2.6.0", @@ -13335,7 +13220,6 @@ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", "dev": true, - "peer": true, "dependencies": { "@aashutoshrathi/word-wrap": "^1.2.3", "deep-is": "^0.1.3", @@ -13413,7 +13297,6 @@ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, - "peer": true, "dependencies": { "callsites": "^3.0.0" }, @@ -13628,7 +13511,6 @@ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, - "peer": true, "engines": { "node": ">= 0.8.0" } @@ -13763,8 +13645,7 @@ "type": "consulting", "url": "https://feross.org/support" } - ], - "peer": true + ] }, "node_modules/rc": { "version": "1.2.8", @@ -14048,7 +13929,6 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, - "peer": true, "engines": { "node": ">=4" } @@ -14092,7 +13972,6 @@ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true, - "peer": true, "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" @@ -14141,7 +14020,6 @@ "url": "https://feross.org/support" } ], - "peer": true, "dependencies": { "queue-microtask": "^1.2.2" } @@ -15088,8 +14966,7 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true, - "peer": true + "dev": true }, "node_modules/tmpl": { "version": "1.0.5", @@ -15189,7 +15066,6 @@ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, - "peer": true, "dependencies": { "prelude-ls": "^1.2.1" }, @@ -15206,14 +15082,6 @@ "node": ">=4" } }, - "node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "engines": { - "node": ">=8" - } - }, "node_modules/typed-array-buffer": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", diff --git a/package.json b/package.json index 36cf392..b0e96bd 100644 --- a/package.json +++ b/package.json @@ -52,8 +52,11 @@ "@babel/preset-env": "^7.7.6", "@babel/preset-flow": "^7.7.4", "@babel/preset-react": "^7.7.4", + "@eslint/js": "^9.4.0", "babel-jest": "^24.9.0", + "eslint": "^9.4.0", "flow-bin": "^0.113.0", + "globals": "^15.4.0", "jest": "^29.7.0", "mkdirp": "^0.5.1", "prettier": "^3.2.4", @@ -71,7 +74,6 @@ "commander": "^4.0.1", "fb-watchman": "^2.0.1", "glob": "^7.1.6", - "globals": "^12.3.0", "lodash": "^4.17.15", "minimatch": "^3.0.4", "require-relative": "^0.8.7", From 0e5eeb5bc23cf5fbc041a861bea83dcb014a0a1c Mon Sep 17 00:00:00 2001 From: Joe Lencioni Date: Fri, 7 Jun 2024 10:47:21 -0500 Subject: [PATCH 2/8] Remove flow type annotations We know that we do not want to use flow anymore. We may want to adopt TypeScript, but it is unclear if we will in the near term. https://github.com/Galooshi/import-js/issues/593 I want to re-introduce ESLint, and instead of setting up ESLint to be able to parse flow syntax, I decided that we should just remove it. https://github.com/Galooshi/import-js/issues/608 I removed these annotations by running the following command: ``` npx flow-remove-types lib/ -d lib/ ``` Then I formatted the files by running prettier on everything: ``` node_modules/.bin/prettier -w lib/ ``` I think if we wanted to introduce TypeScript that it might be easier to do it from scratch anyway instead of attempting to convert the flow types over to a different type system. --- lib/CommandLineEditor.js | 14 +-- lib/Configuration.js | 59 ++++------- lib/FileUtils.js | 6 +- lib/ImportStatement.js | 106 +++++++------------ lib/ImportStatements.js | 83 +++++++-------- lib/Importer.js | 144 +++++++++++--------------- lib/JsModule.js | 44 +++----- lib/Watcher.js | 76 ++++++-------- lib/__mocks__/requireResolve.js | 6 +- lib/environments/meteorEnvironment.js | 49 ++++----- lib/findCurrentImports.js | 21 ++-- lib/findJsModulesFor.js | 72 +++++-------- lib/findPackageDependencies.js | 12 +-- lib/forwardSlashes.js | 4 +- lib/importjs.js | 107 ++++++++----------- lib/normalizePath.js | 7 +- lib/parse.js | 15 +-- lib/requireResolve.js | 4 +- lib/resolveImportPathAndMain.js | 26 ++--- lib/version.js | 4 +- 20 files changed, 343 insertions(+), 516 deletions(-) diff --git a/lib/CommandLineEditor.js b/lib/CommandLineEditor.js index add1aca..ec0fbce 100644 --- a/lib/CommandLineEditor.js +++ b/lib/CommandLineEditor.js @@ -1,27 +1,27 @@ -// @flow +// export default class CommandLineEditor { - _lines: Array; + _lines; - constructor(lines: Array) { + constructor(lines) { this._lines = lines; } - currentFileContent(): string { + currentFileContent() { return this._lines.join('\n'); } - get(index: number): string { + get(index) { return this._lines[index]; } - remove(index: number) { + remove(index) { this._lines.splice(index, 1); } /** * Insert a line above the specified index */ - insertBefore(index: number, str: string) { + insertBefore(index, str) { this._lines.splice(index, 0, str); } } diff --git a/lib/Configuration.js b/lib/Configuration.js index a38ff00..3a32294 100644 --- a/lib/Configuration.js +++ b/lib/Configuration.js @@ -1,4 +1,4 @@ -// @flow +// import os from 'os'; import path from 'path'; @@ -26,16 +26,16 @@ const ENVIRONMENTS = { meteor: meteorEnvironment, }; -function checkConfiguration(config: Object): Array { +function checkConfiguration(config) { const result = validate(config); return result.messages; } -function checkForDeprecatedConfiguration(config: Object): Array { +function checkForDeprecatedConfiguration(config) { const messages = []; - Object.keys(config).forEach((option: string) => { + Object.keys(config).forEach((option) => { if (DEPRECATED_CONFIGURATION_OPTIONS.indexOf(option) !== -1) { messages.push( `Using ${option} to configure ImportJS is deprecated and ` + @@ -53,7 +53,7 @@ function checkForDeprecatedConfiguration(config: Object): Array { * @throws Error if current version is less than the `minimumVersion` defined * in config. */ -function checkCurrentVersion(minimumVersion: string) { +function checkCurrentVersion(minimumVersion) { if (semver.gte(version(), minimumVersion)) { return; } @@ -63,7 +63,7 @@ function checkCurrentVersion(minimumVersion: string) { ); } -function mergedValue(values: Array, key: string, options: Object): any { +function mergedValue(values, key, options) { let mergedResult; for (let i = 0; i < values.length; i += 1) { let value = values[i]; @@ -95,7 +95,7 @@ function mergedValue(values: Array, key: string, options: Object): any { /** * returns configuration from a JS file in home directory if it exists, or null */ -function loadGlobalJsConfig(): ?Object { +function loadGlobalJsConfig() { for (let i = 0; i < JS_CONFIG_FILES.length; i += 1) { const jsConfigFile = JS_CONFIG_FILES[i]; const globalConfig = FileUtils.readJsFile( @@ -111,18 +111,15 @@ function loadGlobalJsConfig(): ?Object { // Class that initializes configuration from a .importjs.js file export default class Configuration { - pathToCurrentFile: string; + pathToCurrentFile; - messages: Array; + messages; - configs: Array; + configs; - workingDirectory: string; + workingDirectory; - constructor( - pathToCurrentFile: string, - workingDirectory: string = process.cwd(), - ) { + constructor(pathToCurrentFile, workingDirectory = process.cwd()) { this.workingDirectory = workingDirectory; this.pathToCurrentFile = normalizePath(pathToCurrentFile, workingDirectory); @@ -153,7 +150,7 @@ export default class Configuration { pathToCurrentFile: this.pathToCurrentFile, }); } - (userConfig.environments || []).forEach((environment: string) => { + (userConfig.environments || []).forEach((environment) => { const envConfig = ENVIRONMENTS[environment]; if (envConfig) { this.configs.push(envConfig); @@ -166,24 +163,13 @@ export default class Configuration { checkCurrentVersion(this.get('minimumVersion')); } - get( - key: string, - { - pathToImportedModule, - moduleName, - importStatement, - }: { - pathToImportedModule?: string, - moduleName?: string, - importStatement?: string, - } = {}, - ): any { - const applyingConfigs = this.configs.filter((config: Object): boolean => + get(key, { pathToImportedModule, moduleName, importStatement } = {}) { + const applyingConfigs = this.configs.filter((config) => Object.prototype.hasOwnProperty.call(config, key), ); return mergedValue( - applyingConfigs.map((config: Object): any => config[key]), + applyingConfigs.map((config) => config[key]), key, { pathToImportedModule, @@ -195,7 +181,7 @@ export default class Configuration { ); } - loadUserConfig(): ?Object { + loadUserConfig() { return ( this.loadLocalJsConfig() || this.loadLocalJsonConfig() || @@ -203,7 +189,7 @@ export default class Configuration { ); } - loadLocalJsConfig(): ?Object { + loadLocalJsConfig() { for (let i = 0; i < JS_CONFIG_FILES.length; i += 1) { const jsConfigFile = JS_CONFIG_FILES[i]; const jsConfig = FileUtils.readJsFile( @@ -227,7 +213,7 @@ export default class Configuration { return null; } - loadLocalJsonConfig(): ?Object { + loadLocalJsonConfig() { const jsonConfig = FileUtils.readJsonFile( path.join(this.workingDirectory, JSON_CONFIG_FILE), ); @@ -242,7 +228,7 @@ export default class Configuration { return null; } - resolveAlias(variableName: string): ?string { + resolveAlias(variableName) { if (!has(this.get('aliases'), variableName)) { return null; } @@ -264,11 +250,10 @@ export default class Configuration { return importPath; } - resolveNamedExports(variableName: string): ?JsModule { + resolveNamedExports(variableName) { const allNamedExports = this.get('namedExports'); const importPath = Object.keys(allNamedExports).find( - (key: string): boolean => - allNamedExports[key].indexOf(variableName) !== -1, + (key) => allNamedExports[key].indexOf(variableName) !== -1, ); if (!importPath) { diff --git a/lib/FileUtils.js b/lib/FileUtils.js index dcb381e..65c22c4 100644 --- a/lib/FileUtils.js +++ b/lib/FileUtils.js @@ -1,8 +1,8 @@ -// @flow +// import fs from 'fs'; export default { - readJsonFile(absoluteFilePath: string): ?Object { + readJsonFile(absoluteFilePath) { if (!fs.existsSync(absoluteFilePath)) { return null; } @@ -16,7 +16,7 @@ export default { return JSON.parse(contents); }, - readJsFile(absoluteFilePath: string): ?Object { + readJsFile(absoluteFilePath) { if (!fs.existsSync(absoluteFilePath)) { return null; } diff --git a/lib/ImportStatement.js b/lib/ImportStatement.js index 0b7e13e..cf8e0b8 100644 --- a/lib/ImportStatement.js +++ b/lib/ImportStatement.js @@ -1,17 +1,9 @@ -// @flow -function isLineTooLong(line: string, maxLineLength: number): boolean { +// +function isLineTooLong(line, maxLineLength) { return !!maxLineLength && line.length > maxLineLength; } -function equalsAndValue({ - declarationKeyword, - importFunction, - path, -}: { - declarationKeyword: ?string, - importFunction: ?string, - path: string, -}): Object { +function equalsAndValue({ declarationKeyword, importFunction, path }) { if (declarationKeyword === 'import') { return { equals: 'from', value: `'${path}';` }; } @@ -25,29 +17,29 @@ function equalsAndValue({ * `import foo from 'foo';` */ export default class ImportStatement { - assignment: ?string; + assignment; - declarationKeyword: ?string; + declarationKeyword; - hasTypeKeyword: ?boolean; + hasTypeKeyword; - defaultImport: ?string; + defaultImport; - hasSideEffects: boolean; + hasSideEffects; - importFunction: ?string; + importFunction; - namedImports: Array; + namedImports; - areOnlyTypes: boolean; // true if namedImports are all 'type' imports + areOnlyTypes; // true if namedImports are all 'type' imports - originalImportString: ?string; + originalImportString; - leadingContent: ?string; + leadingContent; - path: string; + path; - danglingCommas: boolean; + danglingCommas; constructor({ assignment, @@ -62,19 +54,6 @@ export default class ImportStatement { leadingContent, path, danglingCommas = true, - }: { - assignment?: ?string, - declarationKeyword?: ?string, - hasTypeKeyword?: ?boolean, - defaultImport?: ?string, - hasSideEffects: boolean, - importFunction?: ?string, - namedImports?: Array, - areOnlyTypes?: boolean, - originalImportString?: ?string, - leadingContent?: ?string, - path: string, - danglingCommas: boolean, } = {}) { this.assignment = assignment; this.declarationKeyword = declarationKeyword; @@ -90,13 +69,12 @@ export default class ImportStatement { this.danglingCommas = danglingCommas; } - hasVariable(variableName: string): boolean { + hasVariable(variableName) { if (variableName === this.defaultImport) { return true; } return !!this.namedImports.find( - ({ localName }: { localName: string }): boolean => - localName === variableName, + ({ localName }) => localName === variableName, ); } @@ -104,7 +82,7 @@ export default class ImportStatement { * Deletes a variable from an already existing default import or set of * named imports. */ - deleteVariable(variableName: string) { + deleteVariable(variableName) { let touched = false; if (this.defaultImport === variableName) { @@ -114,8 +92,7 @@ export default class ImportStatement { if (this.hasNamedImports()) { const variableIndex = this.namedImports.findIndex( - ({ localName }: { localName: string }): boolean => - localName === variableName, + ({ localName }) => localName === variableName, ); if (variableIndex !== -1) { this.namedImports.splice(variableIndex, 1); @@ -131,7 +108,7 @@ export default class ImportStatement { /** * @return {Boolean} true if there are named imports */ - hasNamedImports(): boolean { + hasNamedImports() { return !!this.namedImports && this.namedImports.length > 0; } @@ -139,7 +116,7 @@ export default class ImportStatement { * @return {Boolean} true if there is no default import, no named imports, and * no side effects. */ - isEmpty(): boolean { + isEmpty() { return ( !this.defaultImport && !this.hasNamedImports() && !this.hasSideEffects ); @@ -149,38 +126,36 @@ export default class ImportStatement { * @return {Boolean} true if this instance was created through parsing an * existing import and it hasn't been altered since it was created. */ - isParsedAndUntouched(): boolean { + isParsedAndUntouched() { return !!this.originalImportString; } /** * @return {Array} an array that can be used in `sort` and `uniq` */ - toNormalized(): Array { + toNormalized() { if (!this.defaultImport && !this.hasNamedImports() && this.hasSideEffects) { return [this.path]; } return [this.defaultImport || '', ...this.localNames()]; } - localNames(): Array { + localNames() { if (!this.namedImports) { return []; } - return this.namedImports.map( - ({ localName }: { localName: string }): string => localName, - ); + return this.namedImports.map(({ localName }) => localName); } /** * @return {Array} Array of all variables that this ImportStatement * imports. */ - variables(): Array { + variables() { return [this.defaultImport, ...this.localNames()].filter(Boolean); } - toImportStrings(maxLineLength: number, tab: string): Array { + toImportStrings(maxLineLength, tab) { const strings = this._importStrings(maxLineLength, tab); if (this.leadingContent && strings.length > 0) { @@ -190,7 +165,7 @@ export default class ImportStatement { return strings; } - _importStrings(maxLineLength: number, tab: string): Array { + _importStrings(maxLineLength, tab) { if (this.originalImportString) { return [this.originalImportString]; } @@ -223,7 +198,7 @@ export default class ImportStatement { /** * Merge another ImportStatement into this one. */ - merge(importStatement: ImportStatement) { + merge(importStatement) { if ( importStatement.defaultImport && this.defaultImport !== importStatement.defaultImport @@ -247,10 +222,9 @@ export default class ImportStatement { let modified = false; - importStatement.namedImports.forEach((named: Object) => { + importStatement.namedImports.forEach((named) => { const namedImport = originalNamedImports.find( - ({ localName }: { localName: string }): boolean => - localName === named.localName, + ({ localName }) => localName === named.localName, ); if (!namedImport) { this.namedImports.push(named); @@ -261,7 +235,7 @@ export default class ImportStatement { } }); if (modified) { - this.namedImports.sort((a: Object, b: Object): number => { + this.namedImports.sort((a, b) => { if (a.localName < b.localName) { return -1; } @@ -280,7 +254,7 @@ export default class ImportStatement { } } - _assignmentLessImportString(): string { + _assignmentLessImportString() { if (this.declarationKeyword === 'import') { return `import '${this.path}';`; } @@ -288,7 +262,7 @@ export default class ImportStatement { return `${this.importFunction || 'require'}('${this.path}');`; } - _defaultImportString(maxLineLength: number, tab: string): string { + _defaultImportString(maxLineLength, tab) { const { equals, value } = equalsAndValue({ declarationKeyword: this.declarationKeyword, importFunction: this.importFunction, @@ -303,7 +277,7 @@ export default class ImportStatement { return `${this.declarationKeyword || ''} ${this.defaultImport || ''} ${equals}\n${tab}${value}`; } - _namedImportString(maxLineLength: number, tab: string): string { + _namedImportString(maxLineLength, tab) { const { equals, value } = equalsAndValue({ declarationKeyword: this.declarationKeyword, importFunction: this.importFunction, @@ -320,15 +294,7 @@ export default class ImportStatement { } const named = this.namedImports.map( - ({ - localName, - importedName, - isType, - }: { - localName: string, - importedName: ?string, - isType?: boolean, - }): string => { + ({ localName, importedName, isType }) => { const typePrefix = isType && (!this.areOnlyTypes || this.defaultImport) ? 'type ' : ''; if (!importedName) { diff --git a/lib/ImportStatements.js b/lib/ImportStatements.js index ed4f8e4..5f9824a 100644 --- a/lib/ImportStatements.js +++ b/lib/ImportStatements.js @@ -1,4 +1,4 @@ -// @flow +// // Class that sorts ImportStatements as they are pushed in import flattenDeep from 'lodash/flattenDeep'; @@ -39,14 +39,12 @@ const PATH_TYPES = Object.freeze([ const GROUPINGS_ARRAY = Object.freeze( flattenDeep( - STYLES.map((style: string): Array => - PATH_TYPES.map((location: string): string => `${style} ${location}`), - ), + STYLES.map((style) => PATH_TYPES.map((location) => `${style} ${location}`)), ), ); const GROUPINGS = {}; -GROUPINGS_ARRAY.forEach((group: string, index: number) => { +GROUPINGS_ARRAY.forEach((group, index) => { GROUPINGS[group] = index; }); Object.freeze(GROUPINGS); @@ -55,10 +53,10 @@ Object.freeze(GROUPINGS); * Determine import path type (e.g. 'package, 'non-relative', 'relative') */ function importStatementPathType( - importStatement: ImportStatement, - packageDependencies: Set, - coreModules: Array, -): string { + importStatement, + packageDependencies, + coreModules, +) { if (importStatement.path.startsWith('.')) { return PATH_TYPE_RELATIVE; } @@ -73,7 +71,7 @@ function importStatementPathType( // (PATH_TYPE_PACKAGE). if ( Array.from(packageDependencies).some( - (pkg: string): boolean => + (pkg) => importStatement.path === pkg || importStatement.path.startsWith(`${pkg}/`), ) @@ -88,7 +86,7 @@ function importStatementPathType( * Determine import statement style (e.g. 'import', 'const', 'var', or * 'custom') */ -function importStatementStyle(importStatement: ImportStatement): string { +function importStatementStyle(importStatement) { if (importStatement.hasSideEffects) { return STYLE_SIDE_EFFECT; } @@ -110,10 +108,10 @@ function importStatementStyle(importStatement: ImportStatement): string { } function importStatementGroupIndex( - importStatement: ImportStatement, - packageDependencies: Set, - coreModules: Array, -): number { + importStatement, + packageDependencies, + coreModules, +) { const style = importStatementStyle(importStatement); const pathType = importStatementPathType( importStatement, @@ -125,24 +123,24 @@ function importStatementGroupIndex( } export default class ImportStatements { - imports: Object; + imports; - config: Configuration; + config; - constructor(config: Configuration, imports: Object = {}) { + constructor(config, imports = {}) { this.config = config; this.imports = imports; } - clone(): ImportStatements { + clone() { return new ImportStatements(this.config, { ...this.imports }); } /** * Method added to make it behave like an array. */ - forEach(callback: Function) { - Object.keys(this.imports).forEach((key: string) => { + forEach(callback) { + Object.keys(this.imports).forEach((key) => { callback(this.imports[key]); }); } @@ -150,8 +148,8 @@ export default class ImportStatements { /** * Method added to make it behave like an array. */ - find(callback: Function): ?ImportStatement { - const key = Object.keys(this.imports).find((key: string): boolean => + find(callback) { + const key = Object.keys(this.imports).find((key) => callback(this.imports[key]), ); if (!key) { @@ -160,8 +158,8 @@ export default class ImportStatements { return this.imports[key]; } - push(...importStatements: Array): ImportStatements { - importStatements.forEach((importStatement: ImportStatement) => { + push(...importStatements) { + importStatements.forEach((importStatement) => { const existingStatement = this.imports[importStatement.path]; if (existingStatement) { // Import already exists, so this line is likely one of a named imports @@ -176,18 +174,18 @@ export default class ImportStatements { return this; // for chaining } - empty(): boolean { + empty() { return this.size() === 0; } - size(): number { + size() { return Object.keys(this.imports).length; } - deleteVariables(variableNames: Array): ImportStatements { - Object.keys(this.imports).forEach((key: string) => { + deleteVariables(variableNames) { + Object.keys(this.imports).forEach((key) => { const importStatement = this.imports[key]; - variableNames.forEach((variableName: string) => { + variableNames.forEach((variableName) => { importStatement.deleteVariable(variableName); }); if (importStatement.isEmpty()) { @@ -202,16 +200,16 @@ export default class ImportStatements { * Convert the import statements into an array of strings, with an empty * string between each group. */ - toArray(): Array { + toArray() { const maxLineLength = this.config.get('maxLineLength'); const tab = this.config.get('tab'); const strings = []; - this._toGroups().forEach((group: Array) => { - group.forEach((importStatement: ImportStatement) => { + this._toGroups().forEach((group) => { + group.forEach((importStatement) => { const importStrings = importStatement .toImportStrings(maxLineLength, tab) - .map((importString: string): string => + .map((importString) => this.config.get('importStatementFormatter', { importStatement: importString, moduleName: importStatement.path, @@ -238,11 +236,11 @@ export default class ImportStatements { * Sort the import statements by path and group them based on our heuristic * of style and path type. */ - _toGroups(): Array> { + _toGroups() { const groups = []; const importsArray = Object.keys(this.imports).map( - (key: string): ImportStatement => this.imports[key], + (key) => this.imports[key], ); // There's a chance we have duplicate imports (can happen when switching @@ -251,20 +249,15 @@ export default class ImportStatements { // the old ones that are now redundant. let result = partition( importsArray, - (importStatement: ImportStatement): boolean => - !importStatement.isParsedAndUntouched(), + (importStatement) => !importStatement.isParsedAndUntouched(), ); result = flattenDeep(result); if (this.config.get('sortImports')) { - result = sortBy(result, (is: ImportStatement): Array => - is.toNormalized(), - ); + result = sortBy(result, (is) => is.toNormalized()); } - result = uniqBy(result, (is: ImportStatement): Array => - is.toNormalized(), - ); + result = uniqBy(result, (is) => is.toNormalized()); if (!this.config.get('groupImports')) { return [result]; @@ -272,7 +265,7 @@ export default class ImportStatements { const packageDependencies = this.config.get('packageDependencies'); const coreModules = this.config.get('coreModules'); - result.forEach((importStatement: ImportStatement) => { + result.forEach((importStatement) => { // Figure out what group to put this import statement in const groupIndex = importStatementGroupIndex( importStatement, diff --git a/lib/Importer.js b/lib/Importer.js index 56ad5de..cf0495f 100644 --- a/lib/Importer.js +++ b/lib/Importer.js @@ -1,4 +1,4 @@ -// @flow +// import path from 'path'; import requireRelative from 'require-relative'; @@ -14,10 +14,7 @@ import findUndefinedIdentifiers from './findUndefinedIdentifiers'; import findUsedIdentifiers from './findUsedIdentifiers'; import parse, { configureParserPlugins } from './parse'; -function fixImportsMessage( - removedItems: Set, - addedItems: Set, -): ?string { +function fixImportsMessage(removedItems, addedItems) { const messageParts = []; const firstAdded = addedItems.values().next().value; @@ -41,15 +38,9 @@ function fixImportsMessage( return messageParts.join('. '); } -function findFilePathFromImports( - imports: ImportStatements, - dirname: string, - variableName: string, -): ?string { +function findFilePathFromImports(imports, dirname, variableName) { // eslint-disable-next-line no-restricted-syntax - const importStatement = imports.find((is: ImportStatement): boolean => - is.hasVariable(variableName), - ); + const importStatement = imports.find((is) => is.hasVariable(variableName)); if (!importStatement) { return undefined; @@ -64,25 +55,21 @@ function findFilePathFromImports( } export default class Importer { - ast: Object; + ast; - config: Configuration; + config; - editor: CommandLineEditor; + editor; - messages: Array; + messages; - pathToCurrentFile: string; + pathToCurrentFile; - unresolvedImports: Object; + unresolvedImports; - workingDirectory: string; + workingDirectory; - constructor( - lines: Array, - pathToCurrentFile: ?string, - workingDirectory: string = process.cwd(), - ) { + constructor(lines, pathToCurrentFile, workingDirectory = process.cwd()) { this.pathToCurrentFile = pathToCurrentFile || ''; this.editor = new CommandLineEditor(lines); this.config = new Configuration(this.pathToCurrentFile, workingDirectory); @@ -107,7 +94,7 @@ export default class Importer { } } - results(): Object { + results() { return { messages: this.messages, // array fileContent: this.editor.currentFileContent(), // string @@ -118,10 +105,10 @@ export default class Importer { /** * Imports one variable */ - import(variableName: string): Promise { - return new Promise((resolve: Function, reject: Function) => { + import(variableName) { + return new Promise((resolve, reject) => { this.findOneJsModule(variableName) - .then((jsModule: JsModule) => { + .then((jsModule) => { if (!jsModule) { if (!Object.keys(this.unresolvedImports).length) { this.message(`No JS module to import for \`${variableName}\``); @@ -143,7 +130,7 @@ export default class Importer { resolve(this.results()); }) - .catch((error: Object) => { + .catch((error) => { reject(error); }); }); @@ -152,16 +139,16 @@ export default class Importer { /** * Searches for an export */ - search(variableName: string): Promise { + search(variableName) { return findJsModulesFor(this.config, variableName, { search: true }).then( - (modules: Array): Object => ({ + (modules) => ({ modules, messages: this.messages, }), ); } - goto(variableName: string): Promise { + goto(variableName) { const { imports } = this.findCurrentImports(); const filePath = findFilePathFromImports( imports, @@ -175,9 +162,9 @@ export default class Importer { }); } - return new Promise((resolve: Function, reject: Function) => { + return new Promise((resolve, reject) => { findJsModulesFor(this.config, variableName) - .then((jsModules: Array) => { + .then((jsModules) => { if (!jsModules.length) { // The current word is not mappable to one of the JS modules that we // found. This can happen if the user does not select one from the list. @@ -197,14 +184,14 @@ export default class Importer { : path.join(this.workingDirectory, filePath); resolve(results); }) - .catch((error: Object) => { + .catch((error) => { reject(error); }); }); } // Removes unused imports and adds imports for undefined variables - fixImports(): Promise { + fixImports() { const undefinedVariables = findUndefinedIdentifiers( this.ast, this.config.get('globals'), @@ -214,8 +201,8 @@ export default class Importer { const newImports = oldImports.imports.clone(); const unusedImportVariables = new Set(); - oldImports.imports.forEach((importStatement: ImportStatement) => { - importStatement.variables().forEach((variable: string) => { + oldImports.imports.forEach((importStatement) => { + importStatement.variables().forEach((variable) => { if (!usedVariables.has(variable)) { unusedImportVariables.add(variable); } @@ -225,14 +212,14 @@ export default class Importer { const addedItems = new Set(this.injectSideEffectImports(newImports)); - return new Promise((resolve: Function, reject: Function) => { + return new Promise((resolve, reject) => { const allPromises = []; - undefinedVariables.forEach((variable: string) => { + undefinedVariables.forEach((variable) => { allPromises.push(this.findOneJsModule(variable)); }); Promise.all(allPromises) - .then((results: Array) => { - results.forEach((jsModule: JsModule) => { + .then((results) => { + results.forEach((jsModule) => { if (!jsModule) { return; } @@ -252,21 +239,21 @@ export default class Importer { resolve(this.results()); }) - .catch((error: Object) => { + .catch((error) => { reject(error); }); }); } - addImports(imports: Object): Promise { - return new Promise((resolve: Function, reject: Function) => { + addImports(imports) { + return new Promise((resolve, reject) => { const oldImports = this.findCurrentImports(); const newImports = oldImports.imports.clone(); const variables = Object.keys(imports); - const promises = variables.map((variableName: string): Promise => + const promises = variables.map((variableName) => findJsModulesFor(this.config, variableName) - .then((jsModules: Array) => { + .then((jsModules) => { const importData = imports[variableName]; const dataIsObject = typeof importData === 'object'; const importPath = dataIsObject @@ -277,7 +264,7 @@ export default class Importer { : undefined; const foundModule = jsModules.find( - (jsModule: JsModule): boolean => + (jsModule) => jsModule.importPath === importPath && (hasNamedExports === undefined || jsModule.hasNamedExports === hasNamedExports), @@ -312,14 +299,14 @@ export default class Importer { }); } - rewriteImports(): Object { + rewriteImports() { const oldImports = this.findCurrentImports(); const newImports = new ImportStatements(this.config); - return new Promise((resolve: Function, reject: Function) => { + return new Promise((resolve, reject) => { const variables = []; const sideEffectOnlyImports = []; - oldImports.imports.forEach((imp: ImportStatement) => { + oldImports.imports.forEach((imp) => { if (imp.variables().length) { variables.push(...imp.variables()); } else if (imp.hasSideEffects) { @@ -328,14 +315,13 @@ export default class Importer { sideEffectOnlyImports.push(imp); } }); - const promises = variables.map( - (variable: string): Promise> => - findJsModulesFor(this.config, variable), + const promises = variables.map((variable) => + findJsModulesFor(this.config, variable), ); Promise.all(promises) - .then((results: Array>) => { - results.forEach((jsModules: Array) => { + .then((results) => { + results.forEach((jsModules) => { if (!jsModules.length) { return; } @@ -357,33 +343,33 @@ export default class Importer { this.replaceImports(oldImports.range, newImports); resolve(this.results()); }) - .catch((error: Object) => { + .catch((error) => { reject(error); }); }); } - message(str: string) { + message(str) { this.messages.push(str); } - findOneJsModule(variableName: string): Promise { - return new Promise((resolve: Function, reject: Function) => { + findOneJsModule(variableName) { + return new Promise((resolve, reject) => { findJsModulesFor(this.config, variableName) - .then((jsModules: Array) => { + .then((jsModules) => { if (!jsModules.length) { resolve(null); return; } resolve(this.resolveOneJsModule(jsModules, variableName)); }) - .catch((error: Object) => { + .catch((error) => { reject(error); }); }); } - replaceImports(oldImportsRange: Object, newImports: ImportStatements) { + replaceImports(oldImportsRange, newImports) { const importStrings = newImports.toArray(); // Ensure that there is a blank line after the block of all imports @@ -407,14 +393,14 @@ export default class Importer { return; } - importStrings.reverse().forEach((importString: string) => { + importStrings.reverse().forEach((importString) => { // We need to add each line individually because the Vim buffer will // convert newline characters to `~@`. if (importString.indexOf('\n') !== -1) { importString .split('\n') .reverse() - .forEach((line: string) => { + .forEach((line) => { this.editor.insertBefore(oldImportsRange.start, line); }); } else { @@ -427,7 +413,7 @@ export default class Importer { } } - findCurrentImports(): Object { + findCurrentImports() { return findCurrentImports( this.config, this.editor.currentFileContent(), @@ -435,10 +421,7 @@ export default class Importer { ); } - resolveOneJsModule( - jsModules: Array, - variableName: string, - ): ?JsModule { + resolveOneJsModule(jsModules, variableName) { if (jsModules.length === 1) { const jsModule = jsModules[0]; return jsModule; @@ -448,13 +431,13 @@ export default class Importer { return undefined; } - const countSeparators = (importPath: string): number => { + const countSeparators = (importPath) => { const separators = importPath.match(/\//g); return separators ? separators.length : 0; }; this.unresolvedImports[variableName] = jsModules - .map((jsModule: JsModule): Object => ({ + .map((jsModule) => ({ displayName: jsModule .toImportStatement(this.config) .toImportStrings(Infinity, ' ')[0], @@ -469,7 +452,7 @@ export default class Importer { }, })) .sort( - (a: Object, b: Object): number => + (a, b) => countSeparators(a.data.importPath) - countSeparators(b.data.importPath), ); @@ -477,10 +460,7 @@ export default class Importer { return undefined; } - resolveModuleUsingCurrentImports( - jsModules: Array, - variableName: string, - ): ?JsModule { + resolveModuleUsingCurrentImports(jsModules, variableName) { if (jsModules.length === 1) { return jsModules[0]; } @@ -488,7 +468,7 @@ export default class Importer { // Look at the current imports and grab what is already imported for the // variable. const matchingImportStatement = this.findCurrentImports().imports.find( - (ist: ImportStatement): boolean => ist.hasVariable(variableName), + (ist) => ist.hasVariable(variableName), ); if (!matchingImportStatement) { @@ -499,7 +479,7 @@ export default class Importer { // Look for a module matching what is already imported const { path: matchingPath } = matchingImportStatement; return jsModules.find( - (jsModule: JsModule): boolean => + (jsModule) => matchingPath === jsModule.toImportStatement(this.config).path, ); } @@ -519,9 +499,9 @@ export default class Importer { return matchedModule; } - injectSideEffectImports(importStatements: ImportStatements): Array { + injectSideEffectImports(importStatements) { const addedImports = []; - this.config.get('moduleSideEffectImports').forEach((path: string) => { + this.config.get('moduleSideEffectImports').forEach((path) => { const sizeBefore = importStatements.size(); importStatements.push( new ImportStatement({ diff --git a/lib/JsModule.js b/lib/JsModule.js index ab03240..7dc9deb 100644 --- a/lib/JsModule.js +++ b/lib/JsModule.js @@ -1,4 +1,4 @@ -// @flow +// import path from 'path'; @@ -9,7 +9,7 @@ import requireResolve from './requireResolve'; import resolveImportPathAndMain from './resolveImportPathAndMain'; // TODO figure out a more holistic solution than stripping node_modules -function stripNodeModules(path: string): string { +function stripNodeModules(path) { if (path.startsWith('node_modules/')) { return path.slice(13); } @@ -19,17 +19,17 @@ function stripNodeModules(path: string): string { // Class that represents a js module found in the file system export default class JsModule { - hasNamedExports: ?boolean; + hasNamedExports; - isType: boolean; + isType; - importPath: string; + importPath; - filePath: string; + filePath; - variableName: string; + variableName; - workingDirectory: string; + workingDirectory; /** * @param {Boolean} hasNamedExports @@ -52,15 +52,7 @@ export default class JsModule { stripFileExtensions, variableName, workingDirectory = process.cwd(), - }: { - hasNamedExports?: boolean, - isType?: boolean, - makeRelativeTo?: ?string, - relativeFilePath: string, - stripFileExtensions: Array, - variableName: string, - workingDirectory: string, - } = {}): ?JsModule { + } = {}) { const jsModule = new JsModule(); jsModule.filePath = relativeFilePath; @@ -99,11 +91,6 @@ export default class JsModule { isType = false, importPath, variableName, - }: { - hasNamedExports?: boolean, - isType?: boolean, - importPath: string, - variableName: string, } = {}) { this.hasNamedExports = hasNamedExports; this.isType = isType; @@ -111,7 +98,7 @@ export default class JsModule { this.variableName = variableName; } - makeRelativeTo(makeRelativeToPath: string) { + makeRelativeTo(makeRelativeToPath) { let importPath = path.relative( path.dirname(makeRelativeToPath), this.importPath, @@ -127,10 +114,7 @@ export default class JsModule { this.importPath = importPath; } - resolvedFilePath( - pathToCurrentFile: string, - workingDirectory: string = process.cwd(), - ): string { + resolvedFilePath(pathToCurrentFile, workingDirectory = process.cwd()) { if (this.filePath) { return this.filePath; } @@ -160,21 +144,21 @@ export default class JsModule { ); } - _getNamedImports(): Array { + _getNamedImports() { if (!this.hasNamedExports) { return []; } return [{ localName: this.variableName, isType: this.isType }]; } - _getDefaultImport(): string { + _getDefaultImport() { if (this.hasNamedExports) { return ''; } return this.variableName; } - toImportStatement(config: Configuration): ImportStatement { + toImportStatement(config) { const namedImports = this._getNamedImports(); const defaultImport = this._getDefaultImport(); // TODO figure out a more holistic solution than stripping node_modules diff --git a/lib/Watcher.js b/lib/Watcher.js index 0cf7a4c..81f2479 100644 --- a/lib/Watcher.js +++ b/lib/Watcher.js @@ -1,4 +1,4 @@ -// @flow +// import fbWatchman from 'fb-watchman'; import minimatch from 'minimatch'; @@ -11,23 +11,23 @@ import normalizePath from './normalizePath'; const SUBSCRIPTION_NAME = 'import-js-subscription'; export default class Watcher { - workingDirectory: string; + workingDirectory; - excludes: Array; + excludes; - onFilesAdded: Function; + onFilesAdded; - onFilesRemoved: Function; + onFilesRemoved; - storage: ExportsStorage; + storage; constructor({ workingDirectory = process.cwd(), excludes = [], - onFilesAdded = (): Promise => Promise.resolve(), - onFilesRemoved = (): Promise => Promise.resolve(), + onFilesAdded = () => Promise.resolve(), + onFilesRemoved = () => Promise.resolve(), storage, - }: Object) { + }) { this.workingDirectory = workingDirectory; this.excludes = excludes; this.onFilesAdded = onFilesAdded; @@ -35,15 +35,7 @@ export default class Watcher { this.storage = storage; } - subscribe({ - client, - fbWatch, - relativePath, - }: { - client: fbWatchman.Client, - fbWatch: string, - relativePath: string, - }): Promise { + subscribe({ client, fbWatch, relativePath }) { const subscription = { // Match javascript files expression: [ @@ -58,10 +50,10 @@ export default class Watcher { relative_root: relativePath, }; - return new Promise((resolve: Function, reject: Function) => { + return new Promise((resolve, reject) => { client.command( ['subscribe', fbWatch, SUBSCRIPTION_NAME, subscription], - (error: Error) => { + (error) => { if (error) { reject(error); return; @@ -70,14 +62,14 @@ export default class Watcher { }, ); - client.on('subscription', (resp: Object) => { + client.on('subscription', (resp) => { if (resp.subscription !== SUBSCRIPTION_NAME) { return; } const added = []; const removed = []; - resp.files.forEach((file: Object) => { + resp.files.forEach((file) => { const normalizedPath = normalizePath( file.name, this.workingDirectory, @@ -86,9 +78,7 @@ export default class Watcher { return; } if ( - this.excludes.some((pattern: string): boolean => - minimatch(normalizedPath, pattern), - ) + this.excludes.some((pattern) => minimatch(normalizedPath, pattern)) ) { return; } @@ -108,11 +98,11 @@ export default class Watcher { }); } - startSubscription({ client }: { client: fbWatchman.Client }): Promise { - return new Promise((resolve: Function, reject: Function) => { + startSubscription({ client }) { + return new Promise((resolve, reject) => { client.command( ['watch-project', this.workingDirectory], - (error: Error, resp: Object) => { + (error, resp) => { if (error) { reject(error); return; @@ -136,11 +126,11 @@ export default class Watcher { }); } - initialize(): Promise { - return new Promise((resolve: Function, reject: Function) => { + initialize() { + return new Promise((resolve, reject) => { this.initializeWatchman() .then(resolve) - .catch((error: Object) => { + .catch((error) => { winston.warn(` Couldn't initialize the Watchman watcher. This is most likely because you don't have Watchman installed. Follow instructions here if you @@ -162,10 +152,10 @@ export default class Watcher { * resolve if watchman is available, and the file cache is enabled. Will * resolve immediately if previously initialized. */ - initializeWatchman(): Promise { - return new Promise((resolve: Function, reject: Function) => { + initializeWatchman() { + return new Promise((resolve, reject) => { const client = new fbWatchman.Client(); - client.on('error', (error: Error) => { + client.on('error', (error) => { reject(error); }); client.capabilityCheck( @@ -173,7 +163,7 @@ export default class Watcher { optional: [], required: ['relative_root'], }, - (error: Error) => { + (error) => { if (error) { client.end(); reject(error); @@ -185,24 +175,24 @@ export default class Watcher { }); } - initializePolling(): Promise { + initializePolling() { setInterval(() => { this.poll(); }, 30000); return this.poll(); } - poll(): Promise { - return new Promise((resolve: Function, reject: Function) => { + poll() { + return new Promise((resolve, reject) => { findAllFiles(this.workingDirectory, this.excludes) - .then((files: Array) => { + .then((files) => { const mtimes = {}; - files.forEach(({ path: pathToFile, mtime }: Object) => { + files.forEach(({ path: pathToFile, mtime }) => { mtimes[pathToFile] = mtime; }); - this.storage.allFiles().then((storedFiles: Array) => { + this.storage.allFiles().then((storedFiles) => { const removedFiles = []; - storedFiles.forEach((storedFile: string) => { + storedFiles.forEach((storedFile) => { if (storedFile.startsWith('./node_modules/')) { // Ignore this file, as it won't be in the list of all files (we // exclude node_modules by default). @@ -214,7 +204,7 @@ export default class Watcher { } }); this.onFilesAdded(files) - .then((): Promise => this.onFilesRemoved(removedFiles)) + .then(() => this.onFilesRemoved(removedFiles)) .then(resolve) .catch(reject); }); diff --git a/lib/__mocks__/requireResolve.js b/lib/__mocks__/requireResolve.js index cb17c61..87abd8c 100644 --- a/lib/__mocks__/requireResolve.js +++ b/lib/__mocks__/requireResolve.js @@ -1,7 +1,7 @@ -// @flow +// let resolvedPaths = {}; -function __addResolvedPath(alias: string, path: string) { +function __addResolvedPath(alias, path) { resolvedPaths[alias] = path; } @@ -11,7 +11,7 @@ function __reset() { __reset(); -export default function requireResolve(importPath: string): string { +export default function requireResolve(importPath) { return resolvedPaths[importPath] || importPath; } requireResolve.__reset = __reset; diff --git a/lib/environments/meteorEnvironment.js b/lib/environments/meteorEnvironment.js index bf7b48e..8451ad1 100644 --- a/lib/environments/meteorEnvironment.js +++ b/lib/environments/meteorEnvironment.js @@ -1,4 +1,4 @@ -// @flow +// import fs from 'fs'; import os from 'os'; @@ -46,7 +46,7 @@ const coreNamedExports = { 'meteor/tracker': ['Tracker'], }; -function meteorPackageDependencies({ config }: Object): Array { +function meteorPackageDependencies({ config }) { const meteorPackagesPath = path.join( config.workingDirectory, '.meteor/packages', @@ -88,7 +88,7 @@ function meteorPackageDependencies({ config }: Object): Array { // multiline match of characters allowed to be in a package name that are at // the beginning of a line, possibly following white space. const coreModulesSet = new Set(coreModules); - const packages: Array = ( + const packages = ( fs .readFileSync(meteorPackagesPath, 'utf8') // extract an array of package names (possibly with preceding whitespace) @@ -96,13 +96,13 @@ function meteorPackageDependencies({ config }: Object): Array { .match(/^\s*[a-z0-9:.-]+/gm) || [] ) // add 'meteor/' to the start of each name per Meteor convention - .map((pkg: string): string => `meteor/${pkg.trimLeft()}`) + .map((pkg) => `meteor/${pkg.trimLeft()}`) // eliminate those packages that are considered to be core - .filter((pkg: string): boolean => !coreModulesSet.has(pkg)); + .filter((pkg) => !coreModulesSet.has(pkg)); return packages; } -function meteorPackageVersions(projectRootDir: string): ?Map { +function meteorPackageVersions(projectRootDir) { // This function processes all of the package versions found in // .meteor/versions and returns a map containing them. @@ -116,11 +116,11 @@ function meteorPackageVersions(projectRootDir: string): ?Map { } const pkgVersions = new Map(); - const pkgVersionPairs: Array = + const pkgVersionPairs = fs.readFileSync(meteorVersionsPath, 'utf8').match(/^[^@\s]+@[^\s]+$/gm) || []; - pkgVersionPairs.forEach((pkgVersionPair: string) => { + pkgVersionPairs.forEach((pkgVersionPair) => { const [pkg, version] = pkgVersionPair.split('@'); pkgVersions.set(pkg, version); }); @@ -128,11 +128,7 @@ function meteorPackageVersions(projectRootDir: string): ?Map { return pkgVersions; } -function extractExportsFromMeteorPackage( - projectRootDir: string, - pkg: string, - pkgVersion: string, -): ?Array { +function extractExportsFromMeteorPackage(projectRootDir, pkg, pkgVersion) { // This function extracts the named exports from the package specified by pkg // and pkgVersion and returns them as an array of strings. If null is // returned, a problem was encountered in processing. If an empty array is @@ -280,9 +276,9 @@ function extractExportsFromMeteorPackage( // We can't guess which build the current module is being included in. So, // we'll find all declaredExports from all builds and combine them into one // namedExports specification. - const declaredExports: Set = new Set(); + const declaredExports = new Set(); - isopackVer.builds.forEach((build: Object) => { + isopackVer.builds.forEach((build) => { const buildIsopackPath = path.join(isopackRoot, build.path); const buildIsopack = FileUtils.readJsonFile(buildIsopackPath); @@ -292,7 +288,7 @@ function extractExportsFromMeteorPackage( return; } - buildIsopack.declaredExports.forEach((declaredExport: Object) => { + buildIsopack.declaredExports.forEach((declaredExport) => { if (!declaredExport.testOnly) { declaredExports.add(declaredExport.name); } @@ -302,7 +298,7 @@ function extractExportsFromMeteorPackage( // mainModule, we need to attempt to scan it to find exports. if (buildIsopack.resources) { const mainModuleResource = buildIsopack.resources.find( - (resource: Object): boolean => + (resource) => resource.fileOptions && resource.fileOptions.mainModule === true, ); @@ -314,7 +310,7 @@ function extractExportsFromMeteorPackage( const requiredFileContent = fs.readFileSync(pathToRequiredFile, 'utf8'); // returns a set, which we iterate into declaredExports const { named } = findExports(requiredFileContent, pathToRequiredFile); - named.forEach((name: string) => { + named.forEach((name) => { declaredExports.add(name); }); } @@ -324,7 +320,7 @@ function extractExportsFromMeteorPackage( return Array.from(declaredExports); } -function meteorPackageNamedExports({ config }: Object): Object { +function meteorPackageNamedExports({ config }) { // This function seeks to extract the named exports from all non-core, 3rd // party or local meteor packages being utilized in the application. The // meteorPackageDependencies function identifies that list of packages. @@ -338,7 +334,7 @@ function meteorPackageNamedExports({ config }: Object): Object { // meteorPackageDependencies const namedExports = {}; - meteorPackageDependencies({ config }).forEach((meteorPkg: string) => { + meteorPackageDependencies({ config }).forEach((meteorPkg) => { const pkg = meteorPkg.slice(7); const pkgVersion = pkgVersions.get(pkg) || ''; const extractedExports = extractExportsFromMeteorPackage( @@ -359,7 +355,7 @@ function meteorPackageNamedExports({ config }: Object): Object { export default { coreModules, - moduleNameFormatter({ moduleName, pathToImportedModule }: Object): string { + moduleNameFormatter({ moduleName, pathToImportedModule }) { // If the module being imported is a Meteor package, it will begin with // 'meteor/' and should not be altered. if (moduleName.startsWith('meteor/')) { @@ -382,10 +378,7 @@ export default { return moduleName; }, - moduleSideEffectImports({ - pathToCurrentFile, - config, - }: Object): Array { + moduleSideEffectImports({ pathToCurrentFile, config }) { let basePath = ''; if (pathToCurrentFile.endsWith('.js')) { @@ -400,7 +393,7 @@ export default { // DEBUG: should this also include preprocessor files? // ie. .jade, .pug, .less, .scss, .sass - ['.html', '.css'].forEach((ext: string) => { + ['.html', '.css'].forEach((ext) => { const moduleSpecifier = `${basePath}${ext}`; if (fs.existsSync(path.join(config.workingDirectory, moduleSpecifier))) { if (config.get('useRelativePaths')) { @@ -416,7 +409,7 @@ export default { return moduleSpecifiers; }, - namedExports({ config }: Object): Object { + namedExports({ config }) { const allNamedExports = coreNamedExports; // There are no worries about this overwriting the definitions of core // namedExports. meteorPackageNamedExports skips core packages. Even if it @@ -425,7 +418,7 @@ export default { return allNamedExports; }, - packageDependencies({ config }: Object): Set { + packageDependencies({ config }) { const npmPackages = findPackageDependencies( config.workingDirectory, config.get('importDevDependencies'), diff --git a/lib/findCurrentImports.js b/lib/findCurrentImports.js index 1400f10..62e046e 100644 --- a/lib/findCurrentImports.js +++ b/lib/findCurrentImports.js @@ -1,4 +1,4 @@ -// @flow +// import Configuration from './Configuration'; import ImportStatement from './ImportStatement'; @@ -6,19 +6,16 @@ import ImportStatements from './ImportStatements'; const DANGLING_COMMAS = /,[ \n]\}/; -function convertToImportStatement( - node: Object, - source: string, -): ?ImportStatement { +function convertToImportStatement(node, source) { if (node.type === 'ImportDeclaration') { const defaultSpecifier = node.specifiers.find( - (spec: Object): boolean => + (spec) => spec.type === 'ImportDefaultSpecifier' || spec.type === 'ImportNamespaceSpecifier', ); const namedImports = node.specifiers - .map((spec: Object): ?Object => { + .map((spec) => { if (spec.type !== 'ImportSpecifier') { return undefined; } @@ -95,7 +92,7 @@ function convertToImportStatement( const namedImports = declaration.id.type === 'ObjectPattern' - ? declaration.id.properties.map((p: Object): Object => ({ + ? declaration.id.properties.map((p) => ({ localName: p.value.name, })) : undefined; @@ -113,11 +110,7 @@ function convertToImportStatement( return undefined; } -export default function findCurrentImports( - config: Configuration, - currentFileContent: string, - ast: Object, -): Object { +export default function findCurrentImports(config, currentFileContent, ast) { const result = { imports: new ImportStatements(config), range: { @@ -127,7 +120,7 @@ export default function findCurrentImports( }; let done = false; - ast.program.body.forEach((node: Object, index: number) => { + ast.program.body.forEach((node, index) => { if (done) { return; } diff --git a/lib/findJsModulesFor.js b/lib/findJsModulesFor.js index 16dbc29..1476089 100644 --- a/lib/findJsModulesFor.js +++ b/lib/findJsModulesFor.js @@ -1,4 +1,4 @@ -// @flow +// import minimatch from 'minimatch'; import sortBy from 'lodash/sortBy'; @@ -8,18 +8,12 @@ import Configuration from './Configuration'; import JsModule from './JsModule'; import ModuleFinder from './ModuleFinder'; -function findImportsFromEnvironment( - config: Configuration, - variableName: string, -): Array { +function findImportsFromEnvironment(config, variableName) { return config .get('coreModules') - .filter( - (dep: string): boolean => - dep.toLowerCase() === variableName.toLowerCase(), - ) + .filter((dep) => dep.toLowerCase() === variableName.toLowerCase()) .map( - (dep: string): JsModule => + (dep) => new JsModule({ importPath: dep, variableName, @@ -28,18 +22,18 @@ function findImportsFromEnvironment( } function findJsModulesFromModuleFinder( - config: Configuration, - normalizedName: string, - variableName: string, - finder: ModuleFinder, - pathToCurrentFile: string, - options: Object = {}, -): Promise> { - return new Promise((resolve: Function, reject: Function) => { + config, + normalizedName, + variableName, + finder, + pathToCurrentFile, + options = {}, +) { + return new Promise((resolve, reject) => { let isWantedPackageDependency = Boolean; if (!config.get('importDevDependencies')) { const packageDependencies = config.get('packageDependencies'); - isWantedPackageDependency = (packageName: string): boolean => + isWantedPackageDependency = (packageName) => packageDependencies.has(packageName); } @@ -47,19 +41,13 @@ function findJsModulesFromModuleFinder( const method = isSearch ? 'search' : 'find'; finder[method](normalizedName) - .then((exports: Array) => { + .then((exports) => { const modules = exports.map( - ({ - name, - path, - isDefault, - isType, - packageName, - }: Object): ?JsModule => { + ({ name, path, isDefault, isType, packageName }) => { // Filter out modules that are in the `excludes` config. const isExcluded = config .get('excludes') - .some((glob: string): boolean => minimatch(path, glob)); + .some((glob) => minimatch(path, glob)); if (isExcluded) { return undefined; } @@ -98,37 +86,25 @@ function findJsModulesFromModuleFinder( }); } -export function dedupeAndSort(modules: Array): Array { +export function dedupeAndSort(modules) { // We might end up having duplicate modules here. In order to dedupe // these, we remove the module with the longest path - const sorted = sortBy( - modules, - (module: JsModule): number => module.importPath.length, - ); + const sorted = sortBy(modules, (module) => module.importPath.length); const uniques = uniqBy( sorted, // Default export and named export with same name from the same module are not considered dupes - (module: JsModule): string => - [module.importPath, module.hasNamedExports].join(), + (module) => [module.importPath, module.hasNamedExports].join(), ); // Sorting by path, but with default exports before named exports - return sortBy(uniques, (module: JsModule): string => + return sortBy(uniques, (module) => [module.importPath, module.hasNamedExports ? 1 : 0].join(), ); } const NON_PATH_ALIAS_PATTERN = /^[a-zA-Z0-9-_]+$/; -type FindJsModulesForOptionsType = { - search: boolean, -}; - -export default function findJsModulesFor( - config: Configuration, - variableName: string, - options?: FindJsModulesForOptionsType, -): Promise> { - return new Promise((resolve: Function, reject: Function) => { +export default function findJsModulesFor(config, variableName, options) { + return new Promise((resolve, reject) => { let normalizedName = variableName; const alias = config.resolveAlias(variableName); if (alias) { @@ -169,11 +145,11 @@ export default function findJsModulesFor( config.pathToCurrentFile, options, ) - .then((modules: Array) => { + .then((modules) => { matchedModules.push(...modules); resolve(dedupeAndSort(matchedModules)); }) - .catch((error: Object) => { + .catch((error) => { reject(error); }); }); diff --git a/lib/findPackageDependencies.js b/lib/findPackageDependencies.js index a244410..f1f0e14 100644 --- a/lib/findPackageDependencies.js +++ b/lib/findPackageDependencies.js @@ -1,4 +1,4 @@ -// @flow +// import path from 'path'; @@ -8,9 +8,9 @@ import FileUtils from './FileUtils'; * Finds dependencies from package.json */ export default function findPackageDependencies( - workingDirectory: string, - includeDevDependencies: boolean, -): Set { + workingDirectory, + includeDevDependencies, +) { const packageJson = FileUtils.readJsonFile( path.join(workingDirectory, 'package.json'), ); @@ -23,9 +23,9 @@ export default function findPackageDependencies( keys.push('devDependencies'); } const result = new Set(); - keys.forEach((key: string) => { + keys.forEach((key) => { if (Object.prototype.hasOwnProperty.call(packageJson, key)) { - Object.keys(packageJson[key]).forEach((packageName: string) => { + Object.keys(packageJson[key]).forEach((packageName) => { result.add(packageName); }); } diff --git a/lib/forwardSlashes.js b/lib/forwardSlashes.js index ec3f48c..ec2bdc6 100644 --- a/lib/forwardSlashes.js +++ b/lib/forwardSlashes.js @@ -1,4 +1,4 @@ -// @flow -export default function forwardSlashes(path: string): string { +// +export default function forwardSlashes(path) { return path.replace(/(^[A-Z]:\\|\\)/g, '/'); } diff --git a/lib/importjs.js b/lib/importjs.js index 4625a33..c711fa2 100644 --- a/lib/importjs.js +++ b/lib/importjs.js @@ -1,4 +1,4 @@ -// @flow +// import fs from 'fs'; import os from 'os'; import path from 'path'; @@ -13,26 +13,24 @@ import initializeLogging from './initializeLogging'; import initializeModuleFinder from './initializeModuleFinder'; import packageJson from '../package.json'; -import type JsModule from './JsModule'; - const pathToLogFile = path.join(os.tmpdir(), 'importjs.log'); initializeLogging(pathToLogFile); -function stdoutWrite(str: string) { +function stdoutWrite(str) { process.stdout.write(`${str}\n`); } -function stderrWrite(str: string) { +function stderrWrite(str) { process.stderr.write(`${str}\n`); } /** * Grab lines from stdin or directly from the file. */ -function getLines(pathToFile: string): Promise> { - return new Promise((resolve: Function, reject: Function) => { +function getLines(pathToFile) { + return new Promise((resolve, reject) => { if (process.stdin.isTTY) { - fs.readFile(pathToFile, 'utf-8', (err: ?Error, fileContent: string) => { + fs.readFile(pathToFile, 'utf-8', (err, fileContent) => { if (err) { reject(err); return; @@ -44,7 +42,7 @@ function getLines(pathToFile: string): Promise> { const parts = []; process.stdin.resume(); process.stdin.setEncoding('utf-8'); - process.stdin.on('data', (data: string) => { + process.stdin.on('data', (data) => { parts.push(data); }); process.stdin.on('end', () => { @@ -56,19 +54,15 @@ function getLines(pathToFile: string): Promise> { /** * Run a command/method on an importer instance */ -function runCommand( - executor: Function, - pathToFile: string, - { overwrite }: { overwrite: boolean }, -): Promise<*> { +function runCommand(executor, pathToFile, { overwrite }) { const workingDirectory = findProjectRoot(pathToFile); return initializeModuleFinder(workingDirectory) - .then((): Promise<*> => - getLines(pathToFile).then((lines: Array): Promise<*> => { + .then(() => + getLines(pathToFile).then((lines) => { const importer = new Importer(lines, pathToFile, workingDirectory); - return executor(importer).then((result: Object) => { + return executor(importer).then((result) => { if (overwrite) { - fs.writeFile(pathToFile, result.fileContent, (err: ?ErrnoError) => { + fs.writeFile(pathToFile, result.fileContent, (err) => { if (err) throw err; process.exit(0); }); @@ -79,7 +73,7 @@ function runCommand( }); }), ) - .catch((error: Object) => { + .catch((error) => { stderrWrite(error.message); process.exit(1); }); @@ -98,79 +92,68 @@ const sharedOptions = { program .command('word ') .option(...sharedOptions.overwrite) - .action((word: string, pathToFile: string, options: Object) => { - const executor = (importer: Importer): Promise => - importer.import(word); + .action((word, pathToFile, options) => { + const executor = (importer) => importer.import(word); runCommand(executor, pathToFile, options); }); program .command('search ') .option(...sharedOptions.overwrite) - .action((word: string, pathToFile: string, options: Object) => { - const executor = (importer: Importer): Promise> => - importer - .search(word) - .then( - ({ modules }: { modules: Array }): Array => - modules, - ); + .action((word, pathToFile, options) => { + const executor = (importer) => + importer.search(word).then(({ modules }) => modules); runCommand(executor, pathToFile, options); }); program .command('fix ') .option(...sharedOptions.overwrite) - .action((pathToFile: string, options: Object) => { - const executor = (importer: Importer): Promise => - importer.fixImports(); + .action((pathToFile, options) => { + const executor = (importer) => importer.fixImports(); runCommand(executor, pathToFile, options); }); program .command('rewrite ') .option(...sharedOptions.overwrite) - .action((pathToFile: string, options: Object) => { - const executor = (importer: Importer): Promise => - importer.rewriteImports(); + .action((pathToFile, options) => { + const executor = (importer) => importer.rewriteImports(); runCommand(executor, pathToFile, options); }); program .command('add ') .option(...sharedOptions.overwrite) - .action((imports: string, pathToFile: string, options: Object) => { - const executor = (importer: Importer): Promise => - importer.addImports(JSON.parse(imports)); + .action((imports, pathToFile, options) => { + const executor = (importer) => importer.addImports(JSON.parse(imports)); runCommand(executor, pathToFile, options); }); -program - .command('goto ') - .action((word: string, pathToFile: string) => { - const workingDirectory = findProjectRoot(pathToFile); - initializeModuleFinder(workingDirectory) - .then((): Promise<*> => - getLines(pathToFile).then((lines: Array) => { - new Importer(lines, pathToFile, workingDirectory) - .goto(word) - .then((result: Object) => { - stdoutWrite(JSON.stringify(result)); - process.exit(0); - }); - }), - ) - .catch((error: Error) => { - stderrWrite(error.message); - process.exit(1); - }); - }); +program.command('goto ').action((word, pathToFile) => { + const workingDirectory = findProjectRoot(pathToFile); + initializeModuleFinder(workingDirectory) + .then(() => + getLines(pathToFile).then((lines) => { + new Importer(lines, pathToFile, workingDirectory) + .goto(word) + .then((result) => { + stdoutWrite(JSON.stringify(result)); + process.exit(0); + }); + }), + ) + .catch((error) => { + stderrWrite(error.message); + process.exit(1); + }); +}); program .command('start') .description('start a daemon') .option('--parent-pid ', parseInt) - .action(({ parentPid }: Object) => { + .action(({ parentPid }) => { initializeLogging.parentPid = parentPid; daemon(parentPid, pathToLogFile); }); @@ -204,13 +187,13 @@ program.on('--help', () => { stdoutWrite(' Examples:'); stdoutWrite(''); - examples.forEach((example: string) => { + examples.forEach((example) => { stdoutWrite(` $ importjs ${example}`); }); stdoutWrite(''); }); -export default function importjs(argv: Array) { +export default function importjs(argv) { program.parse(argv); if (!argv.slice(2).length) { diff --git a/lib/normalizePath.js b/lib/normalizePath.js index 511d0e8..ee61c33 100644 --- a/lib/normalizePath.js +++ b/lib/normalizePath.js @@ -1,9 +1,6 @@ -// @flow +// -export default function normalizePath( - rawPath: ?string, - workingDirectory: string, -): string { +export default function normalizePath(rawPath, workingDirectory) { if (!rawPath) { return './'; } diff --git a/lib/parse.js b/lib/parse.js index d970491..1866cc5 100644 --- a/lib/parse.js +++ b/lib/parse.js @@ -1,4 +1,4 @@ -// @flow +// export const DEFAULT_PARSER_PLUGINS = [ 'jsx', @@ -33,16 +33,12 @@ export const DEFAULT_PARSER_PLUGINS = [ const TYPESCRIPT_FILE_PATH_REGEX = /\.tsx?$/; let parserPlugins = DEFAULT_PARSER_PLUGINS; -export function configureParserPlugins( - newParserPlugins: Array, -) { +export function configureParserPlugins(newParserPlugins) { parserPlugins = newParserPlugins; return; } -function getParserPlugins( - absolutePathToFile: string, -): Array { +function getParserPlugins(absolutePathToFile) { const typePlugin = TYPESCRIPT_FILE_PATH_REGEX.test(absolutePathToFile) ? 'typescript' : 'flow'; @@ -50,10 +46,7 @@ function getParserPlugins( return [typePlugin, ...parserPlugins]; } -export default function parse( - fileContent: string, - absolutePathToFile: string, -): Object { +export default function parse(fileContent, absolutePathToFile) { // For some reason, we can't `import` @babel/parser using an es6 import. const babelParser = require('@babel/parser'); diff --git a/lib/requireResolve.js b/lib/requireResolve.js index 93cf2f1..7d47114 100644 --- a/lib/requireResolve.js +++ b/lib/requireResolve.js @@ -1,11 +1,11 @@ -// @flow +// import path from 'path'; /** * Thin wrapper around `require.resolve()` to avoid errors thrown, and to make * it easier to mock in tests. */ -export default function requireResolve(absolutePath: string): string { +export default function requireResolve(absolutePath) { if (!path.isAbsolute(absolutePath)) { throw new Error(`Path must be absolute: ${absolutePath}`); } diff --git a/lib/resolveImportPathAndMain.js b/lib/resolveImportPathAndMain.js index cd6375b..4ce7107 100644 --- a/lib/resolveImportPathAndMain.js +++ b/lib/resolveImportPathAndMain.js @@ -1,4 +1,4 @@ -// @flow +// import fs from 'fs'; import path from 'path'; @@ -7,17 +7,13 @@ import escapeRegExp from 'lodash/escapeRegExp'; import FileUtils from './FileUtils'; import forwardSlashes from './forwardSlashes'; -function findIndex(directory: string): ?string { - return ['index.js', 'index.jsx', 'index.ts', 'index.tsx'].find( - (indexFile: string): boolean => - fs.existsSync(path.join(directory, indexFile)), +function findIndex(directory) { + return ['index.js', 'index.jsx', 'index.ts', 'index.tsx'].find((indexFile) => + fs.existsSync(path.join(directory, indexFile)), ); } -function resolveForPackage( - filePath: string, - workingDirectory: string, -): ?Array { +function resolveForPackage(filePath, workingDirectory) { if (!filePath.endsWith('/package.json')) { return null; } @@ -57,10 +53,10 @@ function resolveForPackage( } export default function resolveImportPathAndMain( - filePath: string, - stripFileExtensions: Array, - workingDirectory: string = process.cwd(), -): Array { + filePath, + stripFileExtensions, + workingDirectory = process.cwd(), +) { const resolvedForPackage = resolveForPackage(filePath, workingDirectory); if (resolvedForPackage) { return resolvedForPackage; @@ -75,9 +71,7 @@ export default function resolveImportPathAndMain( return [filePath, null]; } - const extensions = stripFileExtensions.map((ext: string): string => - escapeRegExp(ext), - ); + const extensions = stripFileExtensions.map((ext) => escapeRegExp(ext)); const importPath = filePath.replace(RegExp(`(${extensions.join('|')})$`), ''); return [importPath, null]; } diff --git a/lib/version.js b/lib/version.js index 9c593d9..c206c7b 100644 --- a/lib/version.js +++ b/lib/version.js @@ -1,4 +1,4 @@ -// @flow +// // This gets its own module so that it can be more easily mocked out in tests. @@ -7,6 +7,6 @@ import packageJson from '../package.json'; /** * @return {String} */ -export default function version(): string { +export default function version() { return packageJson.version; } From 7d5c1c92ce08d2c4c482eabf84878c02d7513ee7 Mon Sep 17 00:00:00 2001 From: Joe Lencioni Date: Fri, 7 Jun 2024 10:57:23 -0500 Subject: [PATCH 3/8] Remove Flow dev dependencies TypeScript pretty much won, and we've removed Flow annotations from this repo. --- .babelrc | 3 +- package-lock.json | 121 +++------------------------------------------- package.json | 9 +--- 3 files changed, 10 insertions(+), 123 deletions(-) diff --git a/.babelrc b/.babelrc index d6465d7..02b40ff 100644 --- a/.babelrc +++ b/.babelrc @@ -1,7 +1,6 @@ { - "presets": ["@babel/preset-react", "@babel/preset-env", "@babel/preset-flow"], + "presets": ["@babel/preset-react", "@babel/preset-env"], "plugins": [ - "@babel/plugin-transform-flow-strip-types", "@babel/plugin-proposal-class-properties", "@babel/plugin-transform-runtime" ] diff --git a/package-lock.json b/package-lock.json index b8d6125..5e66516 100644 --- a/package-lock.json +++ b/package-lock.json @@ -32,17 +32,13 @@ }, "devDependencies": { "@babel/cli": "^7.7.5", - "@babel/eslint-parser": "^7.23.3", "@babel/plugin-proposal-class-properties": "^7.7.4", - "@babel/plugin-transform-flow-strip-types": "^7.7.4", "@babel/plugin-transform-runtime": "^7.7.6", "@babel/preset-env": "^7.7.6", - "@babel/preset-flow": "^7.7.4", "@babel/preset-react": "^7.7.4", "@eslint/js": "^9.4.0", "babel-jest": "^24.9.0", "eslint": "^9.4.0", - "flow-bin": "^0.113.0", "globals": "^15.4.0", "jest": "^29.7.0", "mkdirp": "^0.5.1", @@ -149,24 +145,6 @@ "url": "https://opencollective.com/babel" } }, - "node_modules/@babel/eslint-parser": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.23.3.tgz", - "integrity": "sha512-9bTuNlyx7oSstodm1cR1bECj4fkiknsDa1YniISkJemMY3DGhJNYBECbe6QD/q54mp2J8VO66jW3/7uP//iFCw==", - "dev": true, - "dependencies": { - "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", - "eslint-visitor-keys": "^2.1.0", - "semver": "^6.3.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || >=14.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.11.0", - "eslint": "^7.5.0 || ^8.0.0" - } - }, "node_modules/@babel/generator": { "version": "7.23.6", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", @@ -361,9 +339,9 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", - "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.7.tgz", + "integrity": "sha512-Rq76wjt7yz9AAc1KnlRKNAi/dMSVWgDRx43FHoJEbcYU6xOWaE2dVPwcdTukJrjxS65GITyfbvEYHvkirZ6uEg==", "engines": { "node": ">=6.9.0" } @@ -664,11 +642,11 @@ } }, "node_modules/@babel/plugin-syntax-flow": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.23.3.tgz", - "integrity": "sha512-YZiAIpkJAwQXBJLIQbRFayR5c+gJ35Vcz3bg954k7cd73zqjvhacJuL9RbrzPz8qPmZdgqP6EUKwy0PCNhaaPA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.24.7.tgz", + "integrity": "sha512-9G8GYT/dxn/D1IIKOUBmGX0mnmj46mGH9NnZyJLwtCpgh5f7D2VbuKodb+2s9m1Yavh1s7ASQN8lf0eqrb1LTw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1131,22 +1109,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-flow-strip-types": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.23.3.tgz", - "integrity": "sha512-26/pQTf9nQSNVJCrLB1IkHUKyPxR+lMrH2QDPG89+Znu9rAMbtrybdbWeE9bb7gzjmE5iXHEY+e0HUwM6Co93Q==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-flow": "^7.23.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@babel/plugin-transform-for-of": { "version": "7.23.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.23.6.tgz", @@ -1853,23 +1815,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/preset-flow": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.23.3.tgz", - "integrity": "sha512-7yn6hl8RIv+KNk6iIrGZ+D06VhVY35wLVf23Cz/mMu1zOr7u4MMP4j0nZ9tLf8+4ZFpnib8cFYgB/oYg9hfswA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-validator-option": "^7.22.15", - "@babel/plugin-transform-flow-strip-types": "^7.23.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@babel/preset-modules": { "version": "0.1.6-no-external-plugins", "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", @@ -4139,15 +4084,6 @@ "dev": true, "optional": true }, - "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": { - "version": "5.1.1-v1", - "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", - "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==", - "dev": true, - "dependencies": { - "eslint-scope": "5.1.1" - } - }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -5962,37 +5898,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint-scope/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, "node_modules/eslint/node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -6864,18 +6769,6 @@ "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", "dev": true }, - "node_modules/flow-bin": { - "version": "0.113.0", - "resolved": "https://registry.npmjs.org/flow-bin/-/flow-bin-0.113.0.tgz", - "integrity": "sha512-76uE2LGNe50wm+Jup8Np4FBcMbyy5V2iE+K25PPIYLaEMGHrL1jnQfP9L0hTzA5oh2ZJlexRLMlaPqIYIKH9nw==", - "dev": true, - "bin": { - "flow": "cli.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/fn.name": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", diff --git a/package.json b/package.json index b0e96bd..6f5709f 100644 --- a/package.json +++ b/package.json @@ -9,14 +9,13 @@ "scripts": { "build": "babel lib --ignore ./lib/__tests__,./lib/__mocks__ --out-dir build", "clean": "rimraf build", - "flow": "flow", "jest": "jest", "prettier": "prettier --write .", "jest:cover": "jest --coverage", "prepublish": "npm run clean && npm run build", "preversion": "npm run clean && npm run build && npm test", - "test": "npm run --silent prettier && npm run --silent flow && npm run --silent jest", - "test:cover": "npm run --silent flow && npm run --silent jest:cover" + "test": "npm run --silent prettier && npm run --silent jest", + "test:cover": "npm run --silent jest:cover" }, "repository": { "type": "git", @@ -45,17 +44,13 @@ "homepage": "https://github.com/galooshi/import-js#readme", "devDependencies": { "@babel/cli": "^7.7.5", - "@babel/eslint-parser": "^7.23.3", "@babel/plugin-proposal-class-properties": "^7.7.4", - "@babel/plugin-transform-flow-strip-types": "^7.7.4", "@babel/plugin-transform-runtime": "^7.7.6", "@babel/preset-env": "^7.7.6", - "@babel/preset-flow": "^7.7.4", "@babel/preset-react": "^7.7.4", "@eslint/js": "^9.4.0", "babel-jest": "^24.9.0", "eslint": "^9.4.0", - "flow-bin": "^0.113.0", "globals": "^15.4.0", "jest": "^29.7.0", "mkdirp": "^0.5.1", From 98c8ec3ec0d3214ffe81895fa37f76ed43073aaa Mon Sep 17 00:00:00 2001 From: Joe Lencioni Date: Fri, 7 Jun 2024 14:24:28 -0500 Subject: [PATCH 4/8] Add `npm run jest:watch` command For convenience. --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 6f5709f..6fa6343 100644 --- a/package.json +++ b/package.json @@ -10,9 +10,10 @@ "build": "babel lib --ignore ./lib/__tests__,./lib/__mocks__ --out-dir build", "clean": "rimraf build", "jest": "jest", - "prettier": "prettier --write .", "jest:cover": "jest --coverage", + "jest:watch": "jest --watch", "prepublish": "npm run clean && npm run build", + "prettier": "prettier --write .", "preversion": "npm run clean && npm run build && npm test", "test": "npm run --silent prettier && npm run --silent jest", "test:cover": "npm run --silent jest:cover" From 3806e32a23f64b2b74bf3ee428207666b006e453 Mon Sep 17 00:00:00 2001 From: Joe Lencioni Date: Fri, 7 Jun 2024 14:34:03 -0500 Subject: [PATCH 5/8] Configure ESLint better This is a node project, not a browser project, so we need to use the node globals. And we also need to tell ESLint about our tests, and how to ignore the stuff that used to be in the .eslintignore file. This resolves most of the errors. --- .eslintignore | 2 -- eslint.config.mjs | 25 ++++++++++++++++++++----- package.json | 1 + 3 files changed, 21 insertions(+), 7 deletions(-) delete mode 100644 .eslintignore diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index c40a5dc..0000000 --- a/.eslintignore +++ /dev/null @@ -1,2 +0,0 @@ -/build -/coverage diff --git a/eslint.config.mjs b/eslint.config.mjs index 2edbef8..8c0f9b6 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,8 +1,23 @@ -import globals from "globals"; -import pluginJs from "@eslint/js"; - +import globals from 'globals'; +import pluginJs from '@eslint/js'; export default [ - {languageOptions: { globals: globals.browser }}, + { + ignores: ['build/**', 'coverage/**'], + }, + + { + languageOptions: { + globals: globals.node, + }, + }, + pluginJs.configs.recommended, -]; \ No newline at end of file + + { + files: ['**/__mocks__/**', '**/__tests__/**'], + languageOptions: { + globals: globals.jest, + }, + }, +]; diff --git a/package.json b/package.json index 6fa6343..078087e 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "scripts": { "build": "babel lib --ignore ./lib/__tests__,./lib/__mocks__ --out-dir build", "clean": "rimraf build", + "eslint": "eslint", "jest": "jest", "jest:cover": "jest --coverage", "jest:watch": "jest --watch", From 73b24eb11c707a877467806e74afe8a4c46d7909 Mon Sep 17 00:00:00 2001 From: Joe Lencioni Date: Fri, 7 Jun 2024 14:40:53 -0500 Subject: [PATCH 6/8] Fix ESLint errors Now that we have ESLint set up, we need to fix the things it complained about. This handles all of that in one commit. --- lib/ImportStatements.js | 5 ----- lib/Importer.js | 4 +--- lib/JsModule.js | 3 --- lib/ModuleFinder.js | 2 +- lib/Watcher.js | 3 --- lib/__tests__/configurationSchema-test.js | 6 ++++-- lib/configurationSchema.js | 2 +- lib/daemon.js | 2 +- lib/findCurrentImports.js | 3 --- lib/findExports.js | 13 ++++++------- lib/findJsModulesFor.js | 3 --- 11 files changed, 14 insertions(+), 32 deletions(-) diff --git a/lib/ImportStatements.js b/lib/ImportStatements.js index 5f9824a..097e3ae 100644 --- a/lib/ImportStatements.js +++ b/lib/ImportStatements.js @@ -1,14 +1,9 @@ -// - // Class that sorts ImportStatements as they are pushed in import flattenDeep from 'lodash/flattenDeep'; import partition from 'lodash/partition'; import sortBy from 'lodash/sortBy'; import uniqBy from 'lodash/uniqBy'; -import Configuration from './Configuration'; -import ImportStatement from './ImportStatement'; - const STYLE_SIDE_EFFECT = 'side-effect'; const STYLE_IMPORT = 'import'; const STYLE_CONST = 'const'; diff --git a/lib/Importer.js b/lib/Importer.js index cf0495f..be73f3f 100644 --- a/lib/Importer.js +++ b/lib/Importer.js @@ -1,4 +1,3 @@ -// import path from 'path'; import requireRelative from 'require-relative'; @@ -39,7 +38,6 @@ function fixImportsMessage(removedItems, addedItems) { } function findFilePathFromImports(imports, dirname, variableName) { - // eslint-disable-next-line no-restricted-syntax const importStatement = imports.find((is) => is.hasVariable(variableName)); if (!importStatement) { @@ -48,7 +46,7 @@ function findFilePathFromImports(imports, dirname, variableName) { try { return requireRelative.resolve(importStatement.path, dirname); - } catch (e) { + } catch { // it's expected that we can't resolve certain paths. } return undefined; diff --git a/lib/JsModule.js b/lib/JsModule.js index 7dc9deb..e5346b7 100644 --- a/lib/JsModule.js +++ b/lib/JsModule.js @@ -1,8 +1,5 @@ -// - import path from 'path'; -import Configuration from './Configuration'; import ImportStatement from './ImportStatement'; import forwardSlashes from './forwardSlashes'; import requireResolve from './requireResolve'; diff --git a/lib/ModuleFinder.js b/lib/ModuleFinder.js index e0163e9..91038fe 100644 --- a/lib/ModuleFinder.js +++ b/lib/ModuleFinder.js @@ -38,7 +38,7 @@ function expandFiles(files, workingDirectory) { // path.relative won't add "./", but we need it further down the line resolvedPath = `./${resolvedPath}`; } - } catch (e) { + } catch { winston.error( `Failed to resolve "${dep}" relative to ${workingDirectory}`, ); diff --git a/lib/Watcher.js b/lib/Watcher.js index 81f2479..a5c58c5 100644 --- a/lib/Watcher.js +++ b/lib/Watcher.js @@ -1,10 +1,7 @@ -// - import fbWatchman from 'fb-watchman'; import minimatch from 'minimatch'; import winston from 'winston'; -import ExportsStorage from './ExportsStorage'; import findAllFiles from './findAllFiles'; import normalizePath from './normalizePath'; diff --git a/lib/__tests__/configurationSchema-test.js b/lib/__tests__/configurationSchema-test.js index 573bb76..d298c2b 100644 --- a/lib/__tests__/configurationSchema-test.js +++ b/lib/__tests__/configurationSchema-test.js @@ -23,7 +23,9 @@ it('should notify about unknown identifiers, and remove them', () => { const result = validate(data); expect(result.error).toEqual(true); expect(result.messages[0]).toEqual('Unknown configuration: `thisAintRight`'); - expect(data.hasOwnProperty('thisAintRight')).toBe(false); + expect(Object.prototype.hasOwnProperty.call(data, 'thisAintRight')).toBe( + false, + ); }); it('should handle functions', () => { @@ -41,5 +43,5 @@ it('should notify about invalid identifiers, and remove them', () => { expect(result.error).toEqual(true); expect(result.messages.length).toEqual(1); expect(result.messages[0]).toEqual('Invalid configuration: `aliases`'); - expect(data.hasOwnProperty('aliases')).toBe(false); + expect(Object.prototype.hasOwnProperty.call(data, 'aliases')).toBe(false); }); diff --git a/lib/configurationSchema.js b/lib/configurationSchema.js index 5c249f3..2e7252a 100644 --- a/lib/configurationSchema.js +++ b/lib/configurationSchema.js @@ -387,7 +387,7 @@ export function getDefaultConfig() { `Expected the value at SCHEMA.${k} to be an object, but it was of type '${typeof v}'. Got: ${v}`, ); } - if (v.hasOwnProperty('default')) { + if (Object.prototype.hasOwnProperty.call(v, 'default')) { acc[k] = v.default; } return acc; diff --git a/lib/daemon.js b/lib/daemon.js index c7a27e5..6670520 100644 --- a/lib/daemon.js +++ b/lib/daemon.js @@ -30,7 +30,7 @@ export default function daemon(parentPid, pathToLogFile) { ); try { process.kill(parentPid, 0); - } catch (error) { + } catch { winston.info('Parent process seems to have died. Exiting.'); process.exit(1); } diff --git a/lib/findCurrentImports.js b/lib/findCurrentImports.js index 62e046e..ce5166a 100644 --- a/lib/findCurrentImports.js +++ b/lib/findCurrentImports.js @@ -1,6 +1,3 @@ -// - -import Configuration from './Configuration'; import ImportStatement from './ImportStatement'; import ImportStatements from './ImportStatements'; diff --git a/lib/findExports.js b/lib/findExports.js index 45002db..aa28c5d 100644 --- a/lib/findExports.js +++ b/lib/findExports.js @@ -8,7 +8,7 @@ import parse from './parse'; function findESNamedExports(node, { absolutePathToFile }) { if (node.type === 'ExportAllDeclaration') { // Recurse the file referenced by the declaration - // eslint-disable-next-line no-use-before-define + return resolveNestedNamedExports(node, absolutePathToFile); } @@ -141,7 +141,7 @@ function resolveNestedNamedExports(node, absolutePathToFile) { ); const requiredFileContent = fs.readFileSync(pathToRequiredFile, 'utf8'); - // eslint-disable-next-line no-use-before-define + const { named } = findExports(requiredFileContent, pathToRequiredFile); return named; } @@ -152,7 +152,7 @@ function resolveNestedNamedExports(node, absolutePathToFile) { ); const requiredFileContent = fs.readFileSync(pathToRequiredFile, 'utf8'); - // eslint-disable-next-line no-use-before-define + const { named } = findExports(requiredFileContent, pathToRequiredFile); return named; } @@ -255,12 +255,11 @@ function findDefinedNames(node, definedNames) { return; } if (init.type === 'ObjectExpression') { - // eslint-disable-next-line no-param-reassign definedNames[id.name] = init.properties .map(({ key }) => key && key.name) .filter(Boolean); } else if (init.type === 'FunctionExpression') { - definedNames[id.name] = []; // eslint-disable-line no-param-reassign + definedNames[id.name] = []; } }); } @@ -365,7 +364,7 @@ function findRawNamedExports(data) { const result = new Set(); const pattern = /^exports\.(\w+)\s*=\s*[\w.]+;$/gm; let match; - // eslint-disable-next-line no-cond-assign + while ((match = pattern.exec(data)) !== null) { const name = match[1]; if (name !== 'default') { @@ -392,7 +391,7 @@ function findRootNodes(ast) { return callee.object.body.body; } return callee.body.body; - } catch (e) { + } catch { // ignore } return realRootNodes; diff --git a/lib/findJsModulesFor.js b/lib/findJsModulesFor.js index 1476089..93bf470 100644 --- a/lib/findJsModulesFor.js +++ b/lib/findJsModulesFor.js @@ -1,10 +1,7 @@ -// - import minimatch from 'minimatch'; import sortBy from 'lodash/sortBy'; import uniqBy from 'lodash/uniqBy'; -import Configuration from './Configuration'; import JsModule from './JsModule'; import ModuleFinder from './ModuleFinder'; From fd0c5e7cffa70ae4ace2d2e99a3df93388b5f5fd Mon Sep 17 00:00:00 2001 From: Joe Lencioni Date: Fri, 7 Jun 2024 14:54:24 -0500 Subject: [PATCH 7/8] Add Lint GitHub workflow This will help us avoid committing errors. --- .github/workflows/lint.yaml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 .github/workflows/lint.yaml diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml new file mode 100644 index 0000000..19fda19 --- /dev/null +++ b/.github/workflows/lint.yaml @@ -0,0 +1,22 @@ +name: ESLint + +on: [push] + +jobs: + eslint: + name: ESLint + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Set up Node.js + uses: actions/setup-node@v3 + with: + node-version: 20 + + - name: Install dependencies + run: npm ci + + - name: Run ESLint + run: npm run eslint From bc3bd793f9fcba736238db68ea08678afb2c152c Mon Sep 17 00:00:00 2001 From: Joe Lencioni Date: Sun, 9 Jun 2024 08:10:33 -0500 Subject: [PATCH 8/8] Add eslint to `npm test` This will make it easier for folks to catch errors as they work. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 078087e..97be7d3 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "prepublish": "npm run clean && npm run build", "prettier": "prettier --write .", "preversion": "npm run clean && npm run build && npm test", - "test": "npm run --silent prettier && npm run --silent jest", + "test": "npm run --silent prettier && npm run --silent eslint && npm run --silent jest", "test:cover": "npm run --silent jest:cover" }, "repository": {