@asd14/eslint-config 14.5.0 → 15.0.0

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/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package.json",
3
3
  "name": "@asd14/eslint-config",
4
- "version": "14.5.0",
5
- "description": "ASD14's reusable ESLint config",
4
+ "version": "15.0.0",
5
+ "description": "ASD14's reusable ESLint configurations",
6
6
  "sideEffects": false,
7
7
  "publishConfig": {
8
8
  "access": "public"
@@ -15,6 +15,13 @@
15
15
  "dist",
16
16
  "src"
17
17
  ],
18
+ "nx": {
19
+ "projectType": "library",
20
+ "tags": [
21
+ "type:library",
22
+ "target:node"
23
+ ]
24
+ },
18
25
  "type": "module",
19
26
  "exports": {
20
27
  "./node": {
@@ -25,9 +32,9 @@
25
32
  "import": "./src/configs/react.js",
26
33
  "types": "./dist/types/src/configs/react.d.ts"
27
34
  },
28
- "./typescript": {
29
- "import": "./src/configs/typescript.js",
30
- "types": "./dist/types/src/configs/typescript.d.ts"
35
+ "./ts": {
36
+ "import": "./src/configs/ts.js",
37
+ "types": "./dist/types/src/configs/ts.d.ts"
31
38
  },
32
39
  "./nx": {
33
40
  "import": "./src/configs/nx.js",
@@ -49,11 +56,11 @@
49
56
  "typecheck": "tsc --noEmit"
50
57
  },
51
58
  "dependencies": {
52
- "@nx/eslint-plugin": "^22.5.1",
59
+ "@nx/eslint-plugin": "^22.5.3",
53
60
  "eslint-config-prettier": "^10.1.8",
54
61
  "eslint-plugin-import": "^2.32.0",
55
- "eslint-plugin-jest": "^29.14.0",
56
- "eslint-plugin-jsdoc": "^62.5.5",
62
+ "eslint-plugin-jest": "^29.15.0",
63
+ "eslint-plugin-jsdoc": "^62.7.1",
57
64
  "eslint-plugin-json": "^4.0.1",
58
65
  "eslint-plugin-jsx-a11y": "^6.10.2",
59
66
  "eslint-plugin-no-inferred-method-name": "^2.0.0",
@@ -61,24 +68,25 @@
61
68
  "eslint-plugin-promise": "^7.2.1",
62
69
  "eslint-plugin-react": "^7.37.5",
63
70
  "eslint-plugin-react-hooks": "^7.0.1",
64
- "eslint-plugin-react-refresh": "^0.5.0",
65
- "eslint-plugin-testing-library": "^7.15.4",
71
+ "eslint-plugin-react-refresh": "^0.5.2",
72
+ "eslint-plugin-testing-library": "^7.16.0",
66
73
  "eslint-plugin-unicorn": "^63.0.0",
67
- "globals": "^17.3.0",
68
- "typescript-eslint": "^8.55.0"
74
+ "globals": "^17.4.0",
75
+ "typescript-eslint": "^8.56.1"
69
76
  },
70
77
  "devDependencies": {
71
- "@asd14/prettier-config": "^1.1.0",
72
- "@asd14/ts-config": "^1.1.0",
73
- "@commitlint/cli": "^20.4.1",
74
- "@commitlint/config-conventional": "^20.4.1",
78
+ "@asd14/prettier-config": "^1.2.0",
79
+ "@asd14/ts-config": "^1.3.0",
80
+ "@commitlint/cli": "^20.4.2",
81
+ "@commitlint/config-conventional": "^20.4.2",
75
82
  "@semantic-release/git": "^10.0.1",
76
83
  "conventional-changelog-conventionalcommits": "^9.1.0",
77
84
  "semantic-release": "^25.0.3"
78
85
  },
79
86
  "peerDependencies": {
80
87
  "eslint": "^9",
81
- "prettier": "^3"
88
+ "prettier": "^3",
89
+ "typescript": "^5"
82
90
  },
83
91
  "engines": {
84
92
  "node": "^22.12.0 || ^24.0.0"
@@ -1,8 +1,9 @@
1
- import jestPlugin from "eslint-plugin-jest"
2
1
  import prettierConfig from "eslint-plugin-prettier/recommended"
3
2
  import globals from "globals"
4
3
 
5
4
  import baseConfig from "../rules/base.js"
5
+ import devConfig from "../rules/dev.js"
6
+ import commonIgnores from "../rules/ignores.js"
6
7
  import importConfig from "../rules/import.js"
7
8
  import jsdocConfig from "../rules/jsdoc.js"
8
9
  import unicornConfig from "../rules/unicorn.js"
@@ -13,17 +14,15 @@ const nodeSpecificRules = {
13
14
  "unicorn/prevent-abbreviations": [
14
15
  "error",
15
16
  {
17
+ ignore: ["utils", "db", "props"],
16
18
  replacements: {
17
19
  i: false,
18
- utils: false,
19
20
  params: false,
20
21
  lib: false,
21
22
  args: {
22
23
  params: true,
23
24
  },
24
- props: {
25
- options: true,
26
- },
25
+ props: false,
27
26
  fn: false,
28
27
  acc: false,
29
28
  },
@@ -34,7 +33,6 @@ const nodeSpecificRules = {
34
33
  /** @satisfies {import("eslint").Linter.Config} */
35
34
  const nodeConfig = /** @type {const} */ ({
36
35
  name: "ASD14 config for Node.js source files",
37
- ignores: ["node_modules", "dist", "coverage", "build"],
38
36
  languageOptions: {
39
37
  ecmaVersion: "latest",
40
38
  sourceType: "module",
@@ -66,33 +64,4 @@ const nodeConfig = /** @type {const} */ ({
66
64
  },
67
65
  })
68
66
 
69
- const jestConfig = jestPlugin.configs["flat/recommended"]
70
-
71
- /** @satisfies {import("eslint").Linter.Config} */
72
- const nodeJestConfig = /** @type {const} */ ({
73
- name: "ASD14's config for Node.js test files",
74
- languageOptions: jestConfig.languageOptions,
75
- plugins: jestConfig.plugins,
76
- rules: {
77
- ...jestConfig.rules,
78
- "jest/require-top-level-describe": "error",
79
- "jest/consistent-test-it": [
80
- "error",
81
- {
82
- fn: "test",
83
- withinDescribe: "test",
84
- },
85
- ],
86
- "jest/valid-title": [
87
- "error",
88
- {
89
- mustMatch: {
90
- test: "^given \\[.*\\] should \\[.*\\]$",
91
- },
92
- },
93
- ],
94
- },
95
- })
96
-
97
- export { commonIgnores } from "../rules/ignores.js"
98
- export { nodeConfig, nodeJestConfig }
67
+ export { commonIgnores, devConfig, nodeConfig }
package/src/configs/nx.js CHANGED
@@ -1,8 +1,5 @@
1
- import path from "node:path"
2
1
  import nxPlugin from "@nx/eslint-plugin"
3
2
 
4
- import { findUpSync } from "../utils/find-up-sync.js"
5
-
6
3
  const RULES = {
7
4
  // Visibility and publishing rules
8
5
  publicCanOnlyImportPublic: {
@@ -15,33 +12,33 @@ const RULES = {
15
12
  },
16
13
  // Package type rules
17
14
  libsCanOnlyImportLibs: {
18
- sourceTag: "type:lib",
19
- onlyDependOnLibsWithTags: ["type:lib"],
15
+ sourceTag: "type:library",
16
+ onlyDependOnLibsWithTags: ["type:library"],
20
17
  },
21
18
  hooksCanOnlyImportLibsAndHooks: {
22
19
  sourceTag: "type:hook",
23
- onlyDependOnLibsWithTags: ["type:lib", "type:hook"],
20
+ onlyDependOnLibsWithTags: ["type:library", "type:hook"],
24
21
  },
25
22
  uiCanImportAny: {
26
23
  sourceTag: "type:ui",
27
- onlyDependOnLibsWithTags: ["type:ui", "type:lib", "type:hook"],
24
+ onlyDependOnLibsWithTags: ["type:ui", "type:library", "type:hook"],
28
25
  },
29
26
  appsCanImportAny: {
30
27
  sourceTag: "type:app",
31
- onlyDependOnLibsWithTags: ["type:ui", "type:lib", "type:hook"],
28
+ onlyDependOnLibsWithTags: ["type:ui", "type:library", "type:hook"],
32
29
  },
33
- // Runtime rules
34
- apiCanOnlyImportApiOrNode: {
35
- sourceTag: "runtime:api",
36
- onlyDependOnLibsWithTags: ["runtime:api", "runtime:node"],
30
+ // Runtime/Target rules
31
+ apiCanOnlyImportApiOrNodeOrAny: {
32
+ sourceTag: "target:api",
33
+ onlyDependOnLibsWithTags: ["target:api", "target:node", "target:any"],
37
34
  },
38
- reactCanOnlyImportReactOrNode: {
39
- sourceTag: "runtime:react",
40
- onlyDependOnLibsWithTags: ["runtime:react", "runtime:node"],
35
+ reactCanOnlyImportReactOrAny: {
36
+ sourceTag: "target:react",
37
+ onlyDependOnLibsWithTags: ["target:react", "target:any"],
41
38
  },
42
- nodeCanImportNode: {
43
- sourceTag: "runtime:node",
44
- onlyDependOnLibsWithTags: ["runtime:node"],
39
+ nodeCanImportNodeOrAny: {
40
+ sourceTag: "target:node",
41
+ onlyDependOnLibsWithTags: ["target:node", "target:any"],
45
42
  },
46
43
  // Domain rules
47
44
  domainCanOnlyImportSelf: {
@@ -55,9 +52,12 @@ const RULES = {
55
52
  },
56
53
  }
57
54
 
58
- /** @satisfies {import("eslint").Linter.Config} */
55
+ /**
56
+ * Strict NX module boundary rules for source files.
57
+ *
58
+ * @satisfies {import("eslint").Linter.Config}
59
+ */
59
60
  const nxConfig = /** @type {const} */ ({
60
- name: "ASD14 config for source files inside an NX monorepo",
61
61
  plugins: {
62
62
  "@nx": nxPlugin,
63
63
  },
@@ -65,7 +65,10 @@ const nxConfig = /** @type {const} */ ({
65
65
  "@nx/enforce-module-boundaries": [
66
66
  "error",
67
67
  {
68
- allow: [],
68
+ allow: [
69
+ "^.*/types$", // Allow importing types across boundaries (compile-time only)
70
+ "^.*/const$", // Allow importing constants across boundaries (pure data)
71
+ ],
69
72
  depConstraints: [
70
73
  RULES.publicCanOnlyImportPublic,
71
74
  RULES.privateCanImportAny,
@@ -73,9 +76,9 @@ const nxConfig = /** @type {const} */ ({
73
76
  RULES.hooksCanOnlyImportLibsAndHooks,
74
77
  RULES.uiCanImportAny,
75
78
  RULES.appsCanImportAny,
76
- RULES.apiCanOnlyImportApiOrNode,
77
- RULES.reactCanOnlyImportReactOrNode,
78
- RULES.nodeCanImportNode,
79
+ RULES.apiCanOnlyImportApiOrNodeOrAny,
80
+ RULES.reactCanOnlyImportReactOrAny,
81
+ RULES.nodeCanImportNodeOrAny,
79
82
  RULES.domainCanOnlyImportSelf,
80
83
  RULES.noTestImportsInProd,
81
84
  ],
@@ -84,25 +87,18 @@ const nxConfig = /** @type {const} */ ({
84
87
  },
85
88
  })
86
89
 
87
- const MONOREPO_ROOT = path.dirname(findUpSync("nx.json"))
88
-
89
- /** @satisfies {import("eslint").Linter.Config} */
90
+ /**
91
+ * Relaxed NX module boundary rules for dev files (tests, configs, stories).
92
+ * Dev files dont need strict visibility/runtime/domain enforcement since
93
+ * they are not emited in the final bundle.
94
+ *
95
+ * @satisfies {import("eslint").Linter.Config}
96
+ */
90
97
  const nxDevConfig = /** @type {const} */ ({
91
- name: "ASD14 config for dev files inside an NX monorepo",
92
98
  plugins: {
93
99
  "@nx": nxPlugin,
94
100
  },
95
101
  rules: {
96
- /*
97
- * Point to the monorepo root folder since ~all~ most devDependencies
98
- * used in test, story and config files reside in the root package.json.
99
- */
100
- "import/no-extraneous-dependencies": [
101
- "error",
102
- {
103
- packageDir: ["./", MONOREPO_ROOT],
104
- },
105
- ],
106
102
  "@nx/enforce-module-boundaries": [
107
103
  "error",
108
104
  {
@@ -110,7 +106,7 @@ const nxDevConfig = /** @type {const} */ ({
110
106
  depConstraints: [
111
107
  {
112
108
  sourceTag: "*",
113
- onlyDependOnLibsWithTags: ["type:lib"],
109
+ onlyDependOnLibsWithTags: ["type:library"],
114
110
  },
115
111
  ],
116
112
  },
@@ -1,12 +1,12 @@
1
1
  import prettierConfig from "eslint-plugin-prettier/recommended"
2
2
  import globals from "globals"
3
3
 
4
- import { nodeJestConfig } from "./node.js"
5
4
  import baseConfig from "../rules/base.js"
5
+ import devConfig from "../rules/dev.js"
6
+ import commonIgnores from "../rules/ignores.js"
6
7
  import importConfig from "../rules/import.js"
7
8
  import jsdocConfig from "../rules/jsdoc.js"
8
9
  import reactHooksConfig from "../rules/react.js"
9
- import rtlConfig from "../rules/rtl.js"
10
10
  import tsConfig from "../rules/typescript.js"
11
11
  import unicornConfig from "../rules/unicorn.js"
12
12
 
@@ -16,8 +16,10 @@ const reactSpecificRules = {
16
16
  "unicorn/prevent-abbreviations": [
17
17
  "error",
18
18
  {
19
+ ignore: ["utils", "props"],
19
20
  replacements: {
20
21
  i: false,
22
+ ref: false,
21
23
  params: false,
22
24
  lib: false,
23
25
  args: {
@@ -39,8 +41,7 @@ const reactSpecificRules = {
39
41
 
40
42
  /** @satisfies {import("eslint").Linter.Config} */
41
43
  const reactConfig = /** @type {const} */ ({
42
- name: "ASD14 config for React source files",
43
- ignores: ["node_modules", "dist", "coverage", "build"],
44
+ name: "ASD14 config for Typescript + React source files",
44
45
  languageOptions: {
45
46
  ...tsConfig.languageOptions,
46
47
  ecmaVersion: "latest",
@@ -69,9 +70,9 @@ const reactConfig = /** @type {const} */ ({
69
70
  ...baseConfig.rules,
70
71
  ...importConfig.rules,
71
72
  ...jsdocConfig.rules,
73
+ ...tsConfig.rules,
72
74
  ...reactHooksConfig.rules,
73
75
  ...reactSpecificRules,
74
- ...tsConfig.rules,
75
76
  ...unicornConfig.rules,
76
77
  ...prettierConfig.rules,
77
78
  },
@@ -87,19 +88,4 @@ const reactConfig = /** @type {const} */ ({
87
88
  },
88
89
  })
89
90
 
90
- /** @satisfies {import("eslint").Linter.Config} */
91
- const reactJestConfig = /** @type {const} */ ({
92
- ...nodeJestConfig,
93
- name: "ASD14 config for React test files",
94
- plugins: {
95
- ...nodeJestConfig.plugins,
96
- ...rtlConfig.plugins,
97
- },
98
- rules: {
99
- ...nodeJestConfig.rules,
100
- ...rtlConfig.rules,
101
- },
102
- })
103
-
104
- export { commonIgnores } from "../rules/ignores.js"
105
- export { reactConfig, reactJestConfig }
91
+ export { commonIgnores, devConfig, reactConfig }
@@ -1,19 +1,21 @@
1
1
  import { nodeConfig } from "./node.js"
2
- import tsConfig from "../rules/typescript.js"
2
+ import devConfig from "../rules/dev.js"
3
+ import commonIgnores from "../rules/ignores.js"
4
+ import typescriptConfig from "../rules/typescript.js"
3
5
 
4
6
  /** @satisfies {import("eslint").Linter.Config} */
5
- const tsNodeConfig = /** @type {const} */ ({
7
+ const tsConfig = /** @type {const} */ ({
6
8
  name: "ASD14 config for Typescript + Node.js source files",
7
9
  languageOptions: {
8
10
  ...nodeConfig.languageOptions,
9
- ...tsConfig.languageOptions,
11
+ ...typescriptConfig.languageOptions,
10
12
  },
11
13
  plugins: {
12
- ...tsConfig.plugins,
14
+ ...typescriptConfig.plugins,
13
15
  ...nodeConfig.plugins,
14
16
  },
15
17
  rules: {
16
- ...tsConfig.rules,
18
+ ...typescriptConfig.rules,
17
19
  ...nodeConfig.rules,
18
20
  },
19
21
  settings: {
@@ -21,5 +23,4 @@ const tsNodeConfig = /** @type {const} */ ({
21
23
  },
22
24
  })
23
25
 
24
- export { commonIgnores } from "../rules/ignores.js"
25
- export { tsNodeConfig }
26
+ export { commonIgnores, devConfig, tsConfig }
@@ -0,0 +1,10 @@
1
+ /** @satisfies {import("eslint").Linter.Config} */
2
+ export default /** @type {const} */ ({
3
+ rules: {
4
+ /*
5
+ * Point to the monorepo root folder since ~all~ most devDependencies
6
+ * used in test, story and config files reside in the root package.json.
7
+ */
8
+ "import/no-extraneous-dependencies": "off",
9
+ },
10
+ })
@@ -2,7 +2,8 @@
2
2
  * Common ignore patterns for ESLint flat configs
3
3
  * These are build outputs and dependencies that should never be linted
4
4
  */
5
- export const commonIgnores = /** @type {const} */ ([
5
+ export default /** @type {string[]} */ ([
6
+ ".local/**",
6
7
  "node_modules/**",
7
8
  "dist/**",
8
9
  "coverage/**",
@@ -10,30 +10,23 @@ export default /** @type {const} */ ({
10
10
  "error",
11
11
  {
12
12
  reportIntraTagGroupSpacing: false,
13
- reportTagGroupSpacing: false,
13
+ reportTagGroupSpacing: true,
14
+ tagSequence: [
15
+ { tags: ["typedef", "callback"] },
16
+ { tags: ["param", "arg", "argument", "property", "prop"] },
17
+ { tags: ["returns", "return"] },
18
+ { tags: ["throws", "exception"] },
19
+ { tags: ["example"] },
20
+ ],
14
21
  },
15
22
  ],
16
23
  "jsdoc/tag-lines": [
17
24
  "error",
18
- "always",
25
+ "any",
19
26
  {
20
27
  startLines: 1,
21
28
  endLines: 0,
22
29
  applyToEndTag: false,
23
- tags: {
24
- returns: {
25
- lines: "always",
26
- },
27
- property: {
28
- lines: "any",
29
- },
30
- param: {
31
- lines: "any",
32
- },
33
- example: {
34
- lines: "always",
35
- },
36
- },
37
30
  },
38
31
  ],
39
32
  "jsdoc/check-indentation": "error",
@@ -12,6 +12,10 @@ export default /** @type {const} */ ({
12
12
  rules: {
13
13
  ...tsPlugin.configs["strict-type-checked"]?.rules,
14
14
 
15
+ // Temporary: disable due to bug in ESLint 9.39.0
16
+ // https://github.com/eslint/eslint/issues/20272
17
+ "@typescript-eslint/unified-signatures": "off",
18
+
15
19
  "@typescript-eslint/no-unused-vars": [
16
20
  "error",
17
21
  {
File without changes
@@ -12,22 +12,21 @@ import path from "node:path"
12
12
  *
13
13
  * @param {string} fileName - The name of the file to find.
14
14
  * @param {FindUpSyncOptions} [options] - Options for the function.
15
+ *
15
16
  * @returns {string} The absolute path to the file.
16
17
  */
17
18
 
18
19
  /**
19
20
  * Find a file up the directory tree synchronously.
20
21
  *
21
- * @type {FindUpSyncFn}
22
- *
23
22
  * @throws {Error} If the starting folder does not exist.
24
- *
25
23
  * @throws {Error} If the file does not exist up the tree.
26
24
  *
27
25
  * @example
28
26
  * const filePath = findUpSync("lerna.json");
29
27
  * //=> "/Users/johndoe/Projects/WootWoot/lerna.json"
30
28
  *
29
+ * @type {FindUpSyncFn}
31
30
  */
32
31
  const findUpSync = (fileName, options = {}) => {
33
32
  let { cwd } = options