zeno-config 3.0.0 → 4.0.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/README.md +54 -13
- package/bin/gitignore.js +84 -0
- package/package.json +14 -10
- package/src/eslint/index.d.ts +7 -0
- package/src/eslint/index.js +14 -0
- package/src/eslint/rules/baseRules.js +3 -3
- package/src/eslint/rules/nodePluginRules.js +6 -0
- package/src/eslint/rules/reactCompilerPluginRules.js +24 -0
- package/src/eslint/rules/reactHooksPluginRules.js +0 -18
- package/src/eslint/rules/reactYouMightNotNeedAnEffectPluginRules.js +0 -1
- package/src/eslint/rules/typescriptPluginRules.js +4 -0
- package/src/eslint/rules/unicornPluginRules.js +3 -4
- package/src/gitignore +60 -0
- package/src/tsconfig.base.json +12 -12
- package/src/tsconfig.react.json +8 -4
package/README.md
CHANGED
|
@@ -47,6 +47,26 @@ export default defineZenoConfig({
|
|
|
47
47
|
});
|
|
48
48
|
```
|
|
49
49
|
|
|
50
|
+
#### React Compiler
|
|
51
|
+
|
|
52
|
+
If you're using or preparing to adopt [React Compiler](https://react.dev/learn/react-compiler), you can opt in to its ESLint rules:
|
|
53
|
+
|
|
54
|
+
```javascript
|
|
55
|
+
import { defineZenoConfig } from 'zeno-config/eslint';
|
|
56
|
+
|
|
57
|
+
// Preparing a codebase — surface compiler violations as warnings
|
|
58
|
+
export default defineZenoConfig({
|
|
59
|
+
react: true,
|
|
60
|
+
reactCompiler: 'warn',
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
// Full enforcement — compiler rules as errors
|
|
64
|
+
export default defineZenoConfig({
|
|
65
|
+
react: true,
|
|
66
|
+
reactCompiler: true,
|
|
67
|
+
});
|
|
68
|
+
```
|
|
69
|
+
|
|
50
70
|
#### `engines` field in `package.json`
|
|
51
71
|
|
|
52
72
|
Add an `engines` field to your `package.json` with your supported Node.js versions. Some rules for Node.js use this:
|
|
@@ -166,6 +186,26 @@ Example:
|
|
|
166
186
|
}
|
|
167
187
|
```
|
|
168
188
|
|
|
189
|
+
### Gitignore
|
|
190
|
+
|
|
191
|
+
Includes a shared `.gitignore` template with common patterns for your projects. Run the following command to add any missing patterns to your project's `.gitignore` (or create one if it doesn't exist):
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
npx zc-gitignore
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
The command only adds patterns that aren't already present. You can also add it as a setup script:
|
|
198
|
+
|
|
199
|
+
```json
|
|
200
|
+
{
|
|
201
|
+
"scripts": {
|
|
202
|
+
"setup:gitignore": "zc-gitignore"
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
See [src/gitignore](src/gitignore) for the full list of included patterns.
|
|
208
|
+
|
|
169
209
|
### File Extensions Helpers
|
|
170
210
|
|
|
171
211
|
Use in your build configs, webpack, etc:
|
|
@@ -194,18 +234,19 @@ import {
|
|
|
194
234
|
|
|
195
235
|
### `defineZenoConfig(options, additionalESLintConfig)`
|
|
196
236
|
|
|
197
|
-
| Option | Type
|
|
198
|
-
| --------------------------- |
|
|
199
|
-
| `react` | `boolean`
|
|
200
|
-
| `
|
|
201
|
-
| `
|
|
202
|
-
| `
|
|
203
|
-
| `
|
|
204
|
-
| `
|
|
205
|
-
| `
|
|
206
|
-
| `
|
|
207
|
-
| `
|
|
208
|
-
| `
|
|
237
|
+
| Option | Type | Default | Description |
|
|
238
|
+
| --------------------------- | ----------------------- | ----------- | --------------------------------------------------------------------------------------------------------------------- |
|
|
239
|
+
| `react` | `boolean` | `false` | Enable React-specific rules |
|
|
240
|
+
| `reactCompiler` | `boolean \| 'warn'` | `false` | Enable React Compiler rules. Set to `'warn'` to surface violations as warnings (for preparing a codebase), or `true` to enforce as errors |
|
|
241
|
+
| `ts` | `boolean` | `false` | Enable TypeScript-specific rules |
|
|
242
|
+
| `performanceMode` | `boolean` | `false` | Disables expensive rules for better performance |
|
|
243
|
+
| `ignores` | `string[]` | `[]` | Additional directories to ignore (added to defaults: node_modules, dist, build, coverage) |
|
|
244
|
+
| `reactDirs` | `string[]` | `[]` | Directories containing React files (for projects using .js for both React and Node) |
|
|
245
|
+
| `nodeIgnoreDirs` | `string[]` | `[]` | Directories to ignore for Node-specific rules (defaults to `reactDirs` if not set) |
|
|
246
|
+
| `ignoreExports` | `string[]` | `[]` | Export patterns to ignore for import/no-unresolved rule |
|
|
247
|
+
| `additionalDevDependencies` | `string[]` | `[]` | Additional file patterns to allow dev dependencies in (for import/no-extraneous-dependencies) |
|
|
248
|
+
| `extensionsIgnorePattern` | `object` | `{}` | Extension patterns to ignore for import/extensions rule |
|
|
249
|
+
| `webpackConfig` | `string` | `undefined` | Path to webpack config for import resolver |
|
|
209
250
|
|
|
210
251
|
## Advanced Usage
|
|
211
252
|
|
|
@@ -270,7 +311,7 @@ See the TypeScript configuration files:
|
|
|
270
311
|
- `eslint-plugin-n` - Node.js specific rules ([rules](src/eslint/rules/nodePluginRules.js))
|
|
271
312
|
- `eslint-plugin-prettier` - Prettier integration
|
|
272
313
|
- `eslint-plugin-react` (optional) - React specific rules ([rules](src/eslint/rules/reactPluginRules.js))
|
|
273
|
-
- `eslint-plugin-react-hooks` (optional) - React Hooks rules ([rules](src/eslint/rules/reactHooksPluginRules.js))
|
|
314
|
+
- `eslint-plugin-react-hooks` (optional) - React Hooks rules ([rules](src/eslint/rules/reactHooksPluginRules.js)) and React Compiler rules ([rules](src/eslint/rules/reactCompilerPluginRules.js))
|
|
274
315
|
- `eslint-plugin-jsx-a11y` (optional) - Accessibility rules for JSX ([rules](src/eslint/rules/jsxA11yPluginRules.js))
|
|
275
316
|
- `eslint-plugin-react-you-might-not-need-an-effect` (optional) - React Effect optimization ([rules](src/eslint/rules/reactYouMightNotNeedAnEffectPluginRules.js))
|
|
276
317
|
- `typescript-eslint` (optional) - TypeScript rules ([rules](src/eslint/rules/typescriptPluginRules.js))
|
package/bin/gitignore.js
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/* eslint-disable no-console */
|
|
4
|
+
|
|
5
|
+
import { readFileSync, writeFileSync, existsSync } from 'node:fs';
|
|
6
|
+
import { resolve, dirname } from 'node:path';
|
|
7
|
+
import { fileURLToPath } from 'node:url';
|
|
8
|
+
|
|
9
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
10
|
+
const templatePath = resolve(__dirname, '..', 'src', 'gitignore');
|
|
11
|
+
const targetPath = resolve(process.cwd(), '.gitignore');
|
|
12
|
+
|
|
13
|
+
const template = readFileSync(templatePath, 'utf8');
|
|
14
|
+
|
|
15
|
+
if (!existsSync(targetPath)) {
|
|
16
|
+
writeFileSync(targetPath, template);
|
|
17
|
+
console.log('Created .gitignore');
|
|
18
|
+
process.exit(0);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function parseSections(content) {
|
|
22
|
+
const sections = [];
|
|
23
|
+
let current = null;
|
|
24
|
+
|
|
25
|
+
for (const line of content.split('\n')) {
|
|
26
|
+
if (line.startsWith('#')) {
|
|
27
|
+
if (current) {
|
|
28
|
+
sections.push(current);
|
|
29
|
+
}
|
|
30
|
+
current = { comments: [line], patterns: [] };
|
|
31
|
+
} else if (line.trim()) {
|
|
32
|
+
if (!current) {
|
|
33
|
+
current = { comments: [], patterns: [] };
|
|
34
|
+
}
|
|
35
|
+
current.patterns.push(line);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (current) {
|
|
40
|
+
sections.push(current);
|
|
41
|
+
}
|
|
42
|
+
return sections;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const existing = readFileSync(targetPath, 'utf8');
|
|
46
|
+
const existingPatterns = new Set(
|
|
47
|
+
existing
|
|
48
|
+
.split('\n')
|
|
49
|
+
.map((line) => line.trim())
|
|
50
|
+
.filter((line) => line && !line.startsWith('#'))
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
const templateSections = parseSections(template);
|
|
54
|
+
const sectionsToAdd = [];
|
|
55
|
+
|
|
56
|
+
for (const section of templateSections) {
|
|
57
|
+
const missing = section.patterns.filter((p) => !existingPatterns.has(p));
|
|
58
|
+
if (missing.length > 0) {
|
|
59
|
+
sectionsToAdd.push({ comments: section.comments, patterns: missing });
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (sectionsToAdd.length === 0) {
|
|
64
|
+
console.log('.gitignore is already up to date');
|
|
65
|
+
process.exit(0);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const lines = sectionsToAdd.flatMap((section) => [
|
|
69
|
+
'',
|
|
70
|
+
...section.comments,
|
|
71
|
+
...section.patterns,
|
|
72
|
+
]);
|
|
73
|
+
const updated = `${existing.trimEnd()}\n${lines.join('\n')}\n`;
|
|
74
|
+
|
|
75
|
+
writeFileSync(targetPath, updated);
|
|
76
|
+
|
|
77
|
+
const count = sectionsToAdd.reduce((sum, s) => sum + s.patterns.length, 0);
|
|
78
|
+
for (const section of sectionsToAdd) {
|
|
79
|
+
console.log(section.comments.join('\n'));
|
|
80
|
+
for (const p of section.patterns) {
|
|
81
|
+
console.log(` ${p}`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
console.log(`\nAdded ${count} pattern(s) to .gitignore`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zeno-config",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.1",
|
|
4
4
|
"description": "Preconfigured and opinionated ESLint, Prettier, and TypeScript setup",
|
|
5
5
|
"author": "Rick Brenn <brenn.rick@gmail.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -42,8 +42,12 @@
|
|
|
42
42
|
"default": "./src/extensions.js"
|
|
43
43
|
}
|
|
44
44
|
},
|
|
45
|
+
"bin": {
|
|
46
|
+
"zc-gitignore": "./bin/gitignore.js"
|
|
47
|
+
},
|
|
45
48
|
"files": [
|
|
46
|
-
"src/**"
|
|
49
|
+
"src/**",
|
|
50
|
+
"bin/**"
|
|
47
51
|
],
|
|
48
52
|
"peerDependencies": {
|
|
49
53
|
"eslint": "^9.39.2",
|
|
@@ -57,24 +61,24 @@
|
|
|
57
61
|
},
|
|
58
62
|
"devDependencies": {
|
|
59
63
|
"eslint": "9.39.2",
|
|
60
|
-
"prettier": "3.8.
|
|
64
|
+
"prettier": "3.8.1",
|
|
61
65
|
"typescript": "5.9.3"
|
|
62
66
|
},
|
|
63
67
|
"dependencies": {
|
|
64
68
|
"@eslint/js": "9.39.2",
|
|
65
|
-
"@stylistic/eslint-plugin": "5.
|
|
69
|
+
"@stylistic/eslint-plugin": "5.10.0",
|
|
66
70
|
"eslint-config-prettier": "10.1.8",
|
|
67
71
|
"eslint-import-resolver-webpack": "^0.13.10",
|
|
68
|
-
"eslint-plugin-import-x": "4.16.
|
|
72
|
+
"eslint-plugin-import-x": "4.16.2",
|
|
69
73
|
"eslint-plugin-jsx-a11y": "6.10.2",
|
|
70
|
-
"eslint-plugin-n": "17.
|
|
74
|
+
"eslint-plugin-n": "17.24.0",
|
|
71
75
|
"eslint-plugin-prettier": "5.5.5",
|
|
72
76
|
"eslint-plugin-react": "7.37.5",
|
|
73
77
|
"eslint-plugin-react-hooks": "7.0.1",
|
|
74
|
-
"eslint-plugin-react-you-might-not-need-an-effect": "0.
|
|
75
|
-
"eslint-plugin-unicorn": "
|
|
76
|
-
"globals": "17.
|
|
77
|
-
"typescript-eslint": "8.
|
|
78
|
+
"eslint-plugin-react-you-might-not-need-an-effect": "0.9.2",
|
|
79
|
+
"eslint-plugin-unicorn": "63.0.0",
|
|
80
|
+
"globals": "17.4.0",
|
|
81
|
+
"typescript-eslint": "8.57.1"
|
|
78
82
|
},
|
|
79
83
|
"scripts": {
|
|
80
84
|
"inspect": "eslint --inspect-config",
|
package/src/eslint/index.d.ts
CHANGED
|
@@ -23,6 +23,8 @@ interface ReactConfigOptions {
|
|
|
23
23
|
reactDirs?: string[];
|
|
24
24
|
/** Extension patterns to ignore for import rules */
|
|
25
25
|
extensionsIgnorePattern?: Record<string, string>;
|
|
26
|
+
/** Enable React Compiler rules. Set to 'warn' for warnings or true for errors. */
|
|
27
|
+
reactCompiler?: boolean | 'warn';
|
|
26
28
|
}
|
|
27
29
|
|
|
28
30
|
interface TypescriptConfigOptions {
|
|
@@ -33,6 +35,8 @@ interface TypescriptConfigOptions {
|
|
|
33
35
|
interface DefineZenoConfigOptions {
|
|
34
36
|
/** Enable React-specific rules */
|
|
35
37
|
react?: boolean;
|
|
38
|
+
/** Enable React Compiler rules. Set to 'warn' for warnings or true for errors. */
|
|
39
|
+
reactCompiler?: boolean | 'warn';
|
|
36
40
|
/** Enable TypeScript-specific rules */
|
|
37
41
|
ts?: boolean;
|
|
38
42
|
/** Disables expensive rules for performance */
|
|
@@ -90,6 +94,9 @@ interface Rules {
|
|
|
90
94
|
extensions?: string[];
|
|
91
95
|
}) => Linter.RulesRecord;
|
|
92
96
|
getReactHooksPluginRules: () => Linter.RulesRecord;
|
|
97
|
+
getReactCompilerPluginRules: (
|
|
98
|
+
mode?: boolean | 'warn'
|
|
99
|
+
) => Linter.RulesRecord;
|
|
93
100
|
getReactYouMightNotNeedAnEffectPluginRules: () => Linter.RulesRecord;
|
|
94
101
|
getJsxA11yPluginRules: () => Linter.RulesRecord;
|
|
95
102
|
}
|
package/src/eslint/index.js
CHANGED
|
@@ -15,6 +15,7 @@ import getBaseRules from './rules/baseRules.js';
|
|
|
15
15
|
import getImportPluginRules from './rules/importPluginRules.js';
|
|
16
16
|
import getReactPluginRules from './rules/reactPluginRules.js';
|
|
17
17
|
import getReactHooksPluginRules from './rules/reactHooksPluginRules.js';
|
|
18
|
+
import getReactCompilerPluginRules from './rules/reactCompilerPluginRules.js';
|
|
18
19
|
import getStylisticPluginRules from './rules/stylisticPluginRules.js';
|
|
19
20
|
import getNodePluginRules from './rules/nodePluginRules.js';
|
|
20
21
|
import getReactYouMightNotNeedAnEffectPluginRules from './rules/reactYouMightNotNeedAnEffectPluginRules.js';
|
|
@@ -128,6 +129,11 @@ const nodeConfig = (options = {}) => {
|
|
|
128
129
|
...globals.node,
|
|
129
130
|
},
|
|
130
131
|
},
|
|
132
|
+
settings: {
|
|
133
|
+
node: {
|
|
134
|
+
version: '>=20.0.0',
|
|
135
|
+
},
|
|
136
|
+
},
|
|
131
137
|
plugins: {
|
|
132
138
|
n: nodePlugin,
|
|
133
139
|
},
|
|
@@ -142,6 +148,7 @@ const nodeConfig = (options = {}) => {
|
|
|
142
148
|
* @param {Object} [options={}] - Configuration options.
|
|
143
149
|
* @param {string[]} [options.reactDirs] - Directories containing React files (for projects using .js for both React and Node).
|
|
144
150
|
* @param {Object} [options.extensionsIgnorePattern] - Extension patterns to ignore for import rules.
|
|
151
|
+
* @param {boolean|string} [options.reactCompiler=false] - Enable React Compiler rules. Set to 'warn' for warnings or true for errors.
|
|
145
152
|
* @returns {Array} ESLint flat config array.
|
|
146
153
|
*/
|
|
147
154
|
const reactConfig = (options = {}) => {
|
|
@@ -181,6 +188,9 @@ const reactConfig = (options = {}) => {
|
|
|
181
188
|
rules: {
|
|
182
189
|
...getReactPluginRules({ extensions }),
|
|
183
190
|
...getReactHooksPluginRules(),
|
|
191
|
+
...(options.reactCompiler
|
|
192
|
+
? getReactCompilerPluginRules(options.reactCompiler)
|
|
193
|
+
: {}),
|
|
184
194
|
...getReactYouMightNotNeedAnEffectPluginRules(),
|
|
185
195
|
...getJsxA11yPluginRules(),
|
|
186
196
|
|
|
@@ -296,6 +306,7 @@ const internals = {
|
|
|
296
306
|
getUnicornPluginRules,
|
|
297
307
|
getReactPluginRules,
|
|
298
308
|
getReactHooksPluginRules,
|
|
309
|
+
getReactCompilerPluginRules,
|
|
299
310
|
getReactYouMightNotNeedAnEffectPluginRules,
|
|
300
311
|
getJsxA11yPluginRules,
|
|
301
312
|
},
|
|
@@ -306,6 +317,7 @@ const internals = {
|
|
|
306
317
|
*
|
|
307
318
|
* @param {Object|Array} arg1 - Options object or additional config array. If an array, treated as additional config.
|
|
308
319
|
* @param {boolean} [arg1.react=false] - Enable React-specific rules.
|
|
320
|
+
* @param {boolean|string} [arg1.reactCompiler=false] - Enable React Compiler rules. Set to 'warn' for warnings or true for errors.
|
|
309
321
|
* @param {boolean} [arg1.ts=true] - Enable TypeScript-specific rules.
|
|
310
322
|
* @param {boolean} [arg1.performanceMode=false] - Disables expensive rules for performance.
|
|
311
323
|
* @param {string[]} [arg1.ignores=[]] - Additional directories to ignore (added to defaults: dist, build).
|
|
@@ -333,6 +345,7 @@ const internals = {
|
|
|
333
345
|
const defineZenoConfig = (arg1, arg2) => {
|
|
334
346
|
let options = {
|
|
335
347
|
react: false,
|
|
348
|
+
reactCompiler: false,
|
|
336
349
|
ts: false,
|
|
337
350
|
performanceMode: false,
|
|
338
351
|
|
|
@@ -394,6 +407,7 @@ const defineZenoConfig = (arg1, arg2) => {
|
|
|
394
407
|
? configs.getReact({
|
|
395
408
|
reactDirs: options.reactDirs,
|
|
396
409
|
extensionsIgnorePattern: options.extensionsIgnorePattern,
|
|
410
|
+
reactCompiler: options.reactCompiler,
|
|
397
411
|
})
|
|
398
412
|
: [];
|
|
399
413
|
const tsConfigResult = options.ts
|
|
@@ -190,7 +190,7 @@ const getBaseRules = () => {
|
|
|
190
190
|
],
|
|
191
191
|
|
|
192
192
|
// https://eslint.org/docs/latest/rules/no-useless-assignment
|
|
193
|
-
'no-useless-assignment': '
|
|
193
|
+
'no-useless-assignment': 'off',
|
|
194
194
|
|
|
195
195
|
// https://eslint.org/docs/latest/rules/no-useless-backreference
|
|
196
196
|
'no-useless-backreference': 'error',
|
|
@@ -395,7 +395,7 @@ const getBaseRules = () => {
|
|
|
395
395
|
|
|
396
396
|
// https://eslint.org/docs/latest/rules/no-implicit-coercion
|
|
397
397
|
'no-implicit-coercion': [
|
|
398
|
-
'
|
|
398
|
+
'off',
|
|
399
399
|
{
|
|
400
400
|
boolean: true,
|
|
401
401
|
number: true,
|
|
@@ -488,7 +488,7 @@ const getBaseRules = () => {
|
|
|
488
488
|
],
|
|
489
489
|
|
|
490
490
|
// https://eslint.org/docs/latest/rules/no-plusplus
|
|
491
|
-
'no-plusplus': ['
|
|
491
|
+
'no-plusplus': ['off', { allowForLoopAfterthoughts: true }],
|
|
492
492
|
|
|
493
493
|
// https://eslint.org/docs/latest/rules/no-proto
|
|
494
494
|
'no-proto': 'error',
|
|
@@ -96,6 +96,9 @@ const getNodePluginRules = () => {
|
|
|
96
96
|
// https://github.com/eslint-community/eslint-plugin-n/blob/master/docs/rules/prefer-global/console.md
|
|
97
97
|
'n/prefer-global/console': 'error',
|
|
98
98
|
|
|
99
|
+
// https://github.com/eslint-community/eslint-plugin-n/blob/master/docs/rules/prefer-global/crypto.md
|
|
100
|
+
'n/prefer-global/crypto': 'error',
|
|
101
|
+
|
|
99
102
|
// https://github.com/eslint-community/eslint-plugin-n/blob/master/docs/rules/prefer-global/process.md
|
|
100
103
|
'n/prefer-global/process': 'error',
|
|
101
104
|
|
|
@@ -105,6 +108,9 @@ const getNodePluginRules = () => {
|
|
|
105
108
|
// https://github.com/eslint-community/eslint-plugin-n/blob/master/docs/rules/prefer-global/text-encoder.md
|
|
106
109
|
'n/prefer-global/text-encoder': 'error',
|
|
107
110
|
|
|
111
|
+
// https://github.com/eslint-community/eslint-plugin-n/blob/master/docs/rules/prefer-global/timers.md
|
|
112
|
+
'n/prefer-global/timers': 'error',
|
|
113
|
+
|
|
108
114
|
// https://github.com/eslint-community/eslint-plugin-n/blob/master/docs/rules/prefer-global/url.md
|
|
109
115
|
'n/prefer-global/url': 'error',
|
|
110
116
|
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const getReactCompilerPluginRules = (mode) => {
|
|
2
|
+
const level = mode === 'warn' ? 'warn' : 'error';
|
|
3
|
+
|
|
4
|
+
return {
|
|
5
|
+
// https://github.com/facebook/react/tree/main/packages/eslint-plugin-react-hooks
|
|
6
|
+
'react-hooks/config': level,
|
|
7
|
+
'react-hooks/error-boundaries': level,
|
|
8
|
+
'react-hooks/component-hook-factories': level,
|
|
9
|
+
'react-hooks/gating': level,
|
|
10
|
+
'react-hooks/globals': level,
|
|
11
|
+
'react-hooks/immutability': level,
|
|
12
|
+
'react-hooks/preserve-manual-memoization': level,
|
|
13
|
+
'react-hooks/purity': level,
|
|
14
|
+
'react-hooks/refs': level,
|
|
15
|
+
'react-hooks/set-state-in-effect': 'warn',
|
|
16
|
+
'react-hooks/set-state-in-render': level,
|
|
17
|
+
'react-hooks/static-components': level,
|
|
18
|
+
'react-hooks/unsupported-syntax': 'warn',
|
|
19
|
+
'react-hooks/use-memo': level,
|
|
20
|
+
'react-hooks/incompatible-library': 'warn',
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export default getReactCompilerPluginRules;
|
|
@@ -1,26 +1,8 @@
|
|
|
1
1
|
const getReactHooksPluginRules = () => {
|
|
2
2
|
return {
|
|
3
3
|
// https://github.com/facebook/react/tree/main/packages/eslint-plugin-react-hooks
|
|
4
|
-
// Core hooks rules
|
|
5
4
|
'react-hooks/rules-of-hooks': 'error',
|
|
6
5
|
'react-hooks/exhaustive-deps': 'error',
|
|
7
|
-
|
|
8
|
-
// React Compiler rules
|
|
9
|
-
'react-hooks/config': 'error',
|
|
10
|
-
'react-hooks/error-boundaries': 'error',
|
|
11
|
-
'react-hooks/component-hook-factories': 'error',
|
|
12
|
-
'react-hooks/gating': 'error',
|
|
13
|
-
'react-hooks/globals': 'error',
|
|
14
|
-
'react-hooks/immutability': 'error',
|
|
15
|
-
'react-hooks/preserve-manual-memoization': 'error',
|
|
16
|
-
'react-hooks/purity': 'error',
|
|
17
|
-
'react-hooks/refs': 'error',
|
|
18
|
-
'react-hooks/set-state-in-effect': 'warn',
|
|
19
|
-
'react-hooks/set-state-in-render': 'error',
|
|
20
|
-
'react-hooks/static-components': 'error',
|
|
21
|
-
'react-hooks/unsupported-syntax': 'warn',
|
|
22
|
-
'react-hooks/use-memo': 'error',
|
|
23
|
-
'react-hooks/incompatible-library': 'warn',
|
|
24
6
|
};
|
|
25
7
|
};
|
|
26
8
|
|
|
@@ -10,7 +10,6 @@ const getReactYouMightNotNeedAnEffectPluginRules = () => {
|
|
|
10
10
|
'react-you-might-not-need-an-effect/no-pass-live-state-to-parent':
|
|
11
11
|
'warn',
|
|
12
12
|
'react-you-might-not-need-an-effect/no-pass-data-to-parent': 'warn',
|
|
13
|
-
'react-you-might-not-need-an-effect/no-pass-ref-to-parent': 'warn',
|
|
14
13
|
'react-you-might-not-need-an-effect/no-initialize-state': 'warn',
|
|
15
14
|
'react-you-might-not-need-an-effect/no-chain-state-updates': 'warn',
|
|
16
15
|
'react-you-might-not-need-an-effect/no-derived-state': 'warn',
|
|
@@ -505,6 +505,10 @@ const getTypescriptPluginRules = () => {
|
|
|
505
505
|
// requires type information
|
|
506
506
|
'@typescript-eslint/strict-boolean-expressions': 'off',
|
|
507
507
|
|
|
508
|
+
// https://typescript-eslint.io/rules/strict-void-return
|
|
509
|
+
// requires type information
|
|
510
|
+
'@typescript-eslint/strict-void-return': 'off',
|
|
511
|
+
|
|
508
512
|
// https://typescript-eslint.io/rules/switch-exhaustiveness-check
|
|
509
513
|
// requires type information
|
|
510
514
|
'@typescript-eslint/switch-exhaustiveness-check': 'off',
|
|
@@ -56,9 +56,8 @@ const getUnicornPluginRules = () => {
|
|
|
56
56
|
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/import-style.md
|
|
57
57
|
'unicorn/import-style': 'off',
|
|
58
58
|
|
|
59
|
-
// TODO: new rule, enable once released
|
|
60
59
|
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/isolated-functions.md
|
|
61
|
-
|
|
60
|
+
'unicorn/isolated-functions': 'error',
|
|
62
61
|
|
|
63
62
|
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/new-for-builtins.md
|
|
64
63
|
'unicorn/new-for-builtins': 'error',
|
|
@@ -347,7 +346,7 @@ const getUnicornPluginRules = () => {
|
|
|
347
346
|
'unicorn/prefer-prototype-methods': 'error',
|
|
348
347
|
|
|
349
348
|
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-query-selector.md
|
|
350
|
-
'unicorn/prefer-query-selector': '
|
|
349
|
+
'unicorn/prefer-query-selector': 'off',
|
|
351
350
|
|
|
352
351
|
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-reflect-apply.md
|
|
353
352
|
'unicorn/prefer-reflect-apply': 'warn',
|
|
@@ -395,7 +394,7 @@ const getUnicornPluginRules = () => {
|
|
|
395
394
|
'unicorn/prefer-ternary': 'off',
|
|
396
395
|
|
|
397
396
|
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-top-level-await.md
|
|
398
|
-
'unicorn/prefer-top-level-await': '
|
|
397
|
+
'unicorn/prefer-top-level-await': 'off',
|
|
399
398
|
|
|
400
399
|
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-type-error.md
|
|
401
400
|
'unicorn/prefer-type-error': 'warn',
|
package/src/gitignore
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Logs
|
|
2
|
+
logs
|
|
3
|
+
*.log
|
|
4
|
+
npm-debug.log*
|
|
5
|
+
yarn-debug.log*
|
|
6
|
+
yarn-error.log*
|
|
7
|
+
lerna-debug.log*
|
|
8
|
+
.pnpm-debug.log*
|
|
9
|
+
|
|
10
|
+
# Coverage directory
|
|
11
|
+
coverage
|
|
12
|
+
|
|
13
|
+
# Dependency directories
|
|
14
|
+
node_modules
|
|
15
|
+
|
|
16
|
+
# Build output
|
|
17
|
+
dist
|
|
18
|
+
build
|
|
19
|
+
|
|
20
|
+
# Environment variables
|
|
21
|
+
.env
|
|
22
|
+
.env.*
|
|
23
|
+
!.env.example
|
|
24
|
+
|
|
25
|
+
# pnpm
|
|
26
|
+
.pnpm-store
|
|
27
|
+
|
|
28
|
+
# npm
|
|
29
|
+
npm-debug.log*
|
|
30
|
+
|
|
31
|
+
# OS files
|
|
32
|
+
.DS_Store
|
|
33
|
+
|
|
34
|
+
# TypeScript cache
|
|
35
|
+
*.tsbuildinfo
|
|
36
|
+
|
|
37
|
+
# Optional npm cache directory
|
|
38
|
+
.npm
|
|
39
|
+
|
|
40
|
+
# Optional eslint cache
|
|
41
|
+
.eslintcache
|
|
42
|
+
|
|
43
|
+
# Output of 'npm pack'
|
|
44
|
+
*.tgz
|
|
45
|
+
|
|
46
|
+
# Editor directories and files
|
|
47
|
+
.vscode/*
|
|
48
|
+
!.vscode/extensions.json
|
|
49
|
+
.idea
|
|
50
|
+
*.suo
|
|
51
|
+
*.ntvs*
|
|
52
|
+
*.njsproj
|
|
53
|
+
*.sln
|
|
54
|
+
*.sw?
|
|
55
|
+
|
|
56
|
+
# temp lerna install file
|
|
57
|
+
*.lerna_backup
|
|
58
|
+
|
|
59
|
+
# storybook
|
|
60
|
+
storybook-static
|
package/src/tsconfig.base.json
CHANGED
|
@@ -2,30 +2,30 @@
|
|
|
2
2
|
"$schema": "https://json.schemastore.org/tsconfig",
|
|
3
3
|
"compilerOptions": {
|
|
4
4
|
/* Language and Environment */
|
|
5
|
-
"target": "
|
|
6
|
-
"lib": ["
|
|
5
|
+
"target": "ES2023",
|
|
6
|
+
"lib": ["ES2023"],
|
|
7
7
|
|
|
8
8
|
/* Modules */
|
|
9
9
|
"module": "NodeNext", // Node.js native ESM
|
|
10
10
|
"moduleResolution": "NodeNext", // Node.js native ESM resolution
|
|
11
|
-
"
|
|
11
|
+
"moduleDetection": "force", // treat all files as modules
|
|
12
|
+
"verbatimModuleSyntax": true, // enforce explicit import type syntax and matching module syntax
|
|
12
13
|
|
|
13
14
|
/* Emit */
|
|
14
|
-
"outDir": "./dist",
|
|
15
15
|
"noEmit": true, // using external tools for compilation
|
|
16
16
|
"incremental": true, // cache type checking results
|
|
17
|
+
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.tsbuildinfo",
|
|
17
18
|
|
|
18
|
-
/*
|
|
19
|
-
"
|
|
20
|
-
"allowSyntheticDefaultImports": true, // allows default imports from modules with no default export
|
|
21
|
-
"isolatedModules": true, // ensures each file can be independently transpiled
|
|
19
|
+
/* Transpiler Compatibility */
|
|
20
|
+
"erasableSyntaxOnly": true, // disallow const enum, namespace, etc. for type-stripping tool compat
|
|
22
21
|
|
|
23
22
|
/* Type Checking */
|
|
24
|
-
"strict": true,
|
|
23
|
+
"strict": true,
|
|
25
24
|
"noUnusedLocals": false, // using @typescript-eslint/no-unused-vars instead
|
|
26
25
|
"noUnusedParameters": false, // using @typescript-eslint/no-unused-vars instead
|
|
27
|
-
"noFallthroughCasesInSwitch":
|
|
28
|
-
"
|
|
29
|
-
"
|
|
26
|
+
"noFallthroughCasesInSwitch": false, // using eslint no-fallthrough instead
|
|
27
|
+
"noUncheckedIndexedAccess": true, // force handling undefined on index access
|
|
28
|
+
"noUncheckedSideEffectImports": true, // validate side-effect imports resolve
|
|
29
|
+
"skipLibCheck": true // skip type checking of declaration files
|
|
30
30
|
}
|
|
31
31
|
}
|
package/src/tsconfig.react.json
CHANGED
|
@@ -3,11 +3,15 @@
|
|
|
3
3
|
"extends": "./tsconfig.base.json",
|
|
4
4
|
"compilerOptions": {
|
|
5
5
|
/* Language and Environment */
|
|
6
|
-
"lib": ["
|
|
7
|
-
"jsx": "react-jsx", // React 17+ jsx transform
|
|
6
|
+
"lib": ["ES2023", "DOM", "DOM.Iterable"], // browser APIs
|
|
7
|
+
"jsx": "react-jsx", // React 17+ automatic jsx transform
|
|
8
8
|
|
|
9
9
|
/* Modules */
|
|
10
|
-
"module": "ESNext", //
|
|
11
|
-
"moduleResolution": "bundler" //
|
|
10
|
+
"module": "ESNext", // bundler handles module compilation
|
|
11
|
+
"moduleResolution": "bundler", // bundler-style resolution
|
|
12
|
+
"allowImportingTsExtensions": true, // allow .ts/.tsx imports (bundler resolves them)
|
|
13
|
+
|
|
14
|
+
/* Emit */
|
|
15
|
+
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.react.tsbuildinfo"
|
|
12
16
|
}
|
|
13
17
|
}
|