zeno-config 2.2.0 → 4.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/README.md +55 -14
- package/bin/gitignore.js +84 -0
- package/package.json +14 -10
- package/src/eslint/index.d.ts +8 -1
- package/src/eslint/index.js +14 -5
- 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 +4 -5
- 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:
|
|
@@ -70,7 +90,7 @@ export default defineZenoConfig(
|
|
|
70
90
|
ts: true,
|
|
71
91
|
|
|
72
92
|
// Additional directories to ignore (added to defaults: node_modules, dist, build, coverage)
|
|
73
|
-
|
|
93
|
+
ignores: ['out', '.next'],
|
|
74
94
|
|
|
75
95
|
// If using .js extensions for React files, specify React directories
|
|
76
96
|
reactDirs: ['src/client', 'src/components'],
|
|
@@ -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.0",
|
|
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,12 +35,14 @@ 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 */
|
|
39
43
|
performanceMode?: boolean;
|
|
40
44
|
/** Additional directories to ignore (added to defaults: dist, build) */
|
|
41
|
-
|
|
45
|
+
ignores?: string[];
|
|
42
46
|
/** Directories containing React files (for projects using .js for both React and Node) */
|
|
43
47
|
reactDirs?: string[];
|
|
44
48
|
/** Directories to ignore for Node-specific rules only */
|
|
@@ -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';
|
|
@@ -142,6 +143,7 @@ const nodeConfig = (options = {}) => {
|
|
|
142
143
|
* @param {Object} [options={}] - Configuration options.
|
|
143
144
|
* @param {string[]} [options.reactDirs] - Directories containing React files (for projects using .js for both React and Node).
|
|
144
145
|
* @param {Object} [options.extensionsIgnorePattern] - Extension patterns to ignore for import rules.
|
|
146
|
+
* @param {boolean|string} [options.reactCompiler=false] - Enable React Compiler rules. Set to 'warn' for warnings or true for errors.
|
|
145
147
|
* @returns {Array} ESLint flat config array.
|
|
146
148
|
*/
|
|
147
149
|
const reactConfig = (options = {}) => {
|
|
@@ -181,6 +183,9 @@ const reactConfig = (options = {}) => {
|
|
|
181
183
|
rules: {
|
|
182
184
|
...getReactPluginRules({ extensions }),
|
|
183
185
|
...getReactHooksPluginRules(),
|
|
186
|
+
...(options.reactCompiler
|
|
187
|
+
? getReactCompilerPluginRules(options.reactCompiler)
|
|
188
|
+
: {}),
|
|
184
189
|
...getReactYouMightNotNeedAnEffectPluginRules(),
|
|
185
190
|
...getJsxA11yPluginRules(),
|
|
186
191
|
|
|
@@ -296,6 +301,7 @@ const internals = {
|
|
|
296
301
|
getUnicornPluginRules,
|
|
297
302
|
getReactPluginRules,
|
|
298
303
|
getReactHooksPluginRules,
|
|
304
|
+
getReactCompilerPluginRules,
|
|
299
305
|
getReactYouMightNotNeedAnEffectPluginRules,
|
|
300
306
|
getJsxA11yPluginRules,
|
|
301
307
|
},
|
|
@@ -306,9 +312,10 @@ const internals = {
|
|
|
306
312
|
*
|
|
307
313
|
* @param {Object|Array} arg1 - Options object or additional config array. If an array, treated as additional config.
|
|
308
314
|
* @param {boolean} [arg1.react=false] - Enable React-specific rules.
|
|
315
|
+
* @param {boolean|string} [arg1.reactCompiler=false] - Enable React Compiler rules. Set to 'warn' for warnings or true for errors.
|
|
309
316
|
* @param {boolean} [arg1.ts=true] - Enable TypeScript-specific rules.
|
|
310
317
|
* @param {boolean} [arg1.performanceMode=false] - Disables expensive rules for performance.
|
|
311
|
-
* @param {string[]} [arg1.
|
|
318
|
+
* @param {string[]} [arg1.ignores=[]] - Additional directories to ignore (added to defaults: dist, build).
|
|
312
319
|
* @param {string[]} [arg1.reactDirs=[]] - Directories containing React files (for projects using .js for both React and Node).
|
|
313
320
|
* @param {string[]} [arg1.nodeIgnoreDirs=[]] - Directories to ignore for Node-specific rules only.
|
|
314
321
|
* @param {string[]} [arg1.ignoreExports=[]] - Export patterns to ignore for import rules.
|
|
@@ -333,11 +340,12 @@ const internals = {
|
|
|
333
340
|
const defineZenoConfig = (arg1, arg2) => {
|
|
334
341
|
let options = {
|
|
335
342
|
react: false,
|
|
343
|
+
reactCompiler: false,
|
|
336
344
|
ts: false,
|
|
337
345
|
performanceMode: false,
|
|
338
346
|
|
|
339
347
|
// additional directories to ignore (added to defaults: dist, build)
|
|
340
|
-
|
|
348
|
+
ignores: [],
|
|
341
349
|
|
|
342
350
|
// if a project uses .js file extension for both react and node files this will help separate the rules for each
|
|
343
351
|
reactDirs: [],
|
|
@@ -358,8 +366,8 @@ const defineZenoConfig = (arg1, arg2) => {
|
|
|
358
366
|
}
|
|
359
367
|
|
|
360
368
|
// Ensure array options are arrays
|
|
361
|
-
if (!Array.isArray(options.
|
|
362
|
-
options.
|
|
369
|
+
if (!Array.isArray(options.ignores)) {
|
|
370
|
+
options.ignores = [];
|
|
363
371
|
}
|
|
364
372
|
if (!Array.isArray(options.reactDirs)) {
|
|
365
373
|
options.reactDirs = [];
|
|
@@ -394,6 +402,7 @@ const defineZenoConfig = (arg1, arg2) => {
|
|
|
394
402
|
? configs.getReact({
|
|
395
403
|
reactDirs: options.reactDirs,
|
|
396
404
|
extensionsIgnorePattern: options.extensionsIgnorePattern,
|
|
405
|
+
reactCompiler: options.reactCompiler,
|
|
397
406
|
})
|
|
398
407
|
: [];
|
|
399
408
|
const tsConfigResult = options.ts
|
|
@@ -401,7 +410,7 @@ const defineZenoConfig = (arg1, arg2) => {
|
|
|
401
410
|
: [];
|
|
402
411
|
|
|
403
412
|
return defineConfig([
|
|
404
|
-
{ ignores: [...defaultIgnoreDirs, ...options.
|
|
413
|
+
{ ignores: [...defaultIgnoreDirs, ...options.ignores] },
|
|
405
414
|
...configs.getBase({
|
|
406
415
|
ignoreExports: options.ignoreExports,
|
|
407
416
|
additionalDevDependencies: options.additionalDevDependencies,
|
|
@@ -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',
|
|
@@ -386,7 +385,7 @@ const getUnicornPluginRules = () => {
|
|
|
386
385
|
'unicorn/prefer-string-trim-start-end': 'warn',
|
|
387
386
|
|
|
388
387
|
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-structured-clone.md
|
|
389
|
-
'unicorn/prefer-structured-clone': '
|
|
388
|
+
'unicorn/prefer-structured-clone': 'off',
|
|
390
389
|
|
|
391
390
|
// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-switch.md
|
|
392
391
|
'unicorn/prefer-switch': 'off',
|
|
@@ -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
|
}
|