eslint-plugin-react-rsc 5.3.3-next.2 → 5.3.4-beta.1
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.js +90 -3
- package/package.json +7 -7
package/dist/index.js
CHANGED
|
@@ -34,7 +34,7 @@ const rules$4 = { "react-rsc/function-definition": "off" };
|
|
|
34
34
|
//#endregion
|
|
35
35
|
//#region package.json
|
|
36
36
|
var name$4 = "eslint-plugin-react-rsc";
|
|
37
|
-
var version = "5.3.
|
|
37
|
+
var version = "5.3.4-beta.1";
|
|
38
38
|
|
|
39
39
|
//#endregion
|
|
40
40
|
//#region src/utils/create-rule.ts
|
|
@@ -53,7 +53,12 @@ var function_definition_default = createRule({
|
|
|
53
53
|
fixable: "code",
|
|
54
54
|
messages: {
|
|
55
55
|
file: "Functions exported from files with `use server` directive are React Server Functions and therefore must be async.",
|
|
56
|
-
|
|
56
|
+
fileDirectivePosition: "The '{{name}}' directive must be at the very beginning of the file, before any imports or other code.",
|
|
57
|
+
fileDirectiveQuote: "The '{{name}}' directive must be written with single or double quotes, not backticks.",
|
|
58
|
+
local: "Functions with `use server` directive are React Server Functions and therefore must be async.",
|
|
59
|
+
localDirectivePosition: "The '{{name}}' directive must be at the very beginning of the function body.",
|
|
60
|
+
localDirectiveQuote: "The '{{name}}' directive must be written with single or double quotes, not backticks.",
|
|
61
|
+
localDirectiveUnexpected: "The '{{name}}' directive can only be used at the top of a file, not inside a function body."
|
|
57
62
|
},
|
|
58
63
|
schema: []
|
|
59
64
|
},
|
|
@@ -62,7 +67,9 @@ var function_definition_default = createRule({
|
|
|
62
67
|
defaultOptions: []
|
|
63
68
|
});
|
|
64
69
|
function create(context) {
|
|
65
|
-
|
|
70
|
+
const hasUseServer = context.sourceCode.text.includes("use server");
|
|
71
|
+
const hasUseClient = context.sourceCode.text.includes("use client");
|
|
72
|
+
if (!hasUseServer && !hasUseClient) return {};
|
|
66
73
|
const hasFileLevelUseServerDirective = context.sourceCode.ast.body.some(Check.isDirective("use server"));
|
|
67
74
|
/**
|
|
68
75
|
* Check if `node` is an async function, and report if not
|
|
@@ -110,8 +117,68 @@ function create(context) {
|
|
|
110
117
|
if (!Check.isFunction(unwrapped)) return;
|
|
111
118
|
reportNonAsyncFunction(unwrapped, "file");
|
|
112
119
|
}
|
|
120
|
+
/**
|
|
121
|
+
* Check file-level directives for correct position and quote style.
|
|
122
|
+
* Well-formed directives at the beginning of the file will have a `directive` property.
|
|
123
|
+
* If they appear after other code, the parser will not set `directive`.
|
|
124
|
+
*/
|
|
125
|
+
function checkFileLevelDirectives() {
|
|
126
|
+
for (const node of context.sourceCode.ast.body) {
|
|
127
|
+
if (node.type !== AST_NODE_TYPES.ExpressionStatement) continue;
|
|
128
|
+
if (Check.isLiteral("string")(node.expression)) {
|
|
129
|
+
const value = node.expression.value;
|
|
130
|
+
if ((value === "use server" || value === "use client") && node.directive == null) context.report({
|
|
131
|
+
data: { name: value },
|
|
132
|
+
messageId: "fileDirectivePosition",
|
|
133
|
+
node
|
|
134
|
+
});
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
if (node.expression.type === AST_NODE_TYPES.TemplateLiteral && node.expression.quasis.length === 1 && node.expression.expressions.length === 0) {
|
|
138
|
+
const value = node.expression.quasis[0]?.value.cooked;
|
|
139
|
+
if (value === "use server" || value === "use client") context.report({
|
|
140
|
+
data: { name: value },
|
|
141
|
+
messageId: "fileDirectiveQuote",
|
|
142
|
+
node
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Check function-level directives for correct position and quote style.
|
|
149
|
+
* @param node The function node to check
|
|
150
|
+
*/
|
|
151
|
+
function checkFunctionDirectives(node) {
|
|
152
|
+
if (node.body.type !== AST_NODE_TYPES.BlockStatement) return;
|
|
153
|
+
for (const stmt of node.body.body) {
|
|
154
|
+
if (stmt.type !== AST_NODE_TYPES.ExpressionStatement) continue;
|
|
155
|
+
if (Check.isLiteral("string")(stmt.expression)) {
|
|
156
|
+
const value = stmt.expression.value;
|
|
157
|
+
if (value === "use server" && stmt.directive == null) context.report({
|
|
158
|
+
data: { name: value },
|
|
159
|
+
messageId: "localDirectivePosition",
|
|
160
|
+
node: stmt
|
|
161
|
+
});
|
|
162
|
+
if (value === "use client") context.report({
|
|
163
|
+
data: { name: value },
|
|
164
|
+
messageId: "localDirectiveUnexpected",
|
|
165
|
+
node: stmt
|
|
166
|
+
});
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
if (stmt.expression.type === AST_NODE_TYPES.TemplateLiteral && stmt.expression.quasis.length === 1 && stmt.expression.expressions.length === 0) {
|
|
170
|
+
const value = stmt.expression.quasis[0]?.value.cooked;
|
|
171
|
+
if (value === "use server" || value === "use client") context.report({
|
|
172
|
+
data: { name: value },
|
|
173
|
+
messageId: "localDirectiveQuote",
|
|
174
|
+
node: stmt
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
113
179
|
return merge({
|
|
114
180
|
ArrowFunctionExpression(node) {
|
|
181
|
+
checkFunctionDirectives(node);
|
|
115
182
|
checkLocalServerFunction(node);
|
|
116
183
|
},
|
|
117
184
|
ExportDefaultDeclaration(node) {
|
|
@@ -131,10 +198,15 @@ function create(context) {
|
|
|
131
198
|
if (node.source == null && node.specifiers.length > 0) for (const spec of node.specifiers) findAndCheckExportedFunctionDeclarations(spec.local);
|
|
132
199
|
},
|
|
133
200
|
FunctionDeclaration(node) {
|
|
201
|
+
checkFunctionDirectives(node);
|
|
134
202
|
checkLocalServerFunction(node);
|
|
135
203
|
},
|
|
136
204
|
FunctionExpression(node) {
|
|
205
|
+
checkFunctionDirectives(node);
|
|
137
206
|
checkLocalServerFunction(node);
|
|
207
|
+
},
|
|
208
|
+
Program() {
|
|
209
|
+
checkFileLevelDirectives();
|
|
138
210
|
}
|
|
139
211
|
});
|
|
140
212
|
}
|
|
@@ -206,10 +278,25 @@ const settings = { ...settings$1 };
|
|
|
206
278
|
const finalPlugin = {
|
|
207
279
|
...plugin,
|
|
208
280
|
configs: {
|
|
281
|
+
/**
|
|
282
|
+
* Disable experimental rules that might be subject to change in the future
|
|
283
|
+
*/
|
|
209
284
|
["disable-experimental"]: disable_experimental_exports,
|
|
285
|
+
/**
|
|
286
|
+
* Enforce rules that are recommended by ESLint React for general purpose React + React DOM projects
|
|
287
|
+
*/
|
|
210
288
|
["recommended"]: recommended_exports,
|
|
289
|
+
/**
|
|
290
|
+
* Same as the `recommended` preset but disables rules that can be enforced by TypeScript
|
|
291
|
+
*/
|
|
211
292
|
["recommended-typescript"]: recommended_typescript_exports,
|
|
293
|
+
/**
|
|
294
|
+
* More strict version of the `recommended` preset
|
|
295
|
+
*/
|
|
212
296
|
["strict"]: strict_exports,
|
|
297
|
+
/**
|
|
298
|
+
* Same as the `strict` preset but disables rules that can be enforced by TypeScript
|
|
299
|
+
*/
|
|
213
300
|
["strict-typescript"]: strict_typescript_exports
|
|
214
301
|
}
|
|
215
302
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-react-rsc",
|
|
3
|
-
"version": "5.3.
|
|
3
|
+
"version": "5.3.4-beta.1",
|
|
4
4
|
"description": "ESLint React's ESLint plugin for RSC related rules.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -42,17 +42,17 @@
|
|
|
42
42
|
"@typescript-eslint/types": "^8.59.0",
|
|
43
43
|
"@typescript-eslint/utils": "^8.59.0",
|
|
44
44
|
"ts-pattern": "^5.9.0",
|
|
45
|
-
"@eslint-react/ast": "5.3.
|
|
46
|
-
"@eslint-react/core": "5.3.
|
|
47
|
-
"@eslint-react/shared": "5.3.
|
|
48
|
-
"@eslint-react/var": "5.3.
|
|
49
|
-
"@eslint-react/eslint": "5.3.
|
|
45
|
+
"@eslint-react/ast": "5.3.4-beta.1",
|
|
46
|
+
"@eslint-react/core": "5.3.4-beta.1",
|
|
47
|
+
"@eslint-react/shared": "5.3.4-beta.1",
|
|
48
|
+
"@eslint-react/var": "5.3.4-beta.1",
|
|
49
|
+
"@eslint-react/eslint": "5.3.4-beta.1"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
52
|
"@types/react": "^19.2.14",
|
|
53
53
|
"@types/react-dom": "^19.2.3",
|
|
54
54
|
"eslint": "^10.2.1",
|
|
55
|
-
"tsdown": "^0.21.
|
|
55
|
+
"tsdown": "^0.21.10",
|
|
56
56
|
"@local/configs": "0.0.0",
|
|
57
57
|
"@local/eff": "3.0.0-beta.72"
|
|
58
58
|
},
|