@oxlint/migrate 1.50.0 → 1.52.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 +14 -14
- package/dist/bin/oxlint-migrate.mjs +20 -21
- package/dist/src/index.d.mts +86 -2649
- package/dist/src/index.mjs +2 -59
- package/dist/{settings-D8R7axmT.mjs → src-TZG8ybfH.mjs} +212 -49
- package/package.json +14 -11
package/dist/src/index.mjs
CHANGED
|
@@ -1,59 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
//#region src/index.ts
|
|
4
|
-
const buildConfig = (configs, oxlintConfig, options) => {
|
|
5
|
-
if (oxlintConfig === void 0) if (options?.merge) oxlintConfig = {
|
|
6
|
-
plugins: [
|
|
7
|
-
"oxc",
|
|
8
|
-
"typescript",
|
|
9
|
-
"unicorn",
|
|
10
|
-
"react"
|
|
11
|
-
],
|
|
12
|
-
categories: { correctness: "warn" }
|
|
13
|
-
};
|
|
14
|
-
else oxlintConfig = {
|
|
15
|
-
$schema: "./node_modules/oxlint/configuration_schema.json",
|
|
16
|
-
plugins: [],
|
|
17
|
-
categories: { correctness: "off" }
|
|
18
|
-
};
|
|
19
|
-
if (oxlintConfig.$schema === void 0 && options?.merge) oxlintConfig.$schema = "./node_modules/oxlint/configuration_schema.json";
|
|
20
|
-
if (oxlintConfig.env?.builtin === void 0) {
|
|
21
|
-
if (oxlintConfig.env === void 0) oxlintConfig.env = {};
|
|
22
|
-
oxlintConfig.env.builtin = true;
|
|
23
|
-
}
|
|
24
|
-
const overrides = options?.merge ? oxlintConfig.overrides ?? [] : [];
|
|
25
|
-
for (const config of configs) {
|
|
26
|
-
if (config.name?.startsWith("oxlint/")) continue;
|
|
27
|
-
let targetConfig;
|
|
28
|
-
if (config.files === void 0) targetConfig = oxlintConfig;
|
|
29
|
-
else {
|
|
30
|
-
const validFiles = processConfigFiles(config.files, options?.reporter);
|
|
31
|
-
if (validFiles.length === 0) continue;
|
|
32
|
-
targetConfig = { files: validFiles };
|
|
33
|
-
const [push, result] = detectSameOverride(oxlintConfig, targetConfig);
|
|
34
|
-
if (push) overrides.push(result);
|
|
35
|
-
}
|
|
36
|
-
transformIgnorePatterns(config, targetConfig, options);
|
|
37
|
-
transformRuleEntry(config, targetConfig, config.files !== void 0 ? oxlintConfig : void 0, options, config.files === void 0 ? overrides : void 0);
|
|
38
|
-
transformEnvAndGlobals(config, targetConfig, options);
|
|
39
|
-
if (config.files === void 0) transformSettings(config, oxlintConfig, options);
|
|
40
|
-
else warnSettingsInOverride(config, options);
|
|
41
|
-
if ("files" in targetConfig) {
|
|
42
|
-
detectNeededRulesPlugins(targetConfig);
|
|
43
|
-
detectEnvironmentByGlobals(targetConfig);
|
|
44
|
-
cleanUpOxlintConfig(targetConfig);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
oxlintConfig.overrides = overrides;
|
|
48
|
-
detectNeededRulesPlugins(oxlintConfig);
|
|
49
|
-
detectEnvironmentByGlobals(oxlintConfig);
|
|
50
|
-
cleanUpOxlintConfig(oxlintConfig);
|
|
51
|
-
return oxlintConfig;
|
|
52
|
-
};
|
|
53
|
-
const main = async (configs, oxlintConfig, options) => {
|
|
54
|
-
const resolved = await Promise.resolve(fixForJsPlugins(configs));
|
|
55
|
-
return buildConfig(Array.isArray(resolved) ? resolved : [resolved], oxlintConfig, options);
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
//#endregion
|
|
59
|
-
export { main as default };
|
|
1
|
+
import { t as main } from "../src-TZG8ybfH.mjs";
|
|
2
|
+
export { main as default };
|
|
@@ -1,21 +1,15 @@
|
|
|
1
1
|
import globals from "globals";
|
|
2
|
-
|
|
3
2
|
//#region \0rolldown/runtime.js
|
|
4
3
|
var __defProp = Object.defineProperty;
|
|
5
4
|
var __exportAll = (all, no_symbols) => {
|
|
6
5
|
let target = {};
|
|
7
|
-
for (var name in all) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
13
|
-
if (!no_symbols) {
|
|
14
|
-
__defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
15
|
-
}
|
|
6
|
+
for (var name in all) __defProp(target, name, {
|
|
7
|
+
get: all[name],
|
|
8
|
+
enumerable: true
|
|
9
|
+
});
|
|
10
|
+
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
16
11
|
return target;
|
|
17
12
|
};
|
|
18
|
-
|
|
19
13
|
//#endregion
|
|
20
14
|
//#region src/env_globals.ts
|
|
21
15
|
const ES_VERSIONS = [
|
|
@@ -78,8 +72,12 @@ const removeGlobalsWithAreCoveredByEnv = (config) => {
|
|
|
78
72
|
};
|
|
79
73
|
const transformBoolGlobalToString = (config) => {
|
|
80
74
|
if (config.globals === void 0) return;
|
|
81
|
-
for (const [entry, value] of Object.entries(config.globals))
|
|
82
|
-
|
|
75
|
+
for (const [entry, value] of Object.entries(config.globals)) config.globals[entry] = transformEslintGlobalAccessToOxlintGlobalValue(value);
|
|
76
|
+
};
|
|
77
|
+
const transformEslintGlobalAccessToOxlintGlobalValue = (global) => {
|
|
78
|
+
if (global === false || global === "readable" || global === "readonly") return "readonly";
|
|
79
|
+
else if (global === true || global === "writeable" || global === "writable") return "writable";
|
|
80
|
+
else return "off";
|
|
83
81
|
};
|
|
84
82
|
const THRESHOLD_ENVS = [
|
|
85
83
|
"browser",
|
|
@@ -106,8 +104,8 @@ const transformEnvAndGlobals = (eslintConfig, targetConfig, options) => {
|
|
|
106
104
|
if (eslintConfig.languageOptions?.globals !== void 0 && eslintConfig.languageOptions?.globals !== null) {
|
|
107
105
|
if (targetConfig.globals === void 0) targetConfig.globals = {};
|
|
108
106
|
if (options?.merge) {
|
|
109
|
-
for (const [global, globalSetting] of Object.entries(eslintConfig.languageOptions.globals)) if (!(global in targetConfig.globals)) targetConfig.globals[global] = globalSetting;
|
|
110
|
-
} else Object.
|
|
107
|
+
for (const [global, globalSetting] of Object.entries(eslintConfig.languageOptions.globals)) if (!(global in targetConfig.globals)) targetConfig.globals[global] = transformEslintGlobalAccessToOxlintGlobalValue(globalSetting);
|
|
108
|
+
} else for (const [global, globalSetting] of Object.entries(eslintConfig.languageOptions.globals)) targetConfig.globals[global] = transformEslintGlobalAccessToOxlintGlobalValue(globalSetting);
|
|
111
109
|
}
|
|
112
110
|
if (eslintConfig.languageOptions?.ecmaVersion !== void 0) {
|
|
113
111
|
if (eslintConfig.languageOptions.ecmaVersion === "latest") {
|
|
@@ -166,7 +164,6 @@ const cleanUpSupersetEnvs = (config) => {
|
|
|
166
164
|
if (Object.keys(override.env).length === 0) delete override.env;
|
|
167
165
|
}
|
|
168
166
|
};
|
|
169
|
-
|
|
170
167
|
//#endregion
|
|
171
168
|
//#region src/generated/rules.ts
|
|
172
169
|
var rules_exports = /* @__PURE__ */ __exportAll({
|
|
@@ -936,6 +933,7 @@ const nurseryRules = [
|
|
|
936
933
|
"@typescript-eslint/dot-notation",
|
|
937
934
|
"@typescript-eslint/no-unnecessary-condition",
|
|
938
935
|
"@typescript-eslint/no-unnecessary-qualifier",
|
|
936
|
+
"@typescript-eslint/no-unnecessary-type-conversion",
|
|
939
937
|
"@typescript-eslint/no-unnecessary-type-parameters",
|
|
940
938
|
"@typescript-eslint/no-useless-default-assignment",
|
|
941
939
|
"@typescript-eslint/prefer-find",
|
|
@@ -985,6 +983,7 @@ const typeAwareRules = [
|
|
|
985
983
|
"@typescript-eslint/no-unnecessary-template-expression",
|
|
986
984
|
"@typescript-eslint/no-unnecessary-type-arguments",
|
|
987
985
|
"@typescript-eslint/no-unnecessary-type-assertion",
|
|
986
|
+
"@typescript-eslint/no-unnecessary-type-conversion",
|
|
988
987
|
"@typescript-eslint/no-unnecessary-type-parameters",
|
|
989
988
|
"@typescript-eslint/no-unsafe-argument",
|
|
990
989
|
"@typescript-eslint/no-unsafe-assignment",
|
|
@@ -1021,7 +1020,6 @@ const typeAwareRules = [
|
|
|
1021
1020
|
"@typescript-eslint/unbound-method",
|
|
1022
1021
|
"@typescript-eslint/use-unknown-in-catch-callback-variable"
|
|
1023
1022
|
];
|
|
1024
|
-
|
|
1025
1023
|
//#endregion
|
|
1026
1024
|
//#region src/constants.ts
|
|
1027
1025
|
const rulesPrefixesForPlugins = {
|
|
@@ -1043,6 +1041,10 @@ const rulesPrefixesForPlugins = {
|
|
|
1043
1041
|
vitest: "vitest",
|
|
1044
1042
|
vue: "vue"
|
|
1045
1043
|
};
|
|
1044
|
+
const eslintRulesToTypescriptEquivalents = {
|
|
1045
|
+
"dot-notation": "@typescript-eslint/dot-notation",
|
|
1046
|
+
"consistent-return": "@typescript-eslint/consistent-return"
|
|
1047
|
+
};
|
|
1046
1048
|
const typescriptRulesExtendEslintRules = [
|
|
1047
1049
|
"class-methods-use-this",
|
|
1048
1050
|
"default-param-last",
|
|
@@ -1063,7 +1065,6 @@ const typescriptRulesExtendEslintRules = [
|
|
|
1063
1065
|
"no-use-before-define",
|
|
1064
1066
|
"no-useless-constructor"
|
|
1065
1067
|
];
|
|
1066
|
-
|
|
1067
1068
|
//#endregion
|
|
1068
1069
|
//#region src/jsPlugins.ts
|
|
1069
1070
|
const ignorePlugins = new Set([
|
|
@@ -1071,13 +1072,47 @@ const ignorePlugins = new Set([
|
|
|
1071
1072
|
...Object.values(rulesPrefixesForPlugins),
|
|
1072
1073
|
"local"
|
|
1073
1074
|
]);
|
|
1074
|
-
const
|
|
1075
|
+
const tryResolvePackage = (packageName) => {
|
|
1076
|
+
try {
|
|
1077
|
+
import.meta.resolve(packageName);
|
|
1078
|
+
return true;
|
|
1079
|
+
} catch {
|
|
1080
|
+
return false;
|
|
1081
|
+
}
|
|
1082
|
+
};
|
|
1083
|
+
const pluginNameCache = /* @__PURE__ */ new Map();
|
|
1084
|
+
/**
|
|
1085
|
+
* Resolves the npm package name for an ESLint plugin given its scope name.
|
|
1086
|
+
*
|
|
1087
|
+
* For scoped plugin names (starting with `@`), the mapping is unambiguous:
|
|
1088
|
+
* - `@scope` -> `@scope/eslint-plugin`
|
|
1089
|
+
* - `@scope/sub` -> `@scope/eslint-plugin-sub`
|
|
1090
|
+
*
|
|
1091
|
+
* For non-scoped names, the npm package could follow either convention:
|
|
1092
|
+
* - `eslint-plugin-{name}` (e.g. `eslint-plugin-mocha`)
|
|
1093
|
+
* - `@{name}/eslint-plugin` (e.g. `@e18e/eslint-plugin`)
|
|
1094
|
+
*
|
|
1095
|
+
* We try to resolve both candidates against the installed packages and
|
|
1096
|
+
* use the one that is actually present, falling back to the standard
|
|
1097
|
+
* `eslint-plugin-{name}` convention when neither can be resolved.
|
|
1098
|
+
*/
|
|
1099
|
+
const resolveEslintPluginName = (pluginName) => {
|
|
1100
|
+
const cached = pluginNameCache.get(pluginName);
|
|
1101
|
+
if (cached !== void 0) return cached;
|
|
1102
|
+
let result;
|
|
1075
1103
|
if (pluginName.startsWith("@")) {
|
|
1076
1104
|
const [scope, maybeSub] = pluginName.split("/");
|
|
1077
|
-
if (maybeSub)
|
|
1078
|
-
|
|
1105
|
+
if (maybeSub) result = `${scope}/eslint-plugin-${maybeSub}`;
|
|
1106
|
+
else result = `${scope}/eslint-plugin`;
|
|
1107
|
+
} else {
|
|
1108
|
+
const standardName = `eslint-plugin-${pluginName}`;
|
|
1109
|
+
const scopedName = `@${pluginName}/eslint-plugin`;
|
|
1110
|
+
if (tryResolvePackage(standardName)) result = standardName;
|
|
1111
|
+
else if (tryResolvePackage(scopedName)) result = scopedName;
|
|
1112
|
+
else result = standardName;
|
|
1079
1113
|
}
|
|
1080
|
-
|
|
1114
|
+
pluginNameCache.set(pluginName, result);
|
|
1115
|
+
return result;
|
|
1081
1116
|
};
|
|
1082
1117
|
const extractPluginId = (ruleId) => {
|
|
1083
1118
|
const firstSlash = ruleId.indexOf("/");
|
|
@@ -1093,18 +1128,70 @@ const isIgnoredPluginRule = (ruleId) => {
|
|
|
1093
1128
|
if (pluginName === void 0) return true;
|
|
1094
1129
|
return ignorePlugins.has(pluginName);
|
|
1095
1130
|
};
|
|
1096
|
-
|
|
1131
|
+
/**
|
|
1132
|
+
* Derives the npm package name for a plugin from its `meta.name` field.
|
|
1133
|
+
*
|
|
1134
|
+
* If `meta.name` already looks like a full npm package name (contains
|
|
1135
|
+
* "eslint-plugin"), it is returned as-is. Otherwise it is fed through
|
|
1136
|
+
* {@link resolveEslintPluginName} for the usual heuristic resolution.
|
|
1137
|
+
*/
|
|
1138
|
+
const resolveFromMetaName = (metaName) => {
|
|
1139
|
+
if (metaName.includes("eslint-plugin")) return metaName;
|
|
1140
|
+
return resolveEslintPluginName(metaName);
|
|
1141
|
+
};
|
|
1142
|
+
/**
|
|
1143
|
+
* Derives the rule-ID prefix that an npm package exposes.
|
|
1144
|
+
*
|
|
1145
|
+
* Examples:
|
|
1146
|
+
* `eslint-plugin-react-dom` -> `react-dom`
|
|
1147
|
+
* `eslint-plugin-mocha` -> `mocha`
|
|
1148
|
+
* `@stylistic/eslint-plugin` -> `@stylistic`
|
|
1149
|
+
* `@stylistic/eslint-plugin-ts` -> `@stylistic/ts`
|
|
1150
|
+
*/
|
|
1151
|
+
const deriveRulePrefix = (packageName) => {
|
|
1152
|
+
if (packageName.startsWith("@")) {
|
|
1153
|
+
const slashIdx = packageName.indexOf("/");
|
|
1154
|
+
const scope = packageName.substring(0, slashIdx);
|
|
1155
|
+
const rest = packageName.substring(slashIdx + 1);
|
|
1156
|
+
if (rest === "eslint-plugin") return scope;
|
|
1157
|
+
if (rest.startsWith("eslint-plugin-")) return `${scope}/${rest.substring(14)}`;
|
|
1158
|
+
return packageName;
|
|
1159
|
+
}
|
|
1160
|
+
if (packageName.startsWith("eslint-plugin-")) return packageName.substring(14);
|
|
1161
|
+
return packageName;
|
|
1162
|
+
};
|
|
1163
|
+
/**
|
|
1164
|
+
* Resolves the canonical rule name for a jsPlugin rule.
|
|
1165
|
+
*
|
|
1166
|
+
* When a plugin is registered under an alias (e.g. `@eslint-react/dom`) but
|
|
1167
|
+
* its `meta.name` reveals a different canonical package (`eslint-plugin-react-dom`),
|
|
1168
|
+
* the rule must be rewritten so that oxlint can match it to the loaded plugin.
|
|
1169
|
+
*
|
|
1170
|
+
* For example:
|
|
1171
|
+
* `@eslint-react/dom/no-find-dom-node` -> `react-dom/no-find-dom-node`
|
|
1172
|
+
*/
|
|
1173
|
+
const resolveJsPluginRuleName = (rule, plugins) => {
|
|
1174
|
+
const pluginName = extractPluginId(rule);
|
|
1175
|
+
if (pluginName === void 0) return rule;
|
|
1176
|
+
const metaName = plugins?.[pluginName]?.meta?.name;
|
|
1177
|
+
if (!metaName || !metaName.includes("eslint-plugin")) return rule;
|
|
1178
|
+
const canonicalPrefix = deriveRulePrefix(metaName);
|
|
1179
|
+
if (canonicalPrefix === pluginName) return rule;
|
|
1180
|
+
return `${canonicalPrefix}/${rule.substring(pluginName.length + 1)}`;
|
|
1181
|
+
};
|
|
1182
|
+
const enableJsPluginRule = (targetConfig, rule, ruleEntry, plugins) => {
|
|
1097
1183
|
const pluginName = extractPluginId(rule);
|
|
1098
1184
|
if (pluginName === void 0) return false;
|
|
1099
1185
|
if (ignorePlugins.has(pluginName)) return false;
|
|
1100
1186
|
if (targetConfig.jsPlugins === void 0) targetConfig.jsPlugins = [];
|
|
1101
|
-
const
|
|
1187
|
+
const metaName = plugins?.[pluginName]?.meta?.name;
|
|
1188
|
+
const eslintPluginName = metaName ? resolveFromMetaName(metaName) : resolveEslintPluginName(pluginName);
|
|
1102
1189
|
if (!targetConfig.jsPlugins.includes(eslintPluginName)) targetConfig.jsPlugins.push(eslintPluginName);
|
|
1190
|
+
const resolvedRule = resolveJsPluginRuleName(rule, plugins);
|
|
1103
1191
|
targetConfig.rules = targetConfig.rules || {};
|
|
1104
|
-
targetConfig.rules[
|
|
1192
|
+
targetConfig.rules[resolvedRule] = ruleEntry;
|
|
1105
1193
|
return true;
|
|
1106
1194
|
};
|
|
1107
|
-
|
|
1108
1195
|
//#endregion
|
|
1109
1196
|
//#region src/generated/unsupported-rules.json
|
|
1110
1197
|
var unsupportedRules = {
|
|
@@ -1146,6 +1233,7 @@ var unsupportedRules = {
|
|
|
1146
1233
|
"import/no-deprecated": "No need to implement, already implemented by `typescript/no-deprecated` via tsgolint.",
|
|
1147
1234
|
"n/no-restricted-import": "No need to implement, already implemented by `no-restricted-imports` rule.",
|
|
1148
1235
|
"n/no-restricted-require": "No need to implement, already implemented by `no-restricted-imports` rule.",
|
|
1236
|
+
"import/order": "Not implementing this in Oxlint as its behavior is covered very well by [Oxfmt's import sorting](https://oxc.rs/docs/guide/usage/formatter/sorting.html).",
|
|
1149
1237
|
"jsdoc/type-formatting": "Experimental rule in the original plugin, may reconsider once stable.",
|
|
1150
1238
|
"jsdoc/convert-to-jsdoc-comments": "Experimental rule in the original plugin, may reconsider once stable.",
|
|
1151
1239
|
"jsdoc/check-examples": "Deprecated.",
|
|
@@ -1181,6 +1269,8 @@ var unsupportedRules = {
|
|
|
1181
1269
|
"react/jsx-curly-newline": "Stylistic rule from eslint-plugin-react. Should use Oxfmt for stylistic rules, or use JS Plugins to enable this rule.",
|
|
1182
1270
|
"react/jsx-child-element-spacing": "Stylistic rule from eslint-plugin-react. Should use Oxfmt for stylistic rules, or use JS Plugins to enable this rule.",
|
|
1183
1271
|
"react/jsx-one-expression-per-line": "Stylistic rule from eslint-plugin-react. Should use Oxfmt for stylistic rules, or use JS Plugins to enable this rule.",
|
|
1272
|
+
"react/jsx-sort-props": "Stylistic rule from eslint-plugin-react. Should use Oxfmt for stylistic rules, or use JS Plugins to enable this rule.",
|
|
1273
|
+
"react/no-adjacent-inline-elements": "Stylistic rule from eslint-plugin-react. Should use Oxfmt for stylistic rules, or use JS Plugins to enable this rule.",
|
|
1184
1274
|
"react/config": "React Compiler rules will not be implemented in oxlint for now, as they require integration with the react compiler itself. These rules can be used via JS Plugins if desired.",
|
|
1185
1275
|
"react/error-boundaries": "React Compiler rules will not be implemented in oxlint for now, as they require integration with the react compiler itself. These rules can be used via JS Plugins if desired.",
|
|
1186
1276
|
"react/component-hook-factories": "React Compiler rules will not be implemented in oxlint for now, as they require integration with the react compiler itself. These rules can be used via JS Plugins if desired.",
|
|
@@ -1220,6 +1310,8 @@ var unsupportedRules = {
|
|
|
1220
1310
|
"react/sort-default-props": "`defaultProps` is removed entirely in React 19, this rule is no longer relevant. Also stylistic.",
|
|
1221
1311
|
"react/sort-prop-types": "PropTypes are ignored in React 19, and this rule is only relevant if you use the PropTypes package. Also stylistic.",
|
|
1222
1312
|
"react/static-property-placement": "This rule only applies to legacy class components, which are not widely used in modern React.",
|
|
1313
|
+
"react/require-optimization": "This rule only applies to legacy class components, which are not widely used in modern React.",
|
|
1314
|
+
"react/prefer-read-only-props": "This rule is niche and primarily applies to legacy class components, which are not widely used in modern React.",
|
|
1223
1315
|
"typescript/sort-type-constituents": "Deprecated, replaced by `perfectionist/sort-intersection-types` and `perfectionist/sort-union-types` rules.",
|
|
1224
1316
|
"typescript/no-type-alias": "Deprecated, replaced by `typescript-eslint/consistent-type-definitions` rule.",
|
|
1225
1317
|
"typescript/typedef": "Deprecated.",
|
|
@@ -1469,7 +1561,6 @@ var unsupportedRules = {
|
|
|
1469
1561
|
"vue/valid-v-bind-sync": "Deprecated.",
|
|
1470
1562
|
"vue/valid-model-definition": "Deprecated."
|
|
1471
1563
|
};
|
|
1472
|
-
|
|
1473
1564
|
//#endregion
|
|
1474
1565
|
//#region src/utilities.ts
|
|
1475
1566
|
const isEqualDeep = (a, b) => {
|
|
@@ -1497,7 +1588,6 @@ function buildUnsupportedRuleExplanations() {
|
|
|
1497
1588
|
}
|
|
1498
1589
|
return explanations;
|
|
1499
1590
|
}
|
|
1500
|
-
|
|
1501
1591
|
//#endregion
|
|
1502
1592
|
//#region src/plugins_rules.ts
|
|
1503
1593
|
const allRules = Object.values(rules_exports).flat();
|
|
@@ -1571,12 +1661,23 @@ const mergeRuleConfig = (existingConfig, newConfig) => {
|
|
|
1571
1661
|
if (Array.isArray(newConfig) && newConfig.length === 1 && existingIsArray && existingConfig.length > 1) return [newConfig[0], ...existingConfig.slice(1)];
|
|
1572
1662
|
return newConfig;
|
|
1573
1663
|
};
|
|
1574
|
-
const transformRuleEntry = (eslintConfig, targetConfig, baseConfig, options, overrides) => {
|
|
1664
|
+
const transformRuleEntry = (eslintConfig, targetConfig, baseConfig, options, overrides, globalPlugins) => {
|
|
1575
1665
|
if (eslintConfig.rules === void 0) return;
|
|
1576
1666
|
if (targetConfig.rules === void 0) targetConfig.rules = {};
|
|
1577
|
-
|
|
1667
|
+
const effectivePlugins = globalPlugins ? {
|
|
1668
|
+
...globalPlugins,
|
|
1669
|
+
...eslintConfig.plugins
|
|
1670
|
+
} : eslintConfig.plugins;
|
|
1671
|
+
for (const [originalRule, config] of Object.entries(eslintConfig.rules)) {
|
|
1672
|
+
const rule = options?.typeAware && eslintRulesToTypescriptEquivalents[originalRule] !== void 0 ? eslintRulesToTypescriptEquivalents[originalRule] : originalRule;
|
|
1578
1673
|
const normalizedConfig = normalizeSeverityValue(config);
|
|
1579
|
-
if (!options?.merge)
|
|
1674
|
+
if (!options?.merge) {
|
|
1675
|
+
removePreviousOverrideRule(rule, eslintConfig, overrides);
|
|
1676
|
+
if (options?.jsPlugins) {
|
|
1677
|
+
const resolved = resolveJsPluginRuleName(rule, effectivePlugins);
|
|
1678
|
+
if (resolved !== rule) removePreviousOverrideRule(resolved, eslintConfig, overrides);
|
|
1679
|
+
}
|
|
1680
|
+
}
|
|
1580
1681
|
if (allRules.includes(rule)) {
|
|
1581
1682
|
if (!options?.withNursery && nurseryRules.includes(rule)) {
|
|
1582
1683
|
options?.reporter?.markSkipped(rule, "nursery");
|
|
@@ -1595,8 +1696,9 @@ const transformRuleEntry = (eslintConfig, targetConfig, baseConfig, options, ove
|
|
|
1595
1696
|
} else {
|
|
1596
1697
|
if (options?.jsPlugins) {
|
|
1597
1698
|
if (isOffValue(normalizedConfig)) {
|
|
1598
|
-
|
|
1599
|
-
|
|
1699
|
+
const resolvedRule = resolveJsPluginRuleName(rule, effectivePlugins);
|
|
1700
|
+
if (eslintConfig.files === void 0) delete targetConfig.rules[resolvedRule];
|
|
1701
|
+
else if (!isIgnoredPluginRule(rule)) targetConfig.rules[resolvedRule] = normalizedConfig;
|
|
1600
1702
|
if (eslintConfig.files === void 0) {
|
|
1601
1703
|
options?.reporter?.removeSkipped(rule, "js-plugins");
|
|
1602
1704
|
options?.reporter?.removeSkipped(rule, "not-implemented");
|
|
@@ -1604,7 +1706,7 @@ const transformRuleEntry = (eslintConfig, targetConfig, baseConfig, options, ove
|
|
|
1604
1706
|
}
|
|
1605
1707
|
continue;
|
|
1606
1708
|
}
|
|
1607
|
-
if (!enableJsPluginRule(targetConfig, rule, normalizedConfig)) {
|
|
1709
|
+
if (!enableJsPluginRule(targetConfig, rule, normalizedConfig, effectivePlugins)) {
|
|
1608
1710
|
const category = unsupportedRuleExplanations[rule] ? "unsupported" : "not-implemented";
|
|
1609
1711
|
options?.reporter?.markSkipped(rule, category);
|
|
1610
1712
|
}
|
|
@@ -1752,7 +1854,6 @@ const replaceReactRefreshPluginName = (config) => {
|
|
|
1752
1854
|
delete config.rules[rule];
|
|
1753
1855
|
}
|
|
1754
1856
|
};
|
|
1755
|
-
|
|
1756
1857
|
//#endregion
|
|
1757
1858
|
//#region src/cleanup.ts
|
|
1758
1859
|
const TS_ESLINT_DEFAULT_OVERRIDE = {
|
|
@@ -1877,7 +1978,6 @@ function mergeConsecutiveOverridesWithDifferingFiles(config) {
|
|
|
1877
1978
|
}
|
|
1878
1979
|
config.overrides = mergedOverrides;
|
|
1879
1980
|
}
|
|
1880
|
-
|
|
1881
1981
|
//#endregion
|
|
1882
1982
|
//#region src/ignorePatterns.ts
|
|
1883
1983
|
const transformIgnorePatterns = (eslintConfig, targetConfig, options) => {
|
|
@@ -1889,7 +1989,6 @@ const transformIgnorePatterns = (eslintConfig, targetConfig, options) => {
|
|
|
1889
1989
|
if (targetConfig.ignorePatterns === void 0) targetConfig.ignorePatterns = [];
|
|
1890
1990
|
for (const ignores of eslintConfig.ignores) if (!targetConfig.ignorePatterns.includes(ignores)) targetConfig.ignorePatterns.push(ignores);
|
|
1891
1991
|
};
|
|
1892
|
-
|
|
1893
1992
|
//#endregion
|
|
1894
1993
|
//#region src/overrides.ts
|
|
1895
1994
|
const detectSameOverride = (config, override) => {
|
|
@@ -1900,7 +1999,6 @@ const detectSameOverride = (config, override) => {
|
|
|
1900
1999
|
if (matchedOverride !== void 0) return [false, matchedOverride];
|
|
1901
2000
|
return [true, override];
|
|
1902
2001
|
};
|
|
1903
|
-
|
|
1904
2002
|
//#endregion
|
|
1905
2003
|
//#region src/js_plugin_fixes.ts
|
|
1906
2004
|
/**
|
|
@@ -1937,7 +2035,6 @@ function fixForJsPlugins(configs) {
|
|
|
1937
2035
|
const preFixForJsPlugins = () => {
|
|
1938
2036
|
return fixForNextEslintConfig();
|
|
1939
2037
|
};
|
|
1940
|
-
|
|
1941
2038
|
//#endregion
|
|
1942
2039
|
//#region src/files.ts
|
|
1943
2040
|
/**
|
|
@@ -1962,7 +2059,6 @@ function processConfigFiles(files, reporter) {
|
|
|
1962
2059
|
} else simpleFiles.push(file);
|
|
1963
2060
|
return simpleFiles;
|
|
1964
2061
|
}
|
|
1965
|
-
|
|
1966
2062
|
//#endregion
|
|
1967
2063
|
//#region src/settings.ts
|
|
1968
2064
|
const OXLINT_SUPPORTED_SETTINGS_KEYS = [
|
|
@@ -1991,6 +2087,13 @@ const isSupportedSettingsKey = (key) => {
|
|
|
1991
2087
|
return OXLINT_SUPPORTED_SETTINGS_KEYS.includes(key);
|
|
1992
2088
|
};
|
|
1993
2089
|
/**
|
|
2090
|
+
* Format a list of settings keys into a newline-separated, backtick-quoted
|
|
2091
|
+
* string for warning output.
|
|
2092
|
+
*/
|
|
2093
|
+
const formatSettingsKeyList = (keys) => {
|
|
2094
|
+
return keys.map((key) => `\`${key}\``).join("\n");
|
|
2095
|
+
};
|
|
2096
|
+
/**
|
|
1994
2097
|
* Transform ESLint settings to oxlint settings.
|
|
1995
2098
|
*
|
|
1996
2099
|
* Only processes settings for the base config (not overrides) since oxlint
|
|
@@ -2027,24 +2130,22 @@ const transformSettings = (eslintConfig, targetConfig, options) => {
|
|
|
2027
2130
|
}
|
|
2028
2131
|
let settingsValue = value;
|
|
2029
2132
|
if (key === "react" && settingsValue.version === "detect") {
|
|
2030
|
-
options?.reporter?.addWarning("react.version \"detect\" is not supported
|
|
2133
|
+
options?.reporter?.addWarning("react.version \"detect\" is not supported. Specify an explicit version (e.g., \"18.2.0\") in your oxlint config.");
|
|
2031
2134
|
const { version: _, ...restReactSettings } = settingsValue;
|
|
2032
2135
|
settingsValue = restReactSettings;
|
|
2033
2136
|
}
|
|
2034
2137
|
const unsupportedSubKeys = UNSUPPORTED_SETTINGS_SUB_KEYS[key];
|
|
2035
2138
|
if (unsupportedSubKeys !== void 0) {
|
|
2036
|
-
const strippedKeys = [];
|
|
2037
2139
|
for (const subKey of unsupportedSubKeys) if (subKey in settingsValue) {
|
|
2038
|
-
|
|
2140
|
+
skippedKeys.push(`${key}.${subKey}`);
|
|
2039
2141
|
const { [subKey]: _, ...rest } = settingsValue;
|
|
2040
2142
|
settingsValue = rest;
|
|
2041
2143
|
}
|
|
2042
|
-
if (strippedKeys.length > 0) options?.reporter?.addWarning(`Settings not migrated (not supported by oxlint): ${strippedKeys.join(", ")}.`);
|
|
2043
2144
|
}
|
|
2044
2145
|
if (Object.keys(settingsValue).length === 0) continue;
|
|
2045
2146
|
filteredSettings[key] = settingsValue;
|
|
2046
2147
|
}
|
|
2047
|
-
if (skippedKeys.length > 0) options?.reporter?.addWarning(`Settings not migrated (not supported by oxlint)
|
|
2148
|
+
if (skippedKeys.length > 0) options?.reporter?.addWarning(`Settings not migrated (not supported by oxlint):\n${formatSettingsKeyList(skippedKeys)}`);
|
|
2048
2149
|
if (Object.keys(filteredSettings).length === 0) return;
|
|
2049
2150
|
if (targetConfig.settings === void 0) targetConfig.settings = {};
|
|
2050
2151
|
if (options?.merge) deepMerge(targetConfig.settings, filteredSettings);
|
|
@@ -2059,10 +2160,72 @@ const transformSettings = (eslintConfig, targetConfig, options) => {
|
|
|
2059
2160
|
*/
|
|
2060
2161
|
const warnSettingsInOverride = (eslintConfig, options) => {
|
|
2061
2162
|
if (eslintConfig.settings !== void 0 && eslintConfig.settings !== null && Object.keys(eslintConfig.settings).length > 0) {
|
|
2062
|
-
const settingsKeys = Object.keys(eslintConfig.settings)
|
|
2063
|
-
options?.reporter?.addWarning(
|
|
2163
|
+
const settingsKeys = Object.keys(eslintConfig.settings);
|
|
2164
|
+
options?.reporter?.addWarning("Settings found under a 'files' pattern — oxlint does not support settings in overrides and they will be skipped:\n" + formatSettingsKeyList(settingsKeys));
|
|
2064
2165
|
}
|
|
2065
2166
|
};
|
|
2066
|
-
|
|
2067
2167
|
//#endregion
|
|
2068
|
-
|
|
2168
|
+
//#region src/index.ts
|
|
2169
|
+
const buildConfig = (configs, oxlintConfig, options) => {
|
|
2170
|
+
if (oxlintConfig === void 0) if (options?.merge) oxlintConfig = {
|
|
2171
|
+
plugins: [
|
|
2172
|
+
"oxc",
|
|
2173
|
+
"typescript",
|
|
2174
|
+
"unicorn",
|
|
2175
|
+
"react"
|
|
2176
|
+
],
|
|
2177
|
+
categories: { correctness: "warn" }
|
|
2178
|
+
};
|
|
2179
|
+
else oxlintConfig = {
|
|
2180
|
+
$schema: "./node_modules/oxlint/configuration_schema.json",
|
|
2181
|
+
plugins: [],
|
|
2182
|
+
categories: { correctness: "off" }
|
|
2183
|
+
};
|
|
2184
|
+
if (oxlintConfig.$schema === void 0 && options?.merge) oxlintConfig.$schema = "./node_modules/oxlint/configuration_schema.json";
|
|
2185
|
+
if (oxlintConfig.env?.builtin === void 0) {
|
|
2186
|
+
if (oxlintConfig.env === void 0) oxlintConfig.env = {};
|
|
2187
|
+
oxlintConfig.env.builtin = true;
|
|
2188
|
+
}
|
|
2189
|
+
const overrides = options?.merge ? oxlintConfig.overrides ?? [] : [];
|
|
2190
|
+
const globalPlugins = {};
|
|
2191
|
+
for (const config of configs) if (config.plugins) Object.assign(globalPlugins, config.plugins);
|
|
2192
|
+
for (const config of configs) {
|
|
2193
|
+
if (config.name?.startsWith("oxlint/")) continue;
|
|
2194
|
+
let targetConfig;
|
|
2195
|
+
if (config.files === void 0) targetConfig = oxlintConfig;
|
|
2196
|
+
else {
|
|
2197
|
+
const validFiles = processConfigFiles(config.files, options?.reporter);
|
|
2198
|
+
if (validFiles.length === 0) continue;
|
|
2199
|
+
targetConfig = { files: validFiles };
|
|
2200
|
+
const [push, result] = detectSameOverride(oxlintConfig, targetConfig);
|
|
2201
|
+
if (push) overrides.push(result);
|
|
2202
|
+
}
|
|
2203
|
+
transformIgnorePatterns(config, targetConfig, options);
|
|
2204
|
+
transformRuleEntry(config, targetConfig, config.files !== void 0 ? oxlintConfig : void 0, options, config.files === void 0 ? overrides : void 0, globalPlugins);
|
|
2205
|
+
transformEnvAndGlobals(config, targetConfig, options);
|
|
2206
|
+
if (config.files === void 0) transformSettings(config, oxlintConfig, options);
|
|
2207
|
+
else warnSettingsInOverride(config, options);
|
|
2208
|
+
if ("files" in targetConfig) {
|
|
2209
|
+
detectNeededRulesPlugins(targetConfig);
|
|
2210
|
+
detectEnvironmentByGlobals(targetConfig);
|
|
2211
|
+
cleanUpOxlintConfig(targetConfig);
|
|
2212
|
+
}
|
|
2213
|
+
}
|
|
2214
|
+
oxlintConfig.overrides = overrides;
|
|
2215
|
+
detectNeededRulesPlugins(oxlintConfig);
|
|
2216
|
+
detectEnvironmentByGlobals(oxlintConfig);
|
|
2217
|
+
cleanUpOxlintConfig(oxlintConfig);
|
|
2218
|
+
if (options?.typeAware) {
|
|
2219
|
+
if ([...Object.keys(oxlintConfig.rules ?? {}), ...(oxlintConfig.overrides ?? []).flatMap((o) => Object.keys(o.rules ?? {}))].some((rule) => typeAwareRules.includes(rule))) oxlintConfig.options = {
|
|
2220
|
+
...oxlintConfig.options,
|
|
2221
|
+
typeAware: true
|
|
2222
|
+
};
|
|
2223
|
+
}
|
|
2224
|
+
return oxlintConfig;
|
|
2225
|
+
};
|
|
2226
|
+
const main = async (configs, oxlintConfig, options) => {
|
|
2227
|
+
const resolved = await Promise.resolve(fixForJsPlugins(configs));
|
|
2228
|
+
return buildConfig(Array.isArray(resolved) ? resolved : [resolved], oxlintConfig, options);
|
|
2229
|
+
};
|
|
2230
|
+
//#endregion
|
|
2231
|
+
export { nurseryRules as a, buildUnsupportedRuleExplanations as i, preFixForJsPlugins as n, rules_exports as o, isOffValue as r, main as t };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oxlint/migrate",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.52.0",
|
|
4
4
|
"description": "Generates a `.oxlintrc.json` from a existing eslint flat config",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"eslint",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"generate:unsupported": "node --import @oxc-node/core/register ./scripts/fetch-unsupported-rules.ts",
|
|
34
34
|
"generate:all": "pnpm generate:vitest && pnpm generate && pnpm generate:unsupported && pnpm format",
|
|
35
35
|
"format": "oxfmt",
|
|
36
|
-
"lint": "oxlint
|
|
36
|
+
"lint": "oxlint",
|
|
37
37
|
"test": "vitest",
|
|
38
38
|
"build": "tsdown",
|
|
39
39
|
"manual-test": "pnpm build; chmod +x dist/bin/oxlint-migrate.mjs; npx ."
|
|
@@ -41,23 +41,26 @@
|
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"commander": "^14.0.0",
|
|
43
43
|
"globals": "^17.0.0",
|
|
44
|
-
"oxc-parser": "^0.
|
|
44
|
+
"oxc-parser": "^0.116.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
50
|
"@eslint-react/eslint-plugin": "^2.13.0",
|
|
50
|
-
"@eslint/js": "^
|
|
51
|
+
"@eslint/js": "^10.0.0",
|
|
51
52
|
"@logux/eslint-config": "^57.0.0",
|
|
52
53
|
"@oxc-node/core": "^0.0.35",
|
|
53
54
|
"@stylistic/eslint-plugin": "^5.0.0",
|
|
54
55
|
"@stylistic/eslint-plugin-ts": "^4.4.1",
|
|
56
|
+
"@tanstack/eslint-plugin-query": "^5.91.4",
|
|
57
|
+
"@tanstack/eslint-plugin-router": "^1.161.4",
|
|
55
58
|
"@types/eslint-config-prettier": "^6.11.3",
|
|
56
59
|
"@types/node": "^25.0.0",
|
|
57
60
|
"@typescript-eslint/eslint-plugin": "^8.35.0",
|
|
58
61
|
"@typescript-eslint/parser": "^8.35.0",
|
|
59
62
|
"@vitest/coverage-v8": "^4.0.0",
|
|
60
|
-
"eslint": "^
|
|
63
|
+
"eslint": "^10.0.0",
|
|
61
64
|
"eslint-config-next": "^16.0.0",
|
|
62
65
|
"eslint-config-prettier": "^10.1.5",
|
|
63
66
|
"eslint-plugin-header": "^3.1.1",
|
|
@@ -76,19 +79,19 @@
|
|
|
76
79
|
"eslint-plugin-react-web-api": "^2.13.0",
|
|
77
80
|
"eslint-plugin-regexp": "^3.0.0",
|
|
78
81
|
"eslint-plugin-tsdoc": "^0.5.0",
|
|
79
|
-
"eslint-plugin-unicorn": "^
|
|
82
|
+
"eslint-plugin-unicorn": "^63.0.0",
|
|
80
83
|
"husky": "^9.1.7",
|
|
81
84
|
"lint-staged": "^16.1.2",
|
|
82
85
|
"next": "^16.0.0",
|
|
83
|
-
"oxfmt": "^0.
|
|
84
|
-
"oxlint": "^1.
|
|
85
|
-
"oxlint-tsgolint": "^0.
|
|
86
|
-
"tsdown": "^0.
|
|
86
|
+
"oxfmt": "^0.36.0",
|
|
87
|
+
"oxlint": "^1.52.0",
|
|
88
|
+
"oxlint-tsgolint": "^0.16.0",
|
|
89
|
+
"tsdown": "^0.21.0",
|
|
87
90
|
"typescript-eslint": "^8.35.0",
|
|
88
91
|
"vitest": "^4.0.0"
|
|
89
92
|
},
|
|
90
93
|
"lint-staged": {
|
|
91
94
|
"*": "oxfmt --no-error-on-unmatched-pattern"
|
|
92
95
|
},
|
|
93
|
-
"packageManager": "pnpm@10.30.
|
|
96
|
+
"packageManager": "pnpm@10.30.3"
|
|
94
97
|
}
|