@oxlint/migrate 1.57.0 → 1.59.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.
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { a as nurseryRules, i as buildUnsupportedRuleExplanations, n as preFixForJsPlugins, o as rules_exports, r as isOffValue, t as main } from "../src-DEzNNXJD.mjs";
2
+ import { a as nurseryRules, i as buildUnsupportedRuleExplanations, n as preFixForJsPlugins, o as rules_exports, r as isOffValue, s as normalizeRuleToCanonical, t as main } from "../src-DuN61x5i.mjs";
3
3
  import { program } from "commander";
4
4
  import { existsSync, readFileSync, renameSync, writeFileSync } from "node:fs";
5
5
  import path from "node:path";
@@ -30,10 +30,11 @@ const loadESLintConfig = async (filePath) => {
30
30
  };
31
31
  //#endregion
32
32
  //#region package.json
33
- var version = "1.57.0";
33
+ var version = "1.59.0";
34
34
  //#endregion
35
35
  //#region src/walker/comments/replaceRuleDirectiveComment.ts
36
- const allRules = Object.values(rules_exports).flat();
36
+ const allRulesSet = new Set(Object.values(rules_exports).flat());
37
+ const nurseryRulesSet = new Set(nurseryRules);
37
38
  function replaceRuleDirectiveComment(comment, type, options) {
38
39
  const originalComment = comment;
39
40
  comment = comment.split(" -- ")[0].trimStart();
@@ -51,14 +52,13 @@ function replaceRuleDirectiveComment(comment, type, options) {
51
52
  comment = comment.trimStart();
52
53
  if (comment.length === 0) return originalComment;
53
54
  while (comment.length) {
54
- let foundRule = false;
55
- for (const rule of allRules) if (comment.startsWith(rule)) {
56
- if (!options.withNursery && nurseryRules.includes(rule)) continue;
57
- foundRule = true;
58
- comment = comment.substring(rule.length).trimStart();
59
- break;
60
- }
61
- if (!foundRule) return originalComment;
55
+ const commaIdx = comment.indexOf(",");
56
+ const candidateEnd = commaIdx === -1 ? comment.length : commaIdx;
57
+ const candidate = comment.substring(0, candidateEnd).trimEnd();
58
+ const canonical = normalizeRuleToCanonical(candidate);
59
+ if (!allRulesSet.has(canonical)) return originalComment;
60
+ if (!options.withNursery && nurseryRulesSet.has(canonical)) return originalComment;
61
+ comment = comment.substring(candidate.length).trimStart();
62
62
  if (!comment.length) break;
63
63
  if (!comment.startsWith(", ")) return originalComment;
64
64
  comment = comment.substring(1).trimStart();
@@ -1,4 +1,4 @@
1
- //#region node_modules/.pnpm/oxlint@1.57.0_oxlint-tsgolint@0.17.1/node_modules/oxlint/dist/index.d.ts
1
+ //#region node_modules/.pnpm/oxlint@1.59.0_oxlint-tsgolint@0.19.0/node_modules/oxlint/dist/index.d.ts
2
2
  //#region src-js/package/config.generated.d.ts
3
3
  type AllowWarnDeny = ("allow" | "off" | "warn" | "error" | "deny") | number;
4
4
  type GlobalValue = "readonly" | "writable" | "off";
@@ -37,7 +37,7 @@ type ExternalPluginEntry = string | {
37
37
  type GlobSet = string[];
38
38
  type LintPluginOptionsSchema = "eslint" | "react" | "unicorn" | "typescript" | "oxc" | "import" | "jsdoc" | "jest" | "vitest" | "jsx-a11y" | "nextjs" | "react-perf" | "promise" | "node" | "vue";
39
39
  type LintPlugins = LintPluginOptionsSchema[];
40
- type DummyRule = AllowWarnDeny | unknown[];
40
+ type DummyRule = AllowWarnDeny | [AllowWarnDeny, ...unknown[]];
41
41
  type OxlintOverrides = OxlintOverride[];
42
42
  type TagNamePreference = string | {
43
43
  message: string;
@@ -1,2 +1,2 @@
1
- import { t as main } from "../src-DEzNNXJD.mjs";
1
+ import { t as main } from "../src-DuN61x5i.mjs";
2
2
  export { main as default };
@@ -165,6 +165,223 @@ const cleanUpSupersetEnvs = (config) => {
165
165
  }
166
166
  };
167
167
  //#endregion
168
+ //#region src/constants.ts
169
+ const rulesPrefixesForPlugins = {
170
+ import: "import",
171
+ "import-x": "import",
172
+ jest: "jest",
173
+ jsdoc: "jsdoc",
174
+ "jsx-a11y": "jsx-a11y",
175
+ "@next/next": "nextjs",
176
+ node: "node",
177
+ n: "node",
178
+ promise: "promise",
179
+ react: "react",
180
+ "react-perf": "react-perf",
181
+ "react-hooks": "react",
182
+ "react-refresh": "react",
183
+ "@typescript-eslint": "typescript",
184
+ unicorn: "unicorn",
185
+ vitest: "vitest",
186
+ vue: "vue"
187
+ };
188
+ /**
189
+ * Normalizes an ESLint-style rule name to its canonical Oxlint form.
190
+ * e.g. "@typescript-eslint/no-floating-promises" → "typescript/no-floating-promises"
191
+ * "react-hooks/exhaustive-deps" → "react/exhaustive-deps"
192
+ * "@next/next/inline-script-id" → "nextjs/inline-script-id"
193
+ * "no-unused-vars" → "no-unused-vars" (unchanged for unprefixed rules)
194
+ */
195
+ function normalizeRuleToCanonical(rule) {
196
+ for (const [prefix, plugin] of Object.entries(rulesPrefixesForPlugins)) if (prefix !== plugin && rule.startsWith(`${prefix}/`)) return `${plugin}/${rule.slice(prefix.length + 1)}`;
197
+ return rule;
198
+ }
199
+ const eslintRulesToTypescriptEquivalents = {
200
+ "dot-notation": "@typescript-eslint/dot-notation",
201
+ "consistent-return": "@typescript-eslint/consistent-return"
202
+ };
203
+ const typescriptRulesExtendEslintRules = [
204
+ "class-methods-use-this",
205
+ "default-param-last",
206
+ "init-declarations",
207
+ "max-params",
208
+ "no-array-constructor",
209
+ "no-dupe-class-members",
210
+ "no-empty-function",
211
+ "no-invalid-this",
212
+ "no-loop-func",
213
+ "no-loss-of-precision",
214
+ "no-magic-numbers",
215
+ "no-redeclare",
216
+ "no-restricted-imports",
217
+ "no-shadow",
218
+ "no-unused-expressions",
219
+ "no-unused-vars",
220
+ "no-use-before-define",
221
+ "no-useless-constructor"
222
+ ];
223
+ //#endregion
224
+ //#region src/jsPlugins.ts
225
+ const ignorePlugins = new Set([
226
+ ...Object.keys(rulesPrefixesForPlugins),
227
+ ...Object.values(rulesPrefixesForPlugins),
228
+ "local"
229
+ ]);
230
+ const tryResolvePackage = (packageName) => {
231
+ try {
232
+ import.meta.resolve(packageName);
233
+ return true;
234
+ } catch {
235
+ return false;
236
+ }
237
+ };
238
+ const pluginNameCache = /* @__PURE__ */ new Map();
239
+ /**
240
+ * Resolves the npm package name for an ESLint plugin given its scope name.
241
+ *
242
+ * For scoped plugin names (starting with `@`), the mapping is unambiguous:
243
+ * - `@scope` -> `@scope/eslint-plugin`
244
+ * - `@scope/sub` -> `@scope/eslint-plugin-sub`
245
+ *
246
+ * For non-scoped names, the npm package could follow either convention:
247
+ * - `eslint-plugin-{name}` (e.g. `eslint-plugin-mocha`)
248
+ * - `@{name}/eslint-plugin` (e.g. `@e18e/eslint-plugin`)
249
+ *
250
+ * We try to resolve both candidates against the installed packages and
251
+ * use the one that is actually present, falling back to the standard
252
+ * `eslint-plugin-{name}` convention when neither can be resolved.
253
+ */
254
+ const resolveEslintPluginName = (pluginName) => {
255
+ const cached = pluginNameCache.get(pluginName);
256
+ if (cached !== void 0) return cached;
257
+ let result;
258
+ if (pluginName.startsWith("@")) {
259
+ const [scope, maybeSub] = pluginName.split("/");
260
+ if (maybeSub) result = `${scope}/eslint-plugin-${maybeSub}`;
261
+ else result = `${scope}/eslint-plugin`;
262
+ } else {
263
+ const standardName = `eslint-plugin-${pluginName}`;
264
+ const scopedName = `@${pluginName}/eslint-plugin`;
265
+ if (tryResolvePackage(standardName)) result = standardName;
266
+ else if (tryResolvePackage(scopedName)) result = scopedName;
267
+ else result = standardName;
268
+ }
269
+ pluginNameCache.set(pluginName, result);
270
+ return result;
271
+ };
272
+ const extractPluginId = (ruleId) => {
273
+ const firstSlash = ruleId.indexOf("/");
274
+ if (firstSlash === -1) return;
275
+ if (ruleId.startsWith("@")) {
276
+ const secondSlash = ruleId.indexOf("/", firstSlash + 1);
277
+ if (secondSlash !== -1) return ruleId.substring(0, secondSlash);
278
+ }
279
+ return ruleId.substring(0, firstSlash);
280
+ };
281
+ const isIgnoredPluginRule = (ruleId) => {
282
+ const pluginName = extractPluginId(ruleId);
283
+ if (pluginName === void 0) return true;
284
+ return ignorePlugins.has(pluginName);
285
+ };
286
+ /**
287
+ * Derives the npm package name for a plugin from its `meta.name` field.
288
+ *
289
+ * If `meta.name` already looks like a full npm package name (contains
290
+ * "eslint-plugin"), it is returned as-is. Otherwise it is fed through
291
+ * {@link resolveEslintPluginName} for the usual heuristic resolution.
292
+ */
293
+ const resolveFromMetaName = (metaName) => {
294
+ if (metaName.includes("eslint-plugin")) return metaName;
295
+ return resolveEslintPluginName(metaName);
296
+ };
297
+ /**
298
+ * Derives the rule-ID prefix that an npm package exposes.
299
+ *
300
+ * Examples:
301
+ * `eslint-plugin-react-dom` -> `react-dom`
302
+ * `eslint-plugin-mocha` -> `mocha`
303
+ * `@stylistic/eslint-plugin` -> `@stylistic`
304
+ * `@stylistic/eslint-plugin-ts` -> `@stylistic/ts`
305
+ */
306
+ const deriveRulePrefix = (packageName) => {
307
+ if (packageName.startsWith("@")) {
308
+ const slashIdx = packageName.indexOf("/");
309
+ const scope = packageName.substring(0, slashIdx);
310
+ const rest = packageName.substring(slashIdx + 1);
311
+ if (rest === "eslint-plugin") return scope;
312
+ if (rest.startsWith("eslint-plugin-")) return `${scope}/${rest.substring(14)}`;
313
+ return packageName;
314
+ }
315
+ if (packageName.startsWith("eslint-plugin-")) return packageName.substring(14);
316
+ return packageName;
317
+ };
318
+ /**
319
+ * Resolves the canonical rule name for a jsPlugin rule.
320
+ *
321
+ * When a plugin is registered under an alias (e.g. `@eslint-react/dom`) but
322
+ * its `meta.name` reveals a different canonical package (`eslint-plugin-react-dom`),
323
+ * the rule must be rewritten so that oxlint can match it to the loaded plugin.
324
+ *
325
+ * For example:
326
+ * `@eslint-react/dom/no-find-dom-node` -> `react-dom/no-find-dom-node`
327
+ */
328
+ const resolveJsPluginRuleName = (rule, plugins) => {
329
+ const pluginName = extractPluginId(rule);
330
+ if (pluginName === void 0) return rule;
331
+ const metaName = plugins?.[pluginName]?.meta?.name;
332
+ if (!metaName || !metaName.includes("eslint-plugin")) return rule;
333
+ const canonicalPrefix = deriveRulePrefix(metaName);
334
+ if (canonicalPrefix === pluginName) return rule;
335
+ return `${canonicalPrefix}/${rule.substring(pluginName.length + 1)}`;
336
+ };
337
+ const enableJsPluginRule = (targetConfig, rule, ruleEntry, plugins) => {
338
+ const pluginName = extractPluginId(rule);
339
+ if (pluginName === void 0) return false;
340
+ if (ignorePlugins.has(pluginName)) return false;
341
+ if (targetConfig.jsPlugins === void 0 || targetConfig.jsPlugins === null) targetConfig.jsPlugins = [];
342
+ const metaName = plugins?.[pluginName]?.meta?.name;
343
+ const eslintPluginName = metaName ? resolveFromMetaName(metaName) : resolveEslintPluginName(pluginName);
344
+ if (!targetConfig.jsPlugins.includes(eslintPluginName)) targetConfig.jsPlugins.push(eslintPluginName);
345
+ const resolvedRule = resolveJsPluginRuleName(rule, plugins);
346
+ targetConfig.rules = targetConfig.rules ?? {};
347
+ targetConfig.rules[resolvedRule] = ruleEntry;
348
+ return true;
349
+ };
350
+ /**
351
+ * Returns true if any rule name matches the given jsPlugin package.
352
+ *
353
+ * Handles aliased plugins where the ESLint registration name differs from the
354
+ * canonical prefix derived from the npm package name:
355
+ * - `@e18e/eslint-plugin` → prefix `@e18e`, but rules may use `e18e/`
356
+ * - `@eslint/eslint-plugin-markdown` → prefix `@eslint/markdown`, but rules
357
+ * may use `markdown/`
358
+ */
359
+ const hasRulesForPlugin = (ruleNames, pluginPackage) => {
360
+ const prefix = deriveRulePrefix(pluginPackage);
361
+ if (ruleNames.some((rule) => rule.startsWith(`${prefix}/`))) return true;
362
+ if (prefix.startsWith("@")) {
363
+ const slashIdx = prefix.indexOf("/");
364
+ const unscoped = slashIdx === -1 ? prefix.substring(1) : prefix.substring(slashIdx + 1);
365
+ return ruleNames.some((rule) => rule.startsWith(`${unscoped}/`));
366
+ }
367
+ return false;
368
+ };
369
+ /**
370
+ * Removes jsPlugin entries that have no corresponding rules left in the config.
371
+ *
372
+ * This can happen when an earlier ESLint config enables a plugin rule (adding the
373
+ * jsPlugin) but a later config (e.g. eslint-config-prettier) turns all of that
374
+ * plugin's rules off (deleting them from the rules object).
375
+ */
376
+ const cleanUpUnusedJsPlugins = (config) => {
377
+ if (config.jsPlugins === void 0 || config.jsPlugins === null || config.jsPlugins.length === 0) return;
378
+ const ruleNames = Object.keys(config.rules ?? {});
379
+ config.jsPlugins = config.jsPlugins.filter((entry) => {
380
+ return hasRulesForPlugin(ruleNames, typeof entry === "string" ? entry : entry.specifier);
381
+ });
382
+ if (config.jsPlugins.length === 0) delete config.jsPlugins;
383
+ };
384
+ //#endregion
168
385
  //#region src/generated/rules.ts
169
386
  var rules_exports = /* @__PURE__ */ __exportAll({
170
387
  correctnessRules: () => correctnessRules,
@@ -222,31 +439,31 @@ const pedanticRules = [
222
439
  "react/jsx-no-target-blank",
223
440
  "react/jsx-no-useless-fragment",
224
441
  "react/no-unescaped-entities",
225
- "react-hooks/rules-of-hooks",
226
- "@typescript-eslint/ban-ts-comment",
227
- "@typescript-eslint/ban-types",
228
- "@typescript-eslint/no-confusing-void-expression",
229
- "@typescript-eslint/no-deprecated",
230
- "@typescript-eslint/no-misused-promises",
231
- "@typescript-eslint/no-mixed-enums",
232
- "@typescript-eslint/no-unsafe-argument",
233
- "@typescript-eslint/no-unsafe-assignment",
234
- "@typescript-eslint/no-unsafe-call",
235
- "@typescript-eslint/no-unsafe-function-type",
236
- "@typescript-eslint/no-unsafe-member-access",
237
- "@typescript-eslint/no-unsafe-return",
238
- "@typescript-eslint/only-throw-error",
239
- "@typescript-eslint/prefer-enum-initializers",
240
- "@typescript-eslint/prefer-includes",
241
- "@typescript-eslint/prefer-nullish-coalescing",
242
- "@typescript-eslint/prefer-promise-reject-errors",
243
- "@typescript-eslint/prefer-ts-expect-error",
244
- "@typescript-eslint/related-getter-setter-pairs",
245
- "@typescript-eslint/require-await",
246
- "@typescript-eslint/restrict-plus-operands",
247
- "@typescript-eslint/return-await",
248
- "@typescript-eslint/strict-boolean-expressions",
249
- "@typescript-eslint/switch-exhaustiveness-check",
442
+ "react/rules-of-hooks",
443
+ "typescript/ban-ts-comment",
444
+ "typescript/ban-types",
445
+ "typescript/no-confusing-void-expression",
446
+ "typescript/no-deprecated",
447
+ "typescript/no-misused-promises",
448
+ "typescript/no-mixed-enums",
449
+ "typescript/no-unsafe-argument",
450
+ "typescript/no-unsafe-assignment",
451
+ "typescript/no-unsafe-call",
452
+ "typescript/no-unsafe-function-type",
453
+ "typescript/no-unsafe-member-access",
454
+ "typescript/no-unsafe-return",
455
+ "typescript/only-throw-error",
456
+ "typescript/prefer-enum-initializers",
457
+ "typescript/prefer-includes",
458
+ "typescript/prefer-nullish-coalescing",
459
+ "typescript/prefer-promise-reject-errors",
460
+ "typescript/prefer-ts-expect-error",
461
+ "typescript/related-getter-setter-pairs",
462
+ "typescript/require-await",
463
+ "typescript/restrict-plus-operands",
464
+ "typescript/return-await",
465
+ "typescript/strict-boolean-expressions",
466
+ "typescript/switch-exhaustiveness-check",
250
467
  "unicorn/consistent-assert",
251
468
  "unicorn/consistent-empty-array-spread",
252
469
  "unicorn/escape-case",
@@ -280,6 +497,7 @@ const pedanticRules = [
280
497
  "unicorn/prefer-dom-node-dataset",
281
498
  "unicorn/prefer-dom-node-remove",
282
499
  "unicorn/prefer-event-target",
500
+ "unicorn/prefer-import-meta-properties",
283
501
  "unicorn/prefer-math-min-max",
284
502
  "unicorn/prefer-math-trunc",
285
503
  "unicorn/prefer-native-coercion-functions",
@@ -291,11 +509,10 @@ const pedanticRules = [
291
509
  "unicorn/prefer-top-level-await",
292
510
  "unicorn/prefer-type-error",
293
511
  "unicorn/require-number-to-fixed-digits-argument",
294
- "@typescript-eslint/no-array-constructor",
295
- "@typescript-eslint/no-loop-func",
512
+ "typescript/no-array-constructor",
513
+ "typescript/no-loop-func",
296
514
  "unicorn/no-negated-condition",
297
- "@typescript-eslint/no-redeclare",
298
- "import-x/max-dependencies",
515
+ "typescript/no-redeclare",
299
516
  "vitest/no-conditional-in-test"
300
517
  ];
301
518
  const styleRules = [
@@ -330,6 +547,7 @@ const styleRules = [
330
547
  "no-template-curly-in-string",
331
548
  "no-ternary",
332
549
  "no-useless-computed-key",
550
+ "object-shorthand",
333
551
  "operator-assignment",
334
552
  "prefer-const",
335
553
  "prefer-destructuring",
@@ -377,6 +595,7 @@ const styleRules = [
377
595
  "jest/no-test-return-statement",
378
596
  "jest/no-unneeded-async-expect-function",
379
597
  "jest/no-untyped-mock-factory",
598
+ "jest/padding-around-after-all-blocks",
380
599
  "jest/padding-around-test-blocks",
381
600
  "jest/prefer-called-with",
382
601
  "jest/prefer-comparison-matcher",
@@ -408,6 +627,7 @@ const styleRules = [
408
627
  "promise/prefer-await-to-callbacks",
409
628
  "promise/prefer-await-to-then",
410
629
  "promise/prefer-catch",
630
+ "react/hook-use-state",
411
631
  "react/jsx-boolean-value",
412
632
  "react/jsx-curly-brace-presence",
413
633
  "react/jsx-fragments",
@@ -420,23 +640,29 @@ const styleRules = [
420
640
  "react/prefer-es6-class",
421
641
  "react/self-closing-comp",
422
642
  "react/state-in-constructor",
423
- "@typescript-eslint/adjacent-overload-signatures",
424
- "@typescript-eslint/array-type",
425
- "@typescript-eslint/ban-tslint-comment",
426
- "@typescript-eslint/class-literal-property-style",
427
- "@typescript-eslint/consistent-generic-constructors",
428
- "@typescript-eslint/consistent-indexed-object-style",
429
- "@typescript-eslint/consistent-type-assertions",
430
- "@typescript-eslint/consistent-type-definitions",
431
- "@typescript-eslint/consistent-type-imports",
432
- "@typescript-eslint/no-empty-interface",
433
- "@typescript-eslint/no-inferrable-types",
434
- "@typescript-eslint/parameter-properties",
435
- "@typescript-eslint/prefer-for-of",
436
- "@typescript-eslint/prefer-function-type",
437
- "@typescript-eslint/prefer-reduce-type-parameter",
438
- "@typescript-eslint/prefer-return-this-type",
439
- "@typescript-eslint/unified-signatures",
643
+ "typescript/adjacent-overload-signatures",
644
+ "typescript/array-type",
645
+ "typescript/ban-tslint-comment",
646
+ "typescript/class-literal-property-style",
647
+ "typescript/consistent-generic-constructors",
648
+ "typescript/consistent-indexed-object-style",
649
+ "typescript/consistent-type-assertions",
650
+ "typescript/consistent-type-definitions",
651
+ "typescript/consistent-type-exports",
652
+ "typescript/consistent-type-imports",
653
+ "typescript/dot-notation",
654
+ "typescript/no-empty-interface",
655
+ "typescript/no-inferrable-types",
656
+ "typescript/parameter-properties",
657
+ "typescript/prefer-find",
658
+ "typescript/prefer-for-of",
659
+ "typescript/prefer-function-type",
660
+ "typescript/prefer-readonly",
661
+ "typescript/prefer-reduce-type-parameter",
662
+ "typescript/prefer-regexp-exec",
663
+ "typescript/prefer-return-this-type",
664
+ "typescript/prefer-string-starts-ends-with",
665
+ "typescript/unified-signatures",
440
666
  "unicorn/catch-error-name",
441
667
  "unicorn/consistent-date-clone",
442
668
  "unicorn/consistent-existence-index-check",
@@ -479,17 +705,20 @@ const styleRules = [
479
705
  "unicorn/require-array-join-separator",
480
706
  "unicorn/require-module-attributes",
481
707
  "unicorn/switch-case-braces",
708
+ "unicorn/switch-case-break-position",
482
709
  "unicorn/text-encoding-identifier-case",
483
710
  "unicorn/throw-new-error",
484
711
  "vitest/consistent-test-filename",
485
712
  "vitest/consistent-vitest-vi",
486
713
  "vitest/no-import-node-test",
487
714
  "vitest/no-importing-vitest-globals",
715
+ "vitest/prefer-called-exactly-once-with",
488
716
  "vitest/prefer-called-once",
489
717
  "vitest/prefer-called-times",
490
718
  "vitest/prefer-describe-function-title",
491
719
  "vitest/prefer-expect-type-of",
492
720
  "vitest/prefer-import-in-mock",
721
+ "vitest/prefer-importing-vitest-globals",
493
722
  "vitest/prefer-strict-boolean-matchers",
494
723
  "vitest/prefer-to-be-falsy",
495
724
  "vitest/prefer-to-be-object",
@@ -498,22 +727,10 @@ const styleRules = [
498
727
  "vue/define-props-declaration",
499
728
  "vue/define-props-destructuring",
500
729
  "vue/require-typed-ref",
501
- "@typescript-eslint/default-param-last",
502
- "@typescript-eslint/init-declarations",
503
- "@typescript-eslint/max-params",
504
- "@typescript-eslint/no-magic-numbers",
505
- "import-x/consistent-type-specifier-style",
506
- "import-x/exports-last",
507
- "import-x/first",
508
- "import-x/group-exports",
509
- "import-x/no-anonymous-default-export",
510
- "import-x/no-duplicates",
511
- "import-x/no-mutable-exports",
512
- "import-x/no-named-default",
513
- "import-x/no-named-export",
514
- "import-x/no-namespace",
515
- "import-x/no-nodejs-modules",
516
- "import-x/prefer-default-export",
730
+ "typescript/default-param-last",
731
+ "typescript/init-declarations",
732
+ "typescript/max-params",
733
+ "typescript/no-magic-numbers",
517
734
  "vitest/consistent-test-it",
518
735
  "vitest/max-expects",
519
736
  "vitest/max-nested-describe",
@@ -543,12 +760,11 @@ const styleRules = [
543
760
  "vitest/prefer-strict-equal",
544
761
  "vitest/prefer-to-be",
545
762
  "vitest/prefer-to-contain",
763
+ "vitest/prefer-to-have-been-called-times",
546
764
  "vitest/prefer-to-have-length",
547
765
  "vitest/prefer-todo",
548
766
  "vitest/require-hook",
549
- "vitest/require-top-level-describe",
550
- "n/global-require",
551
- "n/no-exports-assign"
767
+ "vitest/require-top-level-describe"
552
768
  ];
553
769
  const suspiciousRules = [
554
770
  "block-scoped-var",
@@ -578,15 +794,17 @@ const suspiciousRules = [
578
794
  "react/no-namespace",
579
795
  "react/react-in-jsx-scope",
580
796
  "react/style-prop-object",
581
- "@typescript-eslint/no-confusing-non-null-assertion",
582
- "@typescript-eslint/no-extraneous-class",
583
- "@typescript-eslint/no-unnecessary-boolean-literal-compare",
584
- "@typescript-eslint/no-unnecessary-template-expression",
585
- "@typescript-eslint/no-unnecessary-type-arguments",
586
- "@typescript-eslint/no-unnecessary-type-assertion",
587
- "@typescript-eslint/no-unnecessary-type-constraint",
588
- "@typescript-eslint/no-unsafe-enum-comparison",
589
- "@typescript-eslint/no-unsafe-type-assertion",
797
+ "typescript/consistent-return",
798
+ "typescript/no-confusing-non-null-assertion",
799
+ "typescript/no-extraneous-class",
800
+ "typescript/no-unnecessary-boolean-literal-compare",
801
+ "typescript/no-unnecessary-template-expression",
802
+ "typescript/no-unnecessary-type-arguments",
803
+ "typescript/no-unnecessary-type-assertion",
804
+ "typescript/no-unnecessary-type-constraint",
805
+ "typescript/no-unnecessary-type-conversion",
806
+ "typescript/no-unsafe-enum-comparison",
807
+ "typescript/no-unsafe-type-assertion",
590
808
  "unicorn/consistent-function-scoping",
591
809
  "unicorn/no-accessor-recursion",
592
810
  "unicorn/no-array-reverse",
@@ -597,14 +815,8 @@ const suspiciousRules = [
597
815
  "unicorn/require-post-message-target-origin",
598
816
  "vue/no-required-prop-with-default",
599
817
  "vue/require-default-export",
600
- "@typescript-eslint/no-shadow",
601
- "@typescript-eslint/no-useless-constructor",
602
- "import-x/no-absolute-path",
603
- "import-x/no-empty-named-blocks",
604
- "import-x/no-named-as-default",
605
- "import-x/no-named-as-default-member",
606
- "import-x/no-self-import",
607
- "import-x/no-unassigned-import",
818
+ "typescript/no-shadow",
819
+ "typescript/no-useless-constructor",
608
820
  "vitest/no-commented-out-tests"
609
821
  ];
610
822
  const restrictionRules = [
@@ -658,23 +870,24 @@ const restrictionRules = [
658
870
  "react/no-react-children",
659
871
  "react/no-unknown-property",
660
872
  "react/only-export-components",
661
- "@typescript-eslint/explicit-function-return-type",
662
- "@typescript-eslint/explicit-module-boundary-types",
663
- "@typescript-eslint/no-dynamic-delete",
664
- "@typescript-eslint/no-empty-object-type",
665
- "@typescript-eslint/no-explicit-any",
666
- "@typescript-eslint/no-import-type-side-effects",
667
- "@typescript-eslint/no-invalid-void-type",
668
- "@typescript-eslint/no-namespace",
669
- "@typescript-eslint/no-non-null-asserted-nullish-coalescing",
670
- "@typescript-eslint/no-non-null-assertion",
671
- "@typescript-eslint/no-require-imports",
672
- "@typescript-eslint/no-restricted-types",
673
- "@typescript-eslint/no-var-requires",
674
- "@typescript-eslint/non-nullable-type-assertion-style",
675
- "@typescript-eslint/prefer-literal-enum-member",
676
- "@typescript-eslint/promise-function-async",
677
- "@typescript-eslint/use-unknown-in-catch-callback-variable",
873
+ "react/prefer-function-component",
874
+ "typescript/explicit-function-return-type",
875
+ "typescript/explicit-module-boundary-types",
876
+ "typescript/no-dynamic-delete",
877
+ "typescript/no-empty-object-type",
878
+ "typescript/no-explicit-any",
879
+ "typescript/no-import-type-side-effects",
880
+ "typescript/no-invalid-void-type",
881
+ "typescript/no-namespace",
882
+ "typescript/no-non-null-asserted-nullish-coalescing",
883
+ "typescript/no-non-null-assertion",
884
+ "typescript/no-require-imports",
885
+ "typescript/no-restricted-types",
886
+ "typescript/no-var-requires",
887
+ "typescript/non-nullable-type-assertion-style",
888
+ "typescript/prefer-literal-enum-member",
889
+ "typescript/promise-function-async",
890
+ "typescript/use-unknown-in-catch-callback-variable",
678
891
  "unicorn/no-abusive-eslint-disable",
679
892
  "unicorn/no-anonymous-default-export",
680
893
  "unicorn/no-array-for-each",
@@ -688,27 +901,14 @@ const restrictionRules = [
688
901
  "unicorn/prefer-module",
689
902
  "unicorn/prefer-node-protocol",
690
903
  "unicorn/prefer-number-properties",
904
+ "vitest/require-test-timeout",
691
905
  "vue/max-props",
692
906
  "vue/no-import-compiler-macros",
693
907
  "vue/no-multiple-slot-args",
694
- "@typescript-eslint/class-methods-use-this",
695
- "@typescript-eslint/no-empty-function",
696
- "@typescript-eslint/no-restricted-imports",
697
- "@typescript-eslint/no-use-before-define",
698
- "import-x/extensions",
699
- "import-x/no-amd",
700
- "import-x/no-commonjs",
701
- "import-x/no-cycle",
702
- "import-x/no-default-export",
703
- "import-x/no-dynamic-require",
704
- "import-x/no-relative-parent-imports",
705
- "import-x/no-webpack-loader-syntax",
706
- "import-x/unambiguous",
707
- "n/handle-callback-err",
708
- "n/no-new-require",
709
- "n/no-path-concat",
710
- "n/no-process-env",
711
- "react-refresh/only-export-components"
908
+ "typescript/class-methods-use-this",
909
+ "typescript/no-empty-function",
910
+ "typescript/no-restricted-imports",
911
+ "typescript/no-use-before-define"
712
912
  ];
713
913
  const correctnessRules = [
714
914
  "constructor-super",
@@ -774,6 +974,7 @@ const correctnessRules = [
774
974
  "jest/no-export",
775
975
  "jest/no-focused-tests",
776
976
  "jest/no-standalone-expect",
977
+ "jest/prefer-snapshot-hint",
777
978
  "jest/require-to-throw-message",
778
979
  "jest/valid-describe-callback",
779
980
  "jest/valid-expect",
@@ -817,31 +1018,31 @@ const correctnessRules = [
817
1018
  "jsx-a11y/role-supports-aria-props",
818
1019
  "jsx-a11y/scope",
819
1020
  "jsx-a11y/tabindex-no-positive",
820
- "@next/next/google-font-display",
821
- "@next/next/google-font-preconnect",
822
- "@next/next/inline-script-id",
823
- "@next/next/next-script-for-ga",
824
- "@next/next/no-assign-module-variable",
825
- "@next/next/no-async-client-component",
826
- "@next/next/no-before-interactive-script-outside-document",
827
- "@next/next/no-css-tags",
828
- "@next/next/no-document-import-in-page",
829
- "@next/next/no-duplicate-head",
830
- "@next/next/no-head-element",
831
- "@next/next/no-head-import-in-document",
832
- "@next/next/no-html-link-for-pages",
833
- "@next/next/no-img-element",
834
- "@next/next/no-page-custom-font",
835
- "@next/next/no-script-component-in-head",
836
- "@next/next/no-styled-jsx-in-document",
837
- "@next/next/no-sync-scripts",
838
- "@next/next/no-title-in-document-head",
839
- "@next/next/no-typos",
840
- "@next/next/no-unwanted-polyfillio",
1021
+ "nextjs/google-font-display",
1022
+ "nextjs/google-font-preconnect",
1023
+ "nextjs/inline-script-id",
1024
+ "nextjs/next-script-for-ga",
1025
+ "nextjs/no-assign-module-variable",
1026
+ "nextjs/no-async-client-component",
1027
+ "nextjs/no-before-interactive-script-outside-document",
1028
+ "nextjs/no-css-tags",
1029
+ "nextjs/no-document-import-in-page",
1030
+ "nextjs/no-duplicate-head",
1031
+ "nextjs/no-head-element",
1032
+ "nextjs/no-head-import-in-document",
1033
+ "nextjs/no-html-link-for-pages",
1034
+ "nextjs/no-img-element",
1035
+ "nextjs/no-page-custom-font",
1036
+ "nextjs/no-script-component-in-head",
1037
+ "nextjs/no-styled-jsx-in-document",
1038
+ "nextjs/no-sync-scripts",
1039
+ "nextjs/no-title-in-document-head",
1040
+ "nextjs/no-typos",
1041
+ "nextjs/no-unwanted-polyfillio",
841
1042
  "promise/no-callback-in-promise",
842
1043
  "promise/no-new-statics",
843
1044
  "promise/valid-params",
844
- "react-hooks/exhaustive-deps",
1045
+ "react/exhaustive-deps",
845
1046
  "react/forward-ref-uses-ref",
846
1047
  "react/jsx-key",
847
1048
  "react/jsx-no-duplicate-props",
@@ -859,32 +1060,32 @@ const correctnessRules = [
859
1060
  "react/no-unsafe",
860
1061
  "react/no-will-update-set-state",
861
1062
  "react/void-dom-elements-no-children",
862
- "@typescript-eslint/await-thenable",
863
- "@typescript-eslint/no-array-delete",
864
- "@typescript-eslint/no-base-to-string",
865
- "@typescript-eslint/no-duplicate-enum-values",
866
- "@typescript-eslint/no-duplicate-type-constituents",
867
- "@typescript-eslint/no-extra-non-null-assertion",
868
- "@typescript-eslint/no-floating-promises",
869
- "@typescript-eslint/no-for-in-array",
870
- "@typescript-eslint/no-implied-eval",
871
- "@typescript-eslint/no-meaningless-void-operator",
872
- "@typescript-eslint/no-misused-new",
873
- "@typescript-eslint/no-misused-spread",
874
- "@typescript-eslint/no-non-null-asserted-optional-chain",
875
- "@typescript-eslint/no-redundant-type-constituents",
876
- "@typescript-eslint/no-this-alias",
877
- "@typescript-eslint/no-unnecessary-parameter-property-assignment",
878
- "@typescript-eslint/no-unsafe-declaration-merging",
879
- "@typescript-eslint/no-unsafe-unary-minus",
880
- "@typescript-eslint/no-useless-empty-export",
881
- "@typescript-eslint/no-wrapper-object-types",
882
- "@typescript-eslint/prefer-as-const",
883
- "@typescript-eslint/prefer-namespace-keyword",
884
- "@typescript-eslint/require-array-sort-compare",
885
- "@typescript-eslint/restrict-template-expressions",
886
- "@typescript-eslint/triple-slash-reference",
887
- "@typescript-eslint/unbound-method",
1063
+ "typescript/await-thenable",
1064
+ "typescript/no-array-delete",
1065
+ "typescript/no-base-to-string",
1066
+ "typescript/no-duplicate-enum-values",
1067
+ "typescript/no-duplicate-type-constituents",
1068
+ "typescript/no-extra-non-null-assertion",
1069
+ "typescript/no-floating-promises",
1070
+ "typescript/no-for-in-array",
1071
+ "typescript/no-implied-eval",
1072
+ "typescript/no-meaningless-void-operator",
1073
+ "typescript/no-misused-new",
1074
+ "typescript/no-misused-spread",
1075
+ "typescript/no-non-null-asserted-optional-chain",
1076
+ "typescript/no-redundant-type-constituents",
1077
+ "typescript/no-this-alias",
1078
+ "typescript/no-unnecessary-parameter-property-assignment",
1079
+ "typescript/no-unsafe-declaration-merging",
1080
+ "typescript/no-unsafe-unary-minus",
1081
+ "typescript/no-useless-empty-export",
1082
+ "typescript/no-wrapper-object-types",
1083
+ "typescript/prefer-as-const",
1084
+ "typescript/prefer-namespace-keyword",
1085
+ "typescript/require-array-sort-compare",
1086
+ "typescript/restrict-template-expressions",
1087
+ "typescript/triple-slash-reference",
1088
+ "typescript/unbound-method",
888
1089
  "unicorn/no-await-in-promise-methods",
889
1090
  "unicorn/no-empty-file",
890
1091
  "unicorn/no-invalid-fetch-options",
@@ -901,7 +1102,9 @@ const correctnessRules = [
901
1102
  "vitest/consistent-each-for",
902
1103
  "vitest/hoisted-apis-on-top",
903
1104
  "vitest/no-conditional-tests",
1105
+ "vitest/require-awaited-expect-poll",
904
1106
  "vitest/require-local-test-context-for-concurrent-snapshots",
1107
+ "vitest/require-mock-type-parameters",
905
1108
  "vitest/warn-todo",
906
1109
  "vue/no-arrow-functions-in-watch",
907
1110
  "vue/no-deprecated-destroyed-lifecycle",
@@ -911,46 +1114,39 @@ const correctnessRules = [
911
1114
  "vue/prefer-import-from-vue",
912
1115
  "vue/valid-define-emits",
913
1116
  "vue/valid-define-props",
914
- "@typescript-eslint/no-dupe-class-members",
915
- "@typescript-eslint/no-loss-of-precision",
916
- "@typescript-eslint/no-unused-expressions",
917
- "@typescript-eslint/no-unused-vars",
918
- "import-x/default",
919
- "import-x/namespace",
1117
+ "typescript/no-dupe-class-members",
1118
+ "typescript/no-loss-of-precision",
1119
+ "typescript/no-unused-expressions",
1120
+ "typescript/no-unused-vars",
920
1121
  "vitest/expect-expect",
921
1122
  "vitest/no-conditional-expect",
922
1123
  "vitest/no-disabled-tests",
923
1124
  "vitest/no-focused-tests",
924
1125
  "vitest/no-standalone-expect",
1126
+ "vitest/prefer-snapshot-hint",
925
1127
  "vitest/require-to-throw-message",
926
1128
  "vitest/valid-describe-callback",
927
- "vitest/valid-expect"
1129
+ "vitest/valid-expect",
1130
+ "vitest/valid-title"
928
1131
  ];
929
1132
  const nurseryRules = [
930
1133
  "getter-return",
1134
+ "no-restricted-exports",
931
1135
  "no-undef",
932
1136
  "no-unreachable",
1137
+ "no-useless-assignment",
933
1138
  "import/export",
934
1139
  "import/named",
935
1140
  "promise/no-return-in-finally",
936
1141
  "react/require-render-return",
937
- "@typescript-eslint/consistent-return",
938
- "@typescript-eslint/consistent-type-exports",
939
- "@typescript-eslint/dot-notation",
940
- "@typescript-eslint/no-unnecessary-condition",
941
- "@typescript-eslint/no-unnecessary-qualifier",
942
- "@typescript-eslint/no-unnecessary-type-conversion",
943
- "@typescript-eslint/no-unnecessary-type-parameters",
944
- "@typescript-eslint/no-useless-default-assignment",
945
- "@typescript-eslint/prefer-find",
946
- "@typescript-eslint/prefer-optional-chain",
947
- "@typescript-eslint/prefer-readonly",
948
- "@typescript-eslint/prefer-readonly-parameter-types",
949
- "@typescript-eslint/prefer-regexp-exec",
950
- "@typescript-eslint/prefer-string-starts-ends-with",
951
- "@typescript-eslint/strict-void-return",
952
- "import-x/export",
953
- "import-x/named"
1142
+ "typescript/no-unnecessary-condition",
1143
+ "typescript/no-unnecessary-qualifier",
1144
+ "typescript/no-unnecessary-type-parameters",
1145
+ "typescript/no-useless-default-assignment",
1146
+ "typescript/prefer-optional-chain",
1147
+ "typescript/prefer-readonly-parameter-types",
1148
+ "typescript/strict-void-return",
1149
+ "unicorn/no-useless-iterator-to-array"
954
1150
  ];
955
1151
  const perfRules = [
956
1152
  "no-await-in-loop",
@@ -966,239 +1162,67 @@ const perfRules = [
966
1162
  "unicorn/prefer-set-has"
967
1163
  ];
968
1164
  const typeAwareRules = [
969
- "@typescript-eslint/await-thenable",
970
- "@typescript-eslint/consistent-return",
971
- "@typescript-eslint/consistent-type-exports",
972
- "@typescript-eslint/dot-notation",
973
- "@typescript-eslint/no-array-delete",
974
- "@typescript-eslint/no-base-to-string",
975
- "@typescript-eslint/no-confusing-void-expression",
976
- "@typescript-eslint/no-deprecated",
977
- "@typescript-eslint/no-duplicate-type-constituents",
978
- "@typescript-eslint/no-floating-promises",
979
- "@typescript-eslint/no-for-in-array",
980
- "@typescript-eslint/no-implied-eval",
981
- "@typescript-eslint/no-meaningless-void-operator",
982
- "@typescript-eslint/no-misused-promises",
983
- "@typescript-eslint/no-misused-spread",
984
- "@typescript-eslint/no-mixed-enums",
985
- "@typescript-eslint/no-redundant-type-constituents",
986
- "@typescript-eslint/no-unnecessary-boolean-literal-compare",
987
- "@typescript-eslint/no-unnecessary-condition",
988
- "@typescript-eslint/no-unnecessary-qualifier",
989
- "@typescript-eslint/no-unnecessary-template-expression",
990
- "@typescript-eslint/no-unnecessary-type-arguments",
991
- "@typescript-eslint/no-unnecessary-type-assertion",
992
- "@typescript-eslint/no-unnecessary-type-conversion",
993
- "@typescript-eslint/no-unnecessary-type-parameters",
994
- "@typescript-eslint/no-unsafe-argument",
995
- "@typescript-eslint/no-unsafe-assignment",
996
- "@typescript-eslint/no-unsafe-call",
997
- "@typescript-eslint/no-unsafe-enum-comparison",
998
- "@typescript-eslint/no-unsafe-member-access",
999
- "@typescript-eslint/no-unsafe-return",
1000
- "@typescript-eslint/no-unsafe-type-assertion",
1001
- "@typescript-eslint/no-unsafe-unary-minus",
1002
- "@typescript-eslint/no-useless-default-assignment",
1003
- "@typescript-eslint/non-nullable-type-assertion-style",
1004
- "@typescript-eslint/only-throw-error",
1005
- "@typescript-eslint/prefer-find",
1006
- "@typescript-eslint/prefer-includes",
1007
- "@typescript-eslint/prefer-nullish-coalescing",
1008
- "@typescript-eslint/prefer-optional-chain",
1009
- "@typescript-eslint/prefer-promise-reject-errors",
1010
- "@typescript-eslint/prefer-readonly",
1011
- "@typescript-eslint/prefer-readonly-parameter-types",
1012
- "@typescript-eslint/prefer-reduce-type-parameter",
1013
- "@typescript-eslint/prefer-regexp-exec",
1014
- "@typescript-eslint/prefer-return-this-type",
1015
- "@typescript-eslint/prefer-string-starts-ends-with",
1016
- "@typescript-eslint/promise-function-async",
1017
- "@typescript-eslint/related-getter-setter-pairs",
1018
- "@typescript-eslint/require-array-sort-compare",
1019
- "@typescript-eslint/require-await",
1020
- "@typescript-eslint/restrict-plus-operands",
1021
- "@typescript-eslint/restrict-template-expressions",
1022
- "@typescript-eslint/return-await",
1023
- "@typescript-eslint/strict-boolean-expressions",
1024
- "@typescript-eslint/strict-void-return",
1025
- "@typescript-eslint/switch-exhaustiveness-check",
1026
- "@typescript-eslint/unbound-method",
1027
- "@typescript-eslint/use-unknown-in-catch-callback-variable"
1165
+ "typescript/await-thenable",
1166
+ "typescript/consistent-return",
1167
+ "typescript/consistent-type-exports",
1168
+ "typescript/dot-notation",
1169
+ "typescript/no-array-delete",
1170
+ "typescript/no-base-to-string",
1171
+ "typescript/no-confusing-void-expression",
1172
+ "typescript/no-deprecated",
1173
+ "typescript/no-duplicate-type-constituents",
1174
+ "typescript/no-floating-promises",
1175
+ "typescript/no-for-in-array",
1176
+ "typescript/no-implied-eval",
1177
+ "typescript/no-meaningless-void-operator",
1178
+ "typescript/no-misused-promises",
1179
+ "typescript/no-misused-spread",
1180
+ "typescript/no-mixed-enums",
1181
+ "typescript/no-redundant-type-constituents",
1182
+ "typescript/no-unnecessary-boolean-literal-compare",
1183
+ "typescript/no-unnecessary-condition",
1184
+ "typescript/no-unnecessary-qualifier",
1185
+ "typescript/no-unnecessary-template-expression",
1186
+ "typescript/no-unnecessary-type-arguments",
1187
+ "typescript/no-unnecessary-type-assertion",
1188
+ "typescript/no-unnecessary-type-conversion",
1189
+ "typescript/no-unnecessary-type-parameters",
1190
+ "typescript/no-unsafe-argument",
1191
+ "typescript/no-unsafe-assignment",
1192
+ "typescript/no-unsafe-call",
1193
+ "typescript/no-unsafe-enum-comparison",
1194
+ "typescript/no-unsafe-member-access",
1195
+ "typescript/no-unsafe-return",
1196
+ "typescript/no-unsafe-type-assertion",
1197
+ "typescript/no-unsafe-unary-minus",
1198
+ "typescript/no-useless-default-assignment",
1199
+ "typescript/non-nullable-type-assertion-style",
1200
+ "typescript/only-throw-error",
1201
+ "typescript/prefer-find",
1202
+ "typescript/prefer-includes",
1203
+ "typescript/prefer-nullish-coalescing",
1204
+ "typescript/prefer-optional-chain",
1205
+ "typescript/prefer-promise-reject-errors",
1206
+ "typescript/prefer-readonly",
1207
+ "typescript/prefer-readonly-parameter-types",
1208
+ "typescript/prefer-reduce-type-parameter",
1209
+ "typescript/prefer-regexp-exec",
1210
+ "typescript/prefer-return-this-type",
1211
+ "typescript/prefer-string-starts-ends-with",
1212
+ "typescript/promise-function-async",
1213
+ "typescript/related-getter-setter-pairs",
1214
+ "typescript/require-array-sort-compare",
1215
+ "typescript/require-await",
1216
+ "typescript/restrict-plus-operands",
1217
+ "typescript/restrict-template-expressions",
1218
+ "typescript/return-await",
1219
+ "typescript/strict-boolean-expressions",
1220
+ "typescript/strict-void-return",
1221
+ "typescript/switch-exhaustiveness-check",
1222
+ "typescript/unbound-method",
1223
+ "typescript/use-unknown-in-catch-callback-variable"
1028
1224
  ];
1029
1225
  //#endregion
1030
- //#region src/constants.ts
1031
- const rulesPrefixesForPlugins = {
1032
- import: "import",
1033
- "import-x": "import",
1034
- jest: "jest",
1035
- jsdoc: "jsdoc",
1036
- "jsx-a11y": "jsx-a11y",
1037
- "@next/next": "nextjs",
1038
- node: "node",
1039
- n: "node",
1040
- promise: "promise",
1041
- react: "react",
1042
- "react-perf": "react-perf",
1043
- "react-hooks": "react",
1044
- "react-refresh": "react",
1045
- "@typescript-eslint": "typescript",
1046
- unicorn: "unicorn",
1047
- vitest: "vitest",
1048
- vue: "vue"
1049
- };
1050
- const eslintRulesToTypescriptEquivalents = {
1051
- "dot-notation": "@typescript-eslint/dot-notation",
1052
- "consistent-return": "@typescript-eslint/consistent-return"
1053
- };
1054
- const typescriptRulesExtendEslintRules = [
1055
- "class-methods-use-this",
1056
- "default-param-last",
1057
- "init-declarations",
1058
- "max-params",
1059
- "no-array-constructor",
1060
- "no-dupe-class-members",
1061
- "no-empty-function",
1062
- "no-invalid-this",
1063
- "no-loop-func",
1064
- "no-loss-of-precision",
1065
- "no-magic-numbers",
1066
- "no-redeclare",
1067
- "no-restricted-imports",
1068
- "no-shadow",
1069
- "no-unused-expressions",
1070
- "no-unused-vars",
1071
- "no-use-before-define",
1072
- "no-useless-constructor"
1073
- ];
1074
- //#endregion
1075
- //#region src/jsPlugins.ts
1076
- const ignorePlugins = new Set([
1077
- ...Object.keys(rulesPrefixesForPlugins),
1078
- ...Object.values(rulesPrefixesForPlugins),
1079
- "local"
1080
- ]);
1081
- const tryResolvePackage = (packageName) => {
1082
- try {
1083
- import.meta.resolve(packageName);
1084
- return true;
1085
- } catch {
1086
- return false;
1087
- }
1088
- };
1089
- const pluginNameCache = /* @__PURE__ */ new Map();
1090
- /**
1091
- * Resolves the npm package name for an ESLint plugin given its scope name.
1092
- *
1093
- * For scoped plugin names (starting with `@`), the mapping is unambiguous:
1094
- * - `@scope` -> `@scope/eslint-plugin`
1095
- * - `@scope/sub` -> `@scope/eslint-plugin-sub`
1096
- *
1097
- * For non-scoped names, the npm package could follow either convention:
1098
- * - `eslint-plugin-{name}` (e.g. `eslint-plugin-mocha`)
1099
- * - `@{name}/eslint-plugin` (e.g. `@e18e/eslint-plugin`)
1100
- *
1101
- * We try to resolve both candidates against the installed packages and
1102
- * use the one that is actually present, falling back to the standard
1103
- * `eslint-plugin-{name}` convention when neither can be resolved.
1104
- */
1105
- const resolveEslintPluginName = (pluginName) => {
1106
- const cached = pluginNameCache.get(pluginName);
1107
- if (cached !== void 0) return cached;
1108
- let result;
1109
- if (pluginName.startsWith("@")) {
1110
- const [scope, maybeSub] = pluginName.split("/");
1111
- if (maybeSub) result = `${scope}/eslint-plugin-${maybeSub}`;
1112
- else result = `${scope}/eslint-plugin`;
1113
- } else {
1114
- const standardName = `eslint-plugin-${pluginName}`;
1115
- const scopedName = `@${pluginName}/eslint-plugin`;
1116
- if (tryResolvePackage(standardName)) result = standardName;
1117
- else if (tryResolvePackage(scopedName)) result = scopedName;
1118
- else result = standardName;
1119
- }
1120
- pluginNameCache.set(pluginName, result);
1121
- return result;
1122
- };
1123
- const extractPluginId = (ruleId) => {
1124
- const firstSlash = ruleId.indexOf("/");
1125
- if (firstSlash === -1) return;
1126
- if (ruleId.startsWith("@")) {
1127
- const secondSlash = ruleId.indexOf("/", firstSlash + 1);
1128
- if (secondSlash !== -1) return ruleId.substring(0, secondSlash);
1129
- }
1130
- return ruleId.substring(0, firstSlash);
1131
- };
1132
- const isIgnoredPluginRule = (ruleId) => {
1133
- const pluginName = extractPluginId(ruleId);
1134
- if (pluginName === void 0) return true;
1135
- return ignorePlugins.has(pluginName);
1136
- };
1137
- /**
1138
- * Derives the npm package name for a plugin from its `meta.name` field.
1139
- *
1140
- * If `meta.name` already looks like a full npm package name (contains
1141
- * "eslint-plugin"), it is returned as-is. Otherwise it is fed through
1142
- * {@link resolveEslintPluginName} for the usual heuristic resolution.
1143
- */
1144
- const resolveFromMetaName = (metaName) => {
1145
- if (metaName.includes("eslint-plugin")) return metaName;
1146
- return resolveEslintPluginName(metaName);
1147
- };
1148
- /**
1149
- * Derives the rule-ID prefix that an npm package exposes.
1150
- *
1151
- * Examples:
1152
- * `eslint-plugin-react-dom` -> `react-dom`
1153
- * `eslint-plugin-mocha` -> `mocha`
1154
- * `@stylistic/eslint-plugin` -> `@stylistic`
1155
- * `@stylistic/eslint-plugin-ts` -> `@stylistic/ts`
1156
- */
1157
- const deriveRulePrefix = (packageName) => {
1158
- if (packageName.startsWith("@")) {
1159
- const slashIdx = packageName.indexOf("/");
1160
- const scope = packageName.substring(0, slashIdx);
1161
- const rest = packageName.substring(slashIdx + 1);
1162
- if (rest === "eslint-plugin") return scope;
1163
- if (rest.startsWith("eslint-plugin-")) return `${scope}/${rest.substring(14)}`;
1164
- return packageName;
1165
- }
1166
- if (packageName.startsWith("eslint-plugin-")) return packageName.substring(14);
1167
- return packageName;
1168
- };
1169
- /**
1170
- * Resolves the canonical rule name for a jsPlugin rule.
1171
- *
1172
- * When a plugin is registered under an alias (e.g. `@eslint-react/dom`) but
1173
- * its `meta.name` reveals a different canonical package (`eslint-plugin-react-dom`),
1174
- * the rule must be rewritten so that oxlint can match it to the loaded plugin.
1175
- *
1176
- * For example:
1177
- * `@eslint-react/dom/no-find-dom-node` -> `react-dom/no-find-dom-node`
1178
- */
1179
- const resolveJsPluginRuleName = (rule, plugins) => {
1180
- const pluginName = extractPluginId(rule);
1181
- if (pluginName === void 0) return rule;
1182
- const metaName = plugins?.[pluginName]?.meta?.name;
1183
- if (!metaName || !metaName.includes("eslint-plugin")) return rule;
1184
- const canonicalPrefix = deriveRulePrefix(metaName);
1185
- if (canonicalPrefix === pluginName) return rule;
1186
- return `${canonicalPrefix}/${rule.substring(pluginName.length + 1)}`;
1187
- };
1188
- const enableJsPluginRule = (targetConfig, rule, ruleEntry, plugins) => {
1189
- const pluginName = extractPluginId(rule);
1190
- if (pluginName === void 0) return false;
1191
- if (ignorePlugins.has(pluginName)) return false;
1192
- if (targetConfig.jsPlugins === void 0 || targetConfig.jsPlugins === null) targetConfig.jsPlugins = [];
1193
- const metaName = plugins?.[pluginName]?.meta?.name;
1194
- const eslintPluginName = metaName ? resolveFromMetaName(metaName) : resolveEslintPluginName(pluginName);
1195
- if (!targetConfig.jsPlugins.includes(eslintPluginName)) targetConfig.jsPlugins.push(eslintPluginName);
1196
- const resolvedRule = resolveJsPluginRuleName(rule, plugins);
1197
- targetConfig.rules = targetConfig.rules ?? {};
1198
- targetConfig.rules[resolvedRule] = ruleEntry;
1199
- return true;
1200
- };
1201
- //#endregion
1202
1226
  //#region src/generated/unsupported-rules.json
1203
1227
  var unsupportedRules = {
1204
1228
  "eslint/no-dupe-args": "Superseded by strict mode.",
@@ -1571,8 +1595,7 @@ var unsupportedRules = {
1571
1595
  //#region src/utilities.ts
1572
1596
  const isEqualDeep = (a, b) => {
1573
1597
  if (a === b) return true;
1574
- const bothAreObjects = a && b && typeof a === "object" && typeof b === "object";
1575
- return Boolean(bothAreObjects && Object.keys(a).length === Object.keys(b).length && Object.entries(a).every(([k, v]) => isEqualDeep(v, b[k])));
1598
+ return Boolean(a && b && typeof a === "object" && typeof b === "object" && Object.keys(a).length === Object.keys(b).length && Object.entries(a).every(([k, v]) => isEqualDeep(v, b[k])));
1576
1599
  };
1577
1600
  /**
1578
1601
  * Builds a lookup map of unsupported rule explanations.
@@ -1694,12 +1717,13 @@ const transformRuleEntry = (eslintConfig, targetConfig, baseConfig, options, ove
1694
1717
  if (resolved !== rule) removePreviousOverrideRule(resolved, eslintConfig, overrides);
1695
1718
  }
1696
1719
  }
1697
- if (allRules.includes(rule)) {
1698
- if (!options?.withNursery && nurseryRules.includes(rule)) {
1720
+ const canonicalRule = normalizeRuleToCanonical(rule);
1721
+ if (allRules.includes(canonicalRule)) {
1722
+ if (!options?.withNursery && nurseryRules.includes(canonicalRule)) {
1699
1723
  options?.reporter?.markSkipped(rule, "nursery");
1700
1724
  continue;
1701
1725
  }
1702
- if (!options?.typeAware && typeAwareRules.includes(rule)) {
1726
+ if (!options?.typeAware && typeAwareRules.includes(canonicalRule)) {
1703
1727
  options?.reporter?.markSkipped(rule, "type-aware");
1704
1728
  continue;
1705
1729
  }
@@ -1846,29 +1870,26 @@ const replaceTypescriptAliasRules = (config) => {
1846
1870
  if (Object.keys(config.rules).length === 0) delete config.rules;
1847
1871
  };
1848
1872
  /**
1849
- * Oxlint supports eslint-plugin-n rules only under the `node` plugin name
1873
+ * Renames rules from an ESLint plugin prefix to the canonical Oxlint plugin prefix.
1850
1874
  */
1851
- const replaceNodePluginName = (config) => {
1875
+ const replaceRulePrefix = (config, oldPrefix, newPrefix) => {
1852
1876
  if (config.rules === void 0) return;
1853
1877
  for (const rule of Object.keys(config.rules)) {
1854
- if (!rule.startsWith("n/")) continue;
1855
- const nodeRule = `node/${rule.slice(2)}`;
1856
- config.rules[nodeRule] = config.rules[rule];
1878
+ if (!rule.startsWith(`${oldPrefix}/`)) continue;
1879
+ const canonicalRule = `${newPrefix}/${rule.slice(oldPrefix.length + 1)}`;
1880
+ config.rules[canonicalRule] = config.rules[rule];
1857
1881
  delete config.rules[rule];
1858
1882
  }
1859
1883
  };
1860
1884
  /**
1861
- * Oxlint supports the eslint-plugin-react-refresh/only-export-components rule
1862
- * under the `react` plugin name.
1885
+ * Renames all ESLint plugin prefixes to their canonical Oxlint equivalents,
1886
+ * driven by the `rulesPrefixesForPlugins` mapping in constants.ts.
1887
+ *
1888
+ * This should run AFTER `replaceTypescriptAliasRules` so that rules which
1889
+ * extend core ESLint rules have already been stripped of their prefix.
1863
1890
  */
1864
- const replaceReactRefreshPluginName = (config) => {
1865
- if (config.rules === void 0) return;
1866
- for (const rule of Object.keys(config.rules)) {
1867
- if (!rule.startsWith("react-refresh/")) continue;
1868
- const reactRefreshRule = `react/${rule.slice(14)}`;
1869
- config.rules[reactRefreshRule] = config.rules[rule];
1870
- delete config.rules[rule];
1871
- }
1891
+ const replaceCanonicalPluginPrefixes = (config) => {
1892
+ for (const [prefix, plugin] of Object.entries(rulesPrefixesForPlugins)) if (prefix !== plugin) replaceRulePrefix(config, prefix, plugin);
1872
1893
  };
1873
1894
  //#endregion
1874
1895
  //#region src/cleanup.ts
@@ -1919,9 +1940,9 @@ const cleanUpOxlintConfig = (config) => {
1919
1940
  removeGlobalsWithAreCoveredByEnv(config);
1920
1941
  transformBoolGlobalToString(config);
1921
1942
  replaceTypescriptAliasRules(config);
1922
- replaceNodePluginName(config);
1923
- replaceReactRefreshPluginName(config);
1943
+ replaceCanonicalPluginPrefixes(config);
1924
1944
  cleanUpRulesWhichAreCoveredByCategory(config);
1945
+ if ("files" in config) cleanUpUnusedJsPlugins(config);
1925
1946
  if (config.globals !== void 0 && config.globals !== null && Object.keys(config.globals).length === 0) delete config.globals;
1926
1947
  if (config.env !== void 0 && config.env !== null) {
1927
1948
  delete config.env.es3;
@@ -1934,6 +1955,7 @@ const cleanUpOxlintConfig = (config) => {
1934
1955
  if (!("files" in config)) {
1935
1956
  cleanUpUselessOverridesEntries(config);
1936
1957
  cleanUpDisabledRootRules(config);
1958
+ cleanUpUnusedJsPlugins(config);
1937
1959
  }
1938
1960
  };
1939
1961
  /**
@@ -2257,4 +2279,4 @@ const main = async (configs, oxlintConfig, options) => {
2257
2279
  return buildConfig(Array.isArray(resolved) ? resolved : [resolved], oxlintConfig, options);
2258
2280
  };
2259
2281
  //#endregion
2260
- export { nurseryRules as a, buildUnsupportedRuleExplanations as i, preFixForJsPlugins as n, rules_exports as o, isOffValue as r, main as t };
2282
+ export { nurseryRules as a, buildUnsupportedRuleExplanations as i, preFixForJsPlugins as n, rules_exports as o, isOffValue as r, normalizeRuleToCanonical as s, main as t };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oxlint/migrate",
3
- "version": "1.57.0",
3
+ "version": "1.59.0",
4
4
  "description": "Generates a `.oxlintrc.json` from a existing eslint flat config",
5
5
  "keywords": [
6
6
  "eslint",
@@ -41,16 +41,17 @@
41
41
  "dependencies": {
42
42
  "commander": "^14.0.0",
43
43
  "globals": "^17.0.0",
44
- "oxc-parser": "^0.121.0",
44
+ "oxc-parser": "^0.123.0",
45
45
  "tinyglobby": "^0.2.14"
46
46
  },
47
47
  "devDependencies": {
48
48
  "@antfu/eslint-config": "^7.0.0",
49
- "@e18e/eslint-plugin": "^0.2.0",
49
+ "@babel/eslint-plugin": "^7.27.1",
50
+ "@e18e/eslint-plugin": "^0.3.0",
50
51
  "@eslint-react/eslint-plugin": "^3.0.0",
51
52
  "@eslint/js": "^10.0.0",
52
53
  "@logux/eslint-config": "^57.0.0",
53
- "@oxc-node/core": "^0.0.35",
54
+ "@oxc-node/core": "^0.1.0",
54
55
  "@stylistic/eslint-plugin": "^5.0.0",
55
56
  "@stylistic/eslint-plugin-ts": "^4.4.1",
56
57
  "@tanstack/eslint-plugin-query": "^5.91.4",
@@ -83,15 +84,16 @@
83
84
  "husky": "^9.1.7",
84
85
  "lint-staged": "^16.1.2",
85
86
  "next": "^16.0.0",
86
- "oxfmt": "^0.41.0",
87
- "oxlint": "^1.57.0",
88
- "oxlint-tsgolint": "^0.17.0",
87
+ "oxfmt": "^0.43.0",
88
+ "oxlint": "^1.59.0",
89
+ "oxlint-tsgolint": "^0.19.0",
89
90
  "tsdown": "^0.21.0",
91
+ "typescript": "^6.0.0",
90
92
  "typescript-eslint": "^8.35.0",
91
93
  "vitest": "^4.0.0"
92
94
  },
93
95
  "lint-staged": {
94
96
  "*": "oxfmt --no-error-on-unmatched-pattern"
95
97
  },
96
- "packageManager": "pnpm@10.32.1"
98
+ "packageManager": "pnpm@10.33.0"
97
99
  }