@fullstacksjs/eslint-config 8.7.3 → 8.7.4-1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/cypress.js CHANGED
@@ -1,13 +1,15 @@
1
+ const { exts } = require('./utils');
2
+
1
3
  /** @type { import('eslint').Linter.Config } */
2
4
  module.exports = {
3
5
  overrides: [
4
6
  {
5
- files: ['**/cypress/**/*.+(js|jsx)', '**/cypress/**/*.+(ts|tsx)'],
6
- plugins: ['cypress'],
7
+ files: [`**/cypress/**/*.${exts}`, `**/*.cy.+${exts}`],
8
+ plugins: ['jest', 'jest-formatting', 'cypress'],
7
9
  env: {
8
10
  'cypress/globals': true,
9
11
  },
10
- extends: ['./rules/cypress'],
12
+ extends: ['./rules/test', './rules/cypress'],
11
13
  },
12
14
  ],
13
15
  };
package/esm.js CHANGED
@@ -1,13 +1,13 @@
1
1
  /** @type { import('eslint').Linter.Config } */
2
2
  module.exports = {
3
3
  rules: {
4
- 'import/extensions': 'off',
4
+ 'import/extensions': ['error', { mjs: 'ignorePackages' }],
5
5
  },
6
6
  overrides: [
7
7
  {
8
8
  files: ['*.ts', '*.tsx'],
9
9
  rules: {
10
- 'import/no-unresolved': [2, { ignore: ['.js$'], caseSensitiveStrict: true }],
10
+ 'import/no-unresolved': ['error', { ignore: ['.js$'], caseSensitiveStrict: true }],
11
11
  },
12
12
  },
13
13
  ],
package/index.js CHANGED
@@ -1,21 +1,14 @@
1
- const fs = require('fs');
2
- const { Packages } = require('@frontendmonster/utils');
3
- const readPkgUp = require('read-pkg-up');
4
-
5
- const { packageJson: pkg } = readPkgUp.sync({
6
- cwd: fs.realpathSync(process.cwd()),
7
- });
8
-
9
- const packages = Packages(pkg);
1
+ const packages = require('./packages');
2
+ const { compact } = require('@fullstacksjs/toolbox');
10
3
 
11
4
  /** @type { import('eslint').Linter.Config } */
12
5
  module.exports = {
13
- extends: [
6
+ extends: compact([
14
7
  require.resolve('./base'),
15
8
  require.resolve('./storybook'),
16
9
  require.resolve('./jest'),
17
10
  packages.ifAnyDep('react', () => require.resolve('./react')),
18
11
  packages.ifAnyDep('typescript', () => require.resolve('./typescript')),
19
12
  packages.ifAnyDep('cypress', () => require.resolve('./cypress')),
20
- ].filter(Boolean),
13
+ ]),
21
14
  };
package/jest.js CHANGED
@@ -1,4 +1,5 @@
1
- const exts = '+(js|jsx|ts|tsx)';
1
+ const { exts } = require('./utils');
2
+
2
3
  const dirs = '+(test|tests|__test__|__tests__|spec|specs)';
3
4
 
4
5
  /** @type { import('eslint').Linter.Config } */
@@ -10,7 +11,7 @@ module.exports = {
10
11
  env: {
11
12
  'jest/globals': true,
12
13
  },
13
- extends: ['./rules/jest'],
14
+ extends: ['./rules/test', './rules/jest'],
14
15
  },
15
16
  ],
16
17
  };
package/nextjs.js CHANGED
@@ -1,12 +1,4 @@
1
- const fs = require('fs');
2
- const { Packages } = require('@frontendmonster/utils');
3
- const readPkgUp = require('read-pkg-up');
4
-
5
- const { packageJson: pkg } = readPkgUp.sync({
6
- cwd: fs.realpathSync(process.cwd()),
7
- });
8
-
9
- const packages = Packages(pkg);
1
+ const packages = require('./packages');
10
2
 
11
3
  /** @type { import('eslint').Linter.Config } */
12
4
  module.exports = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fullstacksjs/eslint-config",
3
- "version": "8.7.3",
3
+ "version": "8.7.4-1",
4
4
  "license": "MIT",
5
5
  "author": "fullstacks <fullstacksjs@gmail.com>",
6
6
  "description": "fullstacks eslint config",
@@ -11,23 +11,22 @@
11
11
  "publishConfig": {
12
12
  "registry": "https://registry.npmjs.org"
13
13
  },
14
- "bin": {
15
- "fullstacksjs-eslint": "./bin/index.js"
16
- },
17
14
  "files": [
18
- "bin",
19
- "rules",
20
15
  "base.js",
16
+ "bin",
17
+ "cypress.js",
18
+ "esm.js",
19
+ "graphql.js",
21
20
  "index.js",
22
21
  "jest.js",
23
22
  "nextjs.js",
24
- "cypress.js",
25
- "storybook.js",
26
- "graphql.js",
23
+ "packages.js",
27
24
  "react.js",
28
- "typescript.js",
25
+ "rules",
26
+ "storybook.js",
29
27
  "typecheck.js",
30
- "esm.js"
28
+ "typescript.js",
29
+ "utils.js"
31
30
  ],
32
31
  "scripts": {
33
32
  "lint": "eslint .",
@@ -39,45 +38,49 @@
39
38
  "check-rules:graphql": "eslint-find-rules --no-core --deprecated --unused ./tests/graphql.js",
40
39
  "check-rules:storybook": "eslint-find-rules --no-core --deprecated --unused ./tests/storybook.js",
41
40
  "spell": "cspell ./* --no-progress",
42
- "test": "npm-run-all --parallel check-rules:* && npm run spell",
41
+ "test": "npm-run-all --parallel check-rules:*",
43
42
  "prepublishOnly": "pinst --disable",
44
43
  "postpublish": "pinst --enable",
45
44
  "pre-commit": "npm run test && lint-staged"
46
45
  },
47
46
  "main": "index.js",
48
47
  "dependencies": {
49
- "@frontendmonster/utils": "0.3.11",
50
- "@graphql-eslint/eslint-plugin": "3.10.7",
51
- "@typescript-eslint/eslint-plugin": "5.36.1",
52
- "@typescript-eslint/parser": "5.36.1",
48
+ "@fullstacksjs/toolbox": "3.0.2",
49
+ "@graphql-eslint/eslint-plugin": "3.13.1",
50
+ "@typescript-eslint/eslint-plugin": "5.46.1",
51
+ "@typescript-eslint/parser": "5.46.1",
53
52
  "eslint-config-prettier": "8.5.0",
54
- "eslint-import-resolver-typescript": "3.5.0",
53
+ "eslint-import-resolver-typescript": "3.5.3",
55
54
  "eslint-plugin-cypress": "2.12.1",
56
55
  "eslint-plugin-fp": "2.3.0",
57
56
  "eslint-plugin-import": "2.26.0",
58
- "eslint-plugin-jest": "27.0.1",
57
+ "eslint-plugin-jest": "27.1.7",
59
58
  "eslint-plugin-jest-formatting": "3.1.0",
60
59
  "eslint-plugin-jsx-a11y": "6.6.1",
61
60
  "eslint-plugin-node": "11.1.0",
62
61
  "eslint-plugin-prettier": "4.2.1",
63
- "eslint-plugin-promise": "6.0.1",
64
- "eslint-plugin-react": "7.31.4",
62
+ "eslint-plugin-promise": "6.1.1",
63
+ "eslint-plugin-react": "7.31.11",
65
64
  "eslint-plugin-react-hooks": "4.6.0",
66
65
  "eslint-plugin-simple-import-sort": "8.0.0",
67
- "eslint-plugin-storybook": "0.6.4",
66
+ "eslint-plugin-storybook": "0.6.8",
68
67
  "read-pkg-up": "7.0.1"
69
68
  },
70
69
  "devDependencies": {
71
- "cspell": "6.8.1",
72
- "eslint": "8.23.0",
70
+ "@semantic-release/github": "8.0.7",
71
+ "@semantic-release/npm": "9.0.1",
72
+ "@semantic-release/release-notes-generator": "10.0.3",
73
+ "cspell": "6.19.2",
74
+ "eslint": "8.29.0",
73
75
  "eslint-find-rules": "4.1.0",
74
- "husky": "8.0.1",
75
- "lint-staged": "13.0.3",
76
- "np": "7.6.2",
76
+ "husky": "8.0.3",
77
+ "lint-staged": "13.1.0",
78
+ "np": "7.6.3",
77
79
  "npm-run-all": "4.1.5",
78
80
  "pinst": "3.0.0",
79
- "prettier": "2.7.1",
80
- "typescript": "4.8.2"
81
+ "prettier": "2.8.3",
82
+ "semantic-release": "19.0.5",
83
+ "typescript": "4.9.5"
81
84
  },
82
85
  "peerDependencies": {
83
86
  "cypress": ">=8",
package/packages.js ADDED
@@ -0,0 +1,9 @@
1
+ const { Packages } = require('@fullstacksjs/toolbox');
2
+ const readPkgUp = require('read-pkg-up');
3
+ const fs = require('node:fs');
4
+
5
+ const { packageJson: pkg } = readPkgUp.sync({
6
+ cwd: fs.realpathSync(process.cwd()),
7
+ });
8
+
9
+ module.exports = Packages(pkg);
package/rules/base.js CHANGED
@@ -8,14 +8,20 @@ module.exports = {
8
8
  'default-case': 'error',
9
9
  'dot-notation': 'error',
10
10
  'eqeqeq': ['error', 'smart'],
11
+ 'grouped-accessor-pairs': 'off',
11
12
  'guard-for-in': 'error',
12
13
  'no-alert': 'error',
14
+ 'no-async-promise-executor': 'off',
13
15
  'no-caller': 'error',
14
16
  'no-case-declarations': 'error',
17
+ 'no-console': 'off',
18
+ 'no-constructor-return': 'error',
15
19
  'no-div-regex': 'error',
20
+ 'no-dupe-else-if': 'error',
16
21
  'no-else-return': 'off',
17
22
  'no-empty-function': 'off',
18
23
  'no-empty-pattern': 'error',
24
+ 'no-empty-static-block': 'warn',
19
25
  'no-eq-null': 'off',
20
26
  'no-eval': 'error',
21
27
  'no-extend-native': 'error',
@@ -27,6 +33,7 @@ module.exports = {
27
33
  'no-implicit-coercion': 'off',
28
34
  'no-implicit-globals': 'error',
29
35
  'no-implied-eval': 'error',
36
+ 'no-import-assign': 'error',
30
37
  'no-invalid-this': 'warn',
31
38
  'no-iterator': 'error',
32
39
  'no-labels': 'error',
@@ -34,23 +41,25 @@ module.exports = {
34
41
  'no-loop-func': 'error',
35
42
  'no-loss-of-precision': 'warn',
36
43
  'no-magic-numbers': 'off',
44
+ 'no-misleading-character-class': 'off',
37
45
  'no-multi-str': 'error',
46
+ 'no-new': 'error',
38
47
  'no-new-func': 'error',
39
48
  'no-new-wrappers': 'error',
40
- 'no-new': 'error',
41
- 'no-octal-escape': 'error',
42
49
  'no-octal': 'error',
50
+ 'no-octal-escape': 'error',
43
51
  'no-param-reassign': 'off',
44
52
  'no-proto': 'error',
45
53
  'no-redeclare': 'error',
46
- 'no-restricted-properties': 'off',
47
54
  'no-restricted-exports': 'off',
55
+ 'no-restricted-properties': 'off',
48
56
  'no-restricted-syntax': ['error', 'WithStatement'],
49
57
  'no-return-assign': 'error',
50
58
  'no-script-url': 'error',
51
59
  'no-self-assign': 'error',
52
60
  'no-self-compare': 'error',
53
61
  'no-sequences': 'error',
62
+ 'no-setter-return': 'error',
54
63
  'no-throw-literal': 'error',
55
64
  'no-unmodified-loop-condition': 'error',
56
65
  'no-unsafe-optional-chaining': 'error',
@@ -64,23 +73,15 @@ module.exports = {
64
73
  'no-void': 'off',
65
74
  'no-warning-comments': ['warn', { terms: ['fixme'], location: 'anywhere' }],
66
75
  'no-with': 'off',
67
- 'prefer-promise-reject-errors': 'off',
68
76
  'prefer-named-capture-group': 'off',
77
+ 'prefer-promise-reject-errors': 'off',
78
+ 'prefer-regex-literals': 'off',
69
79
  'radix': 'error',
70
- 'require-await': 'error',
71
- 'vars-on-top': 'error',
72
- 'yoda': 'error',
73
80
  'require-atomic-updates': 'off',
81
+ 'require-await': 'error',
74
82
  'require-unicode-regexp': 'off',
75
- 'no-misleading-character-class': 'off',
76
- 'no-async-promise-executor': 'off',
77
- 'no-console': 'off',
78
- 'no-constructor-return': 'error',
79
- 'no-dupe-else-if': 'error',
80
- 'no-import-assign': 'error',
81
- 'no-setter-return': 'error',
82
- 'prefer-regex-literals': 'off',
83
- 'grouped-accessor-pairs': 'off',
84
83
  'strict': 'error',
84
+ 'vars-on-top': 'error',
85
+ 'yoda': 'error',
85
86
  },
86
87
  };
package/rules/cypress.js CHANGED
@@ -1,3 +1,5 @@
1
+ const packages = require('../packages');
2
+
1
3
  module.exports = {
2
4
  rules: {
3
5
  'cypress/no-assigning-return-values': 'error',
@@ -7,9 +9,8 @@ module.exports = {
7
9
  'cypress/no-async-tests': 'error',
8
10
  'cypress/no-pause': 'error',
9
11
 
10
- // other modules
11
- 'max-lines-per-function': ['off'],
12
- '@typescript-eslint/method-signature-style': ['off'],
13
- '@typescript-eslint/no-namespace ': ['off'],
12
+ ...packages.ifAnyDep('typescript', () => ({
13
+ '@typescript-eslint/no-namespace': 0,
14
+ })),
14
15
  },
15
16
  };
@@ -20,6 +20,7 @@ module.exports = {
20
20
  'no-inner-declarations': 'error',
21
21
  'no-invalid-regexp': 'error',
22
22
  'no-irregular-whitespace': 'error',
23
+ 'no-new-native-nonconstructor': 'error',
23
24
  'no-nonoctal-decimal-escape': 'error',
24
25
  'no-obj-calls': 'error',
25
26
  'no-prototype-builtins': 'off',
package/rules/jest.js CHANGED
@@ -1,3 +1,5 @@
1
+ const packages = require('../packages');
2
+
1
3
  module.exports = {
2
4
  rules: {
3
5
  'jest/consistent-test-it': 'off',
@@ -8,19 +10,15 @@ module.exports = {
8
10
  'jest/no-commented-out-tests': 'warn',
9
11
  'jest/no-conditional-expect': 'error',
10
12
  'jest/no-conditional-in-test': 'error',
11
- 'jest/no-deprecated-functions': 'error',
12
- 'jest/no-disabled-tests': 'warn',
13
13
  'jest/no-done-callback': 'warn',
14
- 'jest/no-duplicate-hooks': 'off',
15
14
  'jest/no-expect-resolves': 'off',
16
15
  'jest/no-export': 'error',
17
- 'jest/no-focused-tests': 'error',
18
16
  'jest/no-hooks': 'off',
19
- 'jest/no-identical-title': 'error',
20
17
  'jest/no-interpolation-in-snapshots': 'error',
21
18
  'jest/no-jasmine-globals': 'off',
22
19
  'jest/no-large-snapshots': ['warn', { maxSize: 300 }],
23
20
  'jest/no-mocks-import': 'error',
21
+ 'jest/no-restricted-jest-methods': 'off',
24
22
  'jest/no-restricted-matchers': 'error',
25
23
  'jest/no-standalone-expect': 'off',
26
24
  'jest/no-test-callback': 'off',
@@ -44,27 +42,24 @@ module.exports = {
44
42
  'jest/prefer-to-contain': 'warn',
45
43
  'jest/prefer-to-have-length': 'warn',
46
44
  'jest/prefer-todo': 'warn',
47
- 'jest/require-hook': 'error',
45
+ 'jest/require-hook': 'off',
48
46
  'jest/require-to-throw-message': 'off',
49
47
  'jest/require-top-level-describe': 'off',
50
- 'jest/unbound-method': 'error',
51
48
  'jest/valid-describe-callback': 'error',
52
49
  'jest/valid-expect-in-promise': 'error',
53
50
  'jest/valid-expect': 'error',
54
51
  'jest/valid-title': 'warn',
55
52
 
56
- // jest-formatting
57
- 'jest-formatting/padding-around-after-all-blocks': 'warn',
58
- 'jest-formatting/padding-around-after-each-blocks': 'warn',
59
- 'jest-formatting/padding-around-all': 'warn',
60
- 'jest-formatting/padding-around-before-all-blocks': 'warn',
61
- 'jest-formatting/padding-around-before-each-blocks': 'warn',
62
- 'jest-formatting/padding-around-describe-blocks': 'warn',
63
- 'jest-formatting/padding-around-expect-groups': 'warn',
64
- 'jest-formatting/padding-around-test-blocks': 'warn',
53
+ 'jest/no-deprecated-functions': 'off',
54
+ ...packages.ifAnyDep('jest', () => ({
55
+ 'jest/no-deprecated-functions': 'error',
56
+ })),
57
+
58
+ ...packages.ifAnyDep('typescript', () => ({
59
+ '@typescript-eslint/unbound-method': 'off',
60
+ })),
65
61
 
66
62
  // conflicts
67
- '@typescript-eslint/unbound-method': 'off',
68
63
  'fp/no-let': 'off',
69
64
  },
70
65
  };
@@ -0,0 +1,50 @@
1
+ module.exports = [
2
+ {
3
+ selector: 'default',
4
+ format: ['camelCase'],
5
+ },
6
+ {
7
+ selector: 'function',
8
+ format: ['camelCase', 'PascalCase'],
9
+ },
10
+ // variables, CONSTANTS, ReactComponents
11
+ {
12
+ selector: 'variable',
13
+ format: ['camelCase', 'UPPER_CASE', 'PascalCase'],
14
+ },
15
+ {
16
+ selector: 'parameter',
17
+ format: ['camelCase', 'PascalCase'],
18
+ leadingUnderscore: 'allowSingleOrDouble',
19
+ },
20
+ {
21
+ selector: 'memberLike',
22
+ format: null,
23
+ },
24
+ {
25
+ selector: 'memberLike',
26
+ modifiers: ['static'],
27
+ format: ['camelCase', 'PascalCase'],
28
+ leadingUnderscore: 'allow',
29
+ },
30
+ {
31
+ selector: 'memberLike',
32
+ modifiers: ['private'],
33
+ format: ['camelCase'],
34
+ leadingUnderscore: 'allow',
35
+ },
36
+ {
37
+ selector: 'typeLike',
38
+ format: ['PascalCase'],
39
+ },
40
+ {
41
+ selector: 'enumMember',
42
+ format: ['PascalCase'],
43
+ },
44
+ // disallow I prefix for interfaces
45
+ {
46
+ selector: 'interface',
47
+ format: ['PascalCase'],
48
+ custom: { regex: '^I[A-Z]', match: false },
49
+ },
50
+ ];
package/rules/promise.js CHANGED
@@ -14,5 +14,6 @@ module.exports = {
14
14
  'promise/prefer-await-to-callbacks': 'off',
15
15
  'promise/prefer-await-to-then': 'off',
16
16
  'promise/valid-params': 'warn',
17
+ 'promise/no-multiple-resolved': 'warn',
17
18
  },
18
19
  };
package/rules/react.js CHANGED
@@ -11,7 +11,7 @@ module.exports = {
11
11
  'react/forbid-foreign-prop-types': 'error',
12
12
  'react/forbid-prop-types': 'off',
13
13
  'react/function-component-definition': ['warn', { namedComponents: 'arrow-function', unnamedComponents: 'arrow-function' }],
14
- 'react/hook-use-state': 'warn',
14
+ 'react/hook-use-state': 'off',
15
15
  'react/iframe-missing-sandbox': 'error',
16
16
  'react/jsx-boolean-value': 'warn',
17
17
  'react/jsx-child-element-spacing': 'warn',
package/rules/style.js CHANGED
@@ -17,14 +17,15 @@ module.exports = {
17
17
  // __filename, camelCase, PascalCase, CONST_VALUE, stream$, $el
18
18
  '^\\$?(__)?(([A-Z]|[a-z]|[0-9]+)|([A-Z_]))*\\$?$',
19
19
  ],
20
- 'linebreak-style': ['error', 'unix'],
21
20
  'line-comment-position': 'off',
21
+ 'linebreak-style': ['error', 'unix'],
22
22
  'lines-around-comment': 'off',
23
23
  'lines-between-class-members': ['warn', 'always', { exceptAfterSingleLine: false }],
24
+ 'logical-assignment-operators': 'off',
24
25
  'max-classes-per-file': 'off',
25
26
  'max-depth': ['error', 4],
26
- 'max-lines': ['error', { max: 2500, skipBlankLines: false, skipComments: false }],
27
27
  'max-lines-per-function': ['error', 150],
28
+ 'max-lines': ['error', { max: 2500, skipBlankLines: false, skipComments: false }],
28
29
  'max-nested-callbacks': ['error', 7],
29
30
  'max-params': ['error', 7],
30
31
  'max-statements-per-line': ['error', { max: 1 }],
package/rules/test.js ADDED
@@ -0,0 +1,31 @@
1
+ const packages = require('../packages');
2
+
3
+ module.exports = {
4
+ rules: {
5
+ 'jest/no-duplicate-hooks': 'error',
6
+ 'jest/no-disabled-tests': 'error',
7
+ 'jest/no-focused-tests': 'error',
8
+ 'jest/no-identical-title': 'error',
9
+
10
+ // formatting
11
+ 'jest-formatting/padding-around-after-all-blocks': 'warn',
12
+ 'jest-formatting/padding-around-after-each-blocks': 'warn',
13
+ 'jest-formatting/padding-around-all': 'warn',
14
+ 'jest-formatting/padding-around-before-all-blocks': 'warn',
15
+ 'jest-formatting/padding-around-before-each-blocks': 'warn',
16
+ 'jest-formatting/padding-around-describe-blocks': 'warn',
17
+ 'jest-formatting/padding-around-expect-groups': 'warn',
18
+ 'jest-formatting/padding-around-test-blocks': 'warn',
19
+
20
+ // other modules
21
+ 'max-lines-per-function': 'off',
22
+ ...packages.ifAnyDep('react', () => ({
23
+ 'react/jsx-no-constructed-context-values': 'off',
24
+ })),
25
+ ...packages.ifAnyDep('typescript', () => ({
26
+ '@typescript-eslint/method-signature-style': 'off',
27
+ '@typescript-eslint/no-namespace ': 'off',
28
+ '@typescript-eslint/unbound-method': 'off',
29
+ })),
30
+ },
31
+ };
@@ -4,14 +4,18 @@ module.exports = {
4
4
  '@typescript-eslint/consistent-type-exports': 'warn',
5
5
  '@typescript-eslint/dot-notation': [
6
6
  'warn',
7
- { allowPrivateClassPropertyAccess: false, allowProtectedClassPropertyAccess: false, allowIndexSignaturePropertyAccess: true },
7
+ {
8
+ allowPrivateClassPropertyAccess: false,
9
+ allowProtectedClassPropertyAccess: false,
10
+ allowIndexSignaturePropertyAccess: true,
11
+ },
8
12
  ],
9
13
  '@typescript-eslint/no-confusing-void-expression': ['warn', { ignoreArrowShorthand: true, ignoreVoidOperator: true }],
10
14
  '@typescript-eslint/no-floating-promises': ['error', { ignoreVoid: true }],
11
15
  '@typescript-eslint/no-for-in-array': 'error',
12
16
  '@typescript-eslint/no-implied-eval': 'error',
13
17
  '@typescript-eslint/no-meaningless-void-operator': ['warn', { checkNever: false }],
14
- '@typescript-eslint/no-misused-promises': 'error',
18
+ '@typescript-eslint/no-misused-promises': ['warn', { checksVoidReturn: { attributes: false } }],
15
19
  '@typescript-eslint/no-redundant-type-constituents': 'warn',
16
20
  '@typescript-eslint/no-throw-literal': 'error',
17
21
  '@typescript-eslint/no-unnecessary-boolean-literal-compare': 'error',
@@ -30,7 +34,12 @@ module.exports = {
30
34
  '@typescript-eslint/prefer-reduce-type-parameter': 'warn',
31
35
  '@typescript-eslint/prefer-nullish-coalescing': [
32
36
  'warn',
33
- { ignoreConditionalTests: false, ignoreTernaryTests: false, ignoreMixedLogicalExpressions: false, forceSuggestionFixer: false },
37
+ {
38
+ ignoreConditionalTests: false,
39
+ ignoreTernaryTests: false,
40
+ ignoreMixedLogicalExpressions: false,
41
+ allowRuleToRunWithoutStrictNullChecksIKnowWhatIAmDoing: false,
42
+ },
34
43
  ],
35
44
  '@typescript-eslint/prefer-regexp-exec': 'warn',
36
45
  '@typescript-eslint/prefer-return-this-type': 'warn',
@@ -42,45 +51,13 @@ module.exports = {
42
51
  '@typescript-eslint/unbound-method': ['error', { ignoreStatic: true }],
43
52
  '@typescript-eslint/naming-convention': [
44
53
  'warn',
45
- {
46
- selector: 'default',
47
- format: ['camelCase'],
48
- },
49
- // variables, CONSTANTS, ReactComponents
50
- {
51
- selector: 'variable',
52
- format: ['camelCase', 'UPPER_CASE', 'PascalCase'],
53
- },
54
- {
55
- selector: 'parameter',
56
- format: ['camelCase'],
57
- leadingUnderscore: 'allow',
58
- },
59
- {
60
- selector: 'memberLike',
61
- modifiers: ['private'],
62
- format: ['camelCase'],
63
- leadingUnderscore: 'allow',
64
- },
65
- {
66
- selector: 'typeLike',
67
- format: ['PascalCase'],
68
- },
69
- // disallow I prefix for interfaces
70
- {
71
- selector: 'interface',
72
- format: ['PascalCase'],
73
- custom: {
74
- regex: '^I[A-Z]',
75
- match: false,
76
- },
77
- },
78
- // force use is/should/has ... for boolean variables
54
+ ...require('./naming-convention'), // eslint-disable-line node/global-require
55
+ // force use is/should/has for boolean variables
79
56
  {
80
57
  selector: 'variable',
81
58
  types: ['boolean'],
82
- format: ['camelCase'],
83
- prefix: ['is', 'should', 'has', 'can', 'did', 'will', 'enable'],
59
+ format: ['PascalCase'],
60
+ prefix: ['is', 'should', 'has', 'can', 'did', 'will', 'enable', 'loading'],
84
61
  },
85
62
  ],
86
63
 
@@ -30,57 +30,7 @@ module.exports = {
30
30
  '@typescript-eslint/member-naming': 'off',
31
31
  '@typescript-eslint/member-ordering': 'off',
32
32
  '@typescript-eslint/method-signature-style': ['warn', 'property'],
33
- '@typescript-eslint/naming-convention': [
34
- 'warn',
35
- {
36
- selector: 'default',
37
- format: ['camelCase'],
38
- },
39
- {
40
- selector: 'function',
41
- format: ['camelCase', 'PascalCase'],
42
- },
43
- // variables, CONSTANTS, ReactComponents
44
- {
45
- selector: 'variable',
46
- format: ['camelCase', 'UPPER_CASE', 'PascalCase'],
47
- },
48
- {
49
- selector: 'parameter',
50
- format: ['camelCase', 'PascalCase'],
51
- leadingUnderscore: 'allowSingleOrDouble',
52
- },
53
- {
54
- selector: 'memberLike',
55
- format: null,
56
- },
57
- {
58
- selector: 'memberLike',
59
- modifiers: ['static'],
60
- format: ['camelCase', 'PascalCase'],
61
- leadingUnderscore: 'allow',
62
- },
63
- {
64
- selector: 'memberLike',
65
- modifiers: ['private'],
66
- format: ['camelCase'],
67
- leadingUnderscore: 'allow',
68
- },
69
- {
70
- selector: 'typeLike',
71
- format: ['PascalCase'],
72
- },
73
- {
74
- selector: 'enumMember',
75
- format: ['PascalCase'],
76
- },
77
- // disallow I prefix for interfaces
78
- {
79
- selector: 'interface',
80
- format: ['PascalCase'],
81
- custom: { regex: '^I[A-Z]', match: false },
82
- },
83
- ],
33
+ '@typescript-eslint/naming-convention': ['warn', ...require('./naming-convention')], // eslint-disable-line node/global-require
84
34
  '@typescript-eslint/no-array-constructor': 'error',
85
35
  '@typescript-eslint/no-base-to-string': 'off', // false negative
86
36
  '@typescript-eslint/no-confusing-non-null-assertion': 'error',
@@ -100,13 +50,13 @@ module.exports = {
100
50
  '@typescript-eslint/no-magic-numbers': ['off', { ignoreEnums: true }], // Not good enough yet
101
51
  '@typescript-eslint/no-misused-new': 'error',
102
52
  '@typescript-eslint/no-namespace': 'error',
53
+ '@typescript-eslint/consistent-type-imports': ['warn', { prefer: 'type-imports', disallowTypeAnnotations: false }],
103
54
  '@typescript-eslint/no-non-null-asserted-nullish-coalescing': 'error',
104
55
  '@typescript-eslint/no-non-null-asserted-optional-chain': 'error',
105
56
  '@typescript-eslint/no-non-null-assertion': 'off',
106
57
  '@typescript-eslint/no-redeclare': ['off', { ignoreDeclarationMerge: true }], // useful in FP.
107
58
  '@typescript-eslint/no-require-imports': 'error',
108
59
  '@typescript-eslint/no-restricted-imports': 'off',
109
- '@typescript-eslint/consistent-type-imports': ['warn', { prefer: 'type-imports', disallowTypeAnnotations: false }],
110
60
  '@typescript-eslint/no-shadow': 'error',
111
61
  '@typescript-eslint/no-this-alias': 'error',
112
62
  '@typescript-eslint/no-type-alias': 'off',
@@ -114,6 +64,7 @@ module.exports = {
114
64
  '@typescript-eslint/no-unsafe-argument': 'off',
115
65
  '@typescript-eslint/no-unsafe-assignment': 'off',
116
66
  '@typescript-eslint/no-unsafe-call': 'off',
67
+ '@typescript-eslint/no-unsafe-declaration-merging': 'warn',
117
68
  '@typescript-eslint/no-unsafe-member-access': 'off',
118
69
  '@typescript-eslint/no-unsafe-return': 'off',
119
70
  '@typescript-eslint/no-untyped-public-signature': 'off',
@@ -129,7 +80,14 @@ module.exports = {
129
80
  '@typescript-eslint/no-var-requires': 'error',
130
81
  '@typescript-eslint/object-curly-spacing': 'warn',
131
82
  '@typescript-eslint/parameter-properties': 'off',
132
- '@typescript-eslint/padding-line-between-statements': ['warn', { blankLine: 'always', prev: ['return'], next: ['export'] }],
83
+ '@typescript-eslint/padding-line-between-statements': [
84
+ 'warn',
85
+ { blankLine: 'always', prev: '*', next: ['class', 'for', 'while', 'switch', 'do', 'directive', 'function', 'iife', 'block-like'] },
86
+ { blankLine: 'always', prev: ['block-like', 'block'], next: ['return'] },
87
+ { blankLine: 'always', prev: ['block-like'], next: ['const', 'let', 'var'] },
88
+ { blankLine: 'always', prev: ['const', 'let', 'var'], next: ['type', 'interface'] },
89
+ { blankLine: 'always', prev: ['multiline-const', 'multiline-let', 'multiline-var'], next: ['if'] },
90
+ ],
133
91
  '@typescript-eslint/prefer-as-const': 'warn',
134
92
  '@typescript-eslint/prefer-enum-initializers': 'off',
135
93
  '@typescript-eslint/prefer-for-of': 'warn',
@@ -150,7 +108,7 @@ module.exports = {
150
108
  'off',
151
109
  { allowNumber: true, allowBoolean: false, allowAny: false, allowNullish: false, allowRegExp: false },
152
110
  ],
153
- '@typescript-eslint/sort-type-union-intersection-members': [
111
+ '@typescript-eslint/sort-type-constituents': [
154
112
  'warn',
155
113
  {
156
114
  checkIntersections: true,
package/storybook.js CHANGED
@@ -3,7 +3,7 @@ module.exports = {
3
3
  overrides: [
4
4
  {
5
5
  plugins: ['storybook'],
6
- files: ['*.stories.+(ts|tsx|js|jsx|mjs|cjs)', '*.story.+(ts|tsx|js|jsx|mjs|cjs)'],
6
+ files: ['*.stories.+(ts|tsx|js|jsx|mjs|cjs|mdx)', '*.story.+(ts|tsx|js|jsx|mjs|cjs|mdx)'],
7
7
  extends: ['./rules/storybook.js'],
8
8
  },
9
9
  ],
package/typecheck.js CHANGED
@@ -3,7 +3,7 @@ module.exports = {
3
3
  overrides: [
4
4
  {
5
5
  files: ['*.ts', '*.tsx'],
6
- extends: ['./rules/typescript-requiring-type-checking.js'],
6
+ extends: ['./rules/typecheck.js'],
7
7
  },
8
8
  ],
9
9
  };
package/utils.js ADDED
@@ -0,0 +1 @@
1
+ module.exports.exts = '+(js|jsx|mjs|cjs|ts|tsx|mts|cts)';
package/bin/index.js DELETED
@@ -1,9 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- const createOptions = require('./lib/createOptions');
4
- const createTasks = require('./lib/tasks');
5
-
6
- createOptions()
7
- .then(createTasks)
8
- .then(tasks => tasks.run())
9
- .catch(() => {});
@@ -1,51 +0,0 @@
1
- const { readFile } = require('fs/promises');
2
- const inquirer = require('inquirer');
3
-
4
- const isObject = x => typeof x === 'object' && !Array.isArray(x) && x !== null;
5
-
6
- // TODO: add this function to the toolbox
7
- const merge = (obj, obj2) =>
8
- Object.entries(obj)
9
- .concat(Object.entries(obj2))
10
- .reduce((acc, [key, value]) => {
11
- const accValue = acc[key];
12
- return Array.isArray(accValue) && Array.isArray(value)
13
- ? { ...acc, [key]: accValue.concat(value) }
14
- : isObject(accValue) && isObject(value)
15
- ? { ...acc, [key]: merge(accValue, value) }
16
- : { ...acc, [key]: value };
17
- }, {});
18
-
19
- const Choice = {
20
- noConfig: 'noConfig',
21
- overwrite: 'overwrite',
22
- extend: 'extend',
23
- };
24
-
25
- const askWhenConfigExists = async eslintrc => {
26
- const file = await readFile('.eslintrc.json').catch(() => null);
27
- if (file === null) return eslintrc;
28
-
29
- const currentConfig = JSON.parse(file);
30
- const isConfiguredBefore = eslintrc?.extends.every(c => currentConfig?.extends?.includes(c));
31
- if (isConfiguredBefore) return currentConfig;
32
-
33
- const { choice } = await inquirer.prompt({
34
- type: 'list',
35
- name: 'choice',
36
- message: 'config found',
37
- choices: [
38
- {
39
- value: 'overwrite',
40
- name: 'overwrite the current config completely',
41
- },
42
- {
43
- value: 'extend',
44
- name: 'extend the fullstacks config alongside current config',
45
- },
46
- ],
47
- });
48
- return choice === Choice.extend ? merge(currentConfig, eslintrc) : eslintrc;
49
- };
50
-
51
- module.exports = askWhenConfigExists;
@@ -1,25 +0,0 @@
1
- const getUserInput = require('./getUserInput');
2
- const args = require('./parseArgs');
3
-
4
- const eslintrcConfig = {
5
- extends: ['@fullstacksjs'],
6
- };
7
-
8
- const requiredPackages = ['@fullstacksjs/eslint-config', 'eslint', 'prettier'];
9
-
10
- async function createOptions() {
11
- const isTechnologyInArgv = args.t != null;
12
- const optionsFromArgs = { technology: args.t };
13
- const userInput = isTechnologyInArgv ? optionsFromArgs : await getUserInput();
14
-
15
- if (userInput.technology === 'ts') {
16
- requiredPackages.push('typescript');
17
- }
18
-
19
- return {
20
- eslintrc: eslintrcConfig,
21
- packages: requiredPackages,
22
- };
23
- }
24
-
25
- module.exports = createOptions;
@@ -1,15 +0,0 @@
1
- const { writeFile } = require('fs/promises');
2
-
3
- function createFileTask(eslintrc, ctx, task) {
4
- return writeFile('.eslintrc.json', JSON.stringify(eslintrc, null, 2))
5
- .then(() => {
6
- task.title = `.eslintrc - Successfully Generated.`;
7
- })
8
- .catch(() => {
9
- ctx.isEslintrc = false;
10
- task.title = `Generating .eslintrc file`;
11
- throw Error("Couldn't create file");
12
- });
13
- }
14
-
15
- module.exports = createFileTask;
@@ -1,24 +0,0 @@
1
- const inquirer = require('inquirer');
2
-
3
- function getUserInput() {
4
- return inquirer.prompt([
5
- {
6
- type: 'list',
7
- name: 'technology',
8
- message: 'which technology are you using?',
9
- choices: [
10
- {
11
- value: 'ts',
12
- name: 'ESLint alongside TypeScript',
13
- },
14
- {
15
- value: 'js',
16
- name: 'ESLint for JavaScript development',
17
- },
18
- ],
19
- default: 'js',
20
- },
21
- ]);
22
- }
23
-
24
- module.exports = getUserInput;
@@ -1,12 +0,0 @@
1
- const yargs = require('yargs');
2
-
3
- const args = yargs(process.argv.slice(2))
4
- .alias('t', 'technology')
5
- .describe('t', 'Which technology are you using')
6
- .choices('t', ['ts', 'js'])
7
- .usage('Usage: $0 [-t ts|js]')
8
- .example('$0 - ts')
9
- .help('h')
10
- .alias('h', 'help').argv;
11
-
12
- module.exports = args;
package/bin/lib/tasks.js DELETED
@@ -1,30 +0,0 @@
1
- const Listr = require('listr');
2
- const util = require('util');
3
- const askWhenConfigExists = require('./askWhenConfigExists');
4
- const exec = util.promisify(require('child_process').exec);
5
- const createFileTask = require('./generateFile');
6
-
7
- async function createTasks({ packages, eslintrc }) {
8
- const installTasks = packages.map(pkg => ({
9
- title: `Installing ${pkg}`,
10
- task: (ctx, task) => exec(`npm i -D ${pkg}`).then(() => (task.title = `${pkg} Installed`)),
11
- }));
12
-
13
- const config = await askWhenConfigExists(eslintrc);
14
-
15
- return new Listr(
16
- [
17
- {
18
- title: 'Installing dependencies using npm',
19
- task: () => new Listr(installTasks, { exitOnError: true }),
20
- },
21
- {
22
- title: 'Generating .eslintrc.json file',
23
- task: (ctx, task) => createFileTask(config, ctx, task),
24
- },
25
- ],
26
- { exitOnError: false },
27
- );
28
- }
29
-
30
- module.exports = createTasks;