@rotki/eslint-plugin 0.7.0 → 1.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 CHANGED
@@ -1,15 +1,45 @@
1
1
  # @rotki/eslint-plugin
2
2
 
3
- rotki's ESLint plugin.
3
+ [![npm version](https://img.shields.io/npm/v/@rotki/eslint-plugin.svg)](https://www.npmjs.com/package/@rotki/eslint-plugin)
4
4
 
5
- Inspired by [intlify/eslint-plugin-vue-i18n](https://github.com/intlify/eslint-plugin-vue-i18n)
6
- and [vuetifyjs/eslint-plugin-vuetify](https://github.com/vuetifyjs/eslint-plugin-vuetify).
5
+ An ESLint plugin for rotki projects that provides custom rules and configurations to maintain consistent code quality.
7
6
 
8
- The plugin was bootstrapped from on `intlify/eslint-plugin-vue-i18n`.
7
+ ## Overview
8
+
9
+ This ESLint plugin is designed specifically for rotki projects, drawing inspiration from established plugins like:
10
+
11
+ - [intlify/eslint-plugin-vue-i18n](https://github.com/intlify/eslint-plugin-vue-i18n)
12
+ - [vuetifyjs/eslint-plugin-vuetify](https://github.com/vuetifyjs/eslint-plugin-vuetify)
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ # Using pnpm (recommended)
18
+ pnpm add -D @rotki/eslint-plugin
19
+
20
+ # Using npm
21
+ npm install --save-dev @rotki/eslint-plugin
22
+
23
+ # Using yarn
24
+ yarn add -D @rotki/eslint-plugin
25
+ ```
9
26
 
10
27
  ## Documentation
11
28
 
12
- See [here](https://rotki.github.io/eslint-plugin)
29
+ For detailed usage instructions, available rules, and configuration options,
30
+ please visit our [documentation](https://rotki.github.io/eslint-plugin).
31
+
32
+ ## Contributing
33
+
34
+ Contributions are welcome!
35
+ Please read our [Contributing Guide](./CONTRIBUTING.md) before submitting a Pull Request.
36
+ The guide includes detailed information about:
37
+
38
+ - Project prerequisites
39
+ - Development setup
40
+ - Commit message conventions
41
+ - Code style and linting
42
+ - Pull request process
13
43
 
14
44
  ## License
15
45
 
package/dist/index.mjs CHANGED
@@ -1,10 +1,10 @@
1
+ import { TSESTree } from '@typescript-eslint/utils';
1
2
  import createDebug from 'debug';
2
- import { extname } from 'node:path';
3
3
  import * as compat from 'eslint-compat-utils';
4
+ import { extname } from 'node:path';
4
5
  import { pascalCase, kebabCase } from 'scule';
5
- import { TSESTree } from '@typescript-eslint/utils';
6
6
 
7
- const version = "0.7.0";
7
+ const version = "1.0.0";
8
8
  const pkg = {
9
9
  version: version};
10
10
 
@@ -15,6 +15,63 @@ function getSourceCode(context) {
15
15
  return compat.getSourceCode(context);
16
16
  }
17
17
 
18
+ function createRecommended(plugin, name, flat) {
19
+ const rules = Object.fromEntries(Object.entries(plugin.rules).filter(([_key, rule]) => rule.meta.recommended === "recommended" && !rule.meta.deprecated).map(([key]) => [`${name}/${key}`, 2]));
20
+ if (flat) {
21
+ return {
22
+ plugins: {
23
+ [name]: plugin
24
+ },
25
+ rules
26
+ };
27
+ } else {
28
+ return {
29
+ plugins: [name],
30
+ rules
31
+ };
32
+ }
33
+ }
34
+
35
+ function getStringLiteralValue(node, stringOnly = false) {
36
+ if (node.type === "Literal") {
37
+ if (node.value == null) {
38
+ if (!stringOnly && node.bigint != null)
39
+ return node.bigint;
40
+ return null;
41
+ }
42
+ if (typeof node.value === "string")
43
+ return node.value;
44
+ if (!stringOnly)
45
+ return String(node.value);
46
+ return null;
47
+ }
48
+ if (node.type === "TemplateLiteral" && node.expressions.length === 0 && node.quasis.length === 1) {
49
+ return node.quasis[0].value.cooked;
50
+ }
51
+ return null;
52
+ }
53
+ function getStaticPropertyName(node) {
54
+ if (node.type === "Property" || node.type === "MethodDefinition") {
55
+ if (!node.computed) {
56
+ const key2 = node.key;
57
+ if (key2.type === "Identifier")
58
+ return key2.name;
59
+ }
60
+ const key = node.key;
61
+ return getStringLiteralValue(key);
62
+ } else if (node.type === "MemberExpression") {
63
+ if (!node.computed) {
64
+ const property2 = node.property;
65
+ if (property2.type === "Identifier")
66
+ return property2.name;
67
+ return null;
68
+ }
69
+ const property = node.property;
70
+ return getStringLiteralValue(property);
71
+ }
72
+ return null;
73
+ }
74
+
18
75
  const blobUrl = "https://rotki.github.io/eslint-plugin/rules/";
19
76
  function RuleCreator(urlCreator) {
20
77
  return function createNamedRule({
@@ -77,65 +134,107 @@ function defineTemplateBodyVisitor(context, templateBodyVisitor, scriptVisitor,
77
134
  );
78
135
  }
79
136
 
80
- function getStringLiteralValue(node, stringOnly = false) {
81
- if (node.type === "Literal") {
82
- if (node.value == null) {
83
- if (!stringOnly && node.bigint != null)
84
- return node.bigint;
85
- return null;
86
- }
87
- if (typeof node.value === "string")
88
- return node.value;
89
- if (!stringOnly)
90
- return String(node.value);
91
- return null;
92
- }
93
- if (node.type === "TemplateLiteral" && node.expressions.length === 0 && node.quasis.length === 1) {
94
- return node.quasis[0].value.cooked;
137
+ const debug$3 = createDebug("@rotki/eslint-plugin:consistent-ref-type-annotation");
138
+ const RULE_NAME$5 = "consistent-ref-type-annotation";
139
+ const FIXABLE_METHODS = ["ref", "computed"];
140
+ function checkAssignmentDeclaration(context, node, declaration, options) {
141
+ const source = getSourceCode(context);
142
+ const { allowInference } = options;
143
+ let declarationTypeArguments;
144
+ const init = declaration.init;
145
+ if (!(init && init.type === TSESTree.AST_NODE_TYPES.CallExpression))
146
+ return;
147
+ const callee = init.callee;
148
+ if (!(callee && callee.type === TSESTree.AST_NODE_TYPES.Identifier))
149
+ return;
150
+ if (!Array.prototype.includes.call(FIXABLE_METHODS, callee.name))
151
+ return;
152
+ const name = callee.name;
153
+ debug$3(`found ${name}, checking type arguments`);
154
+ const initializationTypeArguments = init.typeArguments;
155
+ const typeAnnotation = declaration.id.typeAnnotation;
156
+ if (typeAnnotation) {
157
+ const typeNode = typeAnnotation.typeAnnotation;
158
+ if (typeNode && typeNode.type === TSESTree.AST_NODE_TYPES.TSTypeReference)
159
+ declarationTypeArguments = typeNode.typeArguments;
95
160
  }
96
- return null;
97
- }
98
- function getStaticPropertyName(node) {
99
- if (node.type === "Property" || node.type === "MethodDefinition") {
100
- if (!node.computed) {
101
- const key2 = node.key;
102
- if (key2.type === "Identifier")
103
- return key2.name;
104
- }
105
- const key = node.key;
106
- return getStringLiteralValue(key);
107
- } else if (node.type === "MemberExpression") {
108
- if (!node.computed) {
109
- const property2 = node.property;
110
- if (property2.type === "Identifier")
111
- return property2.name;
112
- return null;
161
+ if (initializationTypeArguments && !declarationTypeArguments)
162
+ return;
163
+ debug$3(`generating report for ${name}`);
164
+ if (!initializationTypeArguments && !declarationTypeArguments) {
165
+ if (allowInference) {
166
+ debug$3("type inference is allowed");
167
+ } else {
168
+ context.report({
169
+ data: {
170
+ name
171
+ },
172
+ messageId: "missingType",
173
+ node
174
+ });
113
175
  }
114
- const property = node.property;
115
- return getStringLiteralValue(property);
176
+ return;
116
177
  }
117
- return null;
178
+ context.report({
179
+ data: {
180
+ name
181
+ },
182
+ fix(fixer) {
183
+ const fixes = [];
184
+ if (!initializationTypeArguments && callee)
185
+ fixes.push(fixer.insertTextAfter(callee, source.getText(declarationTypeArguments)));
186
+ if (typeAnnotation)
187
+ fixes.push(fixer.remove(typeAnnotation));
188
+ return fixes;
189
+ },
190
+ messageId: "inconsistent",
191
+ node
192
+ });
118
193
  }
119
-
120
- function createRecommended(plugin, name, flat) {
121
- const rules = Object.fromEntries(Object.entries(plugin.rules).filter(([_key, rule]) => rule.meta.recommended === "recommended" && !rule.meta.deprecated).map(([key]) => [`${name}/${key}`, 2]));
122
- if (flat) {
123
- return {
124
- plugins: {
125
- [name]: plugin
126
- },
127
- rules
128
- };
129
- } else {
194
+ const consistentRefTypeAnnotation = createEslintRule({
195
+ create(context, optionsWithDefault) {
196
+ const options = optionsWithDefault[0] || {};
197
+ const allowInference = options.allowInference;
130
198
  return {
131
- plugins: [name],
132
- rules
199
+ VariableDeclaration: (node) => {
200
+ const declarations = node.declarations;
201
+ for (const declaration of declarations) {
202
+ if (declaration.type !== TSESTree.AST_NODE_TYPES.VariableDeclarator)
203
+ continue;
204
+ checkAssignmentDeclaration(context, node, declaration, { allowInference });
205
+ }
206
+ }
133
207
  };
134
- }
135
- }
208
+ },
209
+ defaultOptions: [{ allowInference: false }],
210
+ meta: {
211
+ docs: {
212
+ description: "Ensures consistent type annotation position for ref, computed assignments",
213
+ recommendation: "recommended"
214
+ },
215
+ fixable: "code",
216
+ messages: {
217
+ inconsistent: `Generic type annotation for the {{ name }} call was not on the right side`,
218
+ missingType: `variable assignment for {{ name }} is missing the type annotation`
219
+ },
220
+ schema: [
221
+ {
222
+ additionalProperties: false,
223
+ properties: {
224
+ allowInference: {
225
+ type: "boolean"
226
+ }
227
+ },
228
+ type: "object"
229
+ }
230
+ ],
231
+ type: "problem"
232
+ },
233
+ name: RULE_NAME$5
234
+ });
136
235
 
137
- const RULE_NAME$5 = "no-deprecated-classes";
138
- const debug$3 = createDebug("@rotki/eslint-plugin:no-deprecated-classes");
236
+ const RULE_NAME$4 = "no-deprecated-classes";
237
+ const debug$2 = createDebug("@rotki/eslint-plugin:no-deprecated-classes");
139
238
  const replacements$2 = [
140
239
  ["d-block", "block"],
141
240
  ["d-flex", "flex"],
@@ -187,7 +286,7 @@ function findReplacement(className) {
187
286
  return replace(matches);
188
287
  }
189
288
  }
190
- return undefined;
289
+ return void 0;
191
290
  }
192
291
  function getRange(node) {
193
292
  if (node.type === "VAttribute" && node.value && node.value.range)
@@ -195,7 +294,7 @@ function getRange(node) {
195
294
  return node.range;
196
295
  }
197
296
  function reportReplacement(className, replacement, node, context, position = 1) {
198
- debug$3(`found replacement ${replacement} for ${className}`);
297
+ debug$2(`found replacement ${replacement} for ${className}`);
199
298
  const source = getSourceCode(context);
200
299
  const initialRange = getRange(node);
201
300
  const range = [
@@ -308,11 +407,11 @@ const noDeprecatedClasses = createEslintRule({
308
407
  schema: [],
309
408
  type: "problem"
310
409
  },
311
- name: RULE_NAME$5
410
+ name: RULE_NAME$4
312
411
  });
313
412
 
314
- const debug$2 = createDebug("@rotki/eslint-plugin:no-deprecated-components");
315
- const RULE_NAME$4 = "no-deprecated-components";
413
+ const debug$1 = createDebug("@rotki/eslint-plugin:no-deprecated-components");
414
+ const RULE_NAME$3 = "no-deprecated-components";
316
415
  const vuetify = {
317
416
  VApp: true,
318
417
  VAppBar: true,
@@ -365,7 +464,7 @@ const noDeprecatedComponents = createEslintRule({
365
464
  return;
366
465
  const replacement = replacements$1[tag];
367
466
  if (replacement || legacy && skipInLegacy.includes(tag)) {
368
- debug$2(`${tag} has been deprecated`);
467
+ debug$1(`${tag} has been deprecated`);
369
468
  context.report({
370
469
  data: {
371
470
  name: tag
@@ -374,7 +473,7 @@ const noDeprecatedComponents = createEslintRule({
374
473
  node: element
375
474
  });
376
475
  } else {
377
- debug$2(`${tag} has will be removed`);
476
+ debug$1(`${tag} has will be removed`);
378
477
  context.report({
379
478
  data: {
380
479
  name: tag
@@ -417,11 +516,11 @@ const noDeprecatedComponents = createEslintRule({
417
516
  ],
418
517
  type: "problem"
419
518
  },
420
- name: RULE_NAME$4
519
+ name: RULE_NAME$3
421
520
  });
422
521
 
423
- const debug$1 = createDebug("@rotki/eslint-plugin:no-deprecated-props");
424
- const RULE_NAME$3 = "no-deprecated-props";
522
+ const debug = createDebug("@rotki/eslint-plugin:no-deprecated-props");
523
+ const RULE_NAME$2 = "no-deprecated-props";
425
524
  const replacements = {
426
525
  RuiRadio: {
427
526
  internalValue: "value"
@@ -433,7 +532,7 @@ function hasReplacement(tag) {
433
532
  function getPropName(node) {
434
533
  if (node.directive) {
435
534
  if (node.key.argument?.type !== "VIdentifier")
436
- return undefined;
535
+ return void 0;
437
536
  return kebabCase(node.key.argument.rawName);
438
537
  }
439
538
  return kebabCase(node.key.rawName);
@@ -447,16 +546,16 @@ const noDeprecatedProps = createEslintRule({
447
546
  const tag = pascalCase(node.parent.parent.rawName);
448
547
  if (!hasReplacement(tag))
449
548
  return;
450
- debug$1(`${tag} has replacement properties`);
549
+ debug(`${tag} has replacement properties`);
451
550
  const propName = getPropName(node);
452
551
  const propNameNode = node.directive ? node.key.argument : node.key;
453
552
  if (!propName || !propNameNode) {
454
- debug$1("could not get prop name and/or node");
553
+ debug("could not get prop name and/or node");
455
554
  return;
456
555
  }
457
556
  Object.entries(replacements[tag]).forEach(([prop, replacement]) => {
458
557
  if (kebabCase(prop) === propName) {
459
- debug$1(`preparing a replacement for ${tag}:${propName} -> ${replacement}`);
558
+ debug(`preparing a replacement for ${tag}:${propName} -> ${replacement}`);
460
559
  context.report({
461
560
  data: {
462
561
  prop,
@@ -486,24 +585,27 @@ const noDeprecatedProps = createEslintRule({
486
585
  schema: [],
487
586
  type: "problem"
488
587
  },
489
- name: RULE_NAME$3
588
+ name: RULE_NAME$2
490
589
  });
491
590
 
492
- const RULE_NAME$2 = "no-legacy-library-import";
493
- const legacyLibrary = "@rotki/ui-library-compat";
494
- const newLibrary = "@rotki/ui-library";
495
- const noLegacyLibraryImport = createEslintRule({
591
+ const RULE_NAME$1 = "no-dot-ts-imports";
592
+ const noDotTsImport = createEslintRule({
496
593
  create(context) {
497
594
  return {
498
595
  ImportDeclaration(node) {
499
- if (!node.source.value.startsWith(legacyLibrary))
596
+ const importDeclaration = node.source.value;
597
+ if (!importDeclaration.endsWith(".ts"))
500
598
  return;
501
- const replacement = node.source.value.replace(legacyLibrary, newLibrary);
599
+ const lastIndexOfExtension = importDeclaration.lastIndexOf(".ts");
600
+ const replacement = importDeclaration.substring(0, lastIndexOfExtension);
502
601
  context.report({
602
+ data: {
603
+ import: importDeclaration
604
+ },
503
605
  fix(fixer) {
504
606
  return fixer.replaceText(node.source, `'${replacement}'`);
505
607
  },
506
- messageId: "replacedWith",
608
+ messageId: "invalidTSExtension",
507
609
  node: node.source
508
610
  });
509
611
  }
@@ -512,136 +614,34 @@ const noLegacyLibraryImport = createEslintRule({
512
614
  defaultOptions: [],
513
615
  meta: {
514
616
  docs: {
515
- description: `Reports and replaces imports of ${legacyLibrary} with ${newLibrary}`,
617
+ description: "Checks and replaces .ts extension in import statements.",
516
618
  recommendation: "recommended"
517
619
  },
518
620
  fixable: "code",
519
621
  messages: {
520
- replacedWith: `${legacyLibrary} has been replaced by ${newLibrary}`
622
+ invalidTSExtension: `'{{ import }}' has a .ts extension, please remove it'`
521
623
  },
522
624
  schema: [],
523
625
  type: "problem"
524
626
  },
525
- name: RULE_NAME$2
526
- });
527
-
528
- const debug = createDebug("@rotki/eslint-plugin:consistent-ref-type-annotation");
529
- const RULE_NAME$1 = "consistent-ref-type-annotation";
530
- const FIXABLE_METHODS = ["ref", "computed"];
531
- function checkAssignmentDeclaration(context, node, declaration, options) {
532
- const source = getSourceCode(context);
533
- const { allowInference } = options;
534
- let declarationTypeArguments;
535
- const init = declaration.init;
536
- if (!(init && init.type === TSESTree.AST_NODE_TYPES.CallExpression))
537
- return;
538
- const callee = init.callee;
539
- if (!(callee && callee.type === TSESTree.AST_NODE_TYPES.Identifier))
540
- return;
541
- if (!Array.prototype.includes.call(FIXABLE_METHODS, callee.name))
542
- return;
543
- const name = callee.name;
544
- debug(`found ${name}, checking type arguments`);
545
- const initializationTypeArguments = init.typeArguments;
546
- const typeAnnotation = declaration.id.typeAnnotation;
547
- if (typeAnnotation) {
548
- const typeNode = typeAnnotation.typeAnnotation;
549
- if (typeNode && typeNode.type === TSESTree.AST_NODE_TYPES.TSTypeReference)
550
- declarationTypeArguments = typeNode.typeArguments;
551
- }
552
- if (initializationTypeArguments && !declarationTypeArguments)
553
- return;
554
- debug(`generating report for ${name}`);
555
- if (!initializationTypeArguments && !declarationTypeArguments) {
556
- if (allowInference) {
557
- debug("type inference is allowed");
558
- } else {
559
- context.report({
560
- data: {
561
- name
562
- },
563
- messageId: "missingType",
564
- node
565
- });
566
- }
567
- return;
568
- }
569
- context.report({
570
- data: {
571
- name
572
- },
573
- fix(fixer) {
574
- const fixes = [];
575
- if (!initializationTypeArguments && callee)
576
- fixes.push(fixer.insertTextAfter(callee, source.getText(declarationTypeArguments)));
577
- if (typeAnnotation)
578
- fixes.push(fixer.remove(typeAnnotation));
579
- return fixes;
580
- },
581
- messageId: "inconsistent",
582
- node
583
- });
584
- }
585
- const consistentRefTypeAnnotation = createEslintRule({
586
- create(context, optionsWithDefault) {
587
- const options = optionsWithDefault[0] || {};
588
- const allowInference = options.allowInference;
589
- return {
590
- VariableDeclaration: (node) => {
591
- const declarations = node.declarations;
592
- for (const declaration of declarations) {
593
- if (declaration.type !== TSESTree.AST_NODE_TYPES.VariableDeclarator)
594
- continue;
595
- checkAssignmentDeclaration(context, node, declaration, { allowInference });
596
- }
597
- }
598
- };
599
- },
600
- defaultOptions: [{ allowInference: false }],
601
- meta: {
602
- docs: {
603
- description: "Ensures consistent type annotation position for ref, computed assignments",
604
- recommendation: "recommended"
605
- },
606
- fixable: "code",
607
- messages: {
608
- inconsistent: `Generic type annotation for the {{ name }} call was not on the right side`,
609
- missingType: `variable assignment for {{ name }} is missing the type annotation`
610
- },
611
- schema: [
612
- {
613
- additionalProperties: false,
614
- properties: {
615
- allowInference: {
616
- type: "boolean"
617
- }
618
- },
619
- type: "object"
620
- }
621
- ],
622
- type: "problem"
623
- },
624
627
  name: RULE_NAME$1
625
628
  });
626
629
 
627
- const RULE_NAME = "no-dot-ts-imports";
628
- const noDotTsImport = createEslintRule({
630
+ const RULE_NAME = "no-legacy-library-import";
631
+ const legacyLibrary = "@rotki/ui-library-compat";
632
+ const newLibrary = "@rotki/ui-library";
633
+ const noLegacyLibraryImport = createEslintRule({
629
634
  create(context) {
630
635
  return {
631
636
  ImportDeclaration(node) {
632
- const importDeclaration = node.source.value;
633
- if (!importDeclaration.endsWith(".ts"))
637
+ if (!node.source.value.startsWith(legacyLibrary))
634
638
  return;
635
- const lastIndexOfExtension = importDeclaration.lastIndexOf(".ts");
636
- const replacement = importDeclaration.substring(0, lastIndexOfExtension);
639
+ const replacement = node.source.value.replace(legacyLibrary, newLibrary);
637
640
  context.report({
638
- data: {
639
- import: importDeclaration
640
- },
641
641
  fix(fixer) {
642
642
  return fixer.replaceText(node.source, `'${replacement}'`);
643
643
  },
644
- messageId: "invalidTSExtension",
644
+ messageId: "replacedWith",
645
645
  node: node.source
646
646
  });
647
647
  }
@@ -650,12 +650,12 @@ const noDotTsImport = createEslintRule({
650
650
  defaultOptions: [],
651
651
  meta: {
652
652
  docs: {
653
- description: "Checks and replaces .ts extension in import statements.",
653
+ description: `Reports and replaces imports of ${legacyLibrary} with ${newLibrary}`,
654
654
  recommendation: "recommended"
655
655
  },
656
656
  fixable: "code",
657
657
  messages: {
658
- invalidTSExtension: `'{{ import }}' has a .ts extension, please remove it'`
658
+ replacedWith: `${legacyLibrary} has been replaced by ${newLibrary}`
659
659
  },
660
660
  schema: [],
661
661
  type: "problem"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rotki/eslint-plugin",
3
- "version": "0.7.0",
3
+ "version": "1.0.0",
4
4
  "type": "module",
5
5
  "license": "AGPL-3.0",
6
6
  "bugs": {
@@ -20,7 +20,6 @@
20
20
  "exports": {
21
21
  ".": {
22
22
  "types": "./dist/index.d.ts",
23
- "require": "./dist/index.cjs",
24
23
  "import": "./dist/index.mjs"
25
24
  }
26
25
  },
@@ -29,39 +28,39 @@
29
28
  "eslint": "^9.0.0"
30
29
  },
31
30
  "dependencies": {
32
- "@typescript-eslint/utils": "8.23.0",
31
+ "@typescript-eslint/utils": "8.26.0",
33
32
  "debug": "4.4.0",
34
33
  "eslint-compat-utils": "0.6.4",
35
34
  "jsonc-eslint-parser": "2.4.0",
36
35
  "scule": "1.3.0",
37
- "vue-eslint-parser": "9.4.3",
38
- "yaml-eslint-parser": "1.2.3"
36
+ "vue-eslint-parser": "10.1.1",
37
+ "yaml-eslint-parser": "1.3.0"
39
38
  },
40
39
  "devDependencies": {
41
40
  "@commitlint/cli": "19.7.1",
42
41
  "@commitlint/config-conventional": "19.7.1",
43
- "@rotki/eslint-config": "3.7.0",
42
+ "@rotki/eslint-config": "4.0.1",
44
43
  "@types/debug": "4.1.12",
45
44
  "@types/node": "20",
46
- "@typescript-eslint/eslint-plugin": "8.23.0",
47
- "@typescript-eslint/parser": "8.23.0",
48
- "@typescript-eslint/rule-tester": "8.23.0",
49
- "@vitest/coverage-v8": "3.0.5",
50
- "bumpp": "10.0.1",
45
+ "@typescript-eslint/eslint-plugin": "8.26.0",
46
+ "@typescript-eslint/parser": "8.26.0",
47
+ "@typescript-eslint/rule-tester": "8.26.0",
48
+ "@vitest/coverage-v8": "3.0.8",
49
+ "bumpp": "10.0.3",
51
50
  "debug": "4.4.0",
52
- "eslint": "9.19.0",
51
+ "eslint": "9.21.0",
53
52
  "husky": "9.1.7",
54
53
  "lint-staged": "15.4.3",
55
54
  "rimraf": "6.0.1",
56
- "ts-node": "10.9.2",
57
- "typescript": "5.7.3",
58
- "unbuild": "3.3.1",
55
+ "tsx": "4.19.3",
56
+ "typescript": "5.8.2",
57
+ "unbuild": "3.5.0",
59
58
  "vitepress": "1.6.3",
60
- "vitest": "3.0.5"
59
+ "vitest": "3.0.8"
61
60
  },
62
61
  "engines": {
63
62
  "node": ">=20",
64
- "pnpm": ">=9 <10"
63
+ "pnpm": ">=10 <11"
65
64
  },
66
65
  "lint-staged": {
67
66
  "*.{js,cjs,ts,vue,yml,json,md}": "eslint"
@@ -69,15 +68,15 @@
69
68
  "scripts": {
70
69
  "clean": "rimraf .nyc_output coverage dist docs/.vitepress/dist",
71
70
  "coverage": "nyc report --reporter lcov && opener coverage/lcov-report/index.html",
72
- "generate": "node --experimental-specifier-resolution=node --loader ts-node/esm scripts/update-rule-docs.ts",
73
- "generate:index": "node --experimental-specifier-resolution=node --loader ts-node/esm scripts/update-docs-index.ts",
71
+ "generate": "tsx scripts/update-rule-docs.ts",
72
+ "generate:index": "tsx scripts/update-docs-index.ts",
74
73
  "lint": "eslint .",
75
74
  "lint:fix": "eslint . --fix",
76
75
  "build": "unbuild",
77
76
  "dev": "unbuild --stub",
78
77
  "test": "vitest",
79
78
  "test:coverage": "vitest run --coverage",
80
- "new": "node --experimental-specifier-resolution=node --loader ts-node/esm ./scripts/new-rule.ts",
79
+ "new": "tsx ./scripts/new-rule.ts",
81
80
  "docs": "vitepress dev docs",
82
81
  "docs:build": "pnpm run generate && pnpm run generate:index && vitepress build docs",
83
82
  "typecheck": "tsc --noEmit",