From c9d3c9894b58d14b68eacb850241526224b00031 Mon Sep 17 00:00:00 2001 From: Amin Yahyaabadi Date: Tue, 30 May 2023 22:55:24 -0700 Subject: [PATCH] feat: fix checking for existence of typescript files --- .vscode/settings.json | 3 + package.json | 3 + pnpm-lock.yaml | 155 ++++++++++++++++++++++++++++++++++++++++++ src/typescript.js | 44 ++++++------ src/utils.js | 30 ++++++++ 5 files changed, 211 insertions(+), 24 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 src/utils.js diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..a2b5c76 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "cSpell.words": ["globify"] +} diff --git a/package.json b/package.json index faa74dd..9e0e73f 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "@babel/plugin-syntax-jsx": "^7.21.4", "@typescript-eslint/eslint-plugin": "6.0.0-alpha.138", "@typescript-eslint/parser": "6.0.0-alpha.138", + "anymatch": "^3.1.3", "eslint": "^8.41.0", "eslint-config-prettier": "^8.8.0", "eslint-plugin-html": "^7.1.0", @@ -37,6 +38,8 @@ "eslint-plugin-optimize-regex": "^1.2.1", "eslint-plugin-react": "^7.32.2", "eslint-plugin-yaml": "^0.5.0", + "globify-gitignore": "^1.0.3", + "make-synchronous": "^0.1.1", "prettier": "2.8.8", "read-pkg-up": "^7.0.1", "semver": "^7.5.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 189e34b..44b4770 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -23,6 +23,9 @@ dependencies: '@typescript-eslint/parser': specifier: 6.0.0-alpha.138 version: 6.0.0-alpha.138(eslint@8.41.0)(typescript@5.0.4) + anymatch: + specifier: ^3.1.3 + version: 3.1.3 eslint: specifier: ^8.41.0 version: 8.41.0 @@ -53,6 +56,12 @@ dependencies: eslint-plugin-yaml: specifier: ^0.5.0 version: 0.5.0 + globify-gitignore: + specifier: ^1.0.3 + version: 1.0.3 + make-synchronous: + specifier: ^0.1.1 + version: 0.1.1 prettier: specifier: 2.8.8 version: 2.8.8 @@ -930,6 +939,14 @@ packages: engines: {node: '>=12'} dev: true + /anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + dev: false + /aproba@2.0.0: resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} dev: true @@ -974,6 +991,12 @@ packages: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} + /array-uniq@1.0.3: + resolution: {integrity: sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==} + engines: {node: '>=0.10.0'} + dev: false + optional: true + /array.prototype.flat@1.3.1: resolution: {integrity: sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==} engines: {node: '>= 0.4'} @@ -1287,6 +1310,12 @@ packages: resolution: {integrity: sha512-x1mgZEXK8jHIfAxm+xgdpHpk50IN3z3q3zP261/WS+uvePxW8izXuCu6AHz0lkuYTlATDehiZ/tNyYBdSQsOUQ==} dev: false + /chainsaw@0.0.9: + resolution: {integrity: sha512-nG8PYH+/4xB+8zkV4G844EtfvZ5tTiLFoX3dZ4nhF4t3OCKIb9UvaFyNmeZO2zOSmRWzBoTD+napN6hiL+EgcA==} + dependencies: + traverse: 0.3.9 + dev: false + /chalk@1.1.3: resolution: {integrity: sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==} engines: {node: '>=0.10.0'} @@ -1477,6 +1506,11 @@ packages: shebang-command: 2.0.0 which: 2.0.2 + /crypto-random-string@2.0.0: + resolution: {integrity: sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==} + engines: {node: '>=8'} + dev: false + /crypto-random-string@4.0.0: resolution: {integrity: sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==} engines: {node: '>=12'} @@ -1540,6 +1574,10 @@ packages: mimic-response: 3.1.0 dev: true + /dedent@0.7.0: + resolution: {integrity: sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==} + dev: false + /deep-equal@2.2.1: resolution: {integrity: sha512-lKdkdV6EOGoVn65XaOsPdH4rMxTZOnmFyuIkMjM1i5HHCbfjC97dawgTAy0deYNfuqUqW+Q5VrVaQYtUpSd6yQ==} dependencies: @@ -1876,6 +1914,11 @@ packages: engines: {node: '>=0.8.0'} dev: false + /escape-string-regexp@2.0.0: + resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} + engines: {node: '>=8'} + dev: false + /escape-string-regexp@4.0.0: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} @@ -2686,6 +2729,17 @@ packages: slash: 4.0.0 dev: true + /globify-gitignore@1.0.3: + resolution: {integrity: sha512-yfwxPrXeIf6EvirmOZ8LOPxETorIbusANNnHdpXtmDwMW10NSEv4j2kgjWUR9OTRHtdchc07AFmgXLc29Wv89w==} + dependencies: + dedent: 0.7.0 + is-valid-path: 0.1.1 + remove: 0.1.5 + optionalDependencies: + make-unique: 1.0.4 + sort-es: 1.6.10 + dev: false + /gopd@1.0.1: resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} dependencies: @@ -2785,6 +2839,12 @@ packages: dependencies: function-bind: 1.1.1 + /hashish@0.0.4: + resolution: {integrity: sha512-xyD4XgslstNAs72ENaoFvgMwtv8xhiDtC2AtzCG+8yF7W/Knxxm9BX+e2s25mm+HxMKh0rBmXVOEGF3zNImXvA==} + dependencies: + traverse: 0.6.7 + dev: false + /hosted-git-info@2.8.9: resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} dev: false @@ -3035,6 +3095,11 @@ packages: hasBin: true dev: true + /is-extglob@1.0.0: + resolution: {integrity: sha512-7Q+VbVafe6x2T+Tu6NcOf6sRklazEPmBoB3IWk3WdGZM2iGUwU/Oe3Wtq5lSEkDTTlpp8yx+5t4pzO/i9Ty1ww==} + engines: {node: '>=0.10.0'} + dev: false + /is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} @@ -3044,6 +3109,13 @@ packages: engines: {node: '>=8'} dev: true + /is-glob@2.0.1: + resolution: {integrity: sha512-a1dBeB19NXsf/E0+FHqkagizel/LQw2DjSQpvQrj3zT+jYPpaUCryPnrQajXKFLCMuf4I6FhRpaGtw4lPrG6Eg==} + engines: {node: '>=0.10.0'} + dependencies: + is-extglob: 1.0.0 + dev: false + /is-glob@4.0.3: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} @@ -3066,6 +3138,13 @@ packages: is-path-inside: 3.0.3 dev: true + /is-invalid-path@0.1.0: + resolution: {integrity: sha512-aZMG0T3F34mTg4eTdszcGXx54oiZ4NtHSft3hWNJMGJXUUqdIj3cOZuHcU0nCWWcY3jd7yRe/3AEm3vSNTpBGQ==} + engines: {node: '>=0.10.0'} + dependencies: + is-glob: 2.0.1 + dev: false + /is-lambda@1.0.1: resolution: {integrity: sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==} dev: true @@ -3173,6 +3252,13 @@ packages: resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==} dev: true + /is-valid-path@0.1.1: + resolution: {integrity: sha512-+kwPrVDu9Ms03L90Qaml+79+6DZHqHyRoANI6IsZJ/g8frhnfchDOBCa0RbQ6/kdHt5CS5OeIEyrYznNuVN+8A==} + engines: {node: '>=0.10.0'} + dependencies: + is-invalid-path: 0.1.0 + dev: false + /is-weakmap@2.0.1: resolution: {integrity: sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==} dev: false @@ -3476,6 +3562,23 @@ packages: - supports-color dev: true + /make-synchronous@0.1.1: + resolution: {integrity: sha512-Y4SxxqhaoyMDokJQ0AZz0E+bLhRkOSR7Z/IQoTKPdS6HYi3aobal2kMHoHHoqBadPWjf07P4K1FQLXOx3wf9Yw==} + engines: {node: '>=12'} + dependencies: + subsume: 3.0.0 + type-fest: 0.16.0 + dev: false + + /make-unique@1.0.4: + resolution: {integrity: sha512-fhy5iusM7DNzilx1gW1YvAm1d6VjZ1TRoD52+U4ZrfMwIMzHObPGEcvssZwvUgO9R2ef8XOakx6lGMVgS68QcQ==} + engines: {node: '>=0.10.0'} + requiresBuild: true + dependencies: + array-uniq: 1.0.3 + dev: false + optional: true + /mdast-util-from-markdown@1.3.0: resolution: {integrity: sha512-HN3W1gRIuN/ZW295c7zi7g9lVBllMgZE40RxCX37wrTPWXCWtpvOZdfnuK+1WNpvZje6XuJeI3Wnb4TJEUem+g==} dependencies: @@ -3921,6 +4024,11 @@ packages: validate-npm-package-license: 3.0.4 dev: true + /normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + dev: false + /normalize-url@8.0.0: resolution: {integrity: sha512-uVFpKhj5MheNBJRTiMZ9pE/7hD1QTeEvugSJW/OmLzAp78PB5O6adfMNTvmfKhXBkvCzC+rqifWcVYpGFwTjnw==} engines: {node: '>=14.16'} @@ -4563,6 +4671,12 @@ packages: engines: {node: '>=8'} dev: true + /remove@0.1.5: + resolution: {integrity: sha512-AJMA9oWvJzdTjwIGwSQZsjGQiRx73YTmiOWmfCp1fpLa/D4n7jKcpoA+CZiVLJqKcEKUuh1Suq80c5wF+L/qVQ==} + dependencies: + seq: 0.3.5 + dev: false + /require-from-string@2.0.2: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} @@ -4688,6 +4802,13 @@ packages: dependencies: lru-cache: 6.0.0 + /seq@0.3.5: + resolution: {integrity: sha512-sisY2Ln1fj43KBkRtXkesnRHYNdswIkIibvNe/0UKm2GZxjMbqmccpiatoKr/k2qX5VKiLU8xm+tz/74LAho4g==} + dependencies: + chainsaw: 0.0.9 + hashish: 0.0.4 + dev: false + /set-blocking@2.0.0: resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} dev: true @@ -4778,6 +4899,12 @@ packages: smart-buffer: 4.2.0 dev: true + /sort-es@1.6.10: + resolution: {integrity: sha512-ak1DcREJVojhwOz89bL4Yezh11G8+DnQFM9EkN+2+h9jphtYDuw1iPdPepyMPVHIIhFc849OXC5kXf0TfrmMpw==} + requiresBuild: true + dev: false + optional: true + /sort-object-keys@1.1.3: resolution: {integrity: sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg==} dev: true @@ -4976,6 +5103,14 @@ packages: engines: {node: '>=14.16'} dev: true + /subsume@3.0.0: + resolution: {integrity: sha512-6n/UfV8UWKwJNO8OAOiKntwEMihuBeeoJfzpL542C+OuvT4iWG9SwjrXkOmsxjb4SteHUsos9SvrdqZ9+ICwTQ==} + engines: {node: '>=8'} + dependencies: + escape-string-regexp: 2.0.0 + unique-string: 2.0.0 + dev: false + /supports-color@2.0.0: resolution: {integrity: sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==} engines: {node: '>=0.8.0'} @@ -5046,6 +5181,14 @@ packages: dependencies: is-number: 7.0.0 + /traverse@0.3.9: + resolution: {integrity: sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ==} + dev: false + + /traverse@0.6.7: + resolution: {integrity: sha512-/y956gpUo9ZNCb99YjxG7OaslxZWHfCHAUUfshwqOXmxUIvqLjVO581BT+gM59+QV9tFe6/CGG53tsA1Y7RSdg==} + dev: false + /ts-api-utils@0.0.46(typescript@5.0.4): resolution: {integrity: sha512-YKJeSx39n0mMk+hrpyHKyTgxA3s7Pz/j1cXYR+t8HcwwZupzOR5xDGKnOEw3gmLaUeFUQt3FJD39AH9Ajn/mdA==} engines: {node: '>=16.13.0'} @@ -5086,6 +5229,11 @@ packages: prelude-ls: 1.2.1 dev: false + /type-fest@0.16.0: + resolution: {integrity: sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==} + engines: {node: '>=10'} + dev: false + /type-fest@0.20.2: resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} engines: {node: '>=10'} @@ -5168,6 +5316,13 @@ packages: imurmurhash: 0.1.4 dev: true + /unique-string@2.0.0: + resolution: {integrity: sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==} + engines: {node: '>=8'} + dependencies: + crypto-random-string: 2.0.0 + dev: false + /unique-string@3.0.0: resolution: {integrity: sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==} engines: {node: '>=12'} diff --git a/src/typescript.js b/src/typescript.js index 1f6cfc2..bde5009 100644 --- a/src/typescript.js +++ b/src/typescript.js @@ -1,36 +1,32 @@ const { eslintRulesExtra } = require("./official-eslint-rules") const { pluginImportRulesExtra, pluginImportTypeScriptRulesExtra } = require("./plugin-import-rules") const { pluginNodeRules } = require("./plugin-node-rules") -const fs = require("fs") -const path = require("path") +const { globifyGitIgnoreFile } = require("globify-gitignore") +const makeSynchronous = require("make-synchronous") +const { findOneFile } = require("./utils") const tsFiles = ["**/*.tsx", "**/*.ts"] const project = ["**/tsconfig.json", "!**/node_modules/**/tsconfig.json"] -function findOneFile(cwd, fileEnding, ignoredFolders) { - // recursively search the current folder for a file with the given fileEnding, ignoring the given folders, and return true as soon as one is found - const files = fs.readdirSync(cwd, { withFileTypes: true, recursive: false }) - for (const file of files) { - if (file.isDirectory()) { - if (!ignoredFolders.includes(file.name)) { - // if the folder is not ignored, search it recursively - const found = findOneFile(path.join(cwd, file.name), fileEnding, ignoredFolders) - if (found) { - return true - } - } - } else if (file.name.endsWith(fileEnding)) { - // if the file ends with the given fileEnding, return true - return true +/** Check if there are any tsconfig.json files */ +async function disableProjectBasedRules() { + // get all the files that are ignored by git + const ignore = (await globifyGitIgnoreFile(".", true)).map((entry) => { + if (entry.included) { + return `!${entry.glob}` } + return entry.glob + }) + ignore.push("./**/.git/**") + + // check if there are any ts files + const hasTsFile = findOneFile(process.cwd(), tsFiles, ignore) + if (!hasTsFile) { + return true } - return false -} -/** Check if there are any tsconfig.json files */ -function disableProjectBasedRules() { - const hasTsFile = findOneFile(process.cwd(), ".ts", ["node_modules", ".git"]) - const hasTsConfig = findOneFile(process.cwd(), "tsconfig.json", ["node_modules", ".git"]) + // check if there is a tsconfig.json file + const hasTsConfig = findOneFile(process.cwd(), project, ignore) // if there is no tsconfig.json file, but there are ts files, disable the project-based rules const disable = !hasTsConfig && hasTsFile @@ -82,7 +78,7 @@ const pluginTypeScriptRulesExtra = { // "@typescript-eslint/prefer-string-starts-ends-with": "error", } -const pluginTypeScriptProjectRules = disableProjectBasedRules() +const pluginTypeScriptProjectRules = makeSynchronous(disableProjectBasedRules()) ? {} : { "@typescript-eslint/no-floating-promises": "error", diff --git a/src/utils.js b/src/utils.js new file mode 100644 index 0000000..471fcfa --- /dev/null +++ b/src/utils.js @@ -0,0 +1,30 @@ +const { readdirSync } = require("fs") +const { join } = require("path") +const { default: anymatch } = require("anymatch") + +/** + * @param {string} cwd + * @param {string} search + * @param {string[]} ignored + */ +function findOneFile(cwd, search, ignored) { + // recursively search the current folder for a file with the given fileEnding, ignoring the given folders, and return true as soon as one is found + const files = readdirSync(cwd, { withFileTypes: true, recursive: false }) + for (const file of files) { + const path = join(cwd, file.name) + if (file.isDirectory()) { + if (!anymatch(ignored, path)) { + // if the folder is not ignored, search it recursively + const found = findOneFile(path, search, ignored) + if (found) { + return true + } + } + } else if (anymatch(search, path)) { + // if the file ends with the given fileEnding, return true + return true + } + } + return false +} +exports.findOneFile = findOneFile