@chanyuxi/eslint-waltz 1.0.0 → 1.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/dist/cli.js CHANGED
@@ -1490,9 +1490,9 @@ async function syncVSCodeSettings(cwd = process.cwd()) {
1490
1490
  }
1491
1491
  const eol = source.includes('\r\n') ? '\r\n' : '\n';
1492
1492
  const formattingOptions = {
1493
+ eol,
1493
1494
  insertSpaces: true,
1494
1495
  tabSize: 2,
1495
- eol,
1496
1496
  };
1497
1497
  for (const setting of managedSettings) {
1498
1498
  source = applyEdits(source, modify(source, setting.path, setting.value, { formattingOptions }));
@@ -1508,13 +1508,6 @@ async function syncVSCodeSettings(cwd = process.cwd()) {
1508
1508
  return { changed, filePath };
1509
1509
  }
1510
1510
 
1511
- function printHelp() {
1512
- console.log(`Usage: eslint-waltz <command>
1513
-
1514
- Commands:
1515
- sync-vscode Create or update .vscode/settings.json for ESLint fix-on-save
1516
- `);
1517
- }
1518
1511
  async function main() {
1519
1512
  const [command] = process$1.argv.slice(2);
1520
1513
  if (command === '--help' || command === '-h') {
@@ -1531,6 +1524,13 @@ async function main() {
1531
1524
  ? `Updated ${result.filePath}`
1532
1525
  : `${result.filePath} is already synchronized`);
1533
1526
  }
1527
+ function printHelp() {
1528
+ console.log(`Usage: eslint-waltz <command>
1529
+
1530
+ Commands:
1531
+ sync-vscode Create or update .vscode/settings.json for ESLint fix-on-save
1532
+ `);
1533
+ }
1534
1534
  main().catch((error) => {
1535
1535
  console.error(error instanceof Error ? error.message : error);
1536
1536
  process$1.exitCode = 1;
package/dist/index.d.ts CHANGED
@@ -9868,28 +9868,8 @@ type TailwindcssNoCustomClassname = []|[{
9868
9868
  // ----- tailwindcss/no-unnecessary-arbitrary-value -----
9869
9869
  type TailwindcssNoUnnecessaryArbitraryValue = []|[{}]
9870
9870
 
9871
- type Rules = Record<string, Linter.RuleEntry | undefined> & RuleOptions;
9872
- interface LinterConfig extends Omit<Linter.Config, 'rules'> {
9873
- rules?: Rules;
9874
- }
9875
- type Arraiable<T> = T | Array<T>;
9876
- type UnresolvedLinterConfig = Arraiable<LinterConfig> | Promise<Arraiable<LinterConfig>>;
9877
- interface SharedOptions {
9878
- /**
9879
- * Restrict this module's configuration to the specified files.
9880
- *
9881
- * Each module has its own default file pattern. Providing this option
9882
- * replaces that pattern; it does not add another pattern to the default.
9883
- */
9884
- files?: Linter.Config['files'];
9885
- /**
9886
- * Override rules within this module's file scope.
9887
- *
9888
- * Rule names are not restricted to the plugin used by this module, so core
9889
- * ESLint rules and rules from other configured plugins can also be set here.
9890
- */
9891
- overrides?: LinterConfig['rules'];
9892
- }
9871
+ type ImportsOptions = SharedOptions;
9872
+ type JsoncOptions = SharedOptions;
9893
9873
  interface JsOptions extends SharedOptions {
9894
9874
  /**
9895
9875
  * Add predefined global variables to JavaScript files.
@@ -9899,12 +9879,9 @@ interface JsOptions extends SharedOptions {
9899
9879
  */
9900
9880
  globals?: (keyof typeof globals)[];
9901
9881
  }
9902
- type TsOptions = SharedOptions;
9903
- type StylisticOptions = SharedOptions;
9904
- type JsoncOptions = SharedOptions;
9905
- type ImportsOptions = SharedOptions;
9906
- type ReactOptions = SharedOptions;
9907
- type PerfectionistPreset = 'recommended-alphabetical' | 'recommended-natural' | 'recommended-line-length' | 'recommended-custom';
9882
+ interface LinterConfig extends Omit<Linter.Config, 'rules'> {
9883
+ rules?: Rules;
9884
+ }
9908
9885
  interface PerfectionistOptions extends SharedOptions {
9909
9886
  /**
9910
9887
  * Select one of Perfectionist's full recommended presets.
@@ -9921,6 +9898,25 @@ interface PerfectionistOptions extends SharedOptions {
9921
9898
  */
9922
9899
  settings?: Linter.Config['settings'];
9923
9900
  }
9901
+ type PerfectionistPreset = 'recommended-alphabetical' | 'recommended-custom' | 'recommended-line-length' | 'recommended-natural';
9902
+ type ReactOptions = SharedOptions;
9903
+ interface SharedOptions {
9904
+ /**
9905
+ * Restrict this module's configuration to the specified files.
9906
+ *
9907
+ * Each module has its own default file pattern. Providing this option
9908
+ * replaces that pattern; it does not add another pattern to the default.
9909
+ */
9910
+ files?: Linter.Config['files'];
9911
+ /**
9912
+ * Override rules within this module's file scope.
9913
+ *
9914
+ * Rule names are not restricted to the plugin used by this module, so core
9915
+ * ESLint rules and rules from other configured plugins can also be set here.
9916
+ */
9917
+ overrides?: LinterConfig['rules'];
9918
+ }
9919
+ type StylisticOptions = SharedOptions;
9924
9920
  interface TailwindcssOptions extends SharedOptions {
9925
9921
  /**
9926
9922
  * Configure the shared settings used by `eslint-plugin-tailwindcss`.
@@ -9932,6 +9928,8 @@ interface TailwindcssOptions extends SharedOptions {
9932
9928
  tailwindcss?: PluginSettings;
9933
9929
  };
9934
9930
  }
9931
+ type TsOptions = SharedOptions;
9932
+ type UnresolvedLinterConfig = Arraiable<LinterConfig> | Promise<Arraiable<LinterConfig>>;
9935
9933
  interface WaltzOptions {
9936
9934
  /**
9937
9935
  * Treat patterns from `.gitignore` as global ESLint ignores.
@@ -9943,6 +9941,18 @@ interface WaltzOptions {
9943
9941
  * @see https://github.com/antfu/eslint-config-flat-gitignore
9944
9942
  */
9945
9943
  gitignore?: boolean | FlatGitignoreOptions;
9944
+ /**
9945
+ * Enable rules for validating and ordering imports and exports.
9946
+ *
9947
+ * This configuration is enabled by default. JavaScript files are included
9948
+ * by default, and the scope also includes TypeScript files when `ts` is
9949
+ * enabled. Set this option to `false` to disable it, or pass an options
9950
+ * object to change the file scope or override rules.
9951
+ *
9952
+ * @default true
9953
+ * @see https://github.com/un-ts/eslint-plugin-import-x
9954
+ */
9955
+ imports?: boolean | ImportsOptions;
9946
9956
  /**
9947
9957
  * Configure the core ESLint rules for JavaScript files.
9948
9958
  *
@@ -9954,47 +9964,6 @@ interface WaltzOptions {
9954
9964
  * @see https://github.com/eslint/eslint.git
9955
9965
  */
9956
9966
  js?: JsOptions;
9957
- /**
9958
- * Enable TypeScript support for TypeScript files.
9959
- *
9960
- * `true` enables the TypeScript parser and the recommended
9961
- * `typescript-eslint` rules. By default, this applies to `.ts`, `.tsx`,
9962
- * `.mts`, and `.cts` files, including their JSX variants. Passing an
9963
- * options object additionally allows the TypeScript file scope and rules to
9964
- * be customized with `files` and `overrides`.
9965
- *
9966
- * When enabled, the default stylistic, import, and React configurations also
9967
- * include TypeScript files when those configurations are enabled.
9968
- *
9969
- * @default false
9970
- * @see https://typescript-eslint.io/linting/configs/#recommended-config
9971
- */
9972
- ts?: boolean | TsOptions;
9973
- /**
9974
- * Configure stylistic rules for script files.
9975
- *
9976
- * This configuration is always enabled and uses `@stylistic/eslint-plugin`.
9977
- * It targets JavaScript files by default, and also targets TypeScript files
9978
- * when `ts` is enabled. Perfectionist is provided as a separate default
9979
- * configuration through the `perfectionist` option.
9980
- *
9981
- * @default {}
9982
- * @see https://eslint.style/
9983
- * @see https://perfectionist.dev/rules/sort-jsx-props
9984
- */
9985
- stylistic?: StylisticOptions;
9986
- /**
9987
- * Configure Perfectionist sorting rules.
9988
- *
9989
- * This configuration is enabled by default with
9990
- * `perfectionist/sort-jsx-props`. Set it to `false` to disable it, or pass
9991
- * a `preset` to enable one of the full recommended configurations.
9992
- *
9993
- * @default true
9994
- * @see https://perfectionist.dev/configs
9995
- * @see https://perfectionist.dev/rules/sort-jsx-props
9996
- */
9997
- perfectionist?: boolean | PerfectionistOptions;
9998
9967
  /**
9999
9968
  * Enable linting for JSON, JSON5, and JSONC files.
10000
9969
  *
@@ -10007,17 +9976,17 @@ interface WaltzOptions {
10007
9976
  */
10008
9977
  json?: boolean | JsoncOptions;
10009
9978
  /**
10010
- * Enable rules for validating and ordering imports and exports.
9979
+ * Configure Perfectionist sorting rules.
10011
9980
  *
10012
- * This configuration is enabled by default. JavaScript files are included
10013
- * by default, and the scope also includes TypeScript files when `ts` is
10014
- * enabled. Set this option to `false` to disable it, or pass an options
10015
- * object to change the file scope or override rules.
9981
+ * This configuration is enabled by default with
9982
+ * `perfectionist/sort-jsx-props`. Set it to `false` to disable it, or pass
9983
+ * a `preset` to enable one of the full recommended configurations.
10016
9984
  *
10017
9985
  * @default true
10018
- * @see https://github.com/un-ts/eslint-plugin-import-x
9986
+ * @see https://perfectionist.dev/configs
9987
+ * @see https://perfectionist.dev/rules/sort-jsx-props
10019
9988
  */
10020
- imports?: boolean | ImportsOptions;
9989
+ perfectionist?: boolean | PerfectionistOptions;
10021
9990
  /**
10022
9991
  * Enable React-specific lint rules.
10023
9992
  *
@@ -10029,6 +9998,19 @@ interface WaltzOptions {
10029
9998
  * @see https://github.com/Rel1cx/eslint-react
10030
9999
  */
10031
10000
  react?: boolean | ReactOptions;
10001
+ /**
10002
+ * Configure stylistic rules for script files.
10003
+ *
10004
+ * This configuration is always enabled and uses `@stylistic/eslint-plugin`.
10005
+ * It targets JavaScript files by default, and also targets TypeScript files
10006
+ * when `ts` is enabled. Perfectionist is provided as a separate default
10007
+ * configuration through the `perfectionist` option.
10008
+ *
10009
+ * @default {}
10010
+ * @see https://eslint.style/
10011
+ * @see https://perfectionist.dev/rules/sort-jsx-props
10012
+ */
10013
+ stylistic?: StylisticOptions;
10032
10014
  /**
10033
10015
  * Enable Tailwind CSS class name linting.
10034
10016
  *
@@ -10043,7 +10025,25 @@ interface WaltzOptions {
10043
10025
  * @see https://github.com/francoismassart/eslint-plugin-tailwindcss
10044
10026
  */
10045
10027
  tailwindcss?: boolean | TailwindcssOptions;
10028
+ /**
10029
+ * Enable TypeScript support for TypeScript files.
10030
+ *
10031
+ * `true` enables the TypeScript parser and the recommended
10032
+ * `typescript-eslint` rules. By default, this applies to `.ts`, `.tsx`,
10033
+ * `.mts`, and `.cts` files, including their JSX variants. Passing an
10034
+ * options object additionally allows the TypeScript file scope and rules to
10035
+ * be customized with `files` and `overrides`.
10036
+ *
10037
+ * When enabled, the default stylistic, import, and React configurations also
10038
+ * include TypeScript files when those configurations are enabled.
10039
+ *
10040
+ * @default false
10041
+ * @see https://typescript-eslint.io/linting/configs/#recommended-config
10042
+ */
10043
+ ts?: boolean | TsOptions;
10046
10044
  }
10045
+ type Arraiable<T> = Array<T> | T;
10046
+ type Rules = Record<string, Linter.RuleEntry | undefined> & RuleOptions;
10047
10047
 
10048
10048
  declare function waltz(options?: WaltzOptions, ...orders: LinterConfig[]): Promise<LinterConfig[]>;
10049
10049
 
package/dist/index.js CHANGED
@@ -1,42 +1,20 @@
1
1
  import eslint from '@eslint/js';
2
2
  import globals from 'globals';
3
3
 
4
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
5
- function importDefault(moduleName) {
6
- return import(moduleName).then(m => m.default);
7
- }
8
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
9
- function importDefaultAs(moduleName,
10
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
11
- cast) {
12
- return import(moduleName).then(m => cast(m.default));
13
- }
14
4
  function importGitignoreSeek() {
15
5
  return importDefault('eslint-config-flat-gitignore');
16
6
  }
17
- function importTypeScriptPlugin() {
18
- return importDefaultAs('typescript-eslint', d => d.plugin);
19
- }
20
- function importTypeScriptParser() {
21
- return importDefaultAs('typescript-eslint', d => d.parser);
22
- }
23
- function importTypeScriptRecommendedRules() {
24
- return import('typescript-eslint').then(({ configs }) => Object.assign({}, ...configs.recommended.map(config => config.rules ?? {})));
25
- }
26
- function importStylisticPlugin() {
27
- return importDefault('@stylistic/eslint-plugin');
28
- }
29
- function importJsoncPlugin() {
30
- return importDefaultAs('eslint-plugin-jsonc', d => d);
7
+ function importImportXPlugin() {
8
+ return importDefault('eslint-plugin-import-x');
31
9
  }
32
10
  function importJsoncParser() {
33
11
  return import('jsonc-eslint-parser');
34
12
  }
35
- function importImportXPlugin() {
36
- return importDefault('eslint-plugin-import-x');
13
+ function importJsoncPlugin() {
14
+ return importDefaultAs('eslint-plugin-jsonc', d => d);
37
15
  }
38
- function importReactPlugin() {
39
- return importDefaultAs('eslint-plugin-react-x', d => d);
16
+ function importPerfectionistPlugin() {
17
+ return importDefault('eslint-plugin-perfectionist');
40
18
  }
41
19
  function importReactDebugPlugin() {
42
20
  return importDefaultAs('eslint-plugin-react-debug', d => d);
@@ -50,14 +28,36 @@ function importReactHookExtraPlugin() {
50
28
  function importReactNamingConventionPlugin() {
51
29
  return importDefaultAs('eslint-plugin-react-naming-convention', d => d);
52
30
  }
31
+ function importReactPlugin() {
32
+ return importDefaultAs('eslint-plugin-react-x', d => d);
33
+ }
53
34
  function importReactWebApiPlugin() {
54
35
  return importDefaultAs('eslint-plugin-react-web-api', d => d);
55
36
  }
37
+ function importStylisticPlugin() {
38
+ return importDefault('@stylistic/eslint-plugin');
39
+ }
56
40
  function importTailwindcssPlugin() {
57
41
  return importDefault('eslint-plugin-tailwindcss');
58
42
  }
59
- function importPerfectionistPlugin() {
60
- return importDefault('eslint-plugin-perfectionist');
43
+ function importTypeScriptParser() {
44
+ return importDefaultAs('typescript-eslint', d => d.parser);
45
+ }
46
+ function importTypeScriptPlugin() {
47
+ return importDefaultAs('typescript-eslint', d => d.plugin);
48
+ }
49
+ function importTypeScriptRecommendedRules() {
50
+ return import('typescript-eslint').then(({ configs }) => Object.assign({}, ...configs.recommended.map(config => config.rules ?? {})));
51
+ }
52
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
53
+ function importDefault(moduleName) {
54
+ return import(moduleName).then(m => m.default);
55
+ }
56
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
57
+ function importDefaultAs(moduleName,
58
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
59
+ cast) {
60
+ return import(moduleName).then(m => cast(m.default));
61
61
  }
62
62
 
63
63
  async function gitignore(enable) {
@@ -78,23 +78,23 @@ async function importsConfig(isEnableTypeScript = false, options = {}) {
78
78
  const files = options.files ?? scriptFiles;
79
79
  return [
80
80
  {
81
- name: 'waltz/imports/setup',
82
81
  files,
82
+ name: 'waltz/imports/setup',
83
83
  plugins: {
84
84
  imports: importsPlugin,
85
85
  },
86
86
  },
87
87
  {
88
- name: 'waltz/imports/rules',
89
88
  files,
89
+ name: 'waltz/imports/rules',
90
90
  rules: {
91
- 'imports/named': 'error',
92
- 'imports/namespace': 'error',
93
91
  'imports/default': 'error',
94
92
  'imports/export': 'error',
93
+ 'imports/named': 'error',
94
+ 'imports/namespace': 'error',
95
+ 'imports/no-duplicates': 'warn',
95
96
  'imports/no-named-as-default': 'warn',
96
97
  'imports/no-named-as-default-member': 'warn',
97
- 'imports/no-duplicates': 'warn',
98
98
  'imports/order': [
99
99
  'error',
100
100
  {
@@ -146,7 +146,6 @@ async function importsConfig(isEnableTypeScript = false, options = {}) {
146
146
 
147
147
  function jsConfig(config = {}, relative) {
148
148
  return {
149
- name: 'waltz/js/rules',
150
149
  files: config.files ?? [JS_FILES],
151
150
  languageOptions: {
152
151
  globals: {
@@ -162,6 +161,7 @@ function jsConfig(config = {}, relative) {
162
161
  },
163
162
  },
164
163
  },
164
+ name: 'waltz/js/rules',
165
165
  rules: {
166
166
  ...eslint.configs.recommended.rules,
167
167
  ...config.overrides,
@@ -182,20 +182,21 @@ async function jsoncConfig(options = {}) {
182
182
  ];
183
183
  return [
184
184
  {
185
- name: 'waltz/jsonc/setup',
186
185
  files,
187
- plugins: {
188
- jsonc: jsoncPlugin,
189
- },
190
186
  languageOptions: {
191
187
  parser: jsoncParser,
192
188
  },
189
+ name: 'waltz/jsonc/setup',
190
+ plugins: {
191
+ jsonc: jsoncPlugin,
192
+ },
193
193
  },
194
194
  {
195
- name: 'waltz/jsonc/rules',
196
195
  files,
196
+ name: 'waltz/jsonc/rules',
197
197
  rules: {
198
198
  'jsonc/comma-dangle': 'error',
199
+ 'jsonc/indent': ['error', 2],
199
200
  'jsonc/no-bigint-literals': 'error',
200
201
  'jsonc/no-binary-expression': 'error',
201
202
  'jsonc/no-binary-numeric-literals': 'error',
@@ -209,8 +210,8 @@ async function jsoncConfig(options = {}) {
209
210
  'jsonc/no-nan': 'error',
210
211
  'jsonc/no-number-props': 'error',
211
212
  'jsonc/no-numeric-separators': 'error',
212
- 'jsonc/no-octal-numeric-literals': 'error',
213
213
  'jsonc/no-octal': 'error',
214
+ 'jsonc/no-octal-numeric-literals': 'error',
214
215
  'jsonc/no-parenthesized': 'error',
215
216
  'jsonc/no-plus-sign': 'error',
216
217
  'jsonc/no-regexp-literals': 'error',
@@ -224,13 +225,12 @@ async function jsoncConfig(options = {}) {
224
225
  'jsonc/space-unary-ops': 'error',
225
226
  'jsonc/valid-json-number': 'error',
226
227
  'jsonc/vue-custom-block/no-parsing-error': 'error',
227
- 'jsonc/indent': ['error', 2],
228
228
  ...options.overrides,
229
229
  },
230
230
  },
231
231
  {
232
- name: 'waltz/jsonc/sort/package-json',
233
232
  files: packageJsonFiles,
233
+ name: 'waltz/jsonc/sort/package-json',
234
234
  rules: {
235
235
  'jsonc/sort-array-values': [
236
236
  'error',
@@ -329,8 +329,8 @@ async function jsoncConfig(options = {}) {
329
329
  },
330
330
  },
331
331
  {
332
- name: 'waltz/jsonc/sort/tsconfig-json',
333
332
  files: tsconfigFiles,
333
+ name: 'waltz/jsonc/sort/tsconfig-json',
334
334
  rules: {
335
335
  'jsonc/sort-keys': [
336
336
  'error',
@@ -467,15 +467,15 @@ async function perfectionistConfig(options = {}, relative) {
467
467
  };
468
468
  return [
469
469
  {
470
- name: 'waltz/perfectionist/setup',
471
470
  files: scriptFiles,
471
+ name: 'waltz/perfectionist/setup',
472
472
  plugins: {
473
473
  perfectionist,
474
474
  },
475
475
  },
476
476
  {
477
- name: 'waltz/perfectionist/rules',
478
477
  files: options.files ?? scriptFiles,
478
+ name: 'waltz/perfectionist/rules',
479
479
  ...(options.settings ? { settings: options.settings } : {}),
480
480
  rules: {
481
481
  ...recommendedRules,
@@ -485,6 +485,122 @@ async function perfectionistConfig(options = {}, relative) {
485
485
  ];
486
486
  }
487
487
 
488
+ async function reactConfig(options = {}, relative) {
489
+ const resolvedConfig = typeof options === 'boolean' ? {} : options;
490
+ const [reactPlugin, reactDebugPlugin, reactDomPlugin, reactHookExtraPlugin, reactNamingConventionPlugin, reactWebApiPlugin,] = await Promise.all([
491
+ importReactPlugin(),
492
+ importReactDebugPlugin(),
493
+ importReactDomPlugin(),
494
+ importReactHookExtraPlugin(),
495
+ importReactNamingConventionPlugin(),
496
+ importReactWebApiPlugin(),
497
+ ]);
498
+ const scriptFiles = relative.isEnableTypeScript
499
+ ? ALL_SCRIPTS_FILES
500
+ : [JS_FILES];
501
+ const ruleFiles = resolvedConfig.files ?? scriptFiles;
502
+ const typeScriptRules = relative.isEnableTypeScript
503
+ ? [
504
+ {
505
+ files: resolvedConfig.files ?? [TS_FILES],
506
+ name: 'waltz/react/typescript-rules',
507
+ rules: {
508
+ '@eslint-react/dom/no-unknown-property': 'off',
509
+ ...resolvedConfig.overrides,
510
+ },
511
+ },
512
+ ]
513
+ : [];
514
+ return [
515
+ {
516
+ files: scriptFiles,
517
+ name: 'waltz/react/setup',
518
+ plugins: {
519
+ '@eslint-react': reactPlugin,
520
+ '@eslint-react/debug': reactDebugPlugin,
521
+ '@eslint-react/dom': reactDomPlugin,
522
+ '@eslint-react/hooks-extra': reactHookExtraPlugin,
523
+ '@eslint-react/naming-convention': reactNamingConventionPlugin,
524
+ '@eslint-react/web-api': reactWebApiPlugin,
525
+ },
526
+ },
527
+ {
528
+ files: ruleFiles,
529
+ name: 'waltz/react/rules',
530
+ rules: {
531
+ '@eslint-react/dom/no-dangerously-set-innerhtml': 'warn',
532
+ '@eslint-react/dom/no-dangerously-set-innerhtml-with-children': 'error',
533
+ '@eslint-react/dom/no-find-dom-node': 'error',
534
+ '@eslint-react/dom/no-flush-sync': 'error',
535
+ '@eslint-react/dom/no-hydrate': 'error',
536
+ '@eslint-react/dom/no-missing-button-type': 'warn',
537
+ '@eslint-react/dom/no-missing-iframe-sandbox': 'warn',
538
+ '@eslint-react/dom/no-render': 'error',
539
+ '@eslint-react/dom/no-render-return-value': 'error',
540
+ '@eslint-react/dom/no-script-url': 'warn',
541
+ '@eslint-react/dom/no-unknown-property': 'warn',
542
+ '@eslint-react/dom/no-unsafe-iframe-sandbox': 'warn',
543
+ '@eslint-react/dom/no-unsafe-target-blank': 'warn',
544
+ '@eslint-react/dom/no-use-form-state': 'error',
545
+ '@eslint-react/dom/no-void-elements-with-children': 'error',
546
+ '@eslint-react/hooks-extra/no-direct-set-state-in-use-effect': 'warn',
547
+ '@eslint-react/naming-convention/context-name': 'warn',
548
+ '@eslint-react/no-access-state-in-setstate': 'error',
549
+ '@eslint-react/no-array-index-key': 'warn',
550
+ '@eslint-react/no-children-count': 'warn',
551
+ '@eslint-react/no-children-for-each': 'warn',
552
+ '@eslint-react/no-children-map': 'warn',
553
+ '@eslint-react/no-children-only': 'warn',
554
+ '@eslint-react/no-children-to-array': 'warn',
555
+ '@eslint-react/no-clone-element': 'warn',
556
+ '@eslint-react/no-component-will-mount': 'error',
557
+ '@eslint-react/no-component-will-receive-props': 'error',
558
+ '@eslint-react/no-component-will-update': 'error',
559
+ '@eslint-react/no-context-provider': 'warn',
560
+ '@eslint-react/no-create-ref': 'error',
561
+ '@eslint-react/no-direct-mutation-state': 'error',
562
+ '@eslint-react/no-duplicate-key': 'warn',
563
+ '@eslint-react/no-forward-ref': 'warn',
564
+ '@eslint-react/no-missing-key': 'error',
565
+ '@eslint-react/no-misused-capture-owner-stack': 'error',
566
+ '@eslint-react/no-nested-component-definitions': 'error',
567
+ '@eslint-react/no-nested-lazy-component-declarations': 'warn',
568
+ '@eslint-react/no-set-state-in-component-did-mount': 'warn',
569
+ '@eslint-react/no-set-state-in-component-did-update': 'warn',
570
+ '@eslint-react/no-set-state-in-component-will-update': 'warn',
571
+ '@eslint-react/no-unsafe-component-will-mount': 'warn',
572
+ '@eslint-react/no-unsafe-component-will-receive-props': 'warn',
573
+ '@eslint-react/no-unsafe-component-will-update': 'warn',
574
+ '@eslint-react/no-unstable-context-value': 'warn',
575
+ '@eslint-react/no-unstable-default-props': 'warn',
576
+ '@eslint-react/no-unused-class-component-members': 'warn',
577
+ '@eslint-react/no-unused-state': 'warn',
578
+ '@eslint-react/no-use-context': 'warn',
579
+ '@eslint-react/web-api/no-leaked-event-listener': 'warn',
580
+ '@eslint-react/web-api/no-leaked-interval': 'warn',
581
+ '@eslint-react/web-api/no-leaked-resize-observer': 'warn',
582
+ '@eslint-react/web-api/no-leaked-timeout': 'warn',
583
+ ...resolvedConfig.overrides,
584
+ },
585
+ settings: {
586
+ 'react-x': {
587
+ additionalComponents: [],
588
+ additionalHooks: {
589
+ useEffect: ['useIsomorphicLayoutEffect'],
590
+ useLayoutEffect: ['useIsomorphicLayoutEffect'],
591
+ },
592
+ importSource: 'react',
593
+ polymorphicPropName: 'as',
594
+ skipImportCheck: true,
595
+ strict: true,
596
+ version: 'detect',
597
+ },
598
+ },
599
+ },
600
+ ...typeScriptRules,
601
+ ];
602
+ }
603
+
488
604
  async function stylisticConfig(options = {}, relative) {
489
605
  const eslintStylistic = await importStylisticPlugin();
490
606
  const scriptFiles = relative.isEnableTypeScript
@@ -560,15 +676,15 @@ async function stylisticConfig(options = {}, relative) {
560
676
  // '@stylistic/jsx-wrap-multilines'
561
677
  return [
562
678
  {
563
- name: 'waltz/stylistic/setup',
564
679
  files: scriptFiles,
680
+ name: 'waltz/stylistic/setup',
565
681
  plugins: {
566
682
  '@stylistic': eslintStylistic,
567
683
  },
568
684
  },
569
685
  {
570
- name: 'waltz/stylistic/rules',
571
686
  files: options.files ?? scriptFiles,
687
+ name: 'waltz/stylistic/rules',
572
688
  rules: {
573
689
  ...configs.rules,
574
690
  ...options.overrides,
@@ -586,24 +702,24 @@ async function tailwindcssConfig(options = {}, relative) {
586
702
  const files = options.files ?? scriptFiles;
587
703
  return [
588
704
  {
589
- name: 'waltz/tailwindcss/setup',
590
705
  files,
706
+ languageOptions: recommended.languageOptions,
707
+ name: 'waltz/tailwindcss/setup',
591
708
  plugins: {
592
709
  tailwindcss,
593
710
  },
594
- languageOptions: recommended.languageOptions,
595
711
  },
596
712
  {
597
- name: 'waltz/tailwindcss/rules',
598
713
  files,
599
- settings: {
600
- ...recommended.settings,
601
- ...options.settings,
602
- },
714
+ name: 'waltz/tailwindcss/rules',
603
715
  rules: {
604
716
  ...recommended.rules,
605
717
  ...options.overrides,
606
718
  },
719
+ settings: {
720
+ ...recommended.settings,
721
+ ...options.settings,
722
+ },
607
723
  },
608
724
  ];
609
725
  }
@@ -617,139 +733,23 @@ async function tsConfig(options = {}) {
617
733
  const resolvedConfig = typeof options === 'boolean' ? {} : options;
618
734
  return [
619
735
  {
620
- name: 'waltz/ts/setup',
621
736
  files: [TS_FILES],
622
- plugins: {
623
- '@typescript-eslint': typeScriptPlugin,
624
- },
625
737
  languageOptions: {
626
738
  parser: typeScriptParser,
627
739
  },
628
- },
629
- {
630
- name: 'waltz/ts/rules',
631
- files: resolvedConfig.files ?? [TS_FILES],
632
- rules: {
633
- ...recommendedRules,
634
- ...resolvedConfig.overrides,
635
- },
636
- },
637
- ];
638
- }
639
-
640
- async function reactConfig(options = {}, relative) {
641
- const resolvedConfig = typeof options === 'boolean' ? {} : options;
642
- const [reactPlugin, reactDebugPlugin, reactDomPlugin, reactHookExtraPlugin, reactNamingConventionPlugin, reactWebApiPlugin,] = await Promise.all([
643
- importReactPlugin(),
644
- importReactDebugPlugin(),
645
- importReactDomPlugin(),
646
- importReactHookExtraPlugin(),
647
- importReactNamingConventionPlugin(),
648
- importReactWebApiPlugin(),
649
- ]);
650
- const scriptFiles = relative.isEnableTypeScript
651
- ? ALL_SCRIPTS_FILES
652
- : [JS_FILES];
653
- const ruleFiles = resolvedConfig.files ?? scriptFiles;
654
- const typeScriptRules = relative.isEnableTypeScript
655
- ? [
656
- {
657
- name: 'waltz/react/typescript-rules',
658
- files: resolvedConfig.files ?? [TS_FILES],
659
- rules: {
660
- '@eslint-react/dom/no-unknown-property': 'off',
661
- ...resolvedConfig.overrides,
662
- },
663
- },
664
- ]
665
- : [];
666
- return [
667
- {
668
- name: 'waltz/react/setup',
669
- files: scriptFiles,
740
+ name: 'waltz/ts/setup',
670
741
  plugins: {
671
- '@eslint-react': reactPlugin,
672
- '@eslint-react/dom': reactDomPlugin,
673
- '@eslint-react/web-api': reactWebApiPlugin,
674
- '@eslint-react/debug': reactDebugPlugin,
675
- '@eslint-react/hooks-extra': reactHookExtraPlugin,
676
- '@eslint-react/naming-convention': reactNamingConventionPlugin,
742
+ '@typescript-eslint': typeScriptPlugin,
677
743
  },
678
744
  },
679
745
  {
680
- name: 'waltz/react/rules',
681
- files: ruleFiles,
746
+ files: resolvedConfig.files ?? [TS_FILES],
747
+ name: 'waltz/ts/rules',
682
748
  rules: {
683
- '@eslint-react/no-access-state-in-setstate': 'error',
684
- '@eslint-react/no-array-index-key': 'warn',
685
- '@eslint-react/no-children-count': 'warn',
686
- '@eslint-react/no-children-for-each': 'warn',
687
- '@eslint-react/no-children-map': 'warn',
688
- '@eslint-react/no-children-only': 'warn',
689
- '@eslint-react/no-children-to-array': 'warn',
690
- '@eslint-react/no-clone-element': 'warn',
691
- '@eslint-react/no-component-will-mount': 'error',
692
- '@eslint-react/no-component-will-receive-props': 'error',
693
- '@eslint-react/no-component-will-update': 'error',
694
- '@eslint-react/no-context-provider': 'warn',
695
- '@eslint-react/no-create-ref': 'error',
696
- '@eslint-react/no-direct-mutation-state': 'error',
697
- '@eslint-react/no-duplicate-key': 'warn',
698
- '@eslint-react/no-forward-ref': 'warn',
699
- '@eslint-react/no-missing-key': 'error',
700
- '@eslint-react/no-misused-capture-owner-stack': 'error',
701
- '@eslint-react/no-nested-component-definitions': 'error',
702
- '@eslint-react/no-nested-lazy-component-declarations': 'warn',
703
- '@eslint-react/no-set-state-in-component-did-mount': 'warn',
704
- '@eslint-react/no-set-state-in-component-did-update': 'warn',
705
- '@eslint-react/no-set-state-in-component-will-update': 'warn',
706
- '@eslint-react/no-unsafe-component-will-mount': 'warn',
707
- '@eslint-react/no-unsafe-component-will-receive-props': 'warn',
708
- '@eslint-react/no-unsafe-component-will-update': 'warn',
709
- '@eslint-react/no-unstable-context-value': 'warn',
710
- '@eslint-react/no-unstable-default-props': 'warn',
711
- '@eslint-react/no-unused-class-component-members': 'warn',
712
- '@eslint-react/no-unused-state': 'warn',
713
- '@eslint-react/no-use-context': 'warn',
714
- '@eslint-react/dom/no-dangerously-set-innerhtml': 'warn',
715
- '@eslint-react/dom/no-dangerously-set-innerhtml-with-children': 'error',
716
- '@eslint-react/dom/no-find-dom-node': 'error',
717
- '@eslint-react/dom/no-flush-sync': 'error',
718
- '@eslint-react/dom/no-hydrate': 'error',
719
- '@eslint-react/dom/no-missing-button-type': 'warn',
720
- '@eslint-react/dom/no-missing-iframe-sandbox': 'warn',
721
- '@eslint-react/dom/no-render': 'error',
722
- '@eslint-react/dom/no-render-return-value': 'error',
723
- '@eslint-react/dom/no-script-url': 'warn',
724
- '@eslint-react/dom/no-unsafe-iframe-sandbox': 'warn',
725
- '@eslint-react/dom/no-unsafe-target-blank': 'warn',
726
- '@eslint-react/dom/no-use-form-state': 'error',
727
- '@eslint-react/dom/no-void-elements-with-children': 'error',
728
- '@eslint-react/web-api/no-leaked-event-listener': 'warn',
729
- '@eslint-react/web-api/no-leaked-interval': 'warn',
730
- '@eslint-react/web-api/no-leaked-resize-observer': 'warn',
731
- '@eslint-react/web-api/no-leaked-timeout': 'warn',
732
- '@eslint-react/hooks-extra/no-direct-set-state-in-use-effect': 'warn',
733
- '@eslint-react/naming-convention/context-name': 'warn',
734
- '@eslint-react/dom/no-unknown-property': 'warn',
749
+ ...recommendedRules,
735
750
  ...resolvedConfig.overrides,
736
751
  },
737
- settings: {
738
- 'react-x': {
739
- version: 'detect',
740
- importSource: 'react',
741
- strict: true,
742
- skipImportCheck: true,
743
- polymorphicPropName: 'as',
744
- additionalComponents: [],
745
- additionalHooks: {
746
- useEffect: ['useIsomorphicLayoutEffect'],
747
- useLayoutEffect: ['useIsomorphicLayoutEffect'],
748
- },
749
- },
750
- },
751
752
  },
752
- ...typeScriptRules,
753
753
  ];
754
754
  }
755
755
 
package/package.json CHANGED
@@ -1,148 +1,148 @@
1
- {
2
- "name": "@chanyuxi/eslint-waltz",
3
- "type": "module",
4
- "version": "1.0.0",
5
- "packageManager": "pnpm@10.4.1",
6
- "description": "A composable ESLint flat config for JavaScript, TypeScript, JSONC, imports, React, Tailwind CSS, and Perfectionist.",
7
- "author": "chanyuxi <2438149743@qq.com> (https://github.com/chanyuxi)",
8
- "license": "ISC",
9
- "homepage": "https://github.com/chanyuxi/eslint-waltz",
10
- "repository": {
11
- "type": "git",
12
- "url": "https://github.com/chanyuxi/eslint-waltz.git"
13
- },
14
- "bugs": {
15
- "url": "https://github.com/chanyuxi/eslint-waltz/issues"
16
- },
17
- "publishConfig": {
18
- "access": "public"
19
- },
20
- "keywords": [
21
- "chanyuxi",
22
- "eslint",
23
- "config",
24
- "integration"
25
- ],
26
- "exports": {
27
- ".": {
28
- "types": "./dist/index.d.ts",
29
- "import": "./dist/index.js",
30
- "default": "./dist/index.js"
31
- }
32
- },
33
- "bin": {
34
- "eslint-waltz": "./dist/cli.js"
35
- },
36
- "files": [
37
- "dist"
38
- ],
39
- "engines": {
40
- "node": ">=20.19.0"
41
- },
42
- "scripts": {
43
- "build": "rimraf ./dist && pnpm gen && rollup -c rollup.config.ts --configPlugin @rollup/plugin-typescript",
44
- "gen": "tsx scripts/typegen.ts",
45
- "lint": "eslint .",
46
- "lint:fix": "eslint . --fix",
47
- "typeCheck": "pnpm gen && tsc --noEmit",
48
- "test": "node --import tsx test/index.ts",
49
- "check": "pnpm run typeCheck && pnpm run lint && pnpm run test",
50
- "changeset": "changeset",
51
- "version": "changeset version && pnpm install --lockfile-only",
52
- "release": "pnpm build && changeset publish",
53
- "prepack": "pnpm build",
54
- "prepare": "husky"
55
- },
56
- "peerDependencies": {
57
- "@eslint/js": "^10.0.1",
58
- "@stylistic/eslint-plugin": "^5.10.0",
59
- "eslint": "^10.10.0",
60
- "eslint-config-flat-gitignore": "^2.4.0",
61
- "eslint-plugin-import-x": "^4.17.1",
62
- "eslint-plugin-jsonc": "^3.4.2",
63
- "eslint-plugin-perfectionist": "^5.11.0",
64
- "eslint-plugin-react-debug": "^5.19.0",
65
- "eslint-plugin-react-dom": "^5.19.0",
66
- "eslint-plugin-react-hooks-extra": "^2.13.0",
67
- "eslint-plugin-react-naming-convention": "^5.19.0",
68
- "eslint-plugin-react-web-api": "^5.19.0",
69
- "eslint-plugin-react-x": "^5.19.0",
70
- "eslint-plugin-tailwindcss": "^4.4.0",
71
- "globals": "^17.12.0",
72
- "jsonc-eslint-parser": "^3.3.0",
73
- "tailwindcss": "^4.0.0",
74
- "typescript-eslint": "^8.70.0"
75
- },
76
- "peerDependenciesMeta": {
77
- "eslint-config-flat-gitignore": {
78
- "optional": true
79
- },
80
- "eslint-plugin-react-debug": {
81
- "optional": true
82
- },
83
- "eslint-plugin-react-dom": {
84
- "optional": true
85
- },
86
- "eslint-plugin-react-hooks-extra": {
87
- "optional": true
88
- },
89
- "eslint-plugin-react-naming-convention": {
90
- "optional": true
91
- },
92
- "eslint-plugin-react-web-api": {
93
- "optional": true
94
- },
95
- "eslint-plugin-react-x": {
96
- "optional": true
97
- },
98
- "eslint-plugin-tailwindcss": {
99
- "optional": true
100
- },
101
- "tailwindcss": {
102
- "optional": true
103
- },
104
- "typescript-eslint": {
105
- "optional": true
106
- }
107
- },
108
- "dependencies": {
109
- "jsonc-parser": "^3.3.1"
110
- },
111
- "devDependencies": {
112
- "@changesets/cli": "^3.0.2",
113
- "@commitlint/cli": "^19.8.1",
114
- "@commitlint/config-conventional": "^19.8.1",
115
- "@commitlint/types": "^19.8.1",
116
- "@eslint/js": "^10.0.1",
117
- "@rollup/plugin-commonjs": "^28.0.6",
118
- "@rollup/plugin-node-resolve": "^16.0.1",
119
- "@rollup/plugin-typescript": "^12.1.4",
120
- "@stylistic/eslint-plugin": "^5.10.0",
121
- "@types/node": "^24.1.0",
122
- "eslint": "^10.10.0",
123
- "eslint-config-flat-gitignore": "^2.4.0",
124
- "eslint-plugin-import-x": "^4.17.1",
125
- "eslint-plugin-jsonc": "^3.4.2",
126
- "eslint-plugin-perfectionist": "^5.11.0",
127
- "eslint-plugin-react-debug": "^5.19.0",
128
- "eslint-plugin-react-dom": "^5.19.0",
129
- "eslint-plugin-react-hooks-extra": "^2.13.0",
130
- "eslint-plugin-react-naming-convention": "^5.19.0",
131
- "eslint-plugin-react-web-api": "^5.19.0",
132
- "eslint-plugin-react-x": "^5.19.0",
133
- "eslint-plugin-tailwindcss": "^4.4.0",
134
- "eslint-typegen": "^2.3.1",
135
- "globals": "^17.12.0",
136
- "husky": "^9.1.7",
137
- "jiti": "^2.7.0",
138
- "jsonc-eslint-parser": "^3.3.0",
139
- "rimraf": "^6.0.1",
140
- "rollup": "^4.46.2",
141
- "rollup-plugin-dts": "^6.2.1",
142
- "tailwindcss": "^4.3.3",
143
- "tslib": "^2.8.1",
144
- "tsx": "^4.20.3",
145
- "typescript": "^5.8.3",
146
- "typescript-eslint": "^8.70.0"
147
- }
148
- }
1
+ {
2
+ "name": "@chanyuxi/eslint-waltz",
3
+ "type": "module",
4
+ "version": "1.1.0",
5
+ "packageManager": "pnpm@10.4.1",
6
+ "description": "A composable ESLint flat config for JavaScript, TypeScript, JSONC, imports, React, Tailwind CSS, and Perfectionist.",
7
+ "author": "chanyuxi <2438149743@qq.com> (https://github.com/chanyuxi)",
8
+ "license": "ISC",
9
+ "homepage": "https://github.com/chanyuxi/eslint-waltz",
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "https://github.com/chanyuxi/eslint-waltz.git"
13
+ },
14
+ "bugs": {
15
+ "url": "https://github.com/chanyuxi/eslint-waltz/issues"
16
+ },
17
+ "publishConfig": {
18
+ "access": "public"
19
+ },
20
+ "keywords": [
21
+ "chanyuxi",
22
+ "eslint",
23
+ "config",
24
+ "integration"
25
+ ],
26
+ "exports": {
27
+ ".": {
28
+ "types": "./dist/index.d.ts",
29
+ "import": "./dist/index.js",
30
+ "default": "./dist/index.js"
31
+ }
32
+ },
33
+ "bin": {
34
+ "eslint-waltz": "./dist/cli.js"
35
+ },
36
+ "files": [
37
+ "dist"
38
+ ],
39
+ "engines": {
40
+ "node": ">=20.19.0"
41
+ },
42
+ "scripts": {
43
+ "build": "rimraf ./dist && pnpm gen && rollup -c rollup.config.ts --configPlugin @rollup/plugin-typescript",
44
+ "gen": "tsx scripts/typegen.ts",
45
+ "lint": "eslint .",
46
+ "lint:fix": "eslint . --fix",
47
+ "typeCheck": "pnpm gen && tsc --noEmit",
48
+ "test": "node --import tsx test/index.ts",
49
+ "check": "pnpm run typeCheck && pnpm run lint && pnpm run test",
50
+ "changeset": "changeset",
51
+ "version": "changeset version && pnpm install --lockfile-only",
52
+ "release": "pnpm build && changeset publish",
53
+ "prepack": "pnpm build",
54
+ "prepare": "husky"
55
+ },
56
+ "peerDependencies": {
57
+ "@eslint/js": "^10.0.1",
58
+ "@stylistic/eslint-plugin": "^5.10.0",
59
+ "eslint": "^10.10.0",
60
+ "eslint-config-flat-gitignore": "^2.4.0",
61
+ "eslint-plugin-import-x": "^4.17.1",
62
+ "eslint-plugin-jsonc": "^3.4.2",
63
+ "eslint-plugin-perfectionist": "^5.11.0",
64
+ "eslint-plugin-react-debug": "^5.19.0",
65
+ "eslint-plugin-react-dom": "^5.19.0",
66
+ "eslint-plugin-react-hooks-extra": "^2.13.0",
67
+ "eslint-plugin-react-naming-convention": "^5.19.0",
68
+ "eslint-plugin-react-web-api": "^5.19.0",
69
+ "eslint-plugin-react-x": "^5.19.0",
70
+ "eslint-plugin-tailwindcss": "^4.4.0",
71
+ "globals": "^17.12.0",
72
+ "jsonc-eslint-parser": "^3.3.0",
73
+ "tailwindcss": "^4.0.0",
74
+ "typescript-eslint": "^8.70.0"
75
+ },
76
+ "peerDependenciesMeta": {
77
+ "eslint-config-flat-gitignore": {
78
+ "optional": true
79
+ },
80
+ "eslint-plugin-react-debug": {
81
+ "optional": true
82
+ },
83
+ "eslint-plugin-react-dom": {
84
+ "optional": true
85
+ },
86
+ "eslint-plugin-react-hooks-extra": {
87
+ "optional": true
88
+ },
89
+ "eslint-plugin-react-naming-convention": {
90
+ "optional": true
91
+ },
92
+ "eslint-plugin-react-web-api": {
93
+ "optional": true
94
+ },
95
+ "eslint-plugin-react-x": {
96
+ "optional": true
97
+ },
98
+ "eslint-plugin-tailwindcss": {
99
+ "optional": true
100
+ },
101
+ "tailwindcss": {
102
+ "optional": true
103
+ },
104
+ "typescript-eslint": {
105
+ "optional": true
106
+ }
107
+ },
108
+ "dependencies": {
109
+ "jsonc-parser": "^3.3.1"
110
+ },
111
+ "devDependencies": {
112
+ "@changesets/cli": "^3.0.2",
113
+ "@commitlint/cli": "^19.8.1",
114
+ "@commitlint/config-conventional": "^19.8.1",
115
+ "@commitlint/types": "^19.8.1",
116
+ "@eslint/js": "^10.0.1",
117
+ "@rollup/plugin-commonjs": "^28.0.6",
118
+ "@rollup/plugin-node-resolve": "^16.0.1",
119
+ "@rollup/plugin-typescript": "^12.1.4",
120
+ "@stylistic/eslint-plugin": "^5.10.0",
121
+ "@types/node": "^24.1.0",
122
+ "eslint": "^10.10.0",
123
+ "eslint-config-flat-gitignore": "^2.4.0",
124
+ "eslint-plugin-import-x": "^4.17.1",
125
+ "eslint-plugin-jsonc": "^3.4.2",
126
+ "eslint-plugin-perfectionist": "^5.11.0",
127
+ "eslint-plugin-react-debug": "^5.19.0",
128
+ "eslint-plugin-react-dom": "^5.19.0",
129
+ "eslint-plugin-react-hooks-extra": "^2.13.0",
130
+ "eslint-plugin-react-naming-convention": "^5.19.0",
131
+ "eslint-plugin-react-web-api": "^5.19.0",
132
+ "eslint-plugin-react-x": "^5.19.0",
133
+ "eslint-plugin-tailwindcss": "^4.4.0",
134
+ "eslint-typegen": "^2.3.1",
135
+ "globals": "^17.12.0",
136
+ "husky": "^9.1.7",
137
+ "jiti": "^2.7.0",
138
+ "jsonc-eslint-parser": "^3.3.0",
139
+ "rimraf": "^6.0.1",
140
+ "rollup": "^4.46.2",
141
+ "rollup-plugin-dts": "^6.2.1",
142
+ "tailwindcss": "^4.3.3",
143
+ "tslib": "^2.8.1",
144
+ "tsx": "^4.20.3",
145
+ "typescript": "^5.8.3",
146
+ "typescript-eslint": "^8.70.0"
147
+ }
148
+ }