@higuma/eslint-config 0.1.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/README.md +87 -0
- package/base.js +80 -0
- package/index.js +7 -0
- package/next.js +34 -0
- package/package.json +47 -0
- package/react.js +50 -0
package/README.md
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# @higuma/eslint-config
|
|
2
|
+
|
|
3
|
+
Shared ESLint flat configs (ESLint 9+) for Higuma Soft projects.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# All projects need these
|
|
9
|
+
npm install --save-dev @higuma/eslint-config eslint typescript-eslint @eslint/js globals \
|
|
10
|
+
eslint-plugin-simple-import-sort eslint-plugin-unused-imports
|
|
11
|
+
|
|
12
|
+
# React / Next.js projects also need
|
|
13
|
+
npm install --save-dev eslint-plugin-react eslint-plugin-react-hooks
|
|
14
|
+
|
|
15
|
+
# Next.js projects also need
|
|
16
|
+
npm install --save-dev @next/eslint-plugin-next
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Configs
|
|
20
|
+
|
|
21
|
+
| Import | Use for |
|
|
22
|
+
|--------|---------|
|
|
23
|
+
| `@higuma/eslint-config/base` | Any TS project — libraries, Node, CLI |
|
|
24
|
+
| `@higuma/eslint-config/react` | React SPA |
|
|
25
|
+
| `@higuma/eslint-config/next` | Next.js app |
|
|
26
|
+
|
|
27
|
+
## Usage
|
|
28
|
+
|
|
29
|
+
### Library (registrie)
|
|
30
|
+
|
|
31
|
+
```js
|
|
32
|
+
// eslint.config.mjs
|
|
33
|
+
import base from '@higuma/eslint-config/base';
|
|
34
|
+
export default base;
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### React SPA
|
|
38
|
+
|
|
39
|
+
```js
|
|
40
|
+
// eslint.config.mjs
|
|
41
|
+
import react from '@higuma/eslint-config/react';
|
|
42
|
+
export default react;
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Next.js
|
|
46
|
+
|
|
47
|
+
```js
|
|
48
|
+
// eslint.config.mjs
|
|
49
|
+
import next from '@higuma/eslint-config/next';
|
|
50
|
+
export default next;
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### With overrides
|
|
54
|
+
|
|
55
|
+
```js
|
|
56
|
+
// eslint.config.mjs
|
|
57
|
+
import base from '@higuma/eslint-config/base';
|
|
58
|
+
|
|
59
|
+
export default [
|
|
60
|
+
...base,
|
|
61
|
+
{
|
|
62
|
+
rules: {
|
|
63
|
+
'no-console': 'warn', // downgrade for this project
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
];
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Rules included in all configs
|
|
70
|
+
|
|
71
|
+
| Rule | Level |
|
|
72
|
+
|------|-------|
|
|
73
|
+
| `simple-import-sort/imports` | error |
|
|
74
|
+
| `unused-imports/no-unused-imports` | error |
|
|
75
|
+
| `@typescript-eslint/no-explicit-any` | error |
|
|
76
|
+
| `@typescript-eslint/no-unused-vars` | error |
|
|
77
|
+
| `@typescript-eslint/no-non-null-assertion` | warn |
|
|
78
|
+
| `@typescript-eslint/consistent-type-imports` | error |
|
|
79
|
+
| `@typescript-eslint/no-floating-promises` | error |
|
|
80
|
+
| `no-console` | error |
|
|
81
|
+
| `no-var` | error |
|
|
82
|
+
| `prefer-const` | error |
|
|
83
|
+
| `eqeqeq` | error |
|
|
84
|
+
| `consistent-return` | error |
|
|
85
|
+
| `no-shadow` | error |
|
|
86
|
+
|
|
87
|
+
Test files (`*.test.ts`, `*.spec.ts`, `test/**`) get `no-explicit-any`, `no-non-null-assertion`, `no-floating-promises`, and `no-console` turned off.
|
package/base.js
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// @higuma/eslint-config/base
|
|
2
|
+
// Strict TypeScript flat config for any project (library, Node, browser).
|
|
3
|
+
// Consumers: registrie and any non-React project.
|
|
4
|
+
|
|
5
|
+
import js from '@eslint/js';
|
|
6
|
+
import globals from 'globals';
|
|
7
|
+
import tseslint from 'typescript-eslint';
|
|
8
|
+
import simpleImportSort from 'eslint-plugin-simple-import-sort';
|
|
9
|
+
import unusedImports from 'eslint-plugin-unused-imports';
|
|
10
|
+
|
|
11
|
+
/** @type {import('eslint').Linter.Config[]} */
|
|
12
|
+
const base = tseslint.config(
|
|
13
|
+
// Global ignores
|
|
14
|
+
{
|
|
15
|
+
ignores: ['dist/**', 'node_modules/**', '.next/**', 'coverage/**'],
|
|
16
|
+
},
|
|
17
|
+
|
|
18
|
+
// ESLint + TS recommended baseline
|
|
19
|
+
js.configs.recommended,
|
|
20
|
+
...tseslint.configs.recommended,
|
|
21
|
+
|
|
22
|
+
// Main rules
|
|
23
|
+
{
|
|
24
|
+
files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],
|
|
25
|
+
languageOptions: {
|
|
26
|
+
globals: {
|
|
27
|
+
...globals.node,
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
plugins: {
|
|
31
|
+
'simple-import-sort': simpleImportSort,
|
|
32
|
+
'unused-imports': unusedImports,
|
|
33
|
+
},
|
|
34
|
+
rules: {
|
|
35
|
+
// — Imports —
|
|
36
|
+
'simple-import-sort/imports': 'error',
|
|
37
|
+
'simple-import-sort/exports': 'error',
|
|
38
|
+
'unused-imports/no-unused-imports': 'error',
|
|
39
|
+
|
|
40
|
+
// — TypeScript —
|
|
41
|
+
'@typescript-eslint/no-explicit-any': 'error',
|
|
42
|
+
'@typescript-eslint/no-unused-vars': [
|
|
43
|
+
'error',
|
|
44
|
+
{
|
|
45
|
+
argsIgnorePattern: '^_',
|
|
46
|
+
varsIgnorePattern: '^_',
|
|
47
|
+
caughtErrorsIgnorePattern: '^_',
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
'@typescript-eslint/no-non-null-assertion': 'warn',
|
|
51
|
+
'@typescript-eslint/consistent-type-imports': [
|
|
52
|
+
'error',
|
|
53
|
+
{ prefer: 'type-imports', fixStyle: 'inline-type-imports' },
|
|
54
|
+
],
|
|
55
|
+
'@typescript-eslint/no-floating-promises': 'error',
|
|
56
|
+
'@typescript-eslint/consistent-type-definitions': ['error', 'type'],
|
|
57
|
+
|
|
58
|
+
// — General —
|
|
59
|
+
'no-console': 'error',
|
|
60
|
+
'no-var': 'error',
|
|
61
|
+
'prefer-const': 'error',
|
|
62
|
+
eqeqeq: ['error', 'always'],
|
|
63
|
+
'consistent-return': 'error',
|
|
64
|
+
'no-shadow': 'error',
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
|
|
68
|
+
// Test files — relaxed
|
|
69
|
+
{
|
|
70
|
+
files: ['**/*.test.ts', '**/*.spec.ts', 'test/**/*.ts', '**/*.test.tsx'],
|
|
71
|
+
rules: {
|
|
72
|
+
'@typescript-eslint/no-explicit-any': 'off',
|
|
73
|
+
'@typescript-eslint/no-non-null-assertion': 'off',
|
|
74
|
+
'@typescript-eslint/no-floating-promises': 'off',
|
|
75
|
+
'no-console': 'off',
|
|
76
|
+
},
|
|
77
|
+
}
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
export default base;
|
package/index.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// @higuma/eslint-config
|
|
2
|
+
// Re-exports all configs for convenience.
|
|
3
|
+
// Prefer named imports: import base from '@higuma/eslint-config/base'
|
|
4
|
+
|
|
5
|
+
export { default as base } from './base.js';
|
|
6
|
+
export { default as react } from './react.js';
|
|
7
|
+
export { default as next } from './next.js';
|
package/next.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// @higuma/eslint-config/next
|
|
2
|
+
// Extends react with Next.js-specific rules.
|
|
3
|
+
// Use for: Next.js app projects.
|
|
4
|
+
|
|
5
|
+
import nextPlugin from '@next/eslint-plugin-next';
|
|
6
|
+
import tseslint from 'typescript-eslint';
|
|
7
|
+
import react from './react.js';
|
|
8
|
+
|
|
9
|
+
/** @type {import('eslint').Linter.Config[]} */
|
|
10
|
+
const next = tseslint.config(
|
|
11
|
+
...react,
|
|
12
|
+
|
|
13
|
+
{
|
|
14
|
+
files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],
|
|
15
|
+
plugins: {
|
|
16
|
+
'@next/next': nextPlugin,
|
|
17
|
+
},
|
|
18
|
+
rules: {
|
|
19
|
+
// Core Next.js rules — all recommended ones as errors
|
|
20
|
+
...Object.fromEntries(
|
|
21
|
+
Object.entries(nextPlugin.configs.recommended.rules ?? {}).map(
|
|
22
|
+
([rule, _]) => [rule, 'error']
|
|
23
|
+
)
|
|
24
|
+
),
|
|
25
|
+
|
|
26
|
+
// Next.js specific overrides
|
|
27
|
+
'@next/next/no-html-link-for-pages': 'error',
|
|
28
|
+
'@next/next/no-img-element': 'error', // enforce next/image
|
|
29
|
+
'@next/next/no-sync-scripts': 'error',
|
|
30
|
+
},
|
|
31
|
+
}
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
export default next;
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@higuma/eslint-config",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Shared ESLint flat configs for Higuma Soft projects.",
|
|
5
|
+
"keywords": ["eslint", "eslint-config", "typescript", "higuma"],
|
|
6
|
+
"author": "Higuma Soft",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"type": "module",
|
|
9
|
+
"main": "./index.js",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": "./index.js",
|
|
12
|
+
"./base": "./base.js",
|
|
13
|
+
"./react": "./react.js",
|
|
14
|
+
"./next": "./next.js"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"*.js",
|
|
18
|
+
"README.md"
|
|
19
|
+
],
|
|
20
|
+
"publishConfig": {
|
|
21
|
+
"access": "public"
|
|
22
|
+
},
|
|
23
|
+
"peerDependencies": {
|
|
24
|
+
"@eslint/js": "^9.0.0",
|
|
25
|
+
"@next/eslint-plugin-next": "^14.0.0",
|
|
26
|
+
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
|
27
|
+
"@typescript-eslint/parser": "^8.0.0",
|
|
28
|
+
"eslint": "^9.0.0",
|
|
29
|
+
"eslint-plugin-react": "^7.0.0",
|
|
30
|
+
"eslint-plugin-react-hooks": "^5.0.0",
|
|
31
|
+
"eslint-plugin-simple-import-sort": "^12.0.0",
|
|
32
|
+
"eslint-plugin-unused-imports": "^4.0.0",
|
|
33
|
+
"globals": "^15.0.0",
|
|
34
|
+
"typescript-eslint": "^8.0.0"
|
|
35
|
+
},
|
|
36
|
+
"peerDependenciesMeta": {
|
|
37
|
+
"@next/eslint-plugin-next": {
|
|
38
|
+
"optional": true
|
|
39
|
+
},
|
|
40
|
+
"eslint-plugin-react": {
|
|
41
|
+
"optional": true
|
|
42
|
+
},
|
|
43
|
+
"eslint-plugin-react-hooks": {
|
|
44
|
+
"optional": true
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
package/react.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// @higuma/eslint-config/react
|
|
2
|
+
// Extends base with React-specific rules.
|
|
3
|
+
// Use for: React SPA projects.
|
|
4
|
+
|
|
5
|
+
import globals from 'globals';
|
|
6
|
+
import reactPlugin from 'eslint-plugin-react';
|
|
7
|
+
import reactHooks from 'eslint-plugin-react-hooks';
|
|
8
|
+
import tseslint from 'typescript-eslint';
|
|
9
|
+
import base from './base.js';
|
|
10
|
+
|
|
11
|
+
/** @type {import('eslint').Linter.Config[]} */
|
|
12
|
+
const react = tseslint.config(
|
|
13
|
+
...base,
|
|
14
|
+
|
|
15
|
+
{
|
|
16
|
+
files: ['**/*.tsx', '**/*.jsx'],
|
|
17
|
+
languageOptions: {
|
|
18
|
+
globals: {
|
|
19
|
+
...globals.browser,
|
|
20
|
+
},
|
|
21
|
+
parserOptions: {
|
|
22
|
+
ecmaFeatures: { jsx: true },
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
plugins: {
|
|
26
|
+
react: reactPlugin,
|
|
27
|
+
'react-hooks': reactHooks,
|
|
28
|
+
},
|
|
29
|
+
settings: {
|
|
30
|
+
react: {
|
|
31
|
+
// Automatically detect React version
|
|
32
|
+
version: 'detect',
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
rules: {
|
|
36
|
+
// Hooks
|
|
37
|
+
'react-hooks/rules-of-hooks': 'error',
|
|
38
|
+
'react-hooks/exhaustive-deps': 'error',
|
|
39
|
+
|
|
40
|
+
// Props
|
|
41
|
+
'react/no-unused-prop-types': 'error',
|
|
42
|
+
|
|
43
|
+
// React 17+ — no need to import React in scope
|
|
44
|
+
'react/react-in-jsx-scope': 'off',
|
|
45
|
+
'react/jsx-uses-react': 'off',
|
|
46
|
+
},
|
|
47
|
+
}
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
export default react;
|