diff --git a/docs/rules/no-status-code-assert.md b/docs/rules/no-status-code-assert.md new file mode 100644 index 0000000..33cc981 --- /dev/null +++ b/docs/rules/no-status-code-assert.md @@ -0,0 +1,16 @@ +# Disallow the use of `statusCode` as a parameter in assert. + +## Fail + +```js +assert(statusCode === StatusCodes.OK); +assert.equal(statusCode, StatusCodes.OK); +assert(response.status === 200); +assert.equal(response.status, 200); +``` + +## Pass + +```js +assert(response.otherProperty === 'test'); +``` diff --git a/package-lock.json b/package-lock.json index e752a55..0e2f915 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,16 +1,17 @@ { "name": "@checkdigit/eslint-plugin", - "version": "7.9.0", + "version": "7.10.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@checkdigit/eslint-plugin", - "version": "7.9.0", + "version": "7.10.0", "license": "MIT", "dependencies": { "@typescript-eslint/type-utils": "^8.18.1", "@typescript-eslint/utils": "^8.18.1", + "http-status-codes": "^2.3.0", "ts-api-utils": "^2.0.0" }, "devDependencies": { @@ -31,7 +32,6 @@ "eslint-plugin-no-secrets": "^2.1.1", "eslint-plugin-node": "^11.1.0", "eslint-plugin-sonarjs": "1.0.4", - "http-status-codes": "^2.3.0", "rimraf": "^6.0.1", "typescript-eslint": "^8.18.1" }, @@ -626,9 +626,9 @@ } }, "node_modules/@checkdigit/prettier-config": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@checkdigit/prettier-config/-/prettier-config-6.0.0.tgz", - "integrity": "sha512-d9F2BGt1yk4fZS6QV9xEY35RwvH5WaR9vftwAxVsEFDH3iIUPL5PU8N8e76NIH2xRxbusC4Vx996zI6oTupmcw==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@checkdigit/prettier-config/-/prettier-config-6.1.0.tgz", + "integrity": "sha512-ngoW4/hqJhzGxVo8M+RR81CaeI89KM7Zn5fJAR0B4gaQEihejTYGF3FzwrcnKQ8CREWcpx108QjFTvviR8G06w==", "dev": true, "license": "MIT", "engines": { @@ -636,7 +636,7 @@ }, "peerDependencies": { "@prettier/plugin-xml": "3.4.1", - "prettier": "3.4.1", + "prettier": "3.4.2", "prettier-plugin-packagejson": "2.5.6", "prettier-plugin-svelte": "3.3.2", "prettier-plugin-tailwindcss": "0.6.9" @@ -2283,9 +2283,9 @@ } }, "node_modules/@swc/core": { - "version": "1.10.4", - "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.10.4.tgz", - "integrity": "sha512-ut3zfiTLORMxhr6y/GBxkHmzcGuVpwJYX4qyXWuBKkpw/0g0S5iO1/wW7RnLnZbAi8wS/n0atRZoaZlXWBkeJg==", + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.10.6.tgz", + "integrity": "sha512-zgXXsI6SAVwr6XsXyMnqlyLoa1lT+r09bAWI1xT3679ejWqI1Vnl14eJG0GjWYXCEMKHCNytfMq3OOQ62C39QQ==", "dev": true, "hasInstallScript": true, "license": "Apache-2.0", @@ -2302,16 +2302,16 @@ "url": "https://opencollective.com/swc" }, "optionalDependencies": { - "@swc/core-darwin-arm64": "1.10.4", - "@swc/core-darwin-x64": "1.10.4", - "@swc/core-linux-arm-gnueabihf": "1.10.4", - "@swc/core-linux-arm64-gnu": "1.10.4", - "@swc/core-linux-arm64-musl": "1.10.4", - "@swc/core-linux-x64-gnu": "1.10.4", - "@swc/core-linux-x64-musl": "1.10.4", - "@swc/core-win32-arm64-msvc": "1.10.4", - "@swc/core-win32-ia32-msvc": "1.10.4", - "@swc/core-win32-x64-msvc": "1.10.4" + "@swc/core-darwin-arm64": "1.10.6", + "@swc/core-darwin-x64": "1.10.6", + "@swc/core-linux-arm-gnueabihf": "1.10.6", + "@swc/core-linux-arm64-gnu": "1.10.6", + "@swc/core-linux-arm64-musl": "1.10.6", + "@swc/core-linux-x64-gnu": "1.10.6", + "@swc/core-linux-x64-musl": "1.10.6", + "@swc/core-win32-arm64-msvc": "1.10.6", + "@swc/core-win32-ia32-msvc": "1.10.6", + "@swc/core-win32-x64-msvc": "1.10.6" }, "peerDependencies": { "@swc/helpers": "*" @@ -2323,9 +2323,9 @@ } }, "node_modules/@swc/core-darwin-arm64": { - "version": "1.10.4", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.10.4.tgz", - "integrity": "sha512-sV/eurLhkjn/197y48bxKP19oqcLydSel42Qsy2zepBltqUx+/zZ8+/IS0Bi7kaWVFxerbW1IPB09uq8Zuvm3g==", + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.10.6.tgz", + "integrity": "sha512-USbMvT8Rw5PvIfF6HyTm+yW84J9c45emzmHBDIWY76vZHkFsS5MepNi+JLQyBzBBgE7ScwBRBNhRx6VNhkSoww==", "cpu": [ "arm64" ], @@ -2341,9 +2341,9 @@ } }, "node_modules/@swc/core-darwin-x64": { - "version": "1.10.4", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.10.4.tgz", - "integrity": "sha512-gjYNU6vrAUO4+FuovEo9ofnVosTFXkF0VDuo1MKPItz6e2pxc2ale4FGzLw0Nf7JB1sX4a8h06CN16/pLJ8Q2w==", + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.10.6.tgz", + "integrity": "sha512-7t2IozcZN4r1p27ei+Kb8IjN4aLoBDn107fPi+aPLcVp2uFgJEUzhCDuZXBNW2057Mx1OHcjzrkaleRpECz3Xg==", "cpu": [ "x64" ], @@ -2359,9 +2359,9 @@ } }, "node_modules/@swc/core-linux-arm-gnueabihf": { - "version": "1.10.4", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.10.4.tgz", - "integrity": "sha512-zd7fXH5w8s+Sfvn2oO464KDWl+ZX1MJiVmE4Pdk46N3PEaNwE0koTfgx2vQRqRG4vBBobzVvzICC3618WcefOA==", + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.10.6.tgz", + "integrity": "sha512-CPgWT+D0bDp/qhXsLkIJ54LmKU1/zvyGaf/yz8A4iR+YoF6R5CSXENXhNJY8cIrb6+uNWJZzHJ+gefB5V51bpA==", "cpu": [ "arm" ], @@ -2377,9 +2377,9 @@ } }, "node_modules/@swc/core-linux-arm64-gnu": { - "version": "1.10.4", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.10.4.tgz", - "integrity": "sha512-+UGfoHDxsMZgFD3tABKLeEZHqLNOkxStu+qCG7atGBhS4Slri6h6zijVvf4yI5X3kbXdvc44XV/hrP/Klnui2A==", + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.10.6.tgz", + "integrity": "sha512-5qZ6hVnqO/ShETXdGSzvdGUVx372qydlj1YWSYiaxQzTAepEBc8TC1NVUgYtOHOKVRkky1d7p6GQ9lymsd4bHw==", "cpu": [ "arm64" ], @@ -2395,9 +2395,9 @@ } }, "node_modules/@swc/core-linux-arm64-musl": { - "version": "1.10.4", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.10.4.tgz", - "integrity": "sha512-cDDj2/uYsOH0pgAnDkovLZvKJpFmBMyXkxEG6Q4yw99HbzO6QzZ5HDGWGWVq/6dLgYKlnnmpjZCPPQIu01mXEg==", + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.10.6.tgz", + "integrity": "sha512-hB2xZFmXCKf2iJF5y2z01PSuLqEoUP3jIX/XlIHN+/AIP7PkSKsValE63LnjlnWPnSEI0IxUyRE3T3FzWE/fQQ==", "cpu": [ "arm64" ], @@ -2413,9 +2413,9 @@ } }, "node_modules/@swc/core-linux-x64-gnu": { - "version": "1.10.4", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.10.4.tgz", - "integrity": "sha512-qJXh9D6Kf5xSdGWPINpLGixAbB5JX8JcbEJpRamhlDBoOcQC79dYfOMEIxWPhTS1DGLyFakAx2FX/b2VmQmj0g==", + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.10.6.tgz", + "integrity": "sha512-PRGPp0I22+oJ8RMGg8M4hXYxEffH3ayu0WoSDPOjfol1F51Wj1tfTWN4wVa2RibzJjkBwMOT0KGLGb/hSEDDXQ==", "cpu": [ "x64" ], @@ -2431,9 +2431,9 @@ } }, "node_modules/@swc/core-linux-x64-musl": { - "version": "1.10.4", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.10.4.tgz", - "integrity": "sha512-A76lIAeyQnHCVt0RL/pG+0er8Qk9+acGJqSZOZm67Ve3B0oqMd871kPtaHBM0BW3OZAhoILgfHW3Op9Q3mx3Cw==", + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.10.6.tgz", + "integrity": "sha512-SoNBxlA86lnoV9vIz/TCyakLkdRhFSHx6tFMKNH8wAhz1kKYbZfDmpYoIzeQqdTh0tpx8e/Zu1zdK4smovsZqQ==", "cpu": [ "x64" ], @@ -2449,9 +2449,9 @@ } }, "node_modules/@swc/core-win32-arm64-msvc": { - "version": "1.10.4", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.10.4.tgz", - "integrity": "sha512-e6j5kBu4fIY7fFxFxnZI0MlEovRvp50Lg59Fw+DVbtqHk3C85dckcy5xKP+UoXeuEmFceauQDczUcGs19SRGSQ==", + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.10.6.tgz", + "integrity": "sha512-6L5Y2E+FVvM+BtoA+mJFjf/SjpFr73w2kHBxINxwH8/PkjAjkePDr5m0ibQhPXV61bTwX49+1otzTY85EsUW9Q==", "cpu": [ "arm64" ], @@ -2467,9 +2467,9 @@ } }, "node_modules/@swc/core-win32-ia32-msvc": { - "version": "1.10.4", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.10.4.tgz", - "integrity": "sha512-RSYHfdKgNXV/amY5Tqk1EWVsyQnhlsM//jeqMLw5Fy9rfxP592W9UTumNikNRPdjI8wKKzNMXDb1U29tQjN0dg==", + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.10.6.tgz", + "integrity": "sha512-kxK3tW8DJwEkAkwy0vhwoBAShRebH1QTe0mvH9tlBQ21rToVZQn+GCV/I44dind80hYPw0Tw2JKFVfoEJyBszg==", "cpu": [ "ia32" ], @@ -2485,9 +2485,9 @@ } }, "node_modules/@swc/core-win32-x64-msvc": { - "version": "1.10.4", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.10.4.tgz", - "integrity": "sha512-1ujYpaqfqNPYdwKBlvJnOqcl+Syn3UrQ4XE0Txz6zMYgyh6cdU6a3pxqLqIUSJ12MtXRA9ZUhEz1ekU3LfLWXw==", + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.10.6.tgz", + "integrity": "sha512-4pJka/+t8XcHee12G/R5VWcilkp5poT2EJhrybpuREkpQ7iC/4WOlOVrohbWQ4AhDQmojYQI/iS+gdF2JFLzTQ==", "cpu": [ "x64" ], @@ -2661,9 +2661,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.10.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.4.tgz", - "integrity": "sha512-99l6wv4HEzBQhvaU/UGoeBoCK61SCROQaCCGyQSgX2tEQ3rKkNZ2S7CEWnS/4s1LV+8ODdK21UeyR1fHP2mXug==", + "version": "22.10.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.5.tgz", + "integrity": "sha512-F8Q+SeGimwOo86fiovQh8qiXfFEh2/ocYv7tU5pJ3EXMSSxk1Joj5wefpFK2fHTf/N6HKGSxIDBT9f3gCxXPkQ==", "dev": true, "license": "MIT", "peer": true, @@ -2699,21 +2699,21 @@ "peer": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.19.0.tgz", - "integrity": "sha512-NggSaEZCdSrFddbctrVjkVZvFC6KGfKfNK0CU7mNK/iKHGKbzT4Wmgm08dKpcZECBu9f5FypndoMyRHkdqfT1Q==", + "version": "8.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.19.1.tgz", + "integrity": "sha512-tJzcVyvvb9h/PB96g30MpxACd9IrunT7GF9wfA9/0TJ1LxGOJx1TdPzSbBBnNED7K9Ka8ybJsnEpiXPktolTLg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.19.0", - "@typescript-eslint/type-utils": "8.19.0", - "@typescript-eslint/utils": "8.19.0", - "@typescript-eslint/visitor-keys": "8.19.0", + "@typescript-eslint/scope-manager": "8.19.1", + "@typescript-eslint/type-utils": "8.19.1", + "@typescript-eslint/utils": "8.19.1", + "@typescript-eslint/visitor-keys": "8.19.1", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", - "ts-api-utils": "^1.3.0" + "ts-api-utils": "^2.0.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2728,30 +2728,17 @@ "typescript": ">=4.8.4 <5.8.0" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/ts-api-utils": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", - "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "typescript": ">=4.2.0" - } - }, "node_modules/@typescript-eslint/parser": { - "version": "8.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.19.0.tgz", - "integrity": "sha512-6M8taKyOETY1TKHp0x8ndycipTVgmp4xtg5QpEZzXxDhNvvHOJi5rLRkLr8SK3jTgD5l4fTlvBiRdfsuWydxBw==", + "version": "8.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.19.1.tgz", + "integrity": "sha512-67gbfv8rAwawjYx3fYArwldTQKoYfezNUT4D5ioWetr/xCrxXxvleo3uuiFuKfejipvq+og7mjz3b0G2bVyUCw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.19.0", - "@typescript-eslint/types": "8.19.0", - "@typescript-eslint/typescript-estree": "8.19.0", - "@typescript-eslint/visitor-keys": "8.19.0", + "@typescript-eslint/scope-manager": "8.19.1", + "@typescript-eslint/types": "8.19.1", + "@typescript-eslint/typescript-estree": "8.19.1", + "@typescript-eslint/visitor-keys": "8.19.1", "debug": "^4.3.4" }, "engines": { @@ -2767,14 +2754,14 @@ } }, "node_modules/@typescript-eslint/rule-tester": { - "version": "8.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/rule-tester/-/rule-tester-8.19.0.tgz", - "integrity": "sha512-wLTQopSNqT/ayzo6i5gzXtud4UM49DsXshGzsYAPwbR8itgTGkdZ5qVfLYfbve9zQpEsaoTpoTrBabPOqCPlJQ==", + "version": "8.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/rule-tester/-/rule-tester-8.19.1.tgz", + "integrity": "sha512-DK86KDq2wkWqH8qN9lT3OQuvFqRHAQBrMQY6emvK8Tar1xKA4fyZh387CNPZ66l8oeXg/OYFIgJBRuxrWV/awA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.19.0", - "@typescript-eslint/utils": "8.19.0", + "@typescript-eslint/typescript-estree": "8.19.1", + "@typescript-eslint/utils": "8.19.1", "ajv": "^6.12.6", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "4.6.2", @@ -2792,13 +2779,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.19.0.tgz", - "integrity": "sha512-hkoJiKQS3GQ13TSMEiuNmSCvhz7ujyqD1x3ShbaETATHrck+9RaDdUbt+osXaUuns9OFwrDTTrjtwsU8gJyyRA==", + "version": "8.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.19.1.tgz", + "integrity": "sha512-60L9KIuN/xgmsINzonOcMDSB8p82h95hoBfSBtXuO4jlR1R9L1xSkmVZKgCPVfavDlXihh4ARNjXhh1gGnLC7Q==", "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.19.0", - "@typescript-eslint/visitor-keys": "8.19.0" + "@typescript-eslint/types": "8.19.1", + "@typescript-eslint/visitor-keys": "8.19.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2809,15 +2796,15 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.19.0.tgz", - "integrity": "sha512-TZs0I0OSbd5Aza4qAMpp1cdCYVnER94IziudE3JU328YUHgWu9gwiwhag+fuLeJ2LkWLXI+F/182TbG+JaBdTg==", + "version": "8.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.19.1.tgz", + "integrity": "sha512-Rp7k9lhDKBMRJB/nM9Ksp1zs4796wVNyihG9/TU9R6KCJDNkQbc2EOKjrBtLYh3396ZdpXLtr/MkaSEmNMtykw==", "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.19.0", - "@typescript-eslint/utils": "8.19.0", + "@typescript-eslint/typescript-estree": "8.19.1", + "@typescript-eslint/utils": "8.19.1", "debug": "^4.3.4", - "ts-api-utils": "^1.3.0" + "ts-api-utils": "^2.0.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2831,22 +2818,10 @@ "typescript": ">=4.8.4 <5.8.0" } }, - "node_modules/@typescript-eslint/type-utils/node_modules/ts-api-utils": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", - "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", - "license": "MIT", - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "typescript": ">=4.2.0" - } - }, "node_modules/@typescript-eslint/types": { - "version": "8.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.19.0.tgz", - "integrity": "sha512-8XQ4Ss7G9WX8oaYvD4OOLCjIQYgRQxO+qCiR2V2s2GxI9AUpo7riNwo6jDhKtTcaJjT8PY54j2Yb33kWtSJsmA==", + "version": "8.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.19.1.tgz", + "integrity": "sha512-JBVHMLj7B1K1v1051ZaMMgLW4Q/jre5qGK0Ew6UgXz1Rqh+/xPzV1aW581OM00X6iOfyr1be+QyW8LOUf19BbA==", "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2857,19 +2832,19 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.19.0.tgz", - "integrity": "sha512-WW9PpDaLIFW9LCbucMSdYUuGeFUz1OkWYS/5fwZwTA+l2RwlWFdJvReQqMUMBw4yJWJOfqd7An9uwut2Oj8sLw==", + "version": "8.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.19.1.tgz", + "integrity": "sha512-jk/TZwSMJlxlNnqhy0Eod1PNEvCkpY6MXOXE/WLlblZ6ibb32i2We4uByoKPv1d0OD2xebDv4hbs3fm11SMw8Q==", "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.19.0", - "@typescript-eslint/visitor-keys": "8.19.0", + "@typescript-eslint/types": "8.19.1", + "@typescript-eslint/visitor-keys": "8.19.1", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" + "ts-api-utils": "^2.0.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2882,28 +2857,16 @@ "typescript": ">=4.8.4 <5.8.0" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/ts-api-utils": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", - "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", - "license": "MIT", - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "typescript": ">=4.2.0" - } - }, "node_modules/@typescript-eslint/utils": { - "version": "8.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.19.0.tgz", - "integrity": "sha512-PTBG+0oEMPH9jCZlfg07LCB2nYI0I317yyvXGfxnvGvw4SHIOuRnQ3kadyyXY6tGdChusIHIbM5zfIbp4M6tCg==", + "version": "8.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.19.1.tgz", + "integrity": "sha512-IxG5gLO0Ne+KaUc8iW1A+XuKLd63o4wlbI1Zp692n1xojCl/THvgIKXJXBZixTh5dd5+yTJ/VXH7GJaaw21qXA==", "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.19.0", - "@typescript-eslint/types": "8.19.0", - "@typescript-eslint/typescript-estree": "8.19.0" + "@typescript-eslint/scope-manager": "8.19.1", + "@typescript-eslint/types": "8.19.1", + "@typescript-eslint/typescript-estree": "8.19.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2918,12 +2881,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.19.0.tgz", - "integrity": "sha512-mCFtBbFBJDCNCWUl5y6sZSCHXw1DEFEk3c/M3nRK2a4XUB8StGFtmcEMizdjKuBzB6e/smJAAWYug3VrdLMr1w==", + "version": "8.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.19.1.tgz", + "integrity": "sha512-fzmjU8CHK853V/avYZAvuVut3ZTfwN5YtMaoi+X9Y9MA9keaWNHC3zEQ9zvyX/7Hj+5JkNyK1l7TOR2hevHB6Q==", "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.19.0", + "@typescript-eslint/types": "8.19.1", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -3386,9 +3349,9 @@ } }, "node_modules/browserslist": { - "version": "4.24.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.3.tgz", - "integrity": "sha512-1CPmv8iobE2fyRMV97dAcMVegvvWKxmq94hkLiAkUGwKVTyDLw33K+ZxiFrREKmmps4rIw6grcCFCnTMSZ/YiA==", + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", + "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", "dev": true, "funding": [ { @@ -3940,9 +3903,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.76", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.76.tgz", - "integrity": "sha512-CjVQyG7n7Sr+eBXE86HIulnL5N8xZY1sgmOPGuq/F0Rr0FJq63lg0kEtOIDfZBk44FnDLf6FUJ+dsJcuiUDdDQ==", + "version": "1.5.79", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.79.tgz", + "integrity": "sha512-nYOxJNxQ9Om4EC88BE4pPoNI8xwSFf8pU/BAeOl4Hh/b/i6V4biTAzwV7pXi3ARKeoYO5JZKMIXTryXSVer5RA==", "dev": true, "license": "ISC", "peer": true @@ -4654,9 +4617,9 @@ } }, "node_modules/esm-env": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.1.tgz", - "integrity": "sha512-U9JedYYjCnadUlXk7e1Kr+aENQhtUaoaV9+gZm1T8LC/YBAPJx3NSPIAurFOC0U5vrdSevnUJS2/wUVxGwPhng==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.2.tgz", + "integrity": "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==", "dev": true, "license": "MIT", "peer": true @@ -4818,16 +4781,16 @@ "license": "MIT" }, "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "micromatch": "^4.0.8" }, "engines": { "node": ">=8.6.0" @@ -5405,7 +5368,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/http-status-codes/-/http-status-codes-2.3.0.tgz", "integrity": "sha512-RJ8XvFvpPM/Dmc5SV+dC4y5PCeOhT3x1Hq0NU3rjGeg5a/CqlhZ7uudknPwZFz4aeAXDcbAyaeP7GAo9lvngtA==", - "dev": true, "license": "MIT" }, "node_modules/human-signals": { @@ -5537,13 +5499,16 @@ "peer": true }, "node_modules/is-async-function": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", - "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.0.tgz", + "integrity": "sha512-GExz9MtyhlZyXYLxzlJRj5WUCE661zhDa1Yna52CN57AJsymh+DvXXjyveSioqSRdxvUrdKdvqB1b5cVKsNpWQ==", "dev": true, "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -7499,9 +7464,9 @@ } }, "node_modules/prettier": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.1.tgz", - "integrity": "sha512-G+YdqtITVZmOJje6QkXQWzl3fSfMxFwm1tjTyo9exhkmWSqC4Yhd1+lug++IlR2mvRVAxEDDWYkQdeSztajqgg==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz", + "integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==", "dev": true, "license": "MIT", "peer": true, @@ -7759,15 +7724,17 @@ "peer": true }, "node_modules/regexp.prototype.flags": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz", - "integrity": "sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==", + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", "set-function-name": "^2.0.2" }, "engines": { @@ -8508,9 +8475,9 @@ } }, "node_modules/svelte": { - "version": "5.16.1", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.16.1.tgz", - "integrity": "sha512-FsA1OjAKMAFSDob6j/Tv2ZV9rY4SeqPd1WXQlQkFkePAozSHLp6tbkU9qa1xJ+uTRzMSM2Vx3USdsYZBXd3H3g==", + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.17.1.tgz", + "integrity": "sha512-HitqD0XhU9OEytPuux/XYzxle4+7D8+fIb1tHbwMzOtBzDZZO+ESEuwMbahJ/3JoklfmRPB/Gzp74L87Qrxfpw==", "dev": true, "license": "MIT", "peer": true, @@ -8886,9 +8853,9 @@ } }, "node_modules/typescript": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz", - "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==", + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", + "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", "license": "Apache-2.0", "peer": true, "bin": { @@ -8900,15 +8867,15 @@ } }, "node_modules/typescript-eslint": { - "version": "8.19.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.19.0.tgz", - "integrity": "sha512-Ni8sUkVWYK4KAcTtPjQ/UTiRk6jcsuDhPpxULapUDi8A/l8TSBk+t1GtJA1RsCzIJg0q6+J7bf35AwQigENWRQ==", + "version": "8.19.1", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.19.1.tgz", + "integrity": "sha512-LKPUQpdEMVOeKluHi8md7rwLcoXHhwvWp3x+sJkMuq3gGm9yaYJtPo8sRZSblMFJ5pcOGCAak/scKf1mvZDlQw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.19.0", - "@typescript-eslint/parser": "8.19.0", - "@typescript-eslint/utils": "8.19.0" + "@typescript-eslint/eslint-plugin": "8.19.1", + "@typescript-eslint/parser": "8.19.1", + "@typescript-eslint/utils": "8.19.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -8950,9 +8917,9 @@ "peer": true }, "node_modules/update-browserslist-db": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", - "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz", + "integrity": "sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg==", "dev": true, "funding": [ { @@ -8972,7 +8939,7 @@ "peer": true, "dependencies": { "escalade": "^3.2.0", - "picocolors": "^1.1.0" + "picocolors": "^1.1.1" }, "bin": { "update-browserslist-db": "cli.js" diff --git a/package.json b/package.json index 8a8708e..c73b29e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@checkdigit/eslint-plugin", - "version": "7.9.0", + "version": "7.10.0", "description": "Check Digit eslint plugins", "keywords": [ "eslint", @@ -63,6 +63,7 @@ "dependencies": { "@typescript-eslint/type-utils": "^8.18.1", "@typescript-eslint/utils": "^8.18.1", + "http-status-codes": "^2.3.0", "ts-api-utils": "^2.0.0" }, "devDependencies": { @@ -83,7 +84,6 @@ "eslint-plugin-no-secrets": "^2.1.1", "eslint-plugin-node": "^11.1.0", "eslint-plugin-sonarjs": "1.0.4", - "http-status-codes": "^2.3.0", "rimraf": "^6.0.1", "typescript-eslint": "^8.18.1" }, diff --git a/src/index.ts b/src/index.ts index a1d3a95..d13a9a9 100644 --- a/src/index.ts +++ b/src/index.ts @@ -12,6 +12,7 @@ import invalidJsonStringify, { ruleId as invalidJsonStringifyRuleId } from './in import noDuplicatedImports, { ruleId as noDuplicatedImportsRuleId } from './no-duplicated-imports.ts'; import noLegacyServiceTyping, { ruleId as noLegacyServiceTypingRuleId } from './no-legacy-service-typing.ts'; import noPromiseInstanceMethod, { ruleId as noPromiseInstanceMethodRuleId } from './no-promise-instance-method.ts'; +import noStatusCodeAssert from './no-status-code-assert.ts'; import requireFixedServicesImport, { ruleId as requireFixedServicesImportRuleId, } from './require-fixed-services-import.ts'; @@ -41,6 +42,7 @@ const rules: Record = { 'no-card-numbers': noCardNumbers, 'no-enum': noEnum, 'no-random-v4-uuid': noRandomV4UUID, + 'no-status-code-assert': noStatusCodeAssert, 'no-uuid': noUuid, 'require-strict-assert': requireStrictAssert, 'require-ts-extension-imports-exports': requireTsExtensionImportsExports, @@ -76,6 +78,7 @@ const configs: Record = { '@checkdigit/no-enum': 'error', '@checkdigit/file-path-comment': 'error', '@checkdigit/no-random-v4-uuid': 'error', + '@checkdigit/no-status-code-assert': 'error', '@checkdigit/no-uuid': 'error', '@checkdigit/require-strict-assert': 'error', '@checkdigit/require-ts-extension-imports-exports': 'error', @@ -110,6 +113,7 @@ const configs: Record = { '@checkdigit/no-enum': 'error', '@checkdigit/file-path-comment': 'off', '@checkdigit/no-random-v4-uuid': 'error', + '@checkdigit/no-status-code-assert': 'error', '@checkdigit/no-uuid': 'error', '@checkdigit/require-strict-assert': 'error', '@checkdigit/require-ts-extension-imports-exports': 'error', diff --git a/src/no-status-code-assert.spec.ts b/src/no-status-code-assert.spec.ts new file mode 100644 index 0000000..02e567a --- /dev/null +++ b/src/no-status-code-assert.spec.ts @@ -0,0 +1,169 @@ +// no-status-code-assert.spec.ts + +import rule, { ruleId } from './no-status-code-assert'; +import createTester from './ts-tester.test'; + +createTester().run(ruleId, rule, { + valid: [ + { + name: 'Valid case with await and expect', + code: `await fixture.api + .put(testURI) + .send(testData) + .expect(StatusCodes.CREATED);`, + }, + { + name: 'Valid case with different property', + code: `assert(response.otherProperty === 'test');`, + }, + { + name: 'Valid case with assert.equal and different property', + code: `assert.equal(response.otherProperty, 'test');`, + }, + { + name: 'Valid case with assert.ok and different property', + code: `assert.ok(response.otherProperty === 'test');`, + }, + { + name: 'Valid case with response.code', + code: `assert(message.code, 'Expected response.value to be StatusCodes.BAD_REQUEST');`, + }, + ], + invalid: [ + { + name: 'Invalid case with statusCode directly', + code: `assert(statusCode === StatusCodes.OK);`, + errors: [ + { + messageId: 'NO_STATUS_CODE_ASSERT', + }, + ], + }, + { + name: 'Invalid case with statusCode directly and different status code', + code: `assert(StatusCodes.BAD_REQUEST === statusCode);`, + errors: [ + { + messageId: 'NO_STATUS_CODE_ASSERT', + }, + ], + }, + { + name: 'Invalid case with statusCode directly in assert.equal', + code: `assert.equal(test.statusCode, StatusCodes.CREATED);`, + errors: [ + { + messageId: 'NO_STATUS_CODE_ASSERT', + }, + ], + }, + { + name: 'Invalid case with statusCode in assert.INTERNAL_SERVER_ERROR', + code: `assert.ok(statusCode === StatusCodes.INTERNAL_SERVER_ERROR);`, + errors: [ + { + messageId: 'NO_STATUS_CODE_ASSERT', + }, + ], + }, + { + name: 'Invalid case with assert.INTERNAL_SERVER_ERROR in statusCode', + code: `assert.ok(StatusCodes.INTERNAL_SERVER_ERROR === statusCode);`, + errors: [ + { + messageId: 'NO_STATUS_CODE_ASSERT', + }, + ], + }, + { + name: 'Invalid case with statusCode in assert.equal', + code: `assert.equal(StatusCodes.CREATED, statusCode);`, + errors: [ + { + messageId: 'NO_STATUS_CODE_ASSERT', + }, + ], + }, + { + name: 'Invalid case with statusCode in assert.equal with status code', + code: `assert.equal(statusCode, StatusCodes.INTERNAL_SERVER_ERROR);`, + errors: [ + { + messageId: 'NO_STATUS_CODE_ASSERT', + }, + ], + }, + { + name: 'Invalid case with statusCode in a binary expression', + code: `assert(testStatusCode === StatusCodes.OK);`, + errors: [ + { + messageId: 'NO_STATUS_CODE_ASSERT', + }, + ], + }, + { + name: 'Invalid case in a binary expression with response.statusCode', + code: `assert(response.statusCode === StatusCodes.OK);`, + errors: [ + { + messageId: 'NO_STATUS_CODE_ASSERT', + }, + ], + }, + { + name: 'Invalid case with StatusCode', + code: `assert(test.code === StatusCodes.BAD_REQUEST);`, + errors: [ + { + messageId: 'NO_STATUS_CODE_ASSERT', + }, + ], + }, + { + name: 'Invalid case with response.status and StatusCodes', + code: `assert(StatusCodes.BAD_REQUEST === response.status);`, + errors: [ + { + messageId: 'NO_STATUS_CODE_ASSERT', + }, + ], + }, + { + name: 'Invalid case with response.value', + code: `assert(response.value === StatusCodes.BAD_REQUEST, 'Expected response.value to be StatusCodes.BAD_REQUEST');`, + errors: [ + { + messageId: 'NO_STATUS_CODE_ASSERT', + }, + ], + }, + { + name: 'Invalid case with response.status and StatusCode BAD_REQUEST', + code: `assert.ok(response.status === StatusCodes.BAD_REQUEST);`, + errors: [ + { + messageId: 'NO_STATUS_CODE_ASSERT', + }, + ], + }, + { + name: 'Invalid case with response.status and 200', + code: `assert.equal(testStatusCode, 200);`, + errors: [ + { + messageId: 'NO_STATUS_CODE_ASSERT', + }, + ], + }, + { + name: 'Invalid case with assert response.status and 400', + code: `assert(response.status === 400);`, + errors: [ + { + messageId: 'NO_STATUS_CODE_ASSERT', + }, + ], + }, + ], +}); diff --git a/src/no-status-code-assert.ts b/src/no-status-code-assert.ts new file mode 100644 index 0000000..691fde0 --- /dev/null +++ b/src/no-status-code-assert.ts @@ -0,0 +1,86 @@ +// no-status-code-assert.ts + +/* + * Copyright (c) 2022-2025 Check Digit, LLC + * + * This code is licensed under the MIT license (see LICENSE.txt for details). + */ + +import { StatusCodes } from 'http-status-codes'; +import { AST_NODE_TYPES, ESLintUtils, TSESLint, TSESTree } from '@typescript-eslint/utils'; +import getDocumentationUrl from './get-documentation-url'; + +export const ruleId = 'no-status-code-assert'; +const NO_STATUS_CODE_ASSERT = 'NO_STATUS_CODE_ASSERT'; + +const createRule = ESLintUtils.RuleCreator((name) => getDocumentationUrl(name)); + +// Checks if a given AST node contains any status code value. +const hasStatusCodeOrValue = (arg: TSESTree.Node): boolean => { + switch (arg.type) { + case AST_NODE_TYPES.MemberExpression: { + const object = arg.object; + const property = arg.property; + if ( + object.type === AST_NODE_TYPES.Identifier && + object.name === 'StatusCodes' && + property.type === AST_NODE_TYPES.Identifier + ) { + return true; + } + break; + } + case AST_NODE_TYPES.Literal: + if (typeof arg.value === 'number' && Object.values(StatusCodes).includes(arg.value)) { + return true; + } + break; + case AST_NODE_TYPES.BinaryExpression: + return hasStatusCodeOrValue(arg.left) || hasStatusCodeOrValue(arg.right); + } + return false; +}; + +// Checks if a given AST node is an identifier with the name 'assert'. +const isAssertIdentifier = (node: TSESTree.Node): boolean => + node.type === AST_NODE_TYPES.Identifier && node.name === 'assert'; + +// Checks if a given AST node is a member expression with the object named 'assert'. +const isAssertMemberExpression = (node: TSESTree.Node): boolean => + node.type === AST_NODE_TYPES.MemberExpression && + node.object.type === AST_NODE_TYPES.Identifier && + node.object.name === 'assert' && + node.property.type === AST_NODE_TYPES.Identifier; + +const isAssertCallWithStatusCode = (callee: TSESTree.Node, args: TSESTree.Node[]): boolean => + (isAssertIdentifier(callee) || isAssertMemberExpression(callee)) && args.some((arg) => hasStatusCodeOrValue(arg)); + +const rule: TSESLint.RuleModule = createRule({ + name: ruleId, + meta: { + type: 'problem', + docs: { + description: 'Disallow using status codes in assertions; use error handling instead', + }, + schema: [], + messages: { + [NO_STATUS_CODE_ASSERT]: 'Do not use status codes in assertions; use error handling instead', + }, + }, + defaultOptions: [], + create(context) { + return { + CallExpression(node: TSESTree.CallExpression) { + const callee = node.callee; + if (isAssertCallWithStatusCode(callee, node.arguments)) { + context.report({ + node, + messageId: NO_STATUS_CODE_ASSERT, + }); + } + }, + }; + }, +}); + +export default rule;