@zhangyu1818/oxlint-config 2.1.0 → 2.2.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/dist/index.d.ts +121 -116
- package/dist/index.js +825 -988
- package/dist/react-agent-rules.d.ts +45 -44
- package/dist/react-agent-rules.js +71 -101
- package/package.json +20 -19
|
@@ -1,52 +1,53 @@
|
|
|
1
|
+
//#region src/react-agent-rules.d.ts
|
|
1
2
|
interface CallExpressionNode {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
arguments: unknown[];
|
|
4
|
+
callee: unknown;
|
|
5
|
+
type: 'CallExpression';
|
|
5
6
|
}
|
|
6
7
|
interface RuleContext {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
report(descriptor: {
|
|
9
|
+
message: string;
|
|
10
|
+
node: unknown;
|
|
11
|
+
}): void;
|
|
11
12
|
}
|
|
12
13
|
declare const plugin: {
|
|
13
|
-
|
|
14
|
-
|
|
14
|
+
meta: {
|
|
15
|
+
name: string;
|
|
16
|
+
};
|
|
17
|
+
rules: {
|
|
18
|
+
'effect-empty-deps-only': {
|
|
19
|
+
meta: {
|
|
20
|
+
schema: never[];
|
|
21
|
+
};
|
|
22
|
+
create(context: RuleContext): {
|
|
23
|
+
CallExpression(node: CallExpressionNode): void;
|
|
24
|
+
};
|
|
15
25
|
};
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
};
|
|
24
|
-
};
|
|
25
|
-
'no-forward-ref': {
|
|
26
|
-
meta: {
|
|
27
|
-
schema: never[];
|
|
28
|
-
};
|
|
29
|
-
create(context: RuleContext): {
|
|
30
|
-
CallExpression(node: CallExpressionNode): void;
|
|
31
|
-
};
|
|
32
|
-
};
|
|
33
|
-
'no-manual-memoization': {
|
|
34
|
-
meta: {
|
|
35
|
-
schema: never[];
|
|
36
|
-
};
|
|
37
|
-
create(context: RuleContext): {
|
|
38
|
-
CallExpression(node: CallExpressionNode): void;
|
|
39
|
-
};
|
|
40
|
-
};
|
|
41
|
-
'no-use-context': {
|
|
42
|
-
meta: {
|
|
43
|
-
schema: never[];
|
|
44
|
-
};
|
|
45
|
-
create(context: RuleContext): {
|
|
46
|
-
CallExpression(node: CallExpressionNode): void;
|
|
47
|
-
};
|
|
48
|
-
};
|
|
26
|
+
'no-forward-ref': {
|
|
27
|
+
meta: {
|
|
28
|
+
schema: never[];
|
|
29
|
+
};
|
|
30
|
+
create(context: RuleContext): {
|
|
31
|
+
CallExpression(node: CallExpressionNode): void;
|
|
32
|
+
};
|
|
49
33
|
};
|
|
34
|
+
'no-manual-memoization': {
|
|
35
|
+
meta: {
|
|
36
|
+
schema: never[];
|
|
37
|
+
};
|
|
38
|
+
create(context: RuleContext): {
|
|
39
|
+
CallExpression(node: CallExpressionNode): void;
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
'no-use-context': {
|
|
43
|
+
meta: {
|
|
44
|
+
schema: never[];
|
|
45
|
+
};
|
|
46
|
+
create(context: RuleContext): {
|
|
47
|
+
CallExpression(node: CallExpressionNode): void;
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
};
|
|
50
51
|
};
|
|
51
|
-
|
|
52
|
-
export { plugin as default };
|
|
52
|
+
//#endregion
|
|
53
|
+
export { plugin as default };
|
|
@@ -1,114 +1,84 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
//#region src/react-agent-rules.ts
|
|
2
|
+
const NO_MANUAL_MEMOIZATION_MESSAGE = "React Compiler automatically optimizes components and values, so manual memoization is not needed.";
|
|
3
|
+
const NO_FORWARD_REF_MESSAGE = "Starting in React 19, ref is a prop, so forwardRef is no longer needed.";
|
|
4
|
+
const NO_USE_CONTEXT_MESSAGE = "In React 19, use is preferred over useContext for reading context because it is more flexible.";
|
|
5
|
+
const EFFECT_EMPTY_DEPS_ONLY_MESSAGE = "Effects here must use an empty dependency array. Use them only for mount and unmount logic. For event-driven logic, use useEffectEvent inside the effect. Do not use effects as a watch mechanism.";
|
|
6
|
+
const manualMemoizationNames = /* @__PURE__ */ new Set([
|
|
7
|
+
"memo",
|
|
8
|
+
"useMemo",
|
|
9
|
+
"useCallback"
|
|
10
|
+
]);
|
|
11
|
+
const effectNames = /* @__PURE__ */ new Set(["useEffect", "useLayoutEffect"]);
|
|
12
|
+
const forwardRefNames = /* @__PURE__ */ new Set(["forwardRef"]);
|
|
13
|
+
const useContextNames = /* @__PURE__ */ new Set(["useContext"]);
|
|
10
14
|
function isRecord(node) {
|
|
11
|
-
|
|
15
|
+
return typeof node === "object" && node !== null;
|
|
12
16
|
}
|
|
13
17
|
function isIdentifier(node, name) {
|
|
14
|
-
|
|
18
|
+
return isRecord(node) && node.type === "Identifier" && node.name === name;
|
|
15
19
|
}
|
|
16
20
|
function isNamedIdentifier(node, names) {
|
|
17
|
-
|
|
21
|
+
return isRecord(node) && node.type === "Identifier" && typeof node.name === "string" && names.has(node.name);
|
|
18
22
|
}
|
|
19
23
|
function isMemberExpression(node) {
|
|
20
|
-
|
|
24
|
+
return isRecord(node) && node.type === "MemberExpression" && typeof node.computed === "boolean" && "object" in node && "property" in node;
|
|
21
25
|
}
|
|
22
26
|
function isReactMember(node, names) {
|
|
23
|
-
|
|
27
|
+
return isMemberExpression(node) && !node.computed && isIdentifier(node.object, "React") && isNamedIdentifier(node.property, names);
|
|
24
28
|
}
|
|
25
29
|
function isEmptyDependencyArray(node) {
|
|
26
|
-
|
|
30
|
+
return isRecord(node) && node.type === "ArrayExpression" && Array.isArray(node.elements) && node.elements.length === 0;
|
|
27
31
|
}
|
|
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
|
-
var effectEmptyDepsOnlyRule = {
|
|
80
|
-
meta: {
|
|
81
|
-
schema: []
|
|
82
|
-
},
|
|
83
|
-
create(context) {
|
|
84
|
-
return {
|
|
85
|
-
CallExpression(node) {
|
|
86
|
-
if (!isNamedIdentifier(node.callee, effectNames) && !isReactMember(node.callee, effectNames)) {
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
const dependencyArray = node.arguments[1];
|
|
90
|
-
if (!isEmptyDependencyArray(dependencyArray)) {
|
|
91
|
-
context.report({
|
|
92
|
-
message: EFFECT_EMPTY_DEPS_ONLY_MESSAGE,
|
|
93
|
-
node
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
};
|
|
100
|
-
var plugin = {
|
|
101
|
-
meta: {
|
|
102
|
-
name: "react-agent-rules"
|
|
103
|
-
},
|
|
104
|
-
rules: {
|
|
105
|
-
"effect-empty-deps-only": effectEmptyDepsOnlyRule,
|
|
106
|
-
"no-forward-ref": noForwardRefRule,
|
|
107
|
-
"no-manual-memoization": noManualMemoizationRule,
|
|
108
|
-
"no-use-context": noUseContextRule
|
|
109
|
-
}
|
|
110
|
-
};
|
|
111
|
-
var react_agent_rules_default = plugin;
|
|
112
|
-
export {
|
|
113
|
-
react_agent_rules_default as default
|
|
32
|
+
const plugin = {
|
|
33
|
+
meta: { name: "react-agent-rules" },
|
|
34
|
+
rules: {
|
|
35
|
+
"effect-empty-deps-only": {
|
|
36
|
+
meta: { schema: [] },
|
|
37
|
+
create(context) {
|
|
38
|
+
return { CallExpression(node) {
|
|
39
|
+
if (!isNamedIdentifier(node.callee, effectNames) && !isReactMember(node.callee, effectNames)) return;
|
|
40
|
+
const dependencyArray = node.arguments[1];
|
|
41
|
+
if (!isEmptyDependencyArray(dependencyArray)) context.report({
|
|
42
|
+
message: EFFECT_EMPTY_DEPS_ONLY_MESSAGE,
|
|
43
|
+
node
|
|
44
|
+
});
|
|
45
|
+
} };
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"no-forward-ref": {
|
|
49
|
+
meta: { schema: [] },
|
|
50
|
+
create(context) {
|
|
51
|
+
return { CallExpression(node) {
|
|
52
|
+
if (isNamedIdentifier(node.callee, forwardRefNames) || isReactMember(node.callee, forwardRefNames)) context.report({
|
|
53
|
+
message: NO_FORWARD_REF_MESSAGE,
|
|
54
|
+
node
|
|
55
|
+
});
|
|
56
|
+
} };
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
"no-manual-memoization": {
|
|
60
|
+
meta: { schema: [] },
|
|
61
|
+
create(context) {
|
|
62
|
+
return { CallExpression(node) {
|
|
63
|
+
if (isNamedIdentifier(node.callee, manualMemoizationNames) || isReactMember(node.callee, manualMemoizationNames)) context.report({
|
|
64
|
+
message: NO_MANUAL_MEMOIZATION_MESSAGE,
|
|
65
|
+
node
|
|
66
|
+
});
|
|
67
|
+
} };
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
"no-use-context": {
|
|
71
|
+
meta: { schema: [] },
|
|
72
|
+
create(context) {
|
|
73
|
+
return { CallExpression(node) {
|
|
74
|
+
if (isNamedIdentifier(node.callee, useContextNames) || isReactMember(node.callee, useContextNames)) context.report({
|
|
75
|
+
message: NO_USE_CONTEXT_MESSAGE,
|
|
76
|
+
node
|
|
77
|
+
});
|
|
78
|
+
} };
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
114
82
|
};
|
|
83
|
+
//#endregion
|
|
84
|
+
export { plugin as default };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhangyu1818/oxlint-config",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "Native Oxlint and Oxfmt config preset package",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"oxc",
|
|
@@ -25,35 +25,36 @@
|
|
|
25
25
|
"import": "./dist/index.js"
|
|
26
26
|
}
|
|
27
27
|
},
|
|
28
|
+
"scripts": {
|
|
29
|
+
"build": "tsdown",
|
|
30
|
+
"format": "oxfmt -c oxfmt.config.ts .",
|
|
31
|
+
"format:check": "oxfmt --check -c oxfmt.config.ts .",
|
|
32
|
+
"lint": "oxlint -c oxlint.config.ts",
|
|
33
|
+
"lint:fix": "oxlint --fix -c oxlint.config.ts",
|
|
34
|
+
"test": "vitest --run",
|
|
35
|
+
"test:smoke": "node tests/package-smoke.mjs",
|
|
36
|
+
"test:watch": "vitest",
|
|
37
|
+
"tsc:check": "tsc"
|
|
38
|
+
},
|
|
28
39
|
"dependencies": {
|
|
29
40
|
"local-pkg": "^1.2.1"
|
|
30
41
|
},
|
|
31
42
|
"devDependencies": {
|
|
32
43
|
"@types/node": "^25.9.3",
|
|
33
|
-
"oxfmt": "^0.
|
|
34
|
-
"oxlint": "^1.
|
|
44
|
+
"oxfmt": "^0.56.0",
|
|
45
|
+
"oxlint": "^1.71.0",
|
|
35
46
|
"oxlint-tsgolint": "^0.23.0",
|
|
36
|
-
"
|
|
47
|
+
"tsdown": "^0.22.3",
|
|
37
48
|
"typescript": "^6.0.3",
|
|
38
|
-
"vitest": "^4.1.
|
|
49
|
+
"vitest": "^4.1.9"
|
|
39
50
|
},
|
|
40
51
|
"peerDependencies": {
|
|
41
|
-
"oxfmt": "^0.
|
|
42
|
-
"oxlint": "^1.
|
|
52
|
+
"oxfmt": "^0.56.0",
|
|
53
|
+
"oxlint": "^1.71.0",
|
|
43
54
|
"oxlint-tsgolint": "^0.23.0"
|
|
44
55
|
},
|
|
45
56
|
"engines": {
|
|
46
57
|
"node": ">=24"
|
|
47
58
|
},
|
|
48
|
-
"
|
|
49
|
-
|
|
50
|
-
"format": "oxfmt -c oxfmt.config.ts .",
|
|
51
|
-
"format:check": "oxfmt --check -c oxfmt.config.ts .",
|
|
52
|
-
"lint": "oxlint -c oxlint.config.ts",
|
|
53
|
-
"lint:fix": "oxlint --fix -c oxlint.config.ts",
|
|
54
|
-
"test": "vitest --run",
|
|
55
|
-
"test:smoke": "node tests/package-smoke.mjs",
|
|
56
|
-
"test:watch": "vitest",
|
|
57
|
-
"tsc:check": "tsc"
|
|
58
|
-
}
|
|
59
|
-
}
|
|
59
|
+
"packageManager": "pnpm@11.9.0"
|
|
60
|
+
}
|