@oxlint/migrate 1.24.0 → 1.26.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
@@ -21,6 +21,7 @@ When no config file provided, the script searches for the default eslint config
21
21
  | `--merge` | \* merge eslint configuration with an existing .oxlintrc.json configuration |
22
22
  | `--type-aware` | Include type aware rules, which are supported with `oxlint --type-aware` |
23
23
  | `--with-nursery` | Include oxlint rules which are currently under development |
24
+ | `--js-plugins` | \*\* Include ESLint plugins via `jsPlugins` key. |
24
25
  | `--output-file <file>` | The oxlint configuration file where to eslint v9 rules will be written to, default: `.oxlintrc.json` |
25
26
  | `--replace-eslint-comments` | Search in the project files for eslint comments and replaces them with oxlint. Some eslint comments are not supported and will be reported. |
26
27
 
@@ -28,6 +29,10 @@ When no config file provided, the script searches for the default eslint config
28
29
  Else we need to disable each rule `plugin/categories` combination, which is not covered by your eslint configuration.
29
30
  This behavior can change in the future.
30
31
 
32
+ \*\* WARNING: Tries to guess the plugin name. Should work with most of the plugin names.
33
+ Not every ESLint API is integrated with `oxlint`.
34
+ Tested ESLint Plugins with `oxlint` can be found in this [Oxc Discussion](https://github.com/oxc-project/oxc/discussions/14862).
35
+
31
36
  ### User Flow
32
37
 
33
38
  - Upgrade `oxlint` and `@oxlint/migrate` to the same version.
@@ -9,6 +9,7 @@ import { walkAndReplaceProjectFiles } from "../src/walker/index.mjs";
9
9
  import { getAllProjectFiles } from "./project-loader.mjs";
10
10
  import { writeFile } from "node:fs/promises";
11
11
  import { preFixForJsPlugins } from "../src/js_plugin_fixes.mjs";
12
+ import { DefaultReporter } from "../src/reporter.mjs";
12
13
  const cwd = process.cwd();
13
14
  const getFileContent = (absoluteFilePath) => {
14
15
  try {
@@ -35,14 +36,19 @@ program.name("oxlint-migrate").version(packageJson.version).argument("[eslint-co
35
36
  ).option(
36
37
  "--type-aware",
37
38
  "Includes supported type-aware rules. Needs the same flag in `oxlint` to enable it."
39
+ ).option(
40
+ "--js-plugins",
41
+ "Tries to convert unsupported oxlint plugins with `jsPlugins`."
38
42
  ).action(async (filePath) => {
39
43
  const cliOptions = program.opts();
40
44
  const oxlintFilePath = path.join(cwd, cliOptions.outputFile);
45
+ const reporter = new DefaultReporter();
41
46
  const options = {
42
- reporter: console.warn,
47
+ reporter,
43
48
  merge: !!cliOptions.merge,
44
49
  withNursery: !!cliOptions.withNursery,
45
- typeAware: !!cliOptions.typeAware
50
+ typeAware: !!cliOptions.typeAware,
51
+ jsPlugins: !!cliOptions.jsPlugins
46
52
  };
47
53
  if (cliOptions.replaceEslintComments) {
48
54
  await walkAndReplaceProjectFiles(
@@ -75,5 +81,8 @@ program.name("oxlint-migrate").version(packageJson.version).argument("[eslint-co
75
81
  renameSync(oxlintFilePath, `${oxlintFilePath}.bak`);
76
82
  }
77
83
  writeFileSync(oxlintFilePath, JSON.stringify(oxlintConfig, null, 2));
84
+ for (const report of reporter.getReports()) {
85
+ console.warn(report);
86
+ }
78
87
  });
79
88
  program.parse();
@@ -1,4 +1,4 @@
1
- const version = "1.24.0";
1
+ const version = "1.26.0";
2
2
  const packageJson = {
3
3
  version
4
4
  };
@@ -1,5 +1,5 @@
1
1
  import { removeGlobalsWithAreCoveredByEnv, transformBoolGlobalToString, ES_VERSIONS, cleanUpUselessOverridesEnv } from "./env_globals.mjs";
2
- import { replaceTypescriptAliasRules, replaceNodePluginName, cleanUpRulesWhichAreCoveredByCategory, cleanUpUselessOverridesRules, cleanUpUselessOverridesPlugins } from "./plugins_rules.mjs";
2
+ import { replaceTypescriptAliasRules, replaceNodePluginName, cleanUpRulesWhichAreCoveredByCategory, cleanUpDisabledRootRules, cleanUpUselessOverridesRules, cleanUpUselessOverridesPlugins } from "./plugins_rules.mjs";
3
3
  import { isEqualDeep } from "./utilities.mjs";
4
4
  const TS_ESLINT_DEFAULT_OVERRIDE = {
5
5
  files: ["**/*.ts", "**/*.tsx", "**/*.mts", "**/*.cts"],
@@ -81,6 +81,7 @@ const cleanUpOxlintConfig = (config) => {
81
81
  }
82
82
  if (!("files" in config)) {
83
83
  cleanUpUselessOverridesEntries(config);
84
+ cleanUpDisabledRootRules(config);
84
85
  }
85
86
  };
86
87
  export {
@@ -111,7 +111,7 @@ const transformEnvAndGlobals = (eslintConfig, targetConfig, options) => {
111
111
  // @ts-ignore
112
112
  eslintConfig.languageOptions.parser.meta?.name
113
113
  )) {
114
- options?.reporter !== void 0 && options.reporter(
114
+ options?.reporter?.report(
115
115
  "special parser detected: " + // @ts-ignore
116
116
  eslintConfig.languageOptions.parser.meta?.name
117
117
  );
@@ -35,6 +35,7 @@ const pedanticRules = [
35
35
  "jsdoc/require-returns-description",
36
36
  "jsdoc/require-returns-type",
37
37
  "react/checked-requires-onchange-or-readonly",
38
+ "react/jsx-no-target-blank",
38
39
  "react/jsx-no-useless-fragment",
39
40
  "react/no-unescaped-entities",
40
41
  "react-hooks/rules-of-hooks",
@@ -42,6 +43,7 @@ const pedanticRules = [
42
43
  "@typescript-eslint/ban-types",
43
44
  "@typescript-eslint/no-misused-promises",
44
45
  "@typescript-eslint/no-confusing-void-expression",
46
+ "@typescript-eslint/no-deprecated",
45
47
  "@typescript-eslint/no-mixed-enums",
46
48
  "@typescript-eslint/no-unsafe-argument",
47
49
  "@typescript-eslint/no-unsafe-assignment",
@@ -57,6 +59,7 @@ const pedanticRules = [
57
59
  "@typescript-eslint/require-await",
58
60
  "@typescript-eslint/restrict-plus-operands",
59
61
  "@typescript-eslint/return-await",
62
+ "@typescript-eslint/strict-boolean-expressions",
60
63
  "@typescript-eslint/switch-exhaustiveness-check",
61
64
  "unicorn/consistent-assert",
62
65
  "unicorn/consistent-empty-array-spread",
@@ -215,6 +218,7 @@ const styleRules = [
215
218
  "react/no-set-state",
216
219
  "react/prefer-es6-class",
217
220
  "react/self-closing-comp",
221
+ "react/state-in-constructor",
218
222
  "@typescript-eslint/adjacent-overload-signatures",
219
223
  "@typescript-eslint/array-type",
220
224
  "@typescript-eslint/ban-tslint-comment",
@@ -268,9 +272,9 @@ const styleRules = [
268
272
  "vitest/prefer-to-be-falsy",
269
273
  "vitest/prefer-to-be-object",
270
274
  "vitest/prefer-to-be-truthy",
271
- "vue/define-props-destructuring",
272
275
  "vue/define-emits-declaration",
273
276
  "vue/define-props-declaration",
277
+ "vue/define-props-destructuring",
274
278
  "vue/require-typed-ref",
275
279
  "@typescript-eslint/default-param-last",
276
280
  "@typescript-eslint/init-declarations",
@@ -594,7 +598,6 @@ const correctnessRules = [
594
598
  "react/forward-ref-uses-ref",
595
599
  "react/jsx-key",
596
600
  "react/jsx-no-duplicate-props",
597
- "react/jsx-no-target-blank",
598
601
  "react/jsx-no-undef",
599
602
  "react/jsx-props-no-spread-multi",
600
603
  "react/no-children-prop",
@@ -3,7 +3,7 @@ const transformIgnorePatterns = (eslintConfig, targetConfig, options) => {
3
3
  return;
4
4
  }
5
5
  if ("files" in targetConfig) {
6
- options?.reporter !== void 0 && options.reporter("ignore list inside overrides is not supported");
6
+ options?.reporter?.report("ignore list inside overrides is not supported");
7
7
  return;
8
8
  }
9
9
  if (targetConfig.ignorePatterns === void 0) {
@@ -59,13 +59,13 @@ const buildConfig = (configs, oxlintConfig, options) => {
59
59
  transformRuleEntry(config, targetConfig, options);
60
60
  transformEnvAndGlobals(config, targetConfig, options);
61
61
  if ("files" in targetConfig) {
62
- detectNeededRulesPlugins(targetConfig, options);
62
+ detectNeededRulesPlugins(targetConfig);
63
63
  detectEnvironmentByGlobals(targetConfig);
64
64
  cleanUpOxlintConfig(targetConfig);
65
65
  }
66
66
  }
67
67
  oxlintConfig.overrides = overrides;
68
- detectNeededRulesPlugins(oxlintConfig, options);
68
+ detectNeededRulesPlugins(oxlintConfig);
69
69
  detectEnvironmentByGlobals(oxlintConfig);
70
70
  cleanUpOxlintConfig(oxlintConfig);
71
71
  return oxlintConfig;
@@ -0,0 +1,3 @@
1
+ import { Linter } from 'eslint';
2
+ import { OxlintConfigOrOverride } from './types.js';
3
+ export declare const enableJsPluginRule: (targetConfig: OxlintConfigOrOverride, rule: string, ruleEntry: Linter.RuleEntry | undefined) => boolean;
@@ -0,0 +1,52 @@
1
+ import { rulesPrefixesForPlugins } from "./constants.mjs";
2
+ const ignorePlugins = /* @__PURE__ */ new Set([
3
+ ...Object.keys(rulesPrefixesForPlugins),
4
+ ...Object.values(rulesPrefixesForPlugins),
5
+ "local"
6
+ // ToDo: handle local plugin rules
7
+ ]);
8
+ const guessEslintPluginName = (pluginName) => {
9
+ if (pluginName.startsWith("@")) {
10
+ const [scope, maybeSub] = pluginName.split("/");
11
+ if (maybeSub) {
12
+ return `${scope}/eslint-plugin-${maybeSub}`;
13
+ }
14
+ return `${scope}/eslint-plugin`;
15
+ }
16
+ return `eslint-plugin-${pluginName}`;
17
+ };
18
+ const extractPluginId = (ruleId) => {
19
+ const firstSlash = ruleId.indexOf("/");
20
+ if (firstSlash === -1) {
21
+ return;
22
+ }
23
+ if (ruleId.startsWith("@")) {
24
+ const secondSlash = ruleId.indexOf("/", firstSlash + 1);
25
+ if (secondSlash !== -1) {
26
+ return ruleId.substring(0, secondSlash);
27
+ }
28
+ }
29
+ return ruleId.substring(0, firstSlash);
30
+ };
31
+ const enableJsPluginRule = (targetConfig, rule, ruleEntry) => {
32
+ const pluginName = extractPluginId(rule);
33
+ if (pluginName === void 0) {
34
+ return false;
35
+ }
36
+ if (ignorePlugins.has(pluginName)) {
37
+ return false;
38
+ }
39
+ if (targetConfig.jsPlugins === void 0) {
40
+ targetConfig.jsPlugins = [];
41
+ }
42
+ const eslintPluginName = guessEslintPluginName(pluginName);
43
+ if (!targetConfig.jsPlugins.includes(eslintPluginName)) {
44
+ targetConfig.jsPlugins.push(eslintPluginName);
45
+ }
46
+ targetConfig.rules = targetConfig.rules || {};
47
+ targetConfig.rules[rule] = ruleEntry;
48
+ return true;
49
+ };
50
+ export {
51
+ enableJsPluginRule
52
+ };
@@ -3,7 +3,8 @@ const fixForAntfuEslintConfig = (config) => {
3
3
  return config.renamePlugins({
4
4
  ts: "@typescript-eslint",
5
5
  test: "vitest",
6
- next: "@next/next"
6
+ next: "@next/next",
7
+ style: "@stylistic"
7
8
  });
8
9
  }
9
10
  return config;
@@ -1,10 +1,11 @@
1
1
  import { Linter } from 'eslint';
2
2
  import { Options, OxlintConfig, OxlintConfigOrOverride } from './types.js';
3
3
  export declare const transformRuleEntry: (eslintConfig: Linter.Config, targetConfig: OxlintConfigOrOverride, options?: Options) => void;
4
- export declare const detectNeededRulesPlugins: (targetConfig: OxlintConfigOrOverride, options?: Options) => void;
4
+ export declare const detectNeededRulesPlugins: (targetConfig: OxlintConfigOrOverride) => void;
5
5
  export declare const cleanUpUselessOverridesPlugins: (config: OxlintConfig) => void;
6
6
  export declare const cleanUpUselessOverridesRules: (config: OxlintConfig) => void;
7
7
  export declare const cleanUpRulesWhichAreCoveredByCategory: (config: OxlintConfigOrOverride) => void;
8
+ export declare const cleanUpDisabledRootRules: (config: OxlintConfig) => void;
8
9
  export declare const replaceTypescriptAliasRules: (config: OxlintConfigOrOverride) => void;
9
10
  /**
10
11
  * Oxlint support them only under the node plugin name
@@ -1,6 +1,7 @@
1
1
  import * as rules from "./generated/rules.mjs";
2
2
  import { nurseryRules } from "./generated/rules.mjs";
3
3
  import { typescriptTypeAwareRules, rulesPrefixesForPlugins, typescriptRulesExtendEslintRules } from "./constants.mjs";
4
+ import { enableJsPluginRule } from "./jsPlugins.mjs";
4
5
  const allRules = Object.values(rules).flat();
5
6
  const isValueInSet = (value, validSet) => validSet.includes(value) || Array.isArray(value) && validSet.includes(value[0]);
6
7
  const isActiveValue = (value) => isValueInSet(value, ["error", "warn", 1, 2]);
@@ -43,11 +44,13 @@ const transformRuleEntry = (eslintConfig, targetConfig, options) => {
43
44
  for (const [rule, config] of Object.entries(eslintConfig.rules)) {
44
45
  if (allRules.includes(rule)) {
45
46
  if (!options?.withNursery && nurseryRules.includes(rule)) {
46
- options?.reporter !== void 0 && options.reporter(`unsupported rule, but in development: ${rule}`);
47
+ options?.reporter?.report(
48
+ `unsupported rule, but in development: ${rule}`
49
+ );
47
50
  continue;
48
51
  }
49
52
  if (!options?.typeAware && typescriptTypeAwareRules.includes(rule)) {
50
- options?.reporter !== void 0 && options.reporter(
53
+ options?.reporter?.report(
51
54
  `type-aware rule detected, but \`--type-aware\` is not enabled: ${rule}`
52
55
  );
53
56
  continue;
@@ -60,13 +63,21 @@ const transformRuleEntry = (eslintConfig, targetConfig, options) => {
60
63
  targetConfig.rules[rule] = normalizeSeverityValue(config);
61
64
  }
62
65
  } else {
63
- if (isActiveValue(config)) {
64
- options?.reporter !== void 0 && options.reporter(`unsupported rule: ${rule}`);
66
+ if (options?.jsPlugins) {
67
+ if (isActiveValue(config) && !enableJsPluginRule(
68
+ targetConfig,
69
+ rule,
70
+ normalizeSeverityValue(config)
71
+ )) {
72
+ options?.reporter?.report(`unsupported rule: ${rule}`);
73
+ }
74
+ } else if (isActiveValue(config)) {
75
+ options?.reporter?.report(`unsupported rule: ${rule}`);
65
76
  }
66
77
  }
67
78
  }
68
79
  };
69
- const detectNeededRulesPlugins = (targetConfig, options) => {
80
+ const detectNeededRulesPlugins = (targetConfig) => {
70
81
  if (targetConfig.rules === void 0) {
71
82
  return;
72
83
  }
@@ -77,18 +88,11 @@ const detectNeededRulesPlugins = (targetConfig, options) => {
77
88
  if (!rule.includes("/")) {
78
89
  continue;
79
90
  }
80
- let found = false;
81
91
  for (const [prefix, plugin] of Object.entries(rulesPrefixesForPlugins)) {
82
- if (rule.startsWith(`${prefix}/`)) {
83
- if (!targetConfig.plugins.includes(plugin)) {
84
- targetConfig.plugins.push(plugin);
85
- }
86
- found = true;
92
+ if (rule.startsWith(`${prefix}/`) && !targetConfig.plugins.includes(plugin)) {
93
+ targetConfig.plugins.push(plugin);
87
94
  }
88
95
  }
89
- if (!found) {
90
- options?.reporter !== void 0 && options.reporter(`unsupported plugin for rule: ${rule}`);
91
- }
92
96
  }
93
97
  if ("files" in targetConfig && targetConfig.plugins.length === 0) {
94
98
  delete targetConfig.plugins;
@@ -146,6 +150,36 @@ const cleanUpRulesWhichAreCoveredByCategory = (config) => {
146
150
  }
147
151
  }
148
152
  };
153
+ const getEnabledCategories = (config) => {
154
+ if (config.categories === void 0) {
155
+ return ["correctness"];
156
+ }
157
+ const categories = Object.entries(config.categories).filter(([, severity]) => severity === "warn" || severity === "error").map(([category]) => category);
158
+ if (Object.keys(config.categories).includes("correctness")) {
159
+ return categories;
160
+ }
161
+ return [...categories, "correctness"];
162
+ };
163
+ const isRuleInEnabledCategory = (rule, enabledCategories) => {
164
+ for (const category of enabledCategories) {
165
+ if (`${category}Rules` in rules && // @ts-expect-error -- ts can not resolve the type
166
+ rules[`${category}Rules`].includes(rule)) {
167
+ return true;
168
+ }
169
+ }
170
+ return false;
171
+ };
172
+ const cleanUpDisabledRootRules = (config) => {
173
+ if (config.rules === void 0) {
174
+ return;
175
+ }
176
+ const enabledCategories = getEnabledCategories(config);
177
+ for (const [rule, settings] of Object.entries(config.rules)) {
178
+ if (isOffValue(settings) && !isRuleInEnabledCategory(rule, enabledCategories)) {
179
+ delete config.rules[rule];
180
+ }
181
+ }
182
+ };
149
183
  const replaceTypescriptAliasRules = (config) => {
150
184
  if (config.rules === void 0) {
151
185
  return;
@@ -181,6 +215,7 @@ const replaceNodePluginName = (config) => {
181
215
  }
182
216
  };
183
217
  export {
218
+ cleanUpDisabledRootRules,
184
219
  cleanUpRulesWhichAreCoveredByCategory,
185
220
  cleanUpUselessOverridesPlugins,
186
221
  cleanUpUselessOverridesRules,
@@ -0,0 +1,10 @@
1
+ import { Reporter } from './types.js';
2
+ export declare class DefaultReporter implements Reporter {
3
+ private reports;
4
+ report(message: string): void;
5
+ getReports(): string[];
6
+ }
7
+ export declare class SilentReporter implements Reporter {
8
+ report(_message: string): void;
9
+ getReports(): string[];
10
+ }
@@ -0,0 +1,12 @@
1
+ class DefaultReporter {
2
+ reports = /* @__PURE__ */ new Set();
3
+ report(message) {
4
+ this.reports.add(message);
5
+ }
6
+ getReports() {
7
+ return Array.from(this.reports);
8
+ }
9
+ }
10
+ export {
11
+ DefaultReporter
12
+ };
@@ -1,5 +1,6 @@
1
1
  import { Linter } from 'eslint';
2
2
  type OxlintConfigPlugins = string[];
3
+ type OxlintConfigJsPlugins = string[];
3
4
  type OxlintConfigCategories = Record<string, unknown>;
4
5
  type OxlintConfigEnv = Record<string, boolean>;
5
6
  type OxlintConfigIgnorePatterns = string[];
@@ -8,6 +9,7 @@ export type OxlintConfigOverride = {
8
9
  env?: OxlintConfigEnv;
9
10
  globals?: Linter.Globals;
10
11
  plugins?: OxlintConfigPlugins;
12
+ jsPlugins?: OxlintConfigJsPlugins;
11
13
  categories?: OxlintConfigCategories;
12
14
  rules?: Partial<Linter.RulesRecord>;
13
15
  };
@@ -16,17 +18,22 @@ export type OxlintConfig = {
16
18
  env?: OxlintConfigEnv;
17
19
  globals?: Linter.Globals;
18
20
  plugins?: OxlintConfigPlugins;
21
+ jsPlugins?: OxlintConfigJsPlugins;
19
22
  categories?: OxlintConfigCategories;
20
23
  rules?: Partial<Linter.RulesRecord>;
21
24
  overrides?: OxlintConfigOverride[];
22
25
  ignorePatterns?: OxlintConfigIgnorePatterns;
23
26
  };
24
27
  export type OxlintConfigOrOverride = OxlintConfig | OxlintConfigOverride;
25
- type Reporter = (warning: string) => void;
28
+ export type Reporter = {
29
+ report(message: string): void;
30
+ getReports(): string[];
31
+ };
26
32
  export type Options = {
27
33
  reporter?: Reporter;
28
34
  merge?: boolean;
29
35
  withNursery?: boolean;
30
36
  typeAware?: boolean;
37
+ jsPlugins?: boolean;
31
38
  };
32
39
  export {};
@@ -10,8 +10,8 @@ const getComments = (absoluteFilePath, partialSourceText, options) => {
10
10
  sourceType: partialSourceText.sourceType
11
11
  }
12
12
  );
13
- if (parserResult.errors.length > 0 && options.reporter) {
14
- options.reporter(`${absoluteFilePath}: failed to parse`);
13
+ if (parserResult.errors.length > 0) {
14
+ options.reporter?.report(`${absoluteFilePath}: failed to parse`);
15
15
  }
16
16
  return parserResult.comments;
17
17
  };
@@ -26,8 +26,8 @@ function replaceCommentsInSourceText(absoluteFilePath, partialSourceText, option
26
26
  sourceText = sourceText.slice(0, comment.start) + newComment + sourceText.slice(comment.end);
27
27
  }
28
28
  } catch (error) {
29
- if (error instanceof Error && options.reporter) {
30
- options.reporter(
29
+ if (error instanceof Error) {
30
+ options.reporter?.report(
31
31
  `${absoluteFilePath}, char offset ${comment.start + partialSourceText.offset}: ${error.message}`
32
32
  );
33
33
  continue;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oxlint/migrate",
3
- "version": "1.24.0",
3
+ "version": "1.26.0",
4
4
  "description": "Generates a `.oxlintrc.json` from a existing eslint flat config",
5
5
  "type": "module",
6
6
  "bin": {
@@ -37,10 +37,9 @@
37
37
  "author": "Sysix <sysix@sysix-coding.de>",
38
38
  "license": "MIT",
39
39
  "devDependencies": {
40
- "@antfu/eslint-config": "^5.0.0",
41
- "@eslint/eslintrc": "^3.3.1",
40
+ "@antfu/eslint-config": "^6.0.0",
42
41
  "@eslint/js": "^9.29.0",
43
- "@logux/eslint-config": "^56.0.0",
42
+ "@logux/eslint-config": "^57.0.0",
44
43
  "@oxc-node/core": "^0.0.32",
45
44
  "@stylistic/eslint-plugin": "^5.0.0",
46
45
  "@stylistic/eslint-plugin-ts": "^4.4.1",
@@ -48,33 +47,36 @@
48
47
  "@types/node": "^24.0.4",
49
48
  "@typescript-eslint/eslint-plugin": "^8.35.0",
50
49
  "@typescript-eslint/parser": "^8.35.0",
51
- "@vitest/coverage-v8": "^3.2.4",
50
+ "@vitest/coverage-v8": "^4.0.0",
52
51
  "eslint": "^9.29.0",
53
- "eslint-config-next": "^15.5.0",
52
+ "eslint-config-next": "^16.0.0",
54
53
  "eslint-config-prettier": "^10.1.5",
55
54
  "eslint-plugin-header": "^3.1.1",
56
55
  "eslint-plugin-import": "^2.32.0",
57
56
  "eslint-plugin-import-x": "^4.16.0",
58
- "eslint-plugin-jsdoc": "^60.0.0",
57
+ "eslint-plugin-jsdoc": "^61.0.0",
59
58
  "eslint-plugin-local": "^6.0.0",
59
+ "eslint-plugin-mocha": "^11.2.0",
60
60
  "eslint-plugin-oxlint": "^1.3.0",
61
+ "eslint-plugin-prettier": "^5.5.4",
61
62
  "eslint-plugin-react": "^7.37.5",
62
- "eslint-plugin-react-hooks": "^5.2.0",
63
+ "eslint-plugin-react-hooks": "^7.0.1",
63
64
  "eslint-plugin-react-perf": "^3.3.3",
64
65
  "eslint-plugin-regexp": "^2.9.0",
65
- "eslint-plugin-unicorn": "^61.0.0",
66
+ "eslint-plugin-tsdoc": "^0.4.0",
67
+ "eslint-plugin-unicorn": "^62.0.0",
66
68
  "husky": "^9.1.7",
67
69
  "jiti": "^2.4.2",
68
70
  "lint-staged": "^16.1.2",
69
- "next": "^15.5.0",
70
- "oxlint": "^1.24.0",
71
+ "next": "^16.0.0",
72
+ "oxlint": "^1.26.0",
71
73
  "oxlint-tsgolint": "^0.2.0",
72
74
  "prettier": "^3.6.1",
73
75
  "typescript": "^5.8.3",
74
76
  "typescript-eslint": "^8.35.0",
75
77
  "vite": "^7.0.0",
76
78
  "vite-plugin-dts": "^4.5.4",
77
- "vitest": "^3.2.4"
79
+ "vitest": "^4.0.0"
78
80
  },
79
81
  "lint-staged": {
80
82
  "*": "prettier --ignore-unknown --write"
@@ -82,11 +84,11 @@
82
84
  "dependencies": {
83
85
  "commander": "^14.0.0",
84
86
  "globals": "^16.3.0",
85
- "oxc-parser": "^0.95.0",
87
+ "oxc-parser": "^0.96.0",
86
88
  "tinyglobby": "^0.2.14"
87
89
  },
88
90
  "peerDependencies": {
89
91
  "jiti": "*"
90
92
  },
91
- "packageManager": "pnpm@10.18.3"
93
+ "packageManager": "pnpm@10.20.0"
92
94
  }