ignore-lint-errors 1.0.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -46,6 +46,9 @@ You must pass `--linter` to indicate which linter to run.
46
46
  # Run eslint
47
47
  pnpx ignore-lint-errors --linter eslint
48
48
 
49
+ # Run oxlint
50
+ pnpx ignore-lint-errors --linter oxlint
51
+
49
52
  # Run stylelint
50
53
  pnpx ignore-lint-errors --linter stylelint
51
54
 
@@ -82,6 +85,17 @@ pnpx ignore-lint-errors --linter eslint --src app tests
82
85
  pnpx ignore-lint-errors --linter eslint --src app/{components,templates}/**/*.gts
83
86
  ```
84
87
 
88
+ ```sh
89
+ # oxlint supports files
90
+ pnpx ignore-lint-errors --linter oxlint --src app/components/example-1.gts app/templates/example-2.gts
91
+
92
+ # oxlint supports directories
93
+ pnpx ignore-lint-errors --linter oxlint --src app tests
94
+
95
+ # oxlint supports globs
96
+ pnpx ignore-lint-errors --linter oxlint --src app/{components,templates}/**/*.gts
97
+ ```
98
+
85
99
  ```sh
86
100
  # stylelint supports files
87
101
  pnpx ignore-lint-errors --linter stylelint --src app/components/example-1.module.css app/templates/example-2.module.css
@@ -113,7 +127,7 @@ pnpm build
113
127
  ## Compatibility
114
128
 
115
129
  - Node.js v22 or above
116
- - Tested against `eslint@v9`, `glint@v2`, `stylelint@v17`, `typescript@v5`
130
+ - Tested against `eslint@v9`, `glint@v2`, `oxlint@v1`, `stylelint@v17`, `typescript@v5`
117
131
 
118
132
 
119
133
  ## Contributing
@@ -8,7 +8,7 @@ process.title = 'ignore-lint-errors';
8
8
  // Set codemod options
9
9
  const argv = yargs(hideBin(process.argv))
10
10
  .option('linter', {
11
- choices: ['eslint', 'stylelint', 'typescript'],
11
+ choices: ['eslint', 'oxlint', 'stylelint', 'typescript'],
12
12
  describe: 'Linter to run',
13
13
  type: 'string',
14
14
  })
@@ -8,6 +8,7 @@ function findDependencies(projectRoot) {
8
8
  return {
9
9
  eslint: projectDependencies.has('eslint'),
10
10
  glint: projectDependencies.has('@glint/ember-tsc'),
11
+ oxlint: projectDependencies.has('oxlint'),
11
12
  stylelint: projectDependencies.has('stylelint'),
12
13
  typescript: projectDependencies.has('typescript'),
13
14
  };
@@ -4,7 +4,10 @@ import { removeFiles } from '@codemod-utils/files';
4
4
  import { ignoreErrors } from '../../utils/ignore-errors/eslint.js';
5
5
  import { outputFilePath, parseOutputFile } from '../../utils/linters/eslint.js';
6
6
  export function ignoreErrorsFromEslint(options) {
7
- const { projectRoot } = options;
7
+ const { dependencies, projectRoot } = options;
8
+ if (!dependencies.eslint) {
9
+ return;
10
+ }
8
11
  const outputFile = readFileSync(join(projectRoot, outputFilePath), 'utf8');
9
12
  const filesWithErrors = parseOutputFile(outputFile, projectRoot);
10
13
  filesWithErrors.forEach(({ filePath, lintErrors }) => {
@@ -1,3 +1,4 @@
1
1
  export * from './eslint.js';
2
+ export * from './oxlint.js';
2
3
  export * from './stylelint.js';
3
4
  export * from './typescript.js';
@@ -0,0 +1,19 @@
1
+ import { readFileSync, writeFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { removeFiles } from '@codemod-utils/files';
4
+ import { ignoreErrors } from '../../utils/ignore-errors/oxlint.js';
5
+ import { outputFilePath, parseOutputFile } from '../../utils/linters/oxlint.js';
6
+ export function ignoreErrorsFromOxlint(options) {
7
+ const { dependencies, projectRoot } = options;
8
+ if (!dependencies.oxlint) {
9
+ return;
10
+ }
11
+ const outputFile = readFileSync(join(projectRoot, outputFilePath), 'utf8');
12
+ const filesWithErrors = parseOutputFile(outputFile);
13
+ filesWithErrors.forEach(({ filePath, lintErrors }) => {
14
+ const file = readFileSync(join(projectRoot, filePath), 'utf8');
15
+ const newFile = ignoreErrors(file, lintErrors);
16
+ writeFileSync(join(projectRoot, filePath), newFile, 'utf8');
17
+ });
18
+ removeFiles([outputFilePath], { projectRoot });
19
+ }
@@ -4,7 +4,10 @@ import { removeFiles } from '@codemod-utils/files';
4
4
  import { ignoreErrors } from '../../utils/ignore-errors/stylelint.js';
5
5
  import { outputFilePath, parseOutputFile, } from '../../utils/linters/stylelint.js';
6
6
  export function ignoreErrorsFromStylelint(options) {
7
- const { projectRoot } = options;
7
+ const { dependencies, projectRoot } = options;
8
+ if (!dependencies.stylelint) {
9
+ return;
10
+ }
8
11
  const outputFile = readFileSync(join(projectRoot, outputFilePath), 'utf8');
9
12
  const filesWithErrors = parseOutputFile(outputFile, projectRoot);
10
13
  filesWithErrors.forEach(({ filePath, lintErrors }) => {
@@ -1,16 +1,20 @@
1
1
  import { readFileSync, writeFileSync } from 'node:fs';
2
2
  import { join } from 'node:path';
3
3
  import { removeFiles } from '@codemod-utils/files';
4
- import { ignoreErrors, ignoreErrorsFallback, isParseable, } from '../../utils/ignore-errors/typescript.js';
4
+ import { areTemplateTagsValid } from '../../utils/ignore-errors/shared/index.js';
5
+ import { ignoreErrors, ignoreErrorsFallback, } from '../../utils/ignore-errors/typescript.js';
5
6
  import { outputFilePath, parseOutputFile, } from '../../utils/linters/typescript.js';
6
7
  export function ignoreErrorsFromTypescript(options) {
7
- const { projectRoot } = options;
8
+ const { dependencies, projectRoot } = options;
9
+ if (!dependencies.typescript) {
10
+ return;
11
+ }
8
12
  const outputFile = readFileSync(join(projectRoot, outputFilePath), 'utf8');
9
13
  const filesWithErrors = parseOutputFile(outputFile);
10
14
  filesWithErrors.forEach(({ filePath, lintErrors }) => {
11
15
  const file = readFileSync(join(projectRoot, filePath), 'utf8');
12
16
  let newFile = ignoreErrors(file, lintErrors);
13
- if (!isParseable(newFile)) {
17
+ if (!areTemplateTagsValid(newFile)) {
14
18
  newFile = ignoreErrorsFallback(file, lintErrors);
15
19
  }
16
20
  writeFileSync(join(projectRoot, filePath), newFile, 'utf8');
@@ -1,23 +1,21 @@
1
- import { ignoreErrorsFromEslint, ignoreErrorsFromStylelint, ignoreErrorsFromTypescript, } from './ignore-errors/index.js';
1
+ import { ignoreErrorsFromEslint, ignoreErrorsFromOxlint, ignoreErrorsFromStylelint, ignoreErrorsFromTypescript, } from './ignore-errors/index.js';
2
2
  export function ignoreErrors(options) {
3
- const { dependencies, linter } = options;
3
+ const { linter } = options;
4
4
  switch (linter) {
5
5
  case 'eslint': {
6
- if (dependencies.eslint) {
7
- ignoreErrorsFromEslint(options);
8
- }
6
+ ignoreErrorsFromEslint(options);
7
+ break;
8
+ }
9
+ case 'oxlint': {
10
+ ignoreErrorsFromOxlint(options);
9
11
  break;
10
12
  }
11
13
  case 'stylelint': {
12
- if (dependencies.stylelint) {
13
- ignoreErrorsFromStylelint(options);
14
- }
14
+ ignoreErrorsFromStylelint(options);
15
15
  break;
16
16
  }
17
17
  case 'typescript': {
18
- if (dependencies.typescript) {
19
- ignoreErrorsFromTypescript(options);
20
- }
18
+ ignoreErrorsFromTypescript(options);
21
19
  break;
22
20
  }
23
21
  }
@@ -27,9 +27,12 @@ function getSrc(options) {
27
27
  }
28
28
  return src.map((token) => `"${token}"`).join(' ');
29
29
  }
30
- export function runEslint(options) {
31
- const { projectRoot } = options;
32
- const command = [
30
+ export function getCommandEslint(options) {
31
+ const { dependencies } = options;
32
+ if (!dependencies.eslint) {
33
+ return undefined;
34
+ }
35
+ return [
33
36
  './node_modules/.bin/eslint',
34
37
  getSrc(options),
35
38
  getConcurrencyOption(options),
@@ -37,10 +40,4 @@ export function runEslint(options) {
37
40
  `--output-file ${outputFilePath}`,
38
41
  '--quiet',
39
42
  ].join(' ');
40
- try {
41
- execSync(command, { cwd: projectRoot });
42
- }
43
- catch {
44
- // Do nothing
45
- }
46
43
  }
@@ -1,3 +1,4 @@
1
1
  export * from './eslint.js';
2
+ export * from './oxlint.js';
2
3
  export * from './stylelint.js';
3
4
  export * from './typescript.js';
@@ -0,0 +1,21 @@
1
+ import { outputFilePath } from '../../utils/linters/oxlint.js';
2
+ function getSrc(options) {
3
+ const { src } = options;
4
+ if (src === undefined) {
5
+ return '';
6
+ }
7
+ return src.map((token) => `"${token}"`).join(' ');
8
+ }
9
+ export function getCommandOxlint(options) {
10
+ const { dependencies } = options;
11
+ if (!dependencies.oxlint) {
12
+ return undefined;
13
+ }
14
+ return [
15
+ './node_modules/.bin/oxlint',
16
+ getSrc(options),
17
+ '--format json',
18
+ '--quiet',
19
+ `> ${outputFilePath}`,
20
+ ].join(' ');
21
+ }
@@ -1,4 +1,3 @@
1
- import { execSync } from 'node:child_process';
2
1
  import { outputFilePath } from '../../utils/linters/stylelint.js';
3
2
  function getSrc(options) {
4
3
  const { src } = options;
@@ -7,9 +6,12 @@ function getSrc(options) {
7
6
  }
8
7
  return src.map((token) => `"${token}"`).join(' ');
9
8
  }
10
- export function runStylelint(options) {
11
- const { projectRoot } = options;
12
- const command = [
9
+ export function getCommandStylelint(options) {
10
+ const { dependencies } = options;
11
+ if (!dependencies.stylelint) {
12
+ return undefined;
13
+ }
14
+ return [
13
15
  './node_modules/.bin/stylelint',
14
16
  getSrc(options),
15
17
  '--formatter json',
@@ -17,10 +19,4 @@ export function runStylelint(options) {
17
19
  '--quiet',
18
20
  '2>/dev/null', // Suppress output to process.stderr
19
21
  ].join(' ');
20
- try {
21
- execSync(command, { cwd: projectRoot });
22
- }
23
- catch {
24
- // Do nothing
25
- }
26
22
  }
@@ -1,14 +1,11 @@
1
- import { execSync } from 'node:child_process';
2
1
  import { outputFilePath } from '../../utils/linters/typescript.js';
3
- export function runTypescript(options) {
4
- const { dependencies, projectRoot } = options;
5
- const command = dependencies.glint
6
- ? `./node_modules/.bin/ember-tsc > ${outputFilePath}`
7
- : `./node_modules/.bin/tsc > ${outputFilePath}`;
8
- try {
9
- execSync(command, { cwd: projectRoot });
2
+ export function getCommandTypescript(options) {
3
+ const { dependencies } = options;
4
+ if (!dependencies.typescript) {
5
+ return undefined;
10
6
  }
11
- catch {
12
- // Do nothing
7
+ if (dependencies.glint) {
8
+ return `./node_modules/.bin/ember-tsc > ${outputFilePath}`;
13
9
  }
10
+ return `./node_modules/.bin/tsc > ${outputFilePath}`;
14
11
  }
@@ -1,29 +1,38 @@
1
+ import { execSync } from 'node:child_process';
1
2
  import { existsSync, mkdirSync } from 'node:fs';
2
3
  import { join } from 'node:path';
3
- import { runEslint, runStylelint, runTypescript } from './lint-files/index.js';
4
+ import { getCommandEslint, getCommandOxlint, getCommandStylelint, getCommandTypescript, } from './lint-files/index.js';
4
5
  export function lintFiles(options) {
5
- const { dependencies, linter, projectRoot } = options;
6
+ const { linter, projectRoot } = options;
6
7
  if (!existsSync(join(projectRoot, '.ignore-lint-errors'))) {
7
8
  mkdirSync(join(projectRoot, '.ignore-lint-errors'));
8
9
  }
10
+ let command;
9
11
  switch (linter) {
10
12
  case 'eslint': {
11
- if (dependencies.eslint) {
12
- runEslint(options);
13
- }
13
+ command = getCommandEslint(options);
14
+ break;
15
+ }
16
+ case 'oxlint': {
17
+ command = getCommandOxlint(options);
14
18
  break;
15
19
  }
16
20
  case 'stylelint': {
17
- if (dependencies.stylelint) {
18
- runStylelint(options);
19
- }
21
+ command = getCommandStylelint(options);
20
22
  break;
21
23
  }
22
24
  case 'typescript': {
23
- if (dependencies.typescript) {
24
- runTypescript(options);
25
- }
25
+ command = getCommandTypescript(options);
26
26
  break;
27
27
  }
28
28
  }
29
+ if (command === undefined) {
30
+ return;
31
+ }
32
+ try {
33
+ execSync(command, { cwd: projectRoot });
34
+ }
35
+ catch {
36
+ // Do nothing
37
+ }
29
38
  }
@@ -0,0 +1,23 @@
1
+ import { EOL } from 'node:os';
2
+ import { getIgnoredRules } from './shared/index.js';
3
+ export function ignoreErrors(file, lintErrors) {
4
+ const lines = file.split(EOL);
5
+ const ignoreDirective = 'oxlint-disable-next-line';
6
+ lintErrors.forEach(({ line, message }) => {
7
+ const currentIndex = line - 1;
8
+ const previousIndex = Math.max(currentIndex - 1, 0);
9
+ const ignoredRules = getIgnoredRules(lines[previousIndex], {
10
+ ignoreDirective,
11
+ });
12
+ if (ignoredRules.length === 0) {
13
+ lines.splice(currentIndex, 0, `// ${ignoreDirective} ${message}`);
14
+ }
15
+ else {
16
+ const newMessage = [...ignoredRules, ...message.split(', ')]
17
+ .sort()
18
+ .join(', ');
19
+ lines.splice(previousIndex, 1, `// ${ignoreDirective} ${newMessage}`);
20
+ }
21
+ });
22
+ return lines.join(EOL);
23
+ }
@@ -1,8 +1,43 @@
1
- import { AST } from '@codemod-utils/ast-javascript';
1
+ import { AST as ASTJavaScript } from '@codemod-utils/ast-javascript';
2
+ import { AST as ASTTemplate } from '@codemod-utils/ast-template';
3
+ import { findTemplateTags as upstreamFindTemplateTags } from '@codemod-utils/ast-template-tag';
4
+ export function areTemplateTagsValid(file) {
5
+ let isValid = true;
6
+ try {
7
+ const templateTags = upstreamFindTemplateTags(file);
8
+ templateTags.forEach(({ contents }) => {
9
+ ASTTemplate.traverse(contents);
10
+ });
11
+ }
12
+ catch {
13
+ isValid = false;
14
+ }
15
+ return isValid;
16
+ }
17
+ export function findTemplateTags(file) {
18
+ function getLOC(file) {
19
+ const matches = file.match(/\r?\n/g);
20
+ return (matches ?? []).length;
21
+ }
22
+ const templateTags = upstreamFindTemplateTags(file);
23
+ return templateTags.map((templateTag) => {
24
+ const { contents, range } = templateTag;
25
+ const lineStart = getLOC(file.substring(0, range.startChar)) + 1;
26
+ const lineEnd = getLOC(file.substring(0, range.endChar)) + 1;
27
+ const lineRange = {
28
+ end: lineEnd,
29
+ start: lineStart,
30
+ };
31
+ return {
32
+ contents,
33
+ lineRange,
34
+ };
35
+ });
36
+ }
2
37
  export function getIgnoredRules(lineOfCode, options) {
3
38
  let ignoredRules = [];
4
39
  try {
5
- AST.traverse(lineOfCode, {
40
+ ASTJavaScript.traverse(lineOfCode, {
6
41
  visitComment(path) {
7
42
  // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
8
43
  const comment = path.value.value.trim();
@@ -1,27 +1,6 @@
1
1
  import { EOL } from 'node:os';
2
- import { AST } from '@codemod-utils/ast-template';
3
- import { findTemplateTags as upstreamFindTemplateTags, updateTemplates, } from '@codemod-utils/ast-template-tag';
4
- import { getIgnoredRules } from './shared/index.js';
5
- function findTemplateTags(file) {
6
- function getLOC(file) {
7
- const matches = file.match(/\r?\n/g);
8
- return (matches ?? []).length;
9
- }
10
- const templateTags = upstreamFindTemplateTags(file);
11
- return templateTags.map((templateTag) => {
12
- const { contents, range } = templateTag;
13
- const lineStart = getLOC(file.substring(0, range.startChar)) + 1;
14
- const lineEnd = getLOC(file.substring(0, range.endChar)) + 1;
15
- const lineRange = {
16
- end: lineEnd,
17
- start: lineStart,
18
- };
19
- return {
20
- contents,
21
- lineRange,
22
- };
23
- });
24
- }
2
+ import { updateTemplates } from '@codemod-utils/ast-template-tag';
3
+ import { findTemplateTags, getIgnoredRules } from './shared/index.js';
25
4
  export function ignoreErrors(file, lintErrors) {
26
5
  const lines = file.split(EOL);
27
6
  const templateTags = findTemplateTags(file);
@@ -33,25 +12,26 @@ export function ignoreErrors(file, lintErrors) {
33
12
  });
34
13
  const erroredInTemplate = templateTagIndex >= 0;
35
14
  if (erroredInTemplate) {
36
- const ignoreDirective = `{{! @glint-expect-error: ${message} }}`;
15
+ const comment = `{{! @glint-expect-error: ${message} }}`;
37
16
  const { contents, lineRange } = templateTags[templateTagIndex];
38
- if (lineRange.start !== lineRange.end) {
39
- lines.splice(currentIndex, 0, ignoreDirective);
40
- return;
17
+ if (lineRange.start === lineRange.end) {
18
+ const newTemplate = lines[currentIndex].replace(/<template>(.+)<\/template>/, [`<template>${comment}`, `${contents}</template>`].join(EOL));
19
+ lines.splice(currentIndex, 1, newTemplate);
20
+ }
21
+ else {
22
+ lines.splice(currentIndex, 0, comment);
41
23
  }
42
- const newTemplate = lines[currentIndex].replace(/<template>(.+)<\/template>/, [`<template>${ignoreDirective}`, `${contents}</template>`].join(EOL));
43
- lines.splice(currentIndex, 1, newTemplate);
44
24
  return;
45
25
  }
46
- const ignoreDirective = `// @ts-expect-error: ${message}`;
26
+ const comment = `// @ts-expect-error: ${message}`;
47
27
  const ignoredRules = getIgnoredRules(lines[previousIndex], {
48
28
  ignoreDirective: 'eslint-disable-next-line',
49
29
  });
50
30
  if (ignoredRules.length === 0) {
51
- lines.splice(currentIndex, 0, ignoreDirective);
31
+ lines.splice(currentIndex, 0, comment);
52
32
  }
53
33
  else {
54
- lines.splice(previousIndex, 0, ignoreDirective);
34
+ lines.splice(previousIndex, 0, comment);
55
35
  }
56
36
  });
57
37
  return lines.join(EOL);
@@ -71,36 +51,23 @@ export function ignoreErrorsFallback(file, lintErrors) {
71
51
  hasErrorInTemplate = true;
72
52
  return;
73
53
  }
74
- const ignoreDirective = `// @ts-expect-error: ${message}`;
54
+ const comment = `// @ts-expect-error: ${message}`;
75
55
  const ignoredRules = getIgnoredRules(lines[previousIndex], {
76
56
  ignoreDirective: 'eslint-disable-next-line',
77
57
  });
78
58
  if (ignoredRules.length === 0) {
79
- lines.splice(currentIndex, 0, ignoreDirective);
59
+ lines.splice(currentIndex, 0, comment);
80
60
  }
81
61
  else {
82
- lines.splice(previousIndex, 0, ignoreDirective);
62
+ lines.splice(previousIndex, 0, comment);
83
63
  }
84
64
  });
85
65
  let newFile = lines.join(EOL);
86
66
  if (hasErrorInTemplate) {
87
67
  newFile = updateTemplates(newFile, (code) => {
88
- const ignoreDirective = '{{! @glint-nocheck }}';
89
- return [ignoreDirective, code].join('');
68
+ const comment = '{{! @glint-nocheck }}';
69
+ return [comment, code].join('');
90
70
  });
91
71
  }
92
72
  return newFile;
93
73
  }
94
- export function isParseable(file) {
95
- let isParseable = true;
96
- try {
97
- const templateTags = findTemplateTags(file);
98
- templateTags.forEach(({ contents }) => {
99
- AST.traverse(contents);
100
- });
101
- }
102
- catch {
103
- isParseable = false;
104
- }
105
- return isParseable;
106
- }
@@ -0,0 +1,51 @@
1
+ import { getFilesWithErrors } from './shared/index.js';
2
+ export const outputFilePath = '.ignore-lint-errors/oxlint.txt';
3
+ function extractRuleId(code) {
4
+ const matches = code.match(/^.+\((.+)\)$/);
5
+ if (matches === null) {
6
+ throw new Error(`Unable to extract rule ID (code: ${code})`);
7
+ }
8
+ return matches[1];
9
+ }
10
+ function normalize(file) {
11
+ const filePathToData = new Map();
12
+ const { diagnostics } = JSON.parse(file);
13
+ const filePathToMessages = new Map();
14
+ diagnostics.forEach((diagnostic) => {
15
+ const { code, filename: filePath, labels } = diagnostic;
16
+ const line = labels[0].span.line;
17
+ const ruleId = extractRuleId(code);
18
+ const message = {
19
+ line,
20
+ ruleId,
21
+ };
22
+ if (filePathToMessages.has(filePath)) {
23
+ filePathToMessages.get(filePath).push(message);
24
+ }
25
+ else {
26
+ filePathToMessages.set(filePath, [message]);
27
+ }
28
+ });
29
+ filePathToMessages.forEach((messages, filePath) => {
30
+ const data = new Map();
31
+ const lineToRules = new Map();
32
+ messages.forEach(({ line, ruleId }) => {
33
+ if (lineToRules.has(line)) {
34
+ lineToRules.get(line).push(ruleId);
35
+ }
36
+ else {
37
+ lineToRules.set(line, [ruleId]);
38
+ }
39
+ });
40
+ lineToRules.forEach((rules, line) => {
41
+ const message = Array.from(new Set(rules.sort())).join(', ');
42
+ data.set(line, message);
43
+ });
44
+ filePathToData.set(filePath, data);
45
+ });
46
+ return filePathToData;
47
+ }
48
+ export function parseOutputFile(file) {
49
+ const filePathToData = normalize(file);
50
+ return getFilesWithErrors(filePathToData);
51
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ignore-lint-errors",
3
- "version": "1.0.0",
3
+ "version": "1.1.1",
4
4
  "description": "Codemod to ignore lint errors per line",
5
5
  "keywords": [
6
6
  "codemod",
@@ -24,28 +24,28 @@
24
24
  "dist"
25
25
  ],
26
26
  "dependencies": {
27
- "@codemod-utils/ast-javascript": "^4.0.2",
28
- "@codemod-utils/ast-template": "^4.0.0",
29
- "@codemod-utils/ast-template-tag": "^2.6.0",
30
- "@codemod-utils/files": "^4.0.1",
31
- "@codemod-utils/package-json": "^4.0.3",
27
+ "@codemod-utils/ast-javascript": "^4.2.1",
28
+ "@codemod-utils/ast-template": "^4.1.0",
29
+ "@codemod-utils/ast-template-tag": "^2.7.0",
30
+ "@codemod-utils/files": "^4.1.0",
31
+ "@codemod-utils/package-json": "^4.1.0",
32
32
  "yargs": "^18.0.0"
33
33
  },
34
34
  "devDependencies": {
35
35
  "@changesets/cli": "^2.31.0",
36
- "@codemod-utils/tests": "^3.0.2",
36
+ "@codemod-utils/tests": "^3.1.0",
37
37
  "@ijlee2-frontend-configs/changesets": "^2.1.1",
38
- "@ijlee2-frontend-configs/eslint-config-node": "^3.4.4",
39
- "@ijlee2-frontend-configs/prettier": "^3.2.0",
38
+ "@ijlee2-frontend-configs/eslint-config-node": "^4.1.0",
39
+ "@ijlee2-frontend-configs/prettier": "^3.3.0",
40
40
  "@sondr3/minitest": "^0.1.2",
41
41
  "@tsconfig/node22": "^22.0.5",
42
42
  "@tsconfig/strictest": "^2.0.8",
43
43
  "@types/node": "^22.20.0",
44
44
  "@types/yargs": "^17.0.35",
45
45
  "concurrently": "^10.0.3",
46
- "eslint": "^9.39.4",
47
- "prettier": "^3.8.4",
48
- "typescript": "^5.9.3"
46
+ "eslint": "^10.6.0",
47
+ "prettier": "^3.9.4",
48
+ "typescript": "^6.0.3"
49
49
  },
50
50
  "engines": {
51
51
  "node": "22.* || >= 24"