Files
2023-08-31 21:44:37 -05:00

271 lines
7.7 KiB
JavaScript

module.exports = {
extends: [
"airbnb-base",
"airbnb-typescript/base",
"plugin:jest/recommended",
"plugin:jest/style",
"plugin:@typescript-eslint/recommended",
"plugin:import/typescript",
"prettier",
],
parserOptions: { tsconfigRootDir: __dirname, project: "./tsconfig.eslint.json" },
env: { es2021: true, node: true, "jest/globals": true },
plugins: ["jest"],
ignorePatterns: [
"node_modules",
"dist",
"coverage",
// "**/*.d.ts",
"!.*.js",
"!.*.cjs",
"!.*.mjs",
],
rules: {
// enforce curly brace usage
curly: ["error", "all"],
// allow class methods which do not use this
"class-methods-use-this": "off",
// Allow use of ForOfStatement - no-restricted-syntax does not allow us to turn off a rule. This block overrides the airbnb rule entirely
// https://github.com/airbnb/javascript/blob/7152396219e290426a03e47837e53af6bcd36bbe/packages/eslint-config-airbnb-base/rules/style.js#L257-L263
"no-restricted-syntax": [
"error",
{
selector: "ForInStatement",
message:
"for..in loops iterate over the entire prototype chain, which is virtually never what you want. Use Object.{keys,values,entries}, and iterate over the resulting array.",
},
{
selector: "LabeledStatement",
message:
"Labels are a form of GOTO; using them makes code confusing and hard to maintain and understand.",
},
{
selector: "WithStatement",
message:
"`with` is disallowed in strict mode because it makes code impossible to predict and optimize.",
},
],
// underscore dangle will be handled by @typescript-eslint/naming-convention
"no-underscore-dangle": "off",
// enforce consistent sort order
"sort-imports": ["error", { ignoreCase: true, ignoreDeclarationSort: true }],
// enforce convention in import order
"import/order": [
"error",
{
"newlines-between": "never",
groups: ["builtin", "external", "internal", "parent", "sibling", "index"],
alphabetize: { order: "asc", caseInsensitive: true },
},
],
// ensure consistent array typings
"@typescript-eslint/array-type": "error",
// ban ts-comment except with description
"@typescript-eslint/ban-ts-comment": [
"error",
{
"ts-expect-error": "allow-with-description",
"ts-ignore": "allow-with-description",
"ts-nocheck": true,
"ts-check": false,
},
],
// prefer type imports and exports
"@typescript-eslint/consistent-type-exports": [
"error",
{ fixMixedExportsWithInlineTypeSpecifier: true },
],
"@typescript-eslint/consistent-type-imports": ["error", { prefer: "type-imports" }],
// enforce consistent order of class members
"@typescript-eslint/member-ordering": "error",
// set up naming convention rules
"@typescript-eslint/naming-convention": [
"error",
// camelCase for everything not otherwise indicated
{ selector: "default", format: ["camelCase"] },
// allow known default exclusions
{
selector: "default",
filter: { regex: "^(_id|__v)$", match: true },
format: null,
},
// allow variables to be camelCase or UPPER_CASE
{ selector: "variable", format: ["camelCase", "UPPER_CASE"] },
// allow known variable exclusions
{
selector: "variable",
filter: { regex: "^(_id|__v)$", match: true },
format: null,
},
{
// variables ending in Service should be PascalCase
selector: "variable",
filter: { regex: "^.*Service$", match: true },
format: ["PascalCase"],
},
// do not enforce format on property names
{ selector: "property", format: null },
// PascalCase for classes and TypeScript keywords
{
selector: ["typeLike"],
format: ["PascalCase"],
},
],
// disallow parameter properties in favor of explicit class declarations
"@typescript-eslint/no-parameter-properties": "error",
// ensure unused variables are treated as an error
// overrides @typescript-eslint/recommended -- '@typescript-eslint/no-unused-vars': 'warn'
// https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/src/configs/recommended.ts
"@typescript-eslint/no-unused-vars": "warn",
},
overrides: [
{
files: ["**/*.ts"],
extends: ["plugin:@typescript-eslint/recommended-requiring-type-checking"],
rules: {
// disable rules turned on by @typescript-eslint/recommended-requiring-type-checking which are too noisy
// https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/src/configs/recommended-requiring-type-checking.ts
"@typescript-eslint/no-unsafe-argument": "off",
"@typescript-eslint/no-unsafe-assignment": "off",
"@typescript-eslint/no-unsafe-call": "off",
"@typescript-eslint/no-unsafe-member-access": "off",
"@typescript-eslint/no-unsafe-return": "off",
"@typescript-eslint/restrict-template-expressions": "off",
"@typescript-eslint/unbound-method": "off",
// force explicit member accessibility modifiers
"@typescript-eslint/explicit-member-accessibility": ["error", { accessibility: "no-public" }],
// enforce return types on module boundaries
"@typescript-eslint/explicit-module-boundary-types": "error",
// allow empty functions
"@typescript-eslint/no-empty-function": "off",
},
},
{
files: ["**/index.ts"],
rules: {
// prefer named exports for certain file types
"import/prefer-default-export": "off",
"import/no-default-export": "error",
},
},
{
files: [
"**/test/**/*.[jt]s?(x)",
"**/__tests__/**/*.[jt]s?(x)",
"**/?(*.)+(spec|test).[jt]s?(x)",
],
rules: {
// allow tests to create multiple classes
"max-classes-per-file": "off",
// allow side effect constructors
"no-new": "off",
// allow import with CommonJS export
"import/no-import-module-exports": "off",
// allow dev dependencies
"import/no-extraneous-dependencies": [
"error",
{ devDependencies: true, optionalDependencies: false, peerDependencies: false },
],
// disallow use of "it" for test blocks
"jest/consistent-test-it": ["error", { fn: "test", withinDescribe: "test" }],
// ensure all tests contain an assertion
"jest/expect-expect": "error",
// no commented out tests
"jest/no-commented-out-tests": "error",
// no duplicate test hooks
"jest/no-duplicate-hooks": "error",
// valid titles
"jest/valid-title": "error",
// no if conditionals in tests
"jest/no-if": "error",
// expect statements in test blocks
"jest/no-standalone-expect": "error",
// disallow returning from test
"jest/no-test-return-statement": "error",
// disallow truthy and falsy in tests
"jest/no-restricted-matchers": ["error", { toBeFalsy: null, toBeTruthy: null }],
// prefer called with
"jest/prefer-called-with": "error",
"jest/no-conditional-expect": "off"
},
},
{
files: [
"**/test/**/*.ts?(x)",
"**/__tests__/**/*.ts?(x)",
"**/?(*.)+(spec|test).ts?(x)",
],
rules: {
// allow explicit any in tests
"@typescript-eslint/no-explicit-any": "off",
// allow non-null-assertions
"@typescript-eslint/no-non-null-assertion": "off",
// allow empty arrow functions
"@typescript-eslint/no-empty-function": ["warn", { allow: ["arrowFunctions"] }],
},
},
{
files: ["./.*.js", "./*.js"],
rules: {
// allow requires in config files
"@typescript-eslint/no-var-requires": "off",
},
},
{
files: ["**/*.d.ts"],
rules: {
// allow tests to create multiple classes
"max-classes-per-file": "off",
"@typescript-eslint/naming-convention": "off",
"lines-between-class-members": "off",
"@typescript-eslint/lines-between-class-members": "off",
"@typescript-eslint/member-ordering": "off",
"@typescript-eslint/ban-types": "off"
},
},
],
};