-
Notifications
You must be signed in to change notification settings - Fork 387
Expand file tree
/
Copy pathindex.ts
More file actions
113 lines (99 loc) · 3.07 KB
/
index.ts
File metadata and controls
113 lines (99 loc) · 3.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import oxlintPlugin, {
ALL_REACT_DOCTOR_RULES,
NEXTJS_RULES,
REACT_NATIVE_RULES,
RECOMMENDED_RULES,
SOLID_RULES,
TANSTACK_QUERY_RULES,
TANSTACK_START_RULES,
} from "oxlint-plugin-react-doctor";
import type { EsTreeNode, OxlintRuleSeverity, RuleVisitors } from "oxlint-plugin-react-doctor";
interface EslintRuleContext {
report: (descriptor: { node: EsTreeNode; message: string }) => void;
getFilename?: () => string;
}
interface WrappedRule {
create: (context: EslintRuleContext) => RuleVisitors;
}
interface EslintRuleMeta {
type: "problem" | "suggestion" | "layout";
docs: {
description: string;
url: string;
recommended: boolean;
};
schema: unknown[];
}
interface EslintRule {
meta: EslintRuleMeta;
create: (context: EslintRuleContext) => RuleVisitors;
}
interface EslintFlatConfig {
name: string;
plugins: Record<string, EslintPlugin>;
rules: Record<string, OxlintRuleSeverity>;
}
interface EslintPlugin {
meta: { name: string; version: string };
rules: Record<string, EslintRule>;
configs: {
recommended: EslintFlatConfig;
next: EslintFlatConfig;
"react-native": EslintFlatConfig;
"tanstack-start": EslintFlatConfig;
"tanstack-query": EslintFlatConfig;
solid: EslintFlatConfig;
all: EslintFlatConfig;
};
}
const PLUGIN_NAMESPACE = "react-doctor";
const RULE_DOCS_BASE_URL = "https://react.doctor/rules";
const recommendedRuleKeys = new Set(Object.keys(RECOMMENDED_RULES));
const wrapAsEslintRule = (ruleName: string, ruleImpl: WrappedRule): EslintRule => ({
meta: {
type: "problem",
docs: {
description: ruleName
.replaceAll("-", " ")
.replace(/\b\w/g, (innerChar) => innerChar.toUpperCase()),
url: `${RULE_DOCS_BASE_URL}/${ruleName}`,
recommended: recommendedRuleKeys.has(`${PLUGIN_NAMESPACE}/${ruleName}`),
},
schema: [],
},
create: (context: EslintRuleContext) => ruleImpl.create(context),
});
const eslintShapedRules: Record<string, EslintRule> = Object.fromEntries(
Object.entries(oxlintPlugin.rules).map(([ruleName, ruleImpl]) => [
ruleName,
wrapAsEslintRule(ruleName, ruleImpl),
]),
);
const buildFlatConfig = (
configName: string,
ruleSet: Record<string, OxlintRuleSeverity>,
): EslintFlatConfig => ({
name: `react-doctor/${configName}`,
plugins: {},
rules: { ...ruleSet },
});
const eslintPlugin: EslintPlugin = {
meta: {
name: PLUGIN_NAMESPACE,
version: process.env.VERSION ?? "0.0.0",
},
rules: eslintShapedRules,
configs: {
recommended: buildFlatConfig("recommended", RECOMMENDED_RULES),
next: buildFlatConfig("next", NEXTJS_RULES),
"react-native": buildFlatConfig("react-native", REACT_NATIVE_RULES),
"tanstack-start": buildFlatConfig("tanstack-start", TANSTACK_START_RULES),
"tanstack-query": buildFlatConfig("tanstack-query", TANSTACK_QUERY_RULES),
solid: buildFlatConfig("solid", SOLID_RULES),
all: buildFlatConfig("all", ALL_REACT_DOCTOR_RULES),
},
};
for (const flatConfig of Object.values(eslintPlugin.configs)) {
flatConfig.plugins[PLUGIN_NAMESPACE] = eslintPlugin;
}
export default eslintPlugin;