@sarj/eslint-plugin 16.4.6 → 16.4.8
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.cjs +480 -109
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +757 -386
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,3 +1,122 @@
|
|
|
1
|
+
// package.json
|
|
2
|
+
var package_default = {
|
|
3
|
+
name: "@sarj/eslint-plugin",
|
|
4
|
+
version: "16.4.8",
|
|
5
|
+
packageManager: "npm@12.1.0",
|
|
6
|
+
description: "Custom ESLint rules for hypermodern TypeScript / React / Next.js projects",
|
|
7
|
+
type: "module",
|
|
8
|
+
main: "./dist/index.cjs",
|
|
9
|
+
module: "./dist/index.js",
|
|
10
|
+
types: "./dist/index.d.ts",
|
|
11
|
+
exports: {
|
|
12
|
+
".": {
|
|
13
|
+
types: "./dist/index.d.ts",
|
|
14
|
+
import: "./dist/index.js",
|
|
15
|
+
require: "./dist/index.cjs"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
files: [
|
|
19
|
+
"dist",
|
|
20
|
+
"README.md",
|
|
21
|
+
"LICENSE"
|
|
22
|
+
],
|
|
23
|
+
publishConfig: {
|
|
24
|
+
access: "public"
|
|
25
|
+
},
|
|
26
|
+
sideEffects: false,
|
|
27
|
+
repository: {
|
|
28
|
+
type: "git",
|
|
29
|
+
url: "git+https://github.com/sarj-ai/code-standards.git",
|
|
30
|
+
directory: "packages/typescript"
|
|
31
|
+
},
|
|
32
|
+
homepage: "https://code-standards.sarj.ai/rules/eslint/",
|
|
33
|
+
bugs: {
|
|
34
|
+
url: "https://github.com/sarj-ai/code-standards/issues"
|
|
35
|
+
},
|
|
36
|
+
scripts: {
|
|
37
|
+
build: "tsup",
|
|
38
|
+
dogfood: "npm run build && npm run dogfood:built",
|
|
39
|
+
lint: "eslint . ../../.github/scripts ../standards/src ../standards/eslint.config.mjs --max-warnings 0",
|
|
40
|
+
prepack: "npm run build && npm run verify-package",
|
|
41
|
+
test: "vitest run",
|
|
42
|
+
typecheck: "tsc --noEmit",
|
|
43
|
+
"verify-package": `node -e "const fs=require('node:fs'),p=require('./package.json'),walk=x=>typeof x==='string'?[x]:x&&typeof x==='object'?Object.values(x).flatMap(walk):[];for(const file of new Set([p.main,p.module,p.types,...walk(p.exports)].filter(Boolean).map(x=>x.startsWith('./')?x.slice(2):x))){if(!file.startsWith('dist/'))throw new Error('export must live under dist: '+file);const stat=fs.statSync(file);if(!stat.isFile()||stat.size===0)throw new Error('missing or empty export: '+file)}"`,
|
|
44
|
+
"dogfood:built": `eslint --config eslint.dogfood.config.mjs src tests eslint.config.mjs eslint.dogfood.config.mjs module-constant-naming-options.mjs tsup.config.ts vitest.config.ts --max-warnings 0 && node -e "import('./dist/index.js').then(({default:p}) => console.log('dogfood: '+Object.keys(p.rules).length+' TypeScript rules, 0 diagnostics'))"`
|
|
45
|
+
},
|
|
46
|
+
keywords: [
|
|
47
|
+
"eslint",
|
|
48
|
+
"eslintplugin",
|
|
49
|
+
"eslint-plugin",
|
|
50
|
+
"sarj",
|
|
51
|
+
"react",
|
|
52
|
+
"nextjs",
|
|
53
|
+
"zod"
|
|
54
|
+
],
|
|
55
|
+
author: "sarj-ai",
|
|
56
|
+
license: "MIT",
|
|
57
|
+
dependencies: {
|
|
58
|
+
"@typescript-eslint/typescript-estree": "^8.70.1",
|
|
59
|
+
"@typescript-eslint/utils": "^8.70.1",
|
|
60
|
+
"jsonc-parser": "^3.3.1"
|
|
61
|
+
},
|
|
62
|
+
devDependencies: {
|
|
63
|
+
"@eslint-community/eslint-plugin-eslint-comments": "^4.8.1",
|
|
64
|
+
"@eslint/compat": "^2.1.1",
|
|
65
|
+
"@eslint/js": "10.0.1",
|
|
66
|
+
"@shadcn/lint": "0.2.0",
|
|
67
|
+
"@types/node": "26.6.2",
|
|
68
|
+
"@typescript-eslint/parser": "8.70.1",
|
|
69
|
+
"@typescript-eslint/rule-tester": "8.70.1",
|
|
70
|
+
"@typescript-eslint/utils": "8.70.1",
|
|
71
|
+
"@typescript/native": "npm:typescript@7.0.2",
|
|
72
|
+
"@vitest/eslint-plugin": "1.6.27",
|
|
73
|
+
eslint: "10.11.0",
|
|
74
|
+
"eslint-node-test": "0.4.0",
|
|
75
|
+
"eslint-plugin-better-tailwindcss": "^4.7.0",
|
|
76
|
+
"eslint-plugin-jest": "29.16.6",
|
|
77
|
+
"eslint-plugin-jsdoc": "64.5.4",
|
|
78
|
+
"eslint-plugin-n": "^18.3.0",
|
|
79
|
+
"eslint-plugin-perfectionist": "5.12.1",
|
|
80
|
+
"eslint-plugin-playwright": "2.12.0",
|
|
81
|
+
"eslint-plugin-promise": "^7.3.0",
|
|
82
|
+
"eslint-plugin-react": "^7.37.5",
|
|
83
|
+
"eslint-plugin-react-hooks": "^7.1.1",
|
|
84
|
+
"eslint-plugin-simple-import-sort": "^14.0.0",
|
|
85
|
+
"eslint-plugin-testing-library": "7.16.2",
|
|
86
|
+
"eslint-plugin-unicorn": "^76.0.0",
|
|
87
|
+
"eslint-plugin-zod": "^4.14.2",
|
|
88
|
+
globals: "15.15.0",
|
|
89
|
+
tsup: "latest",
|
|
90
|
+
typescript: "npm:@typescript/typescript6@6.0.2",
|
|
91
|
+
"typescript-eslint": "^8.70.1",
|
|
92
|
+
vitest: "5.0.1"
|
|
93
|
+
},
|
|
94
|
+
peerDependencies: {
|
|
95
|
+
eslint: ">=9.39.4",
|
|
96
|
+
typescript: ">=5.0.0"
|
|
97
|
+
},
|
|
98
|
+
engines: {
|
|
99
|
+
node: ">=22.22.2"
|
|
100
|
+
},
|
|
101
|
+
allowScripts: {
|
|
102
|
+
"esbuild@0.28.2": true,
|
|
103
|
+
"fsevents@2.3.3": true
|
|
104
|
+
},
|
|
105
|
+
peerDependenciesMeta: {
|
|
106
|
+
typescript: {
|
|
107
|
+
optional: true
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
overrides: {
|
|
111
|
+
"brace-expansion@^5.0.0": "5.0.9",
|
|
112
|
+
esbuild: "0.28.2",
|
|
113
|
+
"nanoid@<3.3.18": "3.3.18",
|
|
114
|
+
"eslint-plugin-react": {
|
|
115
|
+
eslint: "$eslint"
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
|
|
1
120
|
// src/rules/require-explicit-contract-implementation.ts
|
|
2
121
|
import { AST_NODE_TYPES, ESLintUtils as ESLintUtils2 } from "@typescript-eslint/utils";
|
|
3
122
|
import * as ts from "typescript";
|
|
@@ -211,6 +330,7 @@ function deepFreeze(value) {
|
|
|
211
330
|
}
|
|
212
331
|
|
|
213
332
|
// src/rules/_paths.ts
|
|
333
|
+
var LINE_TERMINATOR_RE = /[\n\r\u2028\u2029]/u;
|
|
214
334
|
var SCRIPT_FILE_RE = /(?:^|[\\/])scripts[\\/]|\.mjs$/;
|
|
215
335
|
var STORY_FILE_RE = /\.stories\.[cm]?[jt]sx?$/i;
|
|
216
336
|
var STORY_TREE_RE = /(^|\/)stories(?:[_-][^/]*)?\//i;
|
|
@@ -260,8 +380,8 @@ function leadingCommentBodies(sourceText) {
|
|
|
260
380
|
const bodies = [];
|
|
261
381
|
let index = 0;
|
|
262
382
|
if (sourceText.startsWith("#!")) {
|
|
263
|
-
const shebangEnd = sourceText
|
|
264
|
-
index = shebangEnd ===
|
|
383
|
+
const shebangEnd = commentLineEnd(sourceText, 2);
|
|
384
|
+
index = shebangEnd === sourceText.length ? sourceText.length : shebangEnd + 1;
|
|
265
385
|
}
|
|
266
386
|
while (index < sourceText.length) {
|
|
267
387
|
while (/\s/u.test(sourceText[index] ?? "")) index++;
|
|
@@ -275,7 +395,7 @@ function leadingCommentBodies(sourceText) {
|
|
|
275
395
|
const end = sourceText.indexOf("*/", index + 2);
|
|
276
396
|
if (end === -1) break;
|
|
277
397
|
bodies.push(
|
|
278
|
-
...sourceText.slice(index + 2, end).split(
|
|
398
|
+
...sourceText.slice(index + 2, end).split(LINE_TERMINATOR_RE).map((line) => line.replace(/^\s*\*?\s?/u, "").trim()).filter((line) => line.length > 0)
|
|
279
399
|
);
|
|
280
400
|
index = end + 2;
|
|
281
401
|
continue;
|
|
@@ -294,8 +414,8 @@ function isScriptFile(filename) {
|
|
|
294
414
|
return SCRIPT_FILE_RE.test(filename);
|
|
295
415
|
}
|
|
296
416
|
function commentLineEnd(sourceText, start) {
|
|
297
|
-
const end = sourceText.
|
|
298
|
-
return end === -1 ? sourceText.length : end;
|
|
417
|
+
const end = sourceText.slice(start).search(LINE_TERMINATOR_RE);
|
|
418
|
+
return end === -1 ? sourceText.length : start + end;
|
|
299
419
|
}
|
|
300
420
|
|
|
301
421
|
// src/rules/require-explicit-contract-implementation.ts
|
|
@@ -4747,16 +4867,51 @@ var no_cors_wildcard_with_credentials_default = createRule({
|
|
|
4747
4867
|
});
|
|
4748
4868
|
|
|
4749
4869
|
// src/rules/no-duplicate-lifecycle-refresh-listeners.ts
|
|
4750
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES28, ASTUtils as
|
|
4870
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES28, ASTUtils as ASTUtils9 } from "@typescript-eslint/utils";
|
|
4751
4871
|
|
|
4752
4872
|
// src/rules/_static-string.ts
|
|
4753
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES27 } from "@typescript-eslint/utils";
|
|
4873
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES27, ASTUtils as ASTUtils8 } from "@typescript-eslint/utils";
|
|
4754
4874
|
function staticString(node) {
|
|
4755
4875
|
if (node === void 0) return null;
|
|
4756
4876
|
const value = unwrapExpression(node);
|
|
4757
4877
|
if (value.type === AST_NODE_TYPES27.Literal && typeof value.value === "string") return value.value;
|
|
4758
4878
|
return value.type === AST_NODE_TYPES27.TemplateLiteral && value.expressions.length === 0 ? value.quasis[0]?.value.cooked ?? null : null;
|
|
4759
4879
|
}
|
|
4880
|
+
var SCOPED_STRING_VALUES = /* @__PURE__ */ new WeakMap();
|
|
4881
|
+
function scopedStaticString(node, sourceCode) {
|
|
4882
|
+
let value = unwrapExpression(node);
|
|
4883
|
+
if (value.type !== AST_NODE_TYPES27.Identifier) return staticString(value);
|
|
4884
|
+
let values = SCOPED_STRING_VALUES.get(sourceCode);
|
|
4885
|
+
if (values === void 0) {
|
|
4886
|
+
values = /* @__PURE__ */ new WeakMap();
|
|
4887
|
+
SCOPED_STRING_VALUES.set(sourceCode, values);
|
|
4888
|
+
}
|
|
4889
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4890
|
+
const pending = [];
|
|
4891
|
+
let result = null;
|
|
4892
|
+
while (value.type === AST_NODE_TYPES27.Identifier) {
|
|
4893
|
+
const binding = ASTUtils8.findVariable(sourceCode.getScope(value), value.name);
|
|
4894
|
+
if (binding === null || seen.has(binding)) break;
|
|
4895
|
+
if (values.has(binding)) {
|
|
4896
|
+
result = values.get(binding) ?? null;
|
|
4897
|
+
break;
|
|
4898
|
+
}
|
|
4899
|
+
seen.add(binding);
|
|
4900
|
+
pending.push(binding);
|
|
4901
|
+
const definition = binding.defs.length === 1 ? binding.defs[0] : void 0;
|
|
4902
|
+
if (definition?.type !== "Variable" || definition.node.id.type !== AST_NODE_TYPES27.Identifier || definition.node.init === null || binding.references.some((reference) => reference.isWrite() && reference.init !== true)) break;
|
|
4903
|
+
value = unwrapExpression(definition.node.init);
|
|
4904
|
+
if (value.type !== AST_NODE_TYPES27.Identifier) result = staticString(value);
|
|
4905
|
+
}
|
|
4906
|
+
for (const binding of pending) values.set(binding, result);
|
|
4907
|
+
return result;
|
|
4908
|
+
}
|
|
4909
|
+
function staticPropertyName(node, sourceCode) {
|
|
4910
|
+
const direct = ASTUtils8.getPropertyName(node);
|
|
4911
|
+
if (direct !== null || !node.computed) return direct;
|
|
4912
|
+
const key = node.type === AST_NODE_TYPES27.MemberExpression ? node.property : node.key;
|
|
4913
|
+
return key.type === AST_NODE_TYPES27.Identifier ? scopedStaticString(key, sourceCode) : null;
|
|
4914
|
+
}
|
|
4760
4915
|
|
|
4761
4916
|
// src/rules/no-duplicate-lifecycle-refresh-listeners.ts
|
|
4762
4917
|
var NO_DUPLICATE_LIFECYCLE_REFRESH_LISTENERS_DOCUMENTATION = {
|
|
@@ -4776,19 +4931,19 @@ function importedName(node) {
|
|
|
4776
4931
|
function registration(sourceCode, node) {
|
|
4777
4932
|
const unwrappedNodeCallee = unwrapExpression(node.callee);
|
|
4778
4933
|
const receiver = unwrappedNodeCallee.type === AST_NODE_TYPES28.MemberExpression ? unwrapExpression(unwrappedNodeCallee.object) : unwrappedNodeCallee;
|
|
4779
|
-
if (unwrappedNodeCallee.type !== AST_NODE_TYPES28.MemberExpression || receiver.type !== AST_NODE_TYPES28.Identifier || !isUnshadowedGlobal(sourceCode, receiver) ||
|
|
4934
|
+
if (unwrappedNodeCallee.type !== AST_NODE_TYPES28.MemberExpression || receiver.type !== AST_NODE_TYPES28.Identifier || !isUnshadowedGlobal(sourceCode, receiver) || ASTUtils9.getPropertyName(unwrappedNodeCallee) === null || (ASTUtils9.getPropertyName(unwrappedNodeCallee) ?? "") !== "addEventListener" && (ASTUtils9.getPropertyName(unwrappedNodeCallee) ?? "") !== "removeEventListener" || node.arguments.length < 2) return null;
|
|
4780
4935
|
const event = node.arguments[0] === void 0 ? void 0 : unwrapExpression(node.arguments[0]);
|
|
4781
4936
|
const callback = node.arguments[1] === void 0 ? void 0 : unwrapExpression(node.arguments[1]);
|
|
4782
4937
|
if (event === void 0 || callback === void 0) return null;
|
|
4783
4938
|
const eventName = staticString(event);
|
|
4784
4939
|
if (eventName === null || callback.type !== AST_NODE_TYPES28.Identifier) return null;
|
|
4785
|
-
const operation = (
|
|
4940
|
+
const operation = (ASTUtils9.getPropertyName(unwrappedNodeCallee) ?? "") === "addEventListener" ? "add" : "remove";
|
|
4786
4941
|
if (receiver.name === "window" && eventName === "focus") return { operation, event: "focus", callback };
|
|
4787
4942
|
if (receiver.name === "document" && eventName === "visibilitychange") return { operation, event: "visibilitychange", callback };
|
|
4788
4943
|
return null;
|
|
4789
4944
|
}
|
|
4790
4945
|
function isUnshadowedGlobal(sourceCode, node) {
|
|
4791
|
-
const variable =
|
|
4946
|
+
const variable = ASTUtils9.findVariable(sourceCode.getScope(node), node.name);
|
|
4792
4947
|
return variable === null || variable.defs.length === 0;
|
|
4793
4948
|
}
|
|
4794
4949
|
function statementContainer(node) {
|
|
@@ -4827,7 +4982,7 @@ var no_duplicate_lifecycle_refresh_listeners_default = createRule({
|
|
|
4827
4982
|
if (node.source.value !== "next/navigation") return;
|
|
4828
4983
|
for (const specifier of node.specifiers) {
|
|
4829
4984
|
if (specifier.type === AST_NODE_TYPES28.ImportSpecifier && importedName(specifier) === "useRouter") {
|
|
4830
|
-
const variable =
|
|
4985
|
+
const variable = ASTUtils9.findVariable(context.sourceCode.getScope(specifier.local), specifier.local.name);
|
|
4831
4986
|
if (variable !== null) routerHooks.add(variable);
|
|
4832
4987
|
}
|
|
4833
4988
|
}
|
|
@@ -4835,7 +4990,7 @@ var no_duplicate_lifecycle_refresh_listeners_default = createRule({
|
|
|
4835
4990
|
VariableDeclarator(node) {
|
|
4836
4991
|
const initializer = node.init === null ? null : unwrapExpression(node.init);
|
|
4837
4992
|
if (node.id.type !== AST_NODE_TYPES28.Identifier) return;
|
|
4838
|
-
const variable =
|
|
4993
|
+
const variable = ASTUtils9.findVariable(context.sourceCode.getScope(node.id), node.id.name);
|
|
4839
4994
|
if (variable === null || variable.references.some((reference) => reference.isWrite() && !reference.init)) return;
|
|
4840
4995
|
if (initializer?.type === AST_NODE_TYPES28.ArrowFunctionExpression || initializer?.type === AST_NODE_TYPES28.FunctionExpression) {
|
|
4841
4996
|
functionCallbacks.set(initializer, variable);
|
|
@@ -4843,19 +4998,19 @@ var no_duplicate_lifecycle_refresh_listeners_default = createRule({
|
|
|
4843
4998
|
if (initializer?.type !== AST_NODE_TYPES28.CallExpression) return;
|
|
4844
4999
|
const hookCallee = unwrapExpression(initializer.callee);
|
|
4845
5000
|
if (hookCallee.type !== AST_NODE_TYPES28.Identifier) return;
|
|
4846
|
-
const hook =
|
|
5001
|
+
const hook = ASTUtils9.findVariable(context.sourceCode.getScope(hookCallee), hookCallee.name);
|
|
4847
5002
|
if (hook !== null && routerHooks.has(hook)) routers.add(variable);
|
|
4848
5003
|
},
|
|
4849
5004
|
FunctionDeclaration(node) {
|
|
4850
5005
|
if (node.id === null) return;
|
|
4851
|
-
const variable =
|
|
5006
|
+
const variable = ASTUtils9.findVariable(context.sourceCode.getScope(node.id), node.id.name);
|
|
4852
5007
|
if (variable !== null && !variable.references.some((reference) => reference.isWrite() && !reference.init)) functionCallbacks.set(node, variable);
|
|
4853
5008
|
},
|
|
4854
5009
|
CallExpression(node) {
|
|
4855
5010
|
const unwrappedNodeCallee = unwrapExpression(node.callee);
|
|
4856
5011
|
const item = registration(context.sourceCode, node);
|
|
4857
5012
|
if (item !== null) {
|
|
4858
|
-
const callback2 =
|
|
5013
|
+
const callback2 = ASTUtils9.findVariable(context.sourceCode.getScope(item.callback), item.callback.name);
|
|
4859
5014
|
const container = statementContainer(node);
|
|
4860
5015
|
if (callback2 !== null && container !== null) {
|
|
4861
5016
|
const callbacks = registrations.get(container) ?? /* @__PURE__ */ new Map();
|
|
@@ -4867,8 +5022,8 @@ var no_duplicate_lifecycle_refresh_listeners_default = createRule({
|
|
|
4867
5022
|
}
|
|
4868
5023
|
}
|
|
4869
5024
|
const receiver = unwrappedNodeCallee.type === AST_NODE_TYPES28.MemberExpression ? unwrapExpression(unwrappedNodeCallee.object) : unwrappedNodeCallee;
|
|
4870
|
-
if (unwrappedNodeCallee.type !== AST_NODE_TYPES28.MemberExpression || receiver.type !== AST_NODE_TYPES28.Identifier ||
|
|
4871
|
-
const router =
|
|
5025
|
+
if (unwrappedNodeCallee.type !== AST_NODE_TYPES28.MemberExpression || receiver.type !== AST_NODE_TYPES28.Identifier || ASTUtils9.getPropertyName(unwrappedNodeCallee) === null || (ASTUtils9.getPropertyName(unwrappedNodeCallee) ?? "") !== "refresh") return;
|
|
5026
|
+
const router = ASTUtils9.findVariable(context.sourceCode.getScope(receiver), receiver.name);
|
|
4872
5027
|
if (router === null || !routers.has(router)) return;
|
|
4873
5028
|
const fn = enclosingFunction(context.sourceCode, node);
|
|
4874
5029
|
if (fn === null) return;
|
|
@@ -4890,14 +5045,14 @@ var no_duplicate_lifecycle_refresh_listeners_default = createRule({
|
|
|
4890
5045
|
});
|
|
4891
5046
|
|
|
4892
5047
|
// src/rules/_exported-next-config-property.ts
|
|
4893
|
-
import { ASTUtils as
|
|
5048
|
+
import { ASTUtils as ASTUtils10 } from "@typescript-eslint/utils";
|
|
4894
5049
|
function exportedNextConfigProperty(sourceCode, path) {
|
|
4895
5050
|
const resolve2 = (input, seen = /* @__PURE__ */ new Set()) => {
|
|
4896
5051
|
const node = unwrapExpression(input);
|
|
4897
5052
|
if (node.type !== "Identifier") return node;
|
|
4898
5053
|
if (seen.has(node)) return null;
|
|
4899
5054
|
seen.add(node);
|
|
4900
|
-
const binding =
|
|
5055
|
+
const binding = ASTUtils10.findVariable(sourceCode.getScope(node), node.name);
|
|
4901
5056
|
const definition = binding?.defs.length === 1 ? binding.defs[0] : void 0;
|
|
4902
5057
|
if (definition?.type !== "Variable" || definition.parent.kind !== "const" || definition.node.init === null || binding?.references.some((reference) => reference.identifier !== node && reference.init !== true)) return null;
|
|
4903
5058
|
return resolve2(definition.node.init, seen);
|
|
@@ -4907,7 +5062,7 @@ function exportedNextConfigProperty(sourceCode, path) {
|
|
|
4907
5062
|
let current = resolve2(exported);
|
|
4908
5063
|
let selected = null;
|
|
4909
5064
|
for (const name of path) {
|
|
4910
|
-
if (current?.type !== "ObjectExpression" || current.properties.some((property) => property.type !== "Property" ||
|
|
5065
|
+
if (current?.type !== "ObjectExpression" || current.properties.some((property) => property.type !== "Property" || ASTUtils10.getPropertyName(property) === null || property.kind !== "init")) return null;
|
|
4911
5066
|
selected = objectProperty(current, name);
|
|
4912
5067
|
if (selected === null) return null;
|
|
4913
5068
|
current = resolve2(selected.value);
|
|
@@ -4922,7 +5077,7 @@ function exportedConfig(sourceCode) {
|
|
|
4922
5077
|
const assignment = statement.expression;
|
|
4923
5078
|
const left = assignment.left;
|
|
4924
5079
|
if (left.type !== "MemberExpression" || left.computed || left.object.type !== "Identifier" || left.object.name !== "module" || left.property.type !== "Identifier" || left.property.name !== "exports") continue;
|
|
4925
|
-
const binding =
|
|
5080
|
+
const binding = ASTUtils10.findVariable(sourceCode.getScope(left.object), "module");
|
|
4926
5081
|
if (binding === null || binding.defs.length === 0) exported = assignment.right;
|
|
4927
5082
|
}
|
|
4928
5083
|
return exported;
|
|
@@ -4931,7 +5086,7 @@ function objectProperty(node, name) {
|
|
|
4931
5086
|
let selected = null;
|
|
4932
5087
|
for (const property of node.properties) {
|
|
4933
5088
|
if (property.type !== "Property") continue;
|
|
4934
|
-
const key =
|
|
5089
|
+
const key = ASTUtils10.getPropertyName(property);
|
|
4935
5090
|
if (key === name) selected = property;
|
|
4936
5091
|
}
|
|
4937
5092
|
return selected;
|
|
@@ -5013,7 +5168,7 @@ var no_dangerously_allow_svg_default = createRule({
|
|
|
5013
5168
|
});
|
|
5014
5169
|
|
|
5015
5170
|
// src/rules/no-dynamic-sql.ts
|
|
5016
|
-
import { ASTUtils as
|
|
5171
|
+
import { ASTUtils as ASTUtils11, AST_NODE_TYPES as AST_NODE_TYPES30 } from "@typescript-eslint/utils";
|
|
5017
5172
|
|
|
5018
5173
|
// src/rules/_sql.ts
|
|
5019
5174
|
import { AST_NODE_TYPES as AST_NODE_TYPES29 } from "@typescript-eslint/utils";
|
|
@@ -5252,8 +5407,8 @@ function isStaticFragment(expression) {
|
|
|
5252
5407
|
if (expression.type === AST_NODE_TYPES30.Identifier) {
|
|
5253
5408
|
return CONSTANT_CASE_RE.test(expression.name);
|
|
5254
5409
|
}
|
|
5255
|
-
if (expression.type === AST_NODE_TYPES30.MemberExpression &&
|
|
5256
|
-
return CONSTANT_CASE_RE.test(
|
|
5410
|
+
if (expression.type === AST_NODE_TYPES30.MemberExpression && ASTUtils11.getPropertyName(expression) !== null) {
|
|
5411
|
+
return CONSTANT_CASE_RE.test(ASTUtils11.getPropertyName(expression) ?? "");
|
|
5257
5412
|
}
|
|
5258
5413
|
if (expression.type === AST_NODE_TYPES30.Literal) {
|
|
5259
5414
|
return typeof expression.value === "string";
|
|
@@ -5352,10 +5507,10 @@ function staticStatementText(node) {
|
|
|
5352
5507
|
}
|
|
5353
5508
|
function statementMethodName(node, methods) {
|
|
5354
5509
|
const callee = unwrapExpression(node.callee);
|
|
5355
|
-
if (callee.type !== AST_NODE_TYPES30.MemberExpression ||
|
|
5510
|
+
if (callee.type !== AST_NODE_TYPES30.MemberExpression || ASTUtils11.getPropertyName(callee) === null) {
|
|
5356
5511
|
return null;
|
|
5357
5512
|
}
|
|
5358
|
-
const name =
|
|
5513
|
+
const name = ASTUtils11.getPropertyName(callee) ?? "";
|
|
5359
5514
|
return methods.has(name) ? name : null;
|
|
5360
5515
|
}
|
|
5361
5516
|
var no_dynamic_sql_default = createRule({
|
|
@@ -5437,7 +5592,9 @@ var NO_ENUM_DOCUMENTATION = {
|
|
|
5437
5592
|
focusPath: "src/status.ts",
|
|
5438
5593
|
expectedCount: 1,
|
|
5439
5594
|
public: true
|
|
5440
|
-
}
|
|
5595
|
+
},
|
|
5596
|
+
{ id: "authored-after-comment", scenarioId: "native-header-boundary", title: "Keep executable authored code in scope", outcome: "match", files: [{ path: "src/status.ts", source: '// ordinary header\u2028const marker="auto-generated file"; enum Mode {Start} console.log(Mode.Start, marker);' }], focusPath: "src/status.ts", expectedCount: 1, public: true },
|
|
5597
|
+
{ id: "generated-header", scenarioId: "native-header-boundary", title: "Respect a native generated banner", outcome: "no-match", files: [{ path: "src/status.ts", source: '// auto-generated file\u2028const marker="auto-generated file"; enum Mode {Start} console.log(Mode.Start, marker);' }], focusPath: "src/status.ts", expectedCount: 0, public: true }
|
|
5441
5598
|
]
|
|
5442
5599
|
};
|
|
5443
5600
|
function matchesAnyPattern(filename, patterns) {
|
|
@@ -6071,7 +6228,7 @@ var no_fat_try_blocks_default = createRule({
|
|
|
6071
6228
|
});
|
|
6072
6229
|
|
|
6073
6230
|
// src/rules/no-hand-rolled-sleep.ts
|
|
6074
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES33, ASTUtils as
|
|
6231
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES33, ASTUtils as ASTUtils12 } from "@typescript-eslint/utils";
|
|
6075
6232
|
var NO_HAND_ROLLED_SLEEP_DOCUMENTATION = {
|
|
6076
6233
|
summary: "Disallow uncancellable promisified timers and timeout arms.",
|
|
6077
6234
|
rationale: "A timer that outlives an aborted operation or a lost promise race retains work and can keep the process alive until it fires.",
|
|
@@ -6231,7 +6388,7 @@ var no_hand_rolled_sleep_default = createRule({
|
|
|
6231
6388
|
return {};
|
|
6232
6389
|
}
|
|
6233
6390
|
const checkClientModules = optionsArg?.checkClientModules ?? false;
|
|
6234
|
-
const bindingOf = (identifier) =>
|
|
6391
|
+
const bindingOf = (identifier) => ASTUtils12.findVariable(sourceCode.getScope(identifier), identifier.name);
|
|
6235
6392
|
const isGlobal = (identifier) => (bindingOf(identifier)?.defs.length ?? 0) === 0;
|
|
6236
6393
|
const isBuiltinTimer = (callee) => {
|
|
6237
6394
|
callee = unwrapExpression(callee);
|
|
@@ -6398,7 +6555,7 @@ var no_hand_rolled_spinner_default = createRule({
|
|
|
6398
6555
|
});
|
|
6399
6556
|
|
|
6400
6557
|
// src/rules/no-insecure-random-id.ts
|
|
6401
|
-
import { ASTUtils as
|
|
6558
|
+
import { ASTUtils as ASTUtils13 } from "@typescript-eslint/utils";
|
|
6402
6559
|
var NO_INSECURE_RANDOM_ID_DOCUMENTATION = {
|
|
6403
6560
|
summary: "Disallow using `Math.random()` to generate identifiers, tokens, or secrets; use `crypto.randomUUID()` or `crypto.getRandomValues(...)` instead.",
|
|
6404
6561
|
rationale: "Math.random is predictable and lacks the entropy required for security-sensitive values.",
|
|
@@ -6473,7 +6630,7 @@ function isMathRandomCall(node) {
|
|
|
6473
6630
|
return false;
|
|
6474
6631
|
}
|
|
6475
6632
|
const object = unwrapExpression(callee.object);
|
|
6476
|
-
return object.type === "Identifier" && object.name === "Math" &&
|
|
6633
|
+
return object.type === "Identifier" && object.name === "Math" && ASTUtils13.getPropertyName(callee) === "random";
|
|
6477
6634
|
}
|
|
6478
6635
|
function findEnclosingNames(node) {
|
|
6479
6636
|
const names = [];
|
|
@@ -6538,7 +6695,7 @@ function climbValueChain(node) {
|
|
|
6538
6695
|
let current = node;
|
|
6539
6696
|
let parent = current.parent;
|
|
6540
6697
|
while (parent) {
|
|
6541
|
-
if (parent.type === "MemberExpression" && parent.object === current &&
|
|
6698
|
+
if (parent.type === "MemberExpression" && parent.object === current && ASTUtils13.getPropertyName(parent) !== null) {
|
|
6542
6699
|
current = parent;
|
|
6543
6700
|
parent = current.parent;
|
|
6544
6701
|
continue;
|
|
@@ -6591,7 +6748,7 @@ var no_insecure_random_id_default = createRule({
|
|
|
6591
6748
|
if (!isMathRandomCall(node)) {
|
|
6592
6749
|
return;
|
|
6593
6750
|
}
|
|
6594
|
-
if ((
|
|
6751
|
+
if ((ASTUtils13.findVariable(context.sourceCode.getScope(node), "Math")?.defs.length ?? 0) > 0) return;
|
|
6595
6752
|
const names = findEnclosingNames(node);
|
|
6596
6753
|
if (names.some(isStrongSecurityName)) {
|
|
6597
6754
|
context.report({ node, messageId: "insecureRandomId" });
|
|
@@ -6614,8 +6771,8 @@ function appendPropertyName(property, names) {
|
|
|
6614
6771
|
}
|
|
6615
6772
|
function appendAssignedName(assignment, directBinding, names) {
|
|
6616
6773
|
if (directBinding && assignment.left.type === "Identifier") names.push(assignment.left.name);
|
|
6617
|
-
if (directBinding && assignment.left.type === "MemberExpression" &&
|
|
6618
|
-
names.push(
|
|
6774
|
+
if (directBinding && assignment.left.type === "MemberExpression" && ASTUtils13.getPropertyName(assignment.left) !== null) {
|
|
6775
|
+
names.push(ASTUtils13.getPropertyName(assignment.left) ?? "");
|
|
6619
6776
|
}
|
|
6620
6777
|
}
|
|
6621
6778
|
function appendDirectBindingName(id, directBinding, names) {
|
|
@@ -6625,7 +6782,7 @@ function appendDirectBindingName(id, directBinding, names) {
|
|
|
6625
6782
|
// src/rules/no-detached-global-fetch.ts
|
|
6626
6783
|
import {
|
|
6627
6784
|
AST_NODE_TYPES as AST_NODE_TYPES35,
|
|
6628
|
-
ASTUtils as
|
|
6785
|
+
ASTUtils as ASTUtils14
|
|
6629
6786
|
} from "@typescript-eslint/utils";
|
|
6630
6787
|
var NO_DETACHED_GLOBAL_FETCH_DOCUMENTATION = {
|
|
6631
6788
|
summary: "Keep the ambient global fetch receiver-safe when storing or explicitly rebinding it.",
|
|
@@ -6686,7 +6843,7 @@ var no_detached_global_fetch_default = createRule({
|
|
|
6686
6843
|
if (isTestFile(context.filename) || isScriptFile(context.filename) || isGeneratedFile(context.filename, sourceCode.text)) return {};
|
|
6687
6844
|
const aliases = /* @__PURE__ */ new Set();
|
|
6688
6845
|
function bindingOf(identifier) {
|
|
6689
|
-
return
|
|
6846
|
+
return ASTUtils14.findVariable(sourceCode.getScope(identifier), identifier.name);
|
|
6690
6847
|
}
|
|
6691
6848
|
function resolvesToGlobal(identifier) {
|
|
6692
6849
|
const variable = bindingOf(identifier);
|
|
@@ -6791,35 +6948,32 @@ var no_detached_global_fetch_default = createRule({
|
|
|
6791
6948
|
});
|
|
6792
6949
|
|
|
6793
6950
|
// src/rules/no-json-stringify-error.ts
|
|
6794
|
-
import { ASTUtils as
|
|
6951
|
+
import { ASTUtils as ASTUtils15 } from "@typescript-eslint/utils";
|
|
6795
6952
|
var NO_JSON_STRINGIFY_ERROR_DOCUMENTATION = {
|
|
6796
6953
|
summary: "Avoid generic JSON serialization that can omit native Error details.",
|
|
6797
6954
|
rationale: "Native Error details are non-enumerable, so generic JSON serialization discards diagnostic information.",
|
|
6798
6955
|
remediation: "Serialize explicit error fields or use an error-aware serializer.",
|
|
6799
6956
|
category: "correctness",
|
|
6800
|
-
limitations: ["The rule uses stable local catch bindings and unshadowed built-in constructors, not runtime type information. Custom replacers are left to their serializer contract; a catch value is not guaranteed to be an Error."],
|
|
6957
|
+
limitations: ["The rule uses stable local catch bindings and unshadowed built-in constructors, not runtime type information. Custom replacers and explicit toJSON hooks are left to their serializer contract; a catch value is not guaranteed to be an Error. Member values, including cause, do not inherit the base Error's provenance; even an Error-valued member requires explicit value/dataflow proof outside this rule. Known literal __proto__ initializer chains preserve native hook inheritance and own toJSON precedence; computed __proto__ keys remain data. Unknown prototype expressions, hook values/spreads and deferred hook writes conservatively lose default serializer proof. Explicit writes invalidate constructor provenance except a later, separate top-level statement; deferred functions, loops, and unknown property keys conservatively lose constructor proof. Statically owned global/property writes and native Reflect.set/Reflect.defineProperty/Object.defineProperty/Object.defineProperties calls are tracked. Mutator aliases, replaced Reflect/Object methods, external calls, and runtime-only property names are not resolved; uncertain ordering conservatively loses proof."],
|
|
6801
6958
|
examples: [
|
|
6802
6959
|
{ id: "explicit-error-message", title: "Narrow an unknown catch value before selecting fields", outcome: "no-match", files: [{ path: "src/report.ts", source: "try { f(); } catch (err) { JSON.stringify({ error: err instanceof Error ? err.message : String(err) }); }" }], focusPath: "src/report.ts", expectedCount: 0, public: true },
|
|
6803
|
-
{ id: "stringified-error", title: "Do not stringify an Error object", outcome: "match", files: [{ path: "src/report.ts", source: "try { f(); } catch (err) { JSON.stringify({ error: err }); }" }], focusPath: "src/report.ts", expectedCount: 1, public: true }
|
|
6960
|
+
{ id: "stringified-error", title: "Do not stringify an Error object", outcome: "match", files: [{ path: "src/report.ts", source: "try { f(); } catch (err) { JSON.stringify({ error: err }); }" }], focusPath: "src/report.ts", expectedCount: 1, public: true },
|
|
6961
|
+
{ id: "shadowed-error-binding", scenarioId: "binding-provenance", title: "Keep native binding provenance", outcome: "match", files: [{ path: "src/error.ts", source: 'function probe(){try{throw {id:1};}catch(err){if(err instanceof Error)return err.message;{const err=new Error("lost");return JSON.stringify(err);}}}\nconsole.log(probe());' }], focusPath: "src/error.ts", expectedCount: 1, public: true },
|
|
6962
|
+
{ id: "escaped-fallback-binding", scenarioId: "binding-provenance", title: "Keep native binding provenance", outcome: "no-match", files: [{ path: "src/error.ts", source: "function probe(){try{throw {id:1};}catch(err){if(err instanceof Error)return err.message;return JSON.stringify(\\u0065rr);}}\nconsole.log(probe());" }], focusPath: "src/error.ts", expectedCount: 0, public: true },
|
|
6963
|
+
{ id: "constructor-before-write", scenarioId: "explicit-constructor-write", title: "A later write does not change an already constructed native Error", outcome: "match", files: [{ path: "src/error.js", source: "const value=new Error('lost');Error=class Other{message='kept'};JSON.stringify(value);" }], focusPath: "src/error.js", expectedCount: 1, public: true },
|
|
6964
|
+
{ id: "constructor-after-write", scenarioId: "explicit-constructor-write", title: "A replaced constructor does not prove a native Error", outcome: "no-match", files: [{ path: "src/error.js", source: "Error=class Other{message='kept'};const value=new Error();JSON.stringify(value);" }], focusPath: "src/error.js", expectedCount: 0, public: true },
|
|
6965
|
+
{ "id": "native-serializer-before-write", "scenarioId": "explicit-serializer-write", "title": "A later write does not change an earlier native serialization", "outcome": "match", "files": [{ "path": "src/error.js", "source": "const result=JSON.stringify(new Error('lost'));JSON.stringify=value=>'kept:'+value.message;" }], "focusPath": "src/error.js", "expectedCount": 1, "public": true },
|
|
6966
|
+
{ "id": "native-serializer-after-write", "scenarioId": "explicit-serializer-write", "title": "A replaced serializer owns its error-field contract", "outcome": "no-match", "files": [{ "path": "src/error.js", "source": "JSON.stringify=value=>'kept:'+value.message;JSON.stringify(new Error('lost'));" }], "focusPath": "src/error.js", "expectedCount": 0, "public": true },
|
|
6967
|
+
{ "id": "static-serializer-key", "scenarioId": "static-property-provenance", "title": "A constant computed serializer still loses native Error details", "outcome": "match", "files": [{ "path": "src/error.js", "source": "const key='stringify';JSON[key](new Error('lost'));" }], "focusPath": "src/error.js", "expectedCount": 1, "public": true },
|
|
6968
|
+
{ "id": "static-error-field", "scenarioId": "static-property-provenance", "title": "A constant message field selects the explicit string escape hatch", "outcome": "no-match", "files": [{ "path": "src/error.js", "source": "const key='message';const error=new Error('lost');JSON.stringify(error[key]);" }], "focusPath": "src/error.js", "expectedCount": 0, "public": true },
|
|
6969
|
+
{ "id": "scalar-cause", "scenarioId": "member-value-provenance", "title": "Native Error cause can be a string value", "outcome": "no-match", "files": [{ "path": "src/error.js", "source": "const error=new Error('lost',{cause:'kept'});JSON.stringify(error.cause);" }], "focusPath": "src/error.js", "expectedCount": 0, "public": true },
|
|
6970
|
+
{ "id": "whole-error-with-cause", "scenarioId": "member-value-provenance", "title": "Serializing the whole Error still loses its native details", "outcome": "match", "files": [{ "path": "src/error.js", "source": "const error=new Error('lost',{cause:'kept'});JSON.stringify(error);" }], "focusPath": "src/error.js", "expectedCount": 1, "public": true },
|
|
6971
|
+
{ "id": "explicit-to-json-hook", "scenarioId": "custom-serializer-contract", "title": "An explicit callable toJSON owns its serialization contract", "outcome": "no-match", "files": [{ "path": "src/error.js", "source": "JSON.stringify({error:new Error('lost'),toJSON(){return {message:'kept'};}});" }], "focusPath": "src/error.js", "expectedCount": 0, "public": true },
|
|
6972
|
+
{ "id": "noncallable-to-json", "scenarioId": "custom-serializer-contract", "title": "A noncallable toJSON does not replace native serialization", "outcome": "match", "files": [{ "path": "src/error.js", "source": "JSON.stringify({error:new Error('lost'),toJSON:42});" }], "focusPath": "src/error.js", "expectedCount": 1, "public": true },
|
|
6973
|
+
{ "id": "literal-prototype-hook", "scenarioId": "native-prototype-serializer", "title": "A literal prototype hook owns the payload serializer contract", "outcome": "no-match", "files": [{ "path": "src/error.js", "source": "JSON.stringify({error:new Error('lost'),__proto__:{toJSON(){return {message:'kept'};}}});" }], "focusPath": "src/error.js", "expectedCount": 0, "public": true },
|
|
6974
|
+
{ "id": "computed-prototype-data", "scenarioId": "native-prototype-serializer", "title": "A computed prototype name remains ordinary serialized data", "outcome": "match", "files": [{ "path": "src/error.js", "source": "JSON.stringify({error:new Error('lost'),['__proto__']:{toJSON(){return {message:'kept'};}}});" }], "focusPath": "src/error.js", "expectedCount": 1, "public": true }
|
|
6804
6975
|
]
|
|
6805
6976
|
};
|
|
6806
|
-
var SAFE_STRING_PROPS = /* @__PURE__ */ new Set(["message", "stack", "name"]);
|
|
6807
|
-
var PAYLOAD_PROPS = /* @__PURE__ */ new Set([
|
|
6808
|
-
"data",
|
|
6809
|
-
"status",
|
|
6810
|
-
"statuscode",
|
|
6811
|
-
"statustext",
|
|
6812
|
-
"code",
|
|
6813
|
-
"issues",
|
|
6814
|
-
"details",
|
|
6815
|
-
"body",
|
|
6816
|
-
"payload",
|
|
6817
|
-
"response",
|
|
6818
|
-
"info",
|
|
6819
|
-
"meta",
|
|
6820
|
-
"metadata",
|
|
6821
|
-
"context"
|
|
6822
|
-
]);
|
|
6823
6977
|
var BUILTIN_ERROR_CONSTRUCTORS = /* @__PURE__ */ new Set([
|
|
6824
6978
|
"AggregateError",
|
|
6825
6979
|
"Error",
|
|
@@ -6830,25 +6984,211 @@ var BUILTIN_ERROR_CONSTRUCTORS = /* @__PURE__ */ new Set([
|
|
|
6830
6984
|
"TypeError",
|
|
6831
6985
|
"URIError"
|
|
6832
6986
|
]);
|
|
6833
|
-
|
|
6834
|
-
|
|
6835
|
-
|
|
6836
|
-
const
|
|
6837
|
-
if (
|
|
6838
|
-
if (
|
|
6839
|
-
|
|
6840
|
-
|
|
6987
|
+
var TRACKED_BUILTINS = /* @__PURE__ */ new Set([...BUILTIN_ERROR_CONSTRUCTORS, "JSON", "JSON.stringify"]);
|
|
6988
|
+
function nativeObjectName(expression, sourceCode) {
|
|
6989
|
+
const value = unwrapExpression(expression);
|
|
6990
|
+
const scope = sourceCode.getScope(value);
|
|
6991
|
+
if (value.type === "Identifier" && (value.name === "globalThis" || value.name === "JSON") && isGlobalIdentifier(value.name, scope)) return value.name;
|
|
6992
|
+
if (value.type === "MemberExpression" && nativeObjectName(value.object, sourceCode) === "globalThis" && staticPropertyName(value, sourceCode) === "JSON") return "JSON";
|
|
6993
|
+
return null;
|
|
6994
|
+
}
|
|
6995
|
+
function globalBuiltinName(expression, sourceCode) {
|
|
6996
|
+
const value = unwrapExpression(expression);
|
|
6997
|
+
const scope = sourceCode.getScope(value);
|
|
6998
|
+
if (value.type === "Identifier") return TRACKED_BUILTINS.has(value.name) && isGlobalIdentifier(value.name, scope) ? value.name : null;
|
|
6999
|
+
if (value.type !== "MemberExpression") return null;
|
|
7000
|
+
const receiver = nativeObjectName(value.object, sourceCode);
|
|
7001
|
+
const name = staticPropertyName(value, sourceCode);
|
|
7002
|
+
if (receiver === "JSON") return name === "stringify" ? "JSON.stringify" : null;
|
|
7003
|
+
return receiver === "globalThis" && name !== null && name !== "JSON.stringify" && TRACKED_BUILTINS.has(name) ? name : null;
|
|
7004
|
+
}
|
|
7005
|
+
function writePreservesBuiltin(target, sourceCode) {
|
|
7006
|
+
const assignment = target.parent;
|
|
7007
|
+
if (assignment?.type !== "AssignmentExpression" || assignment.left !== target) return false;
|
|
7008
|
+
const name = globalBuiltinName(target, sourceCode);
|
|
7009
|
+
if (name === null) return false;
|
|
7010
|
+
if (assignment.operator === "||=" || assignment.operator === "??=") return true;
|
|
7011
|
+
return (assignment.operator === "=" || assignment.operator === "&&=") && globalBuiltinName(assignment.right, sourceCode) === name;
|
|
7012
|
+
}
|
|
7013
|
+
function mayBeCallable(value) {
|
|
7014
|
+
return !["Literal", "TemplateLiteral", "ObjectExpression", "ArrayExpression"].includes(value.type);
|
|
7015
|
+
}
|
|
7016
|
+
var BUILTIN_WRITES = /* @__PURE__ */ new WeakMap();
|
|
7017
|
+
function directProgramStatement(node) {
|
|
7018
|
+
let current = node;
|
|
7019
|
+
while (current.parent !== void 0) {
|
|
7020
|
+
if (current.parent.type === "Program") return current;
|
|
7021
|
+
if (["FunctionDeclaration", "FunctionExpression", "ArrowFunctionExpression", "ClassBody", "StaticBlock", "ForStatement", "ForInStatement", "ForOfStatement", "WhileStatement", "DoWhileStatement"].includes(current.parent.type)) return null;
|
|
7022
|
+
current = current.parent;
|
|
7023
|
+
}
|
|
7024
|
+
return null;
|
|
7025
|
+
}
|
|
7026
|
+
function hasUnchangedBuiltin(name, read, sourceCode) {
|
|
7027
|
+
const summary = builtinWrites(sourceCode).get(name);
|
|
7028
|
+
if (summary === void 0) return true;
|
|
7029
|
+
const statement = directProgramStatement(read);
|
|
7030
|
+
return !summary.unknownOrder && statement !== null && statement.range[1] <= summary.earliestStatementStart;
|
|
7031
|
+
}
|
|
7032
|
+
function builtinWrites(sourceCode) {
|
|
7033
|
+
const cached = BUILTIN_WRITES.get(sourceCode);
|
|
7034
|
+
if (cached !== void 0) return cached;
|
|
7035
|
+
const writes = /* @__PURE__ */ new Map();
|
|
7036
|
+
const record = (name, node) => {
|
|
7037
|
+
const statement = directProgramStatement(node);
|
|
7038
|
+
const existing = writes.get(name);
|
|
7039
|
+
writes.set(name, { earliestStatementStart: Math.min(existing?.earliestStatementStart ?? Infinity, statement?.range[0] ?? Infinity), unknownOrder: (existing?.unknownOrder ?? false) || statement === null });
|
|
7040
|
+
};
|
|
7041
|
+
for (const scope of sourceCode.scopeManager?.scopes ?? []) {
|
|
7042
|
+
for (const reference of scope.references) {
|
|
7043
|
+
const name = reference.identifier.name;
|
|
7044
|
+
if (reference.identifier.type === "Identifier" && reference.isWrite() && TRACKED_BUILTINS.has(name) && (reference.resolved === null || reference.resolved.defs.length === 0) && !writePreservesBuiltin(reference.identifier, sourceCode)) record(name, reference.identifier);
|
|
7045
|
+
}
|
|
7046
|
+
}
|
|
7047
|
+
const propertyReceiver = (expression) => {
|
|
7048
|
+
const native = nativeObjectName(expression, sourceCode);
|
|
7049
|
+
if (native !== null) return native;
|
|
7050
|
+
const value = unwrapExpression(expression);
|
|
7051
|
+
if (value.type === "Identifier") return ASTUtils15.findVariable(sourceCode.getScope(value), value.name);
|
|
7052
|
+
if (value.type === "MemberExpression" && staticPropertyName(value, sourceCode) === "prototype") {
|
|
7053
|
+
const constructor = globalBuiltinName(value.object, sourceCode);
|
|
7054
|
+
if (constructor !== null && BUILTIN_ERROR_CONSTRUCTORS.has(constructor)) return constructor + ".prototype";
|
|
7055
|
+
}
|
|
7056
|
+
return null;
|
|
7057
|
+
};
|
|
7058
|
+
const propertyWrite = (receiver, name, node) => {
|
|
7059
|
+
if (receiver === "JSON") {
|
|
7060
|
+
if (name === null || name === "stringify") record("JSON.stringify", node);
|
|
7061
|
+
} else if (receiver === "globalThis") {
|
|
7062
|
+
if (name === null) {
|
|
7063
|
+
for (const builtin of TRACKED_BUILTINS) record(builtin, node);
|
|
7064
|
+
} else if (name !== "JSON.stringify" && TRACKED_BUILTINS.has(name)) record(name, node);
|
|
7065
|
+
} else if (name === null || name === "toJSON") record(receiver, node);
|
|
7066
|
+
};
|
|
7067
|
+
const visit = (node) => {
|
|
7068
|
+
if (node.type === "AssignmentExpression") propertyTarget(node.left);
|
|
7069
|
+
else if (node.type === "UpdateExpression") propertyTarget(node.argument);
|
|
7070
|
+
else if (node.type === "ForInStatement" || node.type === "ForOfStatement") propertyTarget(node.left);
|
|
7071
|
+
else if (node.type === "UnaryExpression" && node.operator === "delete") propertyTarget(node.argument);
|
|
7072
|
+
else if (node.type === "CallExpression") mutationCall(node);
|
|
7073
|
+
forEachAstChild(node, sourceCode.visitorKeys, visit);
|
|
7074
|
+
};
|
|
7075
|
+
function propertyTarget(target) {
|
|
7076
|
+
if (target.type === "MemberExpression") {
|
|
7077
|
+
memberPropertyWrite(target);
|
|
7078
|
+
return;
|
|
7079
|
+
}
|
|
7080
|
+
switch (target.type) {
|
|
7081
|
+
case "ObjectPattern":
|
|
7082
|
+
for (const property of target.properties) propertyTarget(property.type === "RestElement" ? property.argument : property.value);
|
|
7083
|
+
return;
|
|
7084
|
+
case "ArrayPattern":
|
|
7085
|
+
for (const element of target.elements) if (element !== null) propertyTarget(element);
|
|
7086
|
+
return;
|
|
7087
|
+
case "AssignmentPattern":
|
|
7088
|
+
propertyTarget(target.left);
|
|
7089
|
+
return;
|
|
7090
|
+
case "RestElement":
|
|
7091
|
+
propertyTarget(target.argument);
|
|
7092
|
+
}
|
|
7093
|
+
}
|
|
7094
|
+
function memberPropertyWrite(target) {
|
|
7095
|
+
const receiver = propertyReceiver(target.object);
|
|
7096
|
+
if (receiver === null || writePreservesBuiltin(target, sourceCode)) return;
|
|
7097
|
+
const name = staticPropertyName(target, sourceCode);
|
|
7098
|
+
if (name === "toJSON") {
|
|
7099
|
+
const assignment = target.parent;
|
|
7100
|
+
if (assignment?.type === "UnaryExpression" && assignment.operator === "delete") return;
|
|
7101
|
+
if (assignment?.type === "AssignmentExpression" && assignment.operator === "=" && !mayBeCallable(assignment.right)) return;
|
|
7102
|
+
}
|
|
7103
|
+
propertyWrite(receiver, name, target);
|
|
7104
|
+
}
|
|
7105
|
+
function mutationCall(node) {
|
|
7106
|
+
const callee = unwrapExpression(node.callee);
|
|
7107
|
+
if (callee.type !== "MemberExpression" || callee.object.type !== "Identifier") return;
|
|
7108
|
+
const owner = callee.object.name;
|
|
7109
|
+
if (!["Reflect", "Object"].includes(owner) || !isGlobalIdentifier(owner, sourceCode.getScope(callee))) return;
|
|
7110
|
+
const method = staticPropertyName(callee, sourceCode);
|
|
7111
|
+
const [target, key, value, receiver] = node.arguments;
|
|
7112
|
+
if (target === void 0 || target.type === "SpreadElement" || key === void 0) return;
|
|
7113
|
+
const object = propertyReceiver(target);
|
|
7114
|
+
if (object === null) return;
|
|
7115
|
+
switch (method) {
|
|
7116
|
+
case "set":
|
|
7117
|
+
if (owner === "Reflect") reflectSet(object, scopedStaticString(key, sourceCode), value, receiver, node);
|
|
7118
|
+
return;
|
|
7119
|
+
case "defineProperty":
|
|
7120
|
+
descriptorWrite(object, scopedStaticString(key, sourceCode), value, node);
|
|
7121
|
+
return;
|
|
7122
|
+
case "defineProperties":
|
|
7123
|
+
if (owner === "Object") descriptorBatch(object, key, node);
|
|
7124
|
+
}
|
|
7125
|
+
}
|
|
7126
|
+
function reflectSet(object, name, value, receiver, node) {
|
|
7127
|
+
if (receiver !== void 0 && receiver.type !== "SpreadElement" && ["ObjectExpression", "ArrayExpression", "Literal"].includes(unwrapExpression(receiver).type)) return;
|
|
7128
|
+
const builtin = builtinPropertyName(object, name);
|
|
7129
|
+
if (value !== void 0 && value.type !== "SpreadElement" && builtin !== null && globalBuiltinName(value, sourceCode) === builtin) return;
|
|
7130
|
+
if (name === "toJSON" && value !== void 0 && !mayBeCallable(value)) return;
|
|
7131
|
+
propertyWrite(object, name, node);
|
|
7132
|
+
}
|
|
7133
|
+
function descriptorBatch(object, descriptors, node) {
|
|
7134
|
+
if (descriptors.type !== "ObjectExpression") {
|
|
7135
|
+
propertyWrite(object, null, node);
|
|
7136
|
+
return;
|
|
7137
|
+
}
|
|
7138
|
+
for (const property of descriptors.properties) {
|
|
7139
|
+
if (property.type !== "Property") {
|
|
7140
|
+
propertyWrite(object, null, node);
|
|
7141
|
+
continue;
|
|
7142
|
+
}
|
|
7143
|
+
descriptorWrite(object, staticPropertyName(property, sourceCode), property.value, node);
|
|
7144
|
+
}
|
|
7145
|
+
}
|
|
7146
|
+
function descriptorWrite(object, name, descriptor, node) {
|
|
7147
|
+
if (descriptor !== void 0 && !descriptorChangesValue(descriptor, builtinPropertyName(object, name))) return;
|
|
7148
|
+
propertyWrite(object, name, node);
|
|
7149
|
+
}
|
|
7150
|
+
function descriptorChangesValue(descriptor, name) {
|
|
7151
|
+
if (descriptor.type !== "ObjectExpression") return true;
|
|
7152
|
+
return descriptor.properties.some((property) => {
|
|
7153
|
+
if (property.type !== "Property") return true;
|
|
7154
|
+
const key = staticPropertyName(property, sourceCode);
|
|
7155
|
+
if (key === "value" && name === "toJSON" && !mayBeCallable(property.value)) return false;
|
|
7156
|
+
if (key === "value" && property.value.type !== "AssignmentPattern" && property.value.type !== "ArrayPattern" && property.value.type !== "ObjectPattern" && property.value.type !== "TSEmptyBodyFunctionExpression") return name === null || globalBuiltinName(property.value, sourceCode) !== name;
|
|
7157
|
+
return key === null || key === "get" || key === "set";
|
|
7158
|
+
});
|
|
7159
|
+
}
|
|
7160
|
+
function builtinPropertyName(object, name) {
|
|
7161
|
+
return object === "JSON" && name === "stringify" ? "JSON.stringify" : name;
|
|
7162
|
+
}
|
|
7163
|
+
visit(sourceCode.ast);
|
|
7164
|
+
BUILTIN_WRITES.set(sourceCode, writes);
|
|
7165
|
+
return writes;
|
|
7166
|
+
}
|
|
7167
|
+
function hasDefaultErrorSerialization(expression, call, sourceCode) {
|
|
7168
|
+
let constructor = null;
|
|
7169
|
+
if (expression.type === "Identifier") {
|
|
7170
|
+
const variable = ASTUtils15.findVariable(sourceCode.getScope(expression), expression.name);
|
|
7171
|
+
if (variable !== null && !hasUnchangedBuiltin(variable, call, sourceCode)) return false;
|
|
7172
|
+
const definition = variable?.defs[0];
|
|
7173
|
+
const initializer = definition?.type === "Variable" ? definition.node.init : null;
|
|
7174
|
+
if (initializer?.type === "NewExpression" && initializer.callee.type === "Identifier") constructor = initializer.callee.name;
|
|
7175
|
+
} else if (expression.type === "NewExpression" && expression.callee.type === "Identifier") constructor = expression.callee.name;
|
|
7176
|
+
const families = constructor === null ? BUILTIN_ERROR_CONSTRUCTORS : ["Error", constructor];
|
|
7177
|
+
return [...families].every((name) => hasUnchangedBuiltin(name + ".prototype", call, sourceCode));
|
|
7178
|
+
}
|
|
7179
|
+
function isBuiltinErrorConstructor(identifier, sourceCode) {
|
|
7180
|
+
return sourceCode.scopeManager !== null && BUILTIN_ERROR_CONSTRUCTORS.has(identifier.name) && isGlobalIdentifier(identifier.name, sourceCode.getScope(identifier)) && hasUnchangedBuiltin(identifier.name, identifier, sourceCode);
|
|
6841
7181
|
}
|
|
6842
7182
|
function isGlobalIdentifier(name, scope) {
|
|
6843
|
-
const binding =
|
|
7183
|
+
const binding = ASTUtils15.findVariable(scope, name);
|
|
6844
7184
|
return binding === null || binding.defs.length === 0;
|
|
6845
7185
|
}
|
|
6846
|
-
function positiveErrorSubject(test) {
|
|
6847
|
-
return instanceofErrorSubject(test) ?? typeGuardSubject(test);
|
|
7186
|
+
function positiveErrorSubject(test, sourceCode) {
|
|
7187
|
+
return instanceofErrorSubject(test, sourceCode) ?? typeGuardSubject(test);
|
|
6848
7188
|
}
|
|
6849
7189
|
var TYPE_GUARD_PATTERN = /^(is|has)[A-Z]/;
|
|
6850
|
-
function instanceofErrorSubject(test) {
|
|
6851
|
-
if (test.type === "BinaryExpression" && test.operator === "instanceof" && test.right.type === "Identifier" && test.right.name === "Error") {
|
|
7190
|
+
function instanceofErrorSubject(test, sourceCode) {
|
|
7191
|
+
if (test.type === "BinaryExpression" && test.operator === "instanceof" && test.right.type === "Identifier" && test.right.name === "Error" && isBuiltinErrorConstructor(test.right, sourceCode)) {
|
|
6852
7192
|
return test.left;
|
|
6853
7193
|
}
|
|
6854
7194
|
return null;
|
|
@@ -6862,36 +7202,34 @@ function typeGuardSubject(test) {
|
|
|
6862
7202
|
return null;
|
|
6863
7203
|
}
|
|
6864
7204
|
function isNarrowedByEarlyReturn(node, argExpr, sourceCode) {
|
|
6865
|
-
const argText = sourceCode.getText(argExpr);
|
|
6866
7205
|
let current = node.parent;
|
|
6867
7206
|
while (current) {
|
|
6868
7207
|
if (current.type === "BlockStatement" || current.type === "Program") {
|
|
6869
|
-
if (hasEarlierErrorGuard(current.body, node,
|
|
7208
|
+
if (hasEarlierErrorGuard(current.body, node, argExpr, sourceCode)) return true;
|
|
6870
7209
|
}
|
|
6871
7210
|
current = current.parent;
|
|
6872
7211
|
}
|
|
6873
7212
|
return false;
|
|
6874
7213
|
}
|
|
6875
7214
|
function isGuardedByInstanceofError(node, argExpr, sourceCode) {
|
|
6876
|
-
const
|
|
6877
|
-
const sameSubject = (subject) => sourceCode.getText(subject) === argText;
|
|
7215
|
+
const sameSubject = (subject) => sameSubjectBinding(subject, argExpr, sourceCode);
|
|
6878
7216
|
let current = node.parent;
|
|
6879
7217
|
while (current) {
|
|
6880
7218
|
if (current.type === "ConditionalExpression") {
|
|
6881
|
-
const subject = positiveErrorSubject(current.test);
|
|
7219
|
+
const subject = positiveErrorSubject(current.test, sourceCode);
|
|
6882
7220
|
if (subject && sameSubject(subject) && nodeWithin(node, current.alternate)) {
|
|
6883
7221
|
return true;
|
|
6884
7222
|
}
|
|
6885
|
-
const negated = negatedInstanceofErrorSubject(current.test);
|
|
7223
|
+
const negated = negatedInstanceofErrorSubject(current.test, sourceCode);
|
|
6886
7224
|
if (negated && sameSubject(negated) && nodeWithin(node, current.consequent)) {
|
|
6887
7225
|
return true;
|
|
6888
7226
|
}
|
|
6889
7227
|
} else if (current.type === "IfStatement") {
|
|
6890
|
-
const subject = positiveErrorSubject(current.test);
|
|
7228
|
+
const subject = positiveErrorSubject(current.test, sourceCode);
|
|
6891
7229
|
if (subject && sameSubject(subject) && nodeWithin(node, current.alternate)) {
|
|
6892
7230
|
return true;
|
|
6893
7231
|
}
|
|
6894
|
-
const negated = negatedInstanceofErrorSubject(current.test);
|
|
7232
|
+
const negated = negatedInstanceofErrorSubject(current.test, sourceCode);
|
|
6895
7233
|
if (negated && sameSubject(negated) && nodeWithin(node, current.consequent)) {
|
|
6896
7234
|
return true;
|
|
6897
7235
|
}
|
|
@@ -6900,25 +7238,35 @@ function isGuardedByInstanceofError(node, argExpr, sourceCode) {
|
|
|
6900
7238
|
}
|
|
6901
7239
|
return false;
|
|
6902
7240
|
}
|
|
6903
|
-
function negatedInstanceofErrorSubject(test) {
|
|
7241
|
+
function negatedInstanceofErrorSubject(test, sourceCode) {
|
|
6904
7242
|
if (test.type === "UnaryExpression" && test.operator === "!") {
|
|
6905
|
-
return positiveErrorSubject(test.argument);
|
|
7243
|
+
return positiveErrorSubject(test.argument, sourceCode);
|
|
6906
7244
|
}
|
|
6907
7245
|
return null;
|
|
6908
7246
|
}
|
|
7247
|
+
function sameSubjectBinding(subject, value, sourceCode) {
|
|
7248
|
+
const left = unwrapExpression(subject);
|
|
7249
|
+
const right = unwrapExpression(value);
|
|
7250
|
+
if (left.type === "Identifier" && right.type === "Identifier") {
|
|
7251
|
+
const binding = ASTUtils15.findVariable(sourceCode.getScope(left), left.name);
|
|
7252
|
+
return binding !== null && binding === ASTUtils15.findVariable(sourceCode.getScope(right), right.name);
|
|
7253
|
+
}
|
|
7254
|
+
return sourceCode.getText(subject) === sourceCode.getText(value);
|
|
7255
|
+
}
|
|
6909
7256
|
function nodeWithin(node, container) {
|
|
6910
7257
|
return container !== null && node.range[0] >= container.range[0] && node.range[1] <= container.range[1];
|
|
6911
7258
|
}
|
|
6912
|
-
function isJsonStringify(callee) {
|
|
7259
|
+
function isJsonStringify(callee, sourceCode) {
|
|
6913
7260
|
if (callee.type !== "MemberExpression") return false;
|
|
6914
7261
|
const receiver = unwrapExpression(callee.object);
|
|
6915
|
-
return callee.type === "MemberExpression" && receiver.type === "Identifier" && receiver.name === "JSON" &&
|
|
7262
|
+
return callee.type === "MemberExpression" && receiver.type === "Identifier" && receiver.name === "JSON" && staticPropertyName(callee, sourceCode) === "stringify";
|
|
6916
7263
|
}
|
|
6917
|
-
function directLiteralValues(argument) {
|
|
7264
|
+
function directLiteralValues(argument, sourceCode) {
|
|
6918
7265
|
argument = unwrapExpression(argument);
|
|
6919
7266
|
if (argument.type === "ObjectExpression") {
|
|
7267
|
+
if (literalHasSerializer(argument, sourceCode)) return [];
|
|
6920
7268
|
return argument.properties.flatMap((property) => {
|
|
6921
|
-
if (property.type !== "Property" ||
|
|
7269
|
+
if (property.type !== "Property" || staticPropertyName(property, sourceCode) === null) return [];
|
|
6922
7270
|
const value = property.value;
|
|
6923
7271
|
if (value.type === "AssignmentPattern" || value.type === "ArrayPattern" || value.type === "ObjectPattern" || value.type === "TSEmptyBodyFunctionExpression") {
|
|
6924
7272
|
return [];
|
|
@@ -6933,30 +7281,40 @@ function directLiteralValues(argument) {
|
|
|
6933
7281
|
}
|
|
6934
7282
|
return argument.type === "SpreadElement" ? [] : [argument];
|
|
6935
7283
|
}
|
|
6936
|
-
function
|
|
7284
|
+
function literalHasSerializer(argument, sourceCode) {
|
|
7285
|
+
for (const property of argument.properties.toReversed()) {
|
|
7286
|
+
if (property.type !== "Property") return true;
|
|
7287
|
+
const key = staticPropertyName(property, sourceCode);
|
|
7288
|
+
if (key === null) return true;
|
|
7289
|
+
if (key === "toJSON") return mayBeCallable(property.value);
|
|
7290
|
+
}
|
|
7291
|
+
for (const property of argument.properties) {
|
|
7292
|
+
if (property.type !== "Property" || property.computed || property.method || property.shorthand || property.kind !== "init" || staticPropertyName(property, sourceCode) !== "__proto__") continue;
|
|
7293
|
+
const prototype = property.value;
|
|
7294
|
+
return prototype.type === "ObjectExpression" ? literalHasSerializer(prototype, sourceCode) : prototype.type !== "Literal" || "regex" in prototype && prototype.regex !== void 0;
|
|
7295
|
+
}
|
|
7296
|
+
return false;
|
|
7297
|
+
}
|
|
7298
|
+
function expressionSuggestsError(expression, sourceCode) {
|
|
6937
7299
|
expression = unwrapExpression(expression);
|
|
6938
7300
|
const unwrappedExpressionCallee = expression.type === "CallExpression" || expression.type === "NewExpression" ? unwrapExpression(expression.callee) : null;
|
|
6939
7301
|
if (expression.type === "Identifier") {
|
|
6940
|
-
return identifierIsProvenError(expression,
|
|
7302
|
+
return identifierIsProvenError(expression, sourceCode);
|
|
6941
7303
|
}
|
|
6942
7304
|
if (expression.type === "NewExpression" && unwrappedExpressionCallee?.type === "Identifier") {
|
|
6943
|
-
return
|
|
6944
|
-
}
|
|
6945
|
-
return expression.type === "MemberExpression" && memberSuggestsError(expression, scope);
|
|
6946
|
-
}
|
|
6947
|
-
function memberSuggestsError(member, scope) {
|
|
6948
|
-
const propName2 = ASTUtils14.getPropertyName(member);
|
|
6949
|
-
const base = member.object;
|
|
6950
|
-
const baseSuggestsError = base.type === "Identifier" && identifierIsProvenError(base, scope);
|
|
6951
|
-
if (baseSuggestsError) {
|
|
6952
|
-
if (propName2 === null) {
|
|
6953
|
-
return true;
|
|
6954
|
-
}
|
|
6955
|
-
const lowered = propName2.toLowerCase();
|
|
6956
|
-
return !SAFE_STRING_PROPS.has(lowered) && !PAYLOAD_PROPS.has(lowered);
|
|
7305
|
+
return isBuiltinErrorConstructor(unwrappedExpressionCallee, sourceCode);
|
|
6957
7306
|
}
|
|
6958
7307
|
return false;
|
|
6959
7308
|
}
|
|
7309
|
+
function identifierIsProvenError(identifier, sourceCode) {
|
|
7310
|
+
const variable = ASTUtils15.findVariable(sourceCode.getScope(identifier), identifier.name);
|
|
7311
|
+
if (variable === null || variable.defs.length !== 1 || variable.references.some((reference) => reference.isWrite() && reference.init !== true)) return false;
|
|
7312
|
+
const definition = variable.defs[0];
|
|
7313
|
+
if (definition?.type === "CatchClause") return true;
|
|
7314
|
+
if (definition?.type !== "Variable") return false;
|
|
7315
|
+
const initializer = definition.node.init;
|
|
7316
|
+
return initializer?.type === "NewExpression" && initializer.callee.type === "Identifier" && isBuiltinErrorConstructor(initializer.callee, sourceCode);
|
|
7317
|
+
}
|
|
6960
7318
|
var no_json_stringify_error_default = createRule({
|
|
6961
7319
|
name: "no-json-stringify-error",
|
|
6962
7320
|
documentation: NO_JSON_STRINGIFY_ERROR_DOCUMENTATION,
|
|
@@ -6975,7 +7333,7 @@ var no_json_stringify_error_default = createRule({
|
|
|
6975
7333
|
return {
|
|
6976
7334
|
CallExpression(node) {
|
|
6977
7335
|
const unwrappedNodeCallee = unwrapExpression(node.callee);
|
|
6978
|
-
if (!isJsonStringify(unwrappedNodeCallee)) {
|
|
7336
|
+
if (!isJsonStringify(unwrappedNodeCallee, context.sourceCode)) {
|
|
6979
7337
|
return;
|
|
6980
7338
|
}
|
|
6981
7339
|
const firstArg = node.arguments[0];
|
|
@@ -6983,11 +7341,11 @@ var no_json_stringify_error_default = createRule({
|
|
|
6983
7341
|
return;
|
|
6984
7342
|
}
|
|
6985
7343
|
const scope = context.sourceCode.getScope(firstArg);
|
|
6986
|
-
if (!isGlobalIdentifier("JSON", scope)) return;
|
|
7344
|
+
if (!isGlobalIdentifier("JSON", scope) || !hasUnchangedBuiltin("JSON", node, context.sourceCode) || !hasUnchangedBuiltin("JSON.stringify", node, context.sourceCode)) return;
|
|
6987
7345
|
const replacer = node.arguments[1] === void 0 ? void 0 : unwrapExpression(node.arguments[1]);
|
|
6988
7346
|
if (replacer !== void 0 && !(replacer.type === "Literal" && replacer.value === null) && !(replacer.type === "Identifier" && replacer.name === "undefined" && isGlobalIdentifier("undefined", scope))) return;
|
|
6989
|
-
const unsafeValue = directLiteralValues(firstArg).find(
|
|
6990
|
-
(value) => expressionSuggestsError(value,
|
|
7347
|
+
const unsafeValue = directLiteralValues(firstArg, context.sourceCode).find(
|
|
7348
|
+
(value) => expressionSuggestsError(value, context.sourceCode) && hasDefaultErrorSerialization(unwrapExpression(value), node, context.sourceCode) && !isGuardedByInstanceofError(node, value, context.sourceCode) && !isNarrowedByEarlyReturn(node, value, context.sourceCode)
|
|
6991
7349
|
);
|
|
6992
7350
|
if (unsafeValue === void 0) {
|
|
6993
7351
|
return;
|
|
@@ -7000,14 +7358,14 @@ var no_json_stringify_error_default = createRule({
|
|
|
7000
7358
|
};
|
|
7001
7359
|
}
|
|
7002
7360
|
});
|
|
7003
|
-
function hasEarlierErrorGuard(statements, node,
|
|
7361
|
+
function hasEarlierErrorGuard(statements, node, argExpr, sourceCode) {
|
|
7004
7362
|
for (const stmt of statements) {
|
|
7005
7363
|
if (stmt.range[0] >= node.range[0]) {
|
|
7006
7364
|
break;
|
|
7007
7365
|
}
|
|
7008
7366
|
if (stmt.type === "IfStatement" && stmt.alternate === null && branchTerminates(stmt.consequent)) {
|
|
7009
|
-
const subject = positiveErrorSubject(stmt.test);
|
|
7010
|
-
if (subject &&
|
|
7367
|
+
const subject = positiveErrorSubject(stmt.test, sourceCode);
|
|
7368
|
+
if (subject && sameSubjectBinding(subject, argExpr, sourceCode)) {
|
|
7011
7369
|
return true;
|
|
7012
7370
|
}
|
|
7013
7371
|
}
|
|
@@ -7023,7 +7381,7 @@ function branchTerminates(branch) {
|
|
|
7023
7381
|
// src/rules/no-json-stringify-object-equality.ts
|
|
7024
7382
|
import {
|
|
7025
7383
|
AST_NODE_TYPES as AST_NODE_TYPES36,
|
|
7026
|
-
ASTUtils as
|
|
7384
|
+
ASTUtils as ASTUtils16,
|
|
7027
7385
|
ESLintUtils as ESLintUtils7
|
|
7028
7386
|
} from "@typescript-eslint/utils";
|
|
7029
7387
|
import ts6 from "typescript";
|
|
@@ -7074,10 +7432,10 @@ function jsonStringifyArgument(node, sourceCode) {
|
|
|
7074
7432
|
if (expression.type !== AST_NODE_TYPES36.CallExpression) return null;
|
|
7075
7433
|
const callee = unwrapExpression(expression.callee);
|
|
7076
7434
|
const calleeReceiver = callee.type === AST_NODE_TYPES36.MemberExpression ? unwrapExpression(callee.object) : callee;
|
|
7077
|
-
if (callee.type !== AST_NODE_TYPES36.MemberExpression || calleeReceiver.type !== AST_NODE_TYPES36.Identifier || calleeReceiver.name !== "JSON" ||
|
|
7435
|
+
if (callee.type !== AST_NODE_TYPES36.MemberExpression || calleeReceiver.type !== AST_NODE_TYPES36.Identifier || calleeReceiver.name !== "JSON" || ASTUtils16.getPropertyName(callee) !== "stringify") {
|
|
7078
7436
|
return null;
|
|
7079
7437
|
}
|
|
7080
|
-
const variable =
|
|
7438
|
+
const variable = ASTUtils16.findVariable(sourceCode.getScope(calleeReceiver), "JSON");
|
|
7081
7439
|
if (variable !== null && variable.defs.length > 0) return null;
|
|
7082
7440
|
const argument = expression.arguments[0];
|
|
7083
7441
|
return argument !== void 0 && argument.type !== AST_NODE_TYPES36.SpreadElement ? argument : null;
|
|
@@ -7163,7 +7521,7 @@ var no_json_stringify_object_equality_default = createRule({
|
|
|
7163
7521
|
|
|
7164
7522
|
// src/rules/no-impossible-zod-literal-bounds.ts
|
|
7165
7523
|
import {
|
|
7166
|
-
ASTUtils as
|
|
7524
|
+
ASTUtils as ASTUtils17,
|
|
7167
7525
|
AST_NODE_TYPES as AST_NODE_TYPES37
|
|
7168
7526
|
} from "@typescript-eslint/utils";
|
|
7169
7527
|
|
|
@@ -7315,7 +7673,7 @@ var no_impossible_zod_literal_bounds_default = createRule({
|
|
|
7315
7673
|
if (callee.type !== AST_NODE_TYPES37.MemberExpression || calleeReceiver.type !== AST_NODE_TYPES37.CallExpression) {
|
|
7316
7674
|
return null;
|
|
7317
7675
|
}
|
|
7318
|
-
const method =
|
|
7676
|
+
const method = ASTUtils17.getPropertyName(callee);
|
|
7319
7677
|
if (method === null) return null;
|
|
7320
7678
|
calls.push({ method, node: current });
|
|
7321
7679
|
current = calleeReceiver;
|
|
@@ -7330,7 +7688,7 @@ var no_impossible_zod_literal_bounds_default = createRule({
|
|
|
7330
7688
|
if (callee.type !== AST_NODE_TYPES37.MemberExpression || calleeReceiver.type !== AST_NODE_TYPES37.Identifier || !namespaces.has(calleeReceiver.name) || !resolvesToTrackedImport(calleeReceiver)) {
|
|
7331
7689
|
return null;
|
|
7332
7690
|
}
|
|
7333
|
-
const name =
|
|
7691
|
+
const name = ASTUtils17.getPropertyName(callee);
|
|
7334
7692
|
return name !== null && KINDS.has(name) ? name : null;
|
|
7335
7693
|
}
|
|
7336
7694
|
function isInsideReshapingCall(node) {
|
|
@@ -7340,7 +7698,7 @@ var no_impossible_zod_literal_bounds_default = createRule({
|
|
|
7340
7698
|
if (parent.type === AST_NODE_TYPES37.CallExpression) {
|
|
7341
7699
|
const callee = unwrapExpression(parent.callee);
|
|
7342
7700
|
const calleeReceiver = callee.type === AST_NODE_TYPES37.MemberExpression ? unwrapExpression(callee.object) : callee;
|
|
7343
|
-
if (callee.type === AST_NODE_TYPES37.MemberExpression && RESHAPING_METHODS.has(
|
|
7701
|
+
if (callee.type === AST_NODE_TYPES37.MemberExpression && RESHAPING_METHODS.has(ASTUtils17.getPropertyName(callee) ?? "") && (calleeReceiver.type === AST_NODE_TYPES37.CallExpression || calleeReceiver.type === AST_NODE_TYPES37.Identifier && namespaces.has(calleeReceiver.name) && resolvesToTrackedImport(calleeReceiver))) {
|
|
7344
7702
|
return true;
|
|
7345
7703
|
}
|
|
7346
7704
|
if (callee.type === AST_NODE_TYPES37.Identifier && preprocessors.has(callee.name) && resolvesToTrackedImport(callee)) {
|
|
@@ -7551,7 +7909,7 @@ var no_in_operator_on_built_in_collections_default = createRule({
|
|
|
7551
7909
|
|
|
7552
7910
|
// src/rules/no-redundant-optional-array-default.ts
|
|
7553
7911
|
import {
|
|
7554
|
-
ASTUtils as
|
|
7912
|
+
ASTUtils as ASTUtils18,
|
|
7555
7913
|
AST_NODE_TYPES as AST_NODE_TYPES38
|
|
7556
7914
|
} from "@typescript-eslint/utils";
|
|
7557
7915
|
var NO_REDUNDANT_OPTIONAL_ARRAY_DEFAULT_DOCUMENTATION = {
|
|
@@ -7689,7 +8047,7 @@ var no_redundant_optional_array_default_default = createRule({
|
|
|
7689
8047
|
return arrayConstructors.has(callee.name) && resolvesToTrackedImport(callee);
|
|
7690
8048
|
}
|
|
7691
8049
|
if (callee.type !== AST_NODE_TYPES38.MemberExpression) return false;
|
|
7692
|
-
const method =
|
|
8050
|
+
const method = ASTUtils18.getPropertyName(callee);
|
|
7693
8051
|
if (method === "array" && (calleeReceiver.type === AST_NODE_TYPES38.Identifier ? namespaces.has(calleeReceiver.name) && resolvesToTrackedImport(calleeReceiver) : isZodSchemaExpression(calleeReceiver))) {
|
|
7694
8052
|
return true;
|
|
7695
8053
|
}
|
|
@@ -7732,13 +8090,13 @@ var no_redundant_optional_array_default_default = createRule({
|
|
|
7732
8090
|
CallExpression(node) {
|
|
7733
8091
|
const defaultCallee = unwrapExpression(node.callee);
|
|
7734
8092
|
const defaultCalleeReceiver = defaultCallee.type === AST_NODE_TYPES38.MemberExpression ? unwrapExpression(defaultCallee.object) : defaultCallee;
|
|
7735
|
-
if (defaultCallee.type !== AST_NODE_TYPES38.MemberExpression ||
|
|
8093
|
+
if (defaultCallee.type !== AST_NODE_TYPES38.MemberExpression || ASTUtils18.getPropertyName(defaultCallee) !== "default" || !hasArrayFallback(node) || defaultCalleeReceiver.type !== AST_NODE_TYPES38.CallExpression) {
|
|
7736
8094
|
return;
|
|
7737
8095
|
}
|
|
7738
8096
|
const optionalCall = defaultCalleeReceiver;
|
|
7739
8097
|
const optionalCallee = unwrapExpression(optionalCall.callee);
|
|
7740
8098
|
const optionalCalleeReceiver = optionalCallee.type === AST_NODE_TYPES38.MemberExpression ? unwrapExpression(optionalCallee.object) : optionalCallee;
|
|
7741
|
-
if (optionalCallee.type !== AST_NODE_TYPES38.MemberExpression ||
|
|
8099
|
+
if (optionalCallee.type !== AST_NODE_TYPES38.MemberExpression || ASTUtils18.getPropertyName(optionalCallee) !== "optional" || optionalCall.arguments.length !== 0 || !isArraySchemaExpression(optionalCalleeReceiver) || sourceCode.getCommentsInside(optionalCall).length > 0) {
|
|
7742
8100
|
return;
|
|
7743
8101
|
}
|
|
7744
8102
|
context.report({
|
|
@@ -7877,10 +8235,10 @@ var interface_contract_members_private_default = createRule({
|
|
|
7877
8235
|
});
|
|
7878
8236
|
|
|
7879
8237
|
// src/rules/no-log-only-catch.ts
|
|
7880
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES42, ASTUtils as
|
|
8238
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES42, ASTUtils as ASTUtils20 } from "@typescript-eslint/utils";
|
|
7881
8239
|
|
|
7882
8240
|
// src/rules/_logging.ts
|
|
7883
|
-
import { ASTUtils as
|
|
8241
|
+
import { ASTUtils as ASTUtils19, AST_NODE_TYPES as AST_NODE_TYPES41 } from "@typescript-eslint/utils";
|
|
7884
8242
|
var LOG_METHODS = /* @__PURE__ */ new Set([
|
|
7885
8243
|
"debug",
|
|
7886
8244
|
"info",
|
|
@@ -7917,7 +8275,7 @@ function calleeName2(callee) {
|
|
|
7917
8275
|
if (callee.type === "Identifier") {
|
|
7918
8276
|
return callee.name;
|
|
7919
8277
|
}
|
|
7920
|
-
return callee.type === "MemberExpression" ?
|
|
8278
|
+
return callee.type === "MemberExpression" ? ASTUtils19.getPropertyName(callee) : null;
|
|
7921
8279
|
}
|
|
7922
8280
|
function createLogMatcher(options = {}) {
|
|
7923
8281
|
const loggerNames = /* @__PURE__ */ new Set([
|
|
@@ -7932,7 +8290,7 @@ function createLogMatcher(options = {}) {
|
|
|
7932
8290
|
return loggerNames.has(expr.name.toLowerCase());
|
|
7933
8291
|
case "MemberExpression": {
|
|
7934
8292
|
const { object } = expr;
|
|
7935
|
-
const property =
|
|
8293
|
+
const property = ASTUtils19.getPropertyName(expr);
|
|
7936
8294
|
if (property !== null) {
|
|
7937
8295
|
const lowered = property.toLowerCase();
|
|
7938
8296
|
if (loggerNames.has(lowered) || LOGGER_FACTORIES.has(lowered)) {
|
|
@@ -7943,7 +8301,7 @@ function createLogMatcher(options = {}) {
|
|
|
7943
8301
|
}
|
|
7944
8302
|
case "CallExpression": {
|
|
7945
8303
|
const callee = unwrapExpression(expr.callee);
|
|
7946
|
-
const name = callee.type === "MemberExpression" ?
|
|
8304
|
+
const name = callee.type === "MemberExpression" ? ASTUtils19.getPropertyName(callee) : null;
|
|
7947
8305
|
if (name !== null && LOGGER_FACTORIES.has(name.toLowerCase())) {
|
|
7948
8306
|
return true;
|
|
7949
8307
|
}
|
|
@@ -7974,7 +8332,7 @@ function createLogMatcher(options = {}) {
|
|
|
7974
8332
|
const callee = unwrapExpression(expr.callee);
|
|
7975
8333
|
const calleeReceiver = callee.type === AST_NODE_TYPES41.MemberExpression ? unwrapExpression(callee.object) : callee;
|
|
7976
8334
|
if (callee.type !== "MemberExpression") return false;
|
|
7977
|
-
const name =
|
|
8335
|
+
const name = ASTUtils19.getPropertyName(callee);
|
|
7978
8336
|
return name !== null && LOG_METHODS.has(name.toLowerCase()) && isLoggerReceiver(calleeReceiver);
|
|
7979
8337
|
}
|
|
7980
8338
|
return { isLoggerReceiver, isLogFunctionCall, isLoggingCall };
|
|
@@ -8048,7 +8406,7 @@ function seededFallbackHandled(tryStatement, scope) {
|
|
|
8048
8406
|
if (previous.declarations.length !== 1 || declarator === void 0) return false;
|
|
8049
8407
|
if (declarator.id.type !== AST_NODE_TYPES42.Identifier) return false;
|
|
8050
8408
|
if (declarator.init == null || !isSeedValue(declarator.init)) return false;
|
|
8051
|
-
const variable =
|
|
8409
|
+
const variable = ASTUtils20.findVariable(scope, declarator.id.name);
|
|
8052
8410
|
if (variable === null) return false;
|
|
8053
8411
|
const [tryStart, tryEnd] = tryStatement.block.range;
|
|
8054
8412
|
let writtenInTry = false;
|
|
@@ -8110,9 +8468,9 @@ var no_log_only_catch_default = createRule({
|
|
|
8110
8468
|
if (left.type !== AST_NODE_TYPES42.MemberExpression || left.computed || left.object.type !== AST_NODE_TYPES42.Identifier || right.type !== AST_NODE_TYPES42.CallExpression || right.optional || right.callee.type !== AST_NODE_TYPES42.Identifier || !["String", "Number", "Boolean", "BigInt"].includes(right.callee.name) || right.arguments.length !== 1) return false;
|
|
8111
8469
|
const argument = right.arguments[0];
|
|
8112
8470
|
if (argument === void 0 || sourceCode.getText(left) !== sourceCode.getText(argument)) return false;
|
|
8113
|
-
const global =
|
|
8471
|
+
const global = ASTUtils20.findVariable(sourceCode.getScope(right.callee), right.callee.name);
|
|
8114
8472
|
if (global !== null && global.defs.length > 0) return false;
|
|
8115
|
-
const root =
|
|
8473
|
+
const root = ASTUtils20.findVariable(sourceCode.getScope(left.object), left.object.name);
|
|
8116
8474
|
if (root === null || root.references.some((reference) => reference.isWrite() && !reference.init)) return false;
|
|
8117
8475
|
return hasFollowingCoercionCheck(owner, left, right.callee.name);
|
|
8118
8476
|
}
|
|
@@ -8183,7 +8541,7 @@ var no_log_only_catch_default = createRule({
|
|
|
8183
8541
|
});
|
|
8184
8542
|
|
|
8185
8543
|
// src/rules/no-bare-return-from-test-catch.ts
|
|
8186
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES43, ASTUtils as
|
|
8544
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES43, ASTUtils as ASTUtils21 } from "@typescript-eslint/utils";
|
|
8187
8545
|
var NO_BARE_RETURN_FROM_TEST_CATCH_DOCUMENTATION = {
|
|
8188
8546
|
summary: "Disallow a bare return from a test catch block when it skips a later assertion.",
|
|
8189
8547
|
rationale: "An unasserted catch return can swallow a failure and skip later assertions; the complete test result also depends on other assertions and hooks.",
|
|
@@ -8280,7 +8638,7 @@ var no_bare_return_from_test_catch_default = createRule({
|
|
|
8280
8638
|
const parameter = catchClause.param;
|
|
8281
8639
|
const returnBlock = node.parent;
|
|
8282
8640
|
if (parameter?.type === AST_NODE_TYPES43.Identifier && returnBlock?.type === AST_NODE_TYPES43.BlockStatement) {
|
|
8283
|
-
const errorBinding =
|
|
8641
|
+
const errorBinding = ASTUtils21.findVariable(context.sourceCode.getScope(parameter), parameter.name);
|
|
8284
8642
|
const assertedError = returnBlock.body.some((statement) => {
|
|
8285
8643
|
if (statement.range[1] >= node.range[0] || statement.type !== AST_NODE_TYPES43.ExpressionStatement) return false;
|
|
8286
8644
|
const expression = statement.expression;
|
|
@@ -8304,7 +8662,7 @@ var no_bare_return_from_test_catch_default = createRule({
|
|
|
8304
8662
|
});
|
|
8305
8663
|
|
|
8306
8664
|
// src/rules/no-bespoke-api-case-conversion.ts
|
|
8307
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES44, ASTUtils as
|
|
8665
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES44, ASTUtils as ASTUtils22 } from "@typescript-eslint/utils";
|
|
8308
8666
|
var NO_BESPOKE_API_CASE_CONVERSION_DOCUMENTATION = {
|
|
8309
8667
|
defaultLevel: "warning",
|
|
8310
8668
|
summary: "Review direct snake_case/camelCase mirror mappings on explicitly API-typed adapter values.",
|
|
@@ -8357,10 +8715,10 @@ function propertyName(node) {
|
|
|
8357
8715
|
}
|
|
8358
8716
|
function memberName3(node) {
|
|
8359
8717
|
const current = unwrapExpression(node);
|
|
8360
|
-
if (current.type !== AST_NODE_TYPES44.MemberExpression ||
|
|
8718
|
+
if (current.type !== AST_NODE_TYPES44.MemberExpression || ASTUtils22.getPropertyName(current) === null) {
|
|
8361
8719
|
return null;
|
|
8362
8720
|
}
|
|
8363
|
-
return
|
|
8721
|
+
return ASTUtils22.getPropertyName(current) ?? "";
|
|
8364
8722
|
}
|
|
8365
8723
|
function isDirectCaseTranslation(left, right) {
|
|
8366
8724
|
if (SNAKE_CASE_RE2.test(left) && LOWER_CAMEL_CASE_RE.test(right)) {
|
|
@@ -8400,7 +8758,7 @@ var no_bespoke_api_case_conversion_default = createRule({
|
|
|
8400
8758
|
else break;
|
|
8401
8759
|
}
|
|
8402
8760
|
if (current.type !== AST_NODE_TYPES44.Identifier) return false;
|
|
8403
|
-
const binding =
|
|
8761
|
+
const binding = ASTUtils22.findVariable(context.sourceCode.getScope(current), current.name);
|
|
8404
8762
|
if (binding?.defs.length !== 1 || binding.references.some((reference) => reference.isWrite() && reference.init !== true)) return false;
|
|
8405
8763
|
const identifier = binding.defs[0]?.name;
|
|
8406
8764
|
if (identifier?.type !== AST_NODE_TYPES44.Identifier) return false;
|
|
@@ -8409,7 +8767,7 @@ var no_bespoke_api_case_conversion_default = createRule({
|
|
|
8409
8767
|
let typeName = annotation.typeName;
|
|
8410
8768
|
while (typeName.type === AST_NODE_TYPES44.TSQualifiedName) typeName = typeName.left;
|
|
8411
8769
|
if (typeName.type !== AST_NODE_TYPES44.Identifier) return false;
|
|
8412
|
-
const typeBinding =
|
|
8770
|
+
const typeBinding = ASTUtils22.findVariable(context.sourceCode.getScope(typeName), typeName.name);
|
|
8413
8771
|
return typeBinding?.defs.length === 1 && typeBinding.defs[0]?.type === "ImportBinding" && typeBinding.defs[0].parent.type === AST_NODE_TYPES44.ImportDeclaration && API_BOUNDARY_IMPORT_RE.test(typeBinding.defs[0].parent.source.value);
|
|
8414
8772
|
};
|
|
8415
8773
|
return {
|
|
@@ -8614,7 +8972,7 @@ var no_vague_suppression_description_default = createRule({
|
|
|
8614
8972
|
});
|
|
8615
8973
|
|
|
8616
8974
|
// src/rules/_runtime-exports.ts
|
|
8617
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES46, ASTUtils as
|
|
8975
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES46, ASTUtils as ASTUtils23 } from "@typescript-eslint/utils";
|
|
8618
8976
|
var GENERIC_MODULE_STEMS = /* @__PURE__ */ new Set([
|
|
8619
8977
|
"common",
|
|
8620
8978
|
"helper",
|
|
@@ -8736,7 +9094,7 @@ function namespaceEmission(declaration) {
|
|
|
8736
9094
|
}
|
|
8737
9095
|
function isCommonJsExportReference(node, sourceCode) {
|
|
8738
9096
|
function isGlobal(node2) {
|
|
8739
|
-
const variable =
|
|
9097
|
+
const variable = ASTUtils23.findVariable(sourceCode.getScope(node2), node2.name);
|
|
8740
9098
|
return variable === null || variable.defs.length === 0;
|
|
8741
9099
|
}
|
|
8742
9100
|
if (node.type === AST_NODE_TYPES46.MemberExpression) {
|
|
@@ -8824,11 +9182,12 @@ var NO_OFFSET_PAGINATION_DOCUMENTATION = {
|
|
|
8824
9182
|
limitations: ["A SELECT/FROM query shape or adjacent LIMIT/OFFSET fragment is required. Isolated OFFSET fragments and test files are excluded; this lexical context does not prove a database execution sink. Performance and concurrent-write behavior depend on indexes, ordering, isolation, and dialect; bounded pages and random page access can justify OFFSET."],
|
|
8825
9183
|
examples: [
|
|
8826
9184
|
{ id: "keyset-pagination", title: "Page from a stable cursor", outcome: "no-match", files: [{ path: "src/runs.ts", source: "db.prepare(`SELECT id FROM runs WHERE id > ? ORDER BY id LIMIT ?`).all();" }], focusPath: "src/runs.ts", expectedCount: 0, public: true },
|
|
8827
|
-
{ id: "offset-pagination", title: "Do not page by offset", outcome: "match", files: [{ path: "src/runs.ts", source: "db.query(`SELECT id FROM runs ORDER BY id LIMIT ? OFFSET ?`);" }], focusPath: "src/runs.ts", expectedCount: 1, public: true }
|
|
9185
|
+
{ id: "offset-pagination", title: "Do not page by offset", outcome: "match", files: [{ path: "src/runs.ts", source: "db.query(`SELECT id FROM runs ORDER BY id LIMIT ? OFFSET ?`);" }], focusPath: "src/runs.ts", expectedCount: 1, public: true },
|
|
9186
|
+
{ id: "decoded-query", scenarioId: "native-decoded-sql", title: "Inspect native-decoded query text", outcome: "match", files: [{ path: "src/page.ts", source: 'db.query("SELECT id FROM runs ORDER BY id LIMIT 1 OFF\\u0053ET 1");' }], focusPath: "src/page.ts", expectedCount: 1, public: true },
|
|
9187
|
+
{ id: "decoded-comment-data", scenarioId: "native-decoded-sql", title: "Ignore native-decoded comment data", outcome: "no-match", files: [{ path: "src/page.ts", source: 'db.query("SELECT id FROM runs /* OFF\\x53ET 1 */");' }], focusPath: "src/page.ts", expectedCount: 0, public: true }
|
|
8828
9188
|
]
|
|
8829
9189
|
};
|
|
8830
9190
|
var OFFSET_PAGINATION = /\bOFFSET\s+(?:%s|%\(\w+\)s|\?\d*|:\w+|@\w+|\$\d+|\d+)/i;
|
|
8831
|
-
var OFFSET_GATE = /offset/i;
|
|
8832
9191
|
var PAGINATION_CONTEXT = /\bSELECT\b[\s\S]*\bFROM\b[\s\S]*\bOFFSET\b|\bLIMIT\s+(?:%s|%\(\w+\)s|\?\d*|:\w+|@\w+|\$\d+|\d+)\s+OFFSET\b/i;
|
|
8833
9192
|
var no_offset_pagination_default = createRule({
|
|
8834
9193
|
name: "no-offset-pagination",
|
|
@@ -8845,7 +9204,7 @@ var no_offset_pagination_default = createRule({
|
|
|
8845
9204
|
},
|
|
8846
9205
|
defaultOptions: [],
|
|
8847
9206
|
create(context) {
|
|
8848
|
-
if (isTestFile(context.filename)
|
|
9207
|
+
if (isTestFile(context.filename)) {
|
|
8849
9208
|
return {};
|
|
8850
9209
|
}
|
|
8851
9210
|
return createSqlListener((sql, node) => {
|
|
@@ -8858,7 +9217,7 @@ var no_offset_pagination_default = createRule({
|
|
|
8858
9217
|
});
|
|
8859
9218
|
|
|
8860
9219
|
// src/rules/no-positional-tuple-return.ts
|
|
8861
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES47, ASTUtils as
|
|
9220
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES47, ASTUtils as ASTUtils24 } from "@typescript-eslint/utils";
|
|
8862
9221
|
var NO_POSITIONAL_TUPLE_RETURN_DOCUMENTATION = {
|
|
8863
9222
|
summary: "Disallow returning a multi-field tuple from a named function; return a named object so call sites cannot mismatch slots.",
|
|
8864
9223
|
rationale: "Tuple fields are identified only by position, so reordering can preserve types while changing meaning.",
|
|
@@ -8992,7 +9351,7 @@ function typeAliases(sourceCode) {
|
|
|
8992
9351
|
get(identifier) {
|
|
8993
9352
|
const declaration = aliases.get(identifier.name);
|
|
8994
9353
|
if (declaration === void 0) return void 0;
|
|
8995
|
-
const binding =
|
|
9354
|
+
const binding = ASTUtils24.findVariable(sourceCode.getScope(identifier), identifier.name);
|
|
8996
9355
|
return binding?.defs.length === 1 && binding.defs[0]?.node === declaration ? declaration.typeAnnotation : void 0;
|
|
8997
9356
|
}
|
|
8998
9357
|
};
|
|
@@ -9303,7 +9662,7 @@ var no_production_browser_source_maps_default = createRule({
|
|
|
9303
9662
|
});
|
|
9304
9663
|
|
|
9305
9664
|
// src/rules/no-raw-env.ts
|
|
9306
|
-
import { ASTUtils as
|
|
9665
|
+
import { ASTUtils as ASTUtils25, AST_NODE_TYPES as AST_NODE_TYPES48 } from "@typescript-eslint/utils";
|
|
9307
9666
|
var NO_RAW_ENV_DOCUMENTATION = {
|
|
9308
9667
|
summary: "Disallow direct `process.env` and `import.meta.env` reads outside validated boundaries.",
|
|
9309
9668
|
rationale: "Raw environment reads are untyped and defer invalid configuration failures until use.",
|
|
@@ -9319,15 +9678,15 @@ var CONFIG_FILE_RE = /(^|[\\/])[\w.-]+\.config\.[cm]?[jt]sx?$/;
|
|
|
9319
9678
|
var ENV_BOUNDARY_FILE_RE = /(^|[\\/])(?:env|client-env|server-env|client-settings|server-settings)\.[cm]?[jt]sx?$/;
|
|
9320
9679
|
function isProcessEnv(node, context) {
|
|
9321
9680
|
const receiver = unwrapExpression(node.object);
|
|
9322
|
-
if (receiver.type !== "Identifier" ||
|
|
9323
|
-
const binding =
|
|
9681
|
+
if (receiver.type !== "Identifier" || ASTUtils25.getPropertyName(node) !== "env") return false;
|
|
9682
|
+
const binding = ASTUtils25.findVariable(context.sourceCode.getScope(receiver), receiver.name);
|
|
9324
9683
|
if (binding === null || binding.defs.length === 0) return receiver.name === "process";
|
|
9325
9684
|
return binding.defs.every(
|
|
9326
9685
|
(definition) => definition.type === "ImportBinding" && definition.parent.type === "ImportDeclaration" && definition.parent.importKind !== "type" && ["node:process", "process"].includes(definition.parent.source.value) && ["ImportDefaultSpecifier", "ImportNamespaceSpecifier"].includes(definition.node.type)
|
|
9327
9686
|
);
|
|
9328
9687
|
}
|
|
9329
9688
|
function isImportMetaEnv(node) {
|
|
9330
|
-
return
|
|
9689
|
+
return ASTUtils25.getPropertyName(node) === "env" && node.object.type === "MetaProperty" && node.object.meta.name === "import" && node.object.property.name === "meta";
|
|
9331
9690
|
}
|
|
9332
9691
|
var BUILD_TIME_CONSTANTS = /* @__PURE__ */ new Set([
|
|
9333
9692
|
"NODE_ENV",
|
|
@@ -9345,7 +9704,7 @@ var PLATFORM_MARKERS = /* @__PURE__ */ new Set([
|
|
|
9345
9704
|
function isExemptVariableAccess(node) {
|
|
9346
9705
|
const parent = node.parent;
|
|
9347
9706
|
if (parent.type !== "MemberExpression" || parent.object !== node) return false;
|
|
9348
|
-
const name =
|
|
9707
|
+
const name = ASTUtils25.getPropertyName(parent);
|
|
9349
9708
|
return name !== null && (BUILD_TIME_CONSTANTS.has(name) || PLATFORM_MARKERS.has(name));
|
|
9350
9709
|
}
|
|
9351
9710
|
function isWriteTarget(node) {
|
|
@@ -9393,7 +9752,7 @@ var no_raw_env_default = createRule({
|
|
|
9393
9752
|
if (callee.type === "Identifier" && callee.name === "createEnv") {
|
|
9394
9753
|
hasValidationCall = true;
|
|
9395
9754
|
} else if (callee.type === "MemberExpression") {
|
|
9396
|
-
const name =
|
|
9755
|
+
const name = ASTUtils25.getPropertyName(callee);
|
|
9397
9756
|
if (name === "parse" || name === "safeParse" || name === "object" && calleeReceiver.type === "Identifier" && calleeReceiver.name === "z") {
|
|
9398
9757
|
hasValidationCall = true;
|
|
9399
9758
|
}
|
|
@@ -9413,7 +9772,7 @@ var no_raw_env_default = createRule({
|
|
|
9413
9772
|
});
|
|
9414
9773
|
|
|
9415
9774
|
// src/rules/no-raw-fetch-outside-clients.ts
|
|
9416
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES49, ASTUtils as
|
|
9775
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES49, ASTUtils as ASTUtils26 } from "@typescript-eslint/utils";
|
|
9417
9776
|
var NO_RAW_FETCH_OUTSIDE_CLIENTS_DOCUMENTATION = {
|
|
9418
9777
|
summary: "Disallow calling the global `fetch` outside the client layer; route outbound HTTP through a client module that owns retry, timeout and status handling.",
|
|
9419
9778
|
rationale: "Scattered fetch calls bypass shared transport policy and are harder to stub and observe consistently.",
|
|
@@ -9602,7 +9961,7 @@ var no_raw_fetch_outside_clients_default = createRule({
|
|
|
9602
9961
|
internalApiPrefixes.push(`${options.basePath}/api`);
|
|
9603
9962
|
}
|
|
9604
9963
|
function resolvesToGlobal(identifier) {
|
|
9605
|
-
const variable =
|
|
9964
|
+
const variable = ASTUtils26.findVariable(
|
|
9606
9965
|
context.sourceCode.getScope(identifier),
|
|
9607
9966
|
identifier.name
|
|
9608
9967
|
);
|
|
@@ -9611,7 +9970,7 @@ var no_raw_fetch_outside_clients_default = createRule({
|
|
|
9611
9970
|
function resolveNode2(node) {
|
|
9612
9971
|
if (node === void 0) return null;
|
|
9613
9972
|
if (node.type !== AST_NODE_TYPES49.Identifier) return node;
|
|
9614
|
-
const variable =
|
|
9973
|
+
const variable = ASTUtils26.findVariable(
|
|
9615
9974
|
context.sourceCode.getScope(node),
|
|
9616
9975
|
node.name
|
|
9617
9976
|
);
|
|
@@ -9691,7 +10050,7 @@ var no_raw_fetch_outside_clients_default = createRule({
|
|
|
9691
10050
|
});
|
|
9692
10051
|
|
|
9693
10052
|
// src/rules/no-restricted-library-load.ts
|
|
9694
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES50, ASTUtils as
|
|
10053
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES50, ASTUtils as ASTUtils27 } from "@typescript-eslint/utils";
|
|
9695
10054
|
var NO_RESTRICTED_LIBRARY_LOAD_DOCUMENTATION = {
|
|
9696
10055
|
summary: "Apply configured library restrictions to literal runtime loads and CommonJS resolution references.",
|
|
9697
10056
|
rationale: "Dynamic imports, CommonJS loads, and package resolution checks can bypass library restrictions enforced for static imports.",
|
|
@@ -9777,7 +10136,7 @@ var no_restricted_library_load_default = createRule({
|
|
|
9777
10136
|
});
|
|
9778
10137
|
}
|
|
9779
10138
|
function isUnshadowedRequire(node) {
|
|
9780
|
-
const variable =
|
|
10139
|
+
const variable = ASTUtils27.findVariable(
|
|
9781
10140
|
context.sourceCode.getScope(node),
|
|
9782
10141
|
node.name
|
|
9783
10142
|
);
|
|
@@ -9811,7 +10170,7 @@ var no_restricted_library_load_default = createRule({
|
|
|
9811
10170
|
});
|
|
9812
10171
|
|
|
9813
10172
|
// src/rules/no-router-refresh-polling.ts
|
|
9814
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES51, ASTUtils as
|
|
10173
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES51, ASTUtils as ASTUtils28 } from "@typescript-eslint/utils";
|
|
9815
10174
|
var NO_ROUTER_REFRESH_POLLING_DOCUMENTATION = {
|
|
9816
10175
|
summary: "Do not poll by calling a Next.js router's refresh method from a timer.",
|
|
9817
10176
|
rationale: "A route refresh refetches and rerenders the whole route on every tick instead of loading the named resource that changed.",
|
|
@@ -9839,10 +10198,10 @@ function enclosingIntervalCallback(sourceCode, node) {
|
|
|
9839
10198
|
}
|
|
9840
10199
|
function isIntervalCallee(sourceCode, node) {
|
|
9841
10200
|
node = unwrapExpression(node);
|
|
9842
|
-
return node.type === AST_NODE_TYPES51.Identifier && node.name === "setInterval" && isUnshadowedGlobal2(sourceCode, node) || node.type === AST_NODE_TYPES51.MemberExpression && node.object.type === AST_NODE_TYPES51.Identifier && (node.object.name === "window" || node.object.name === "globalThis") && isUnshadowedGlobal2(sourceCode, node.object) &&
|
|
10201
|
+
return node.type === AST_NODE_TYPES51.Identifier && node.name === "setInterval" && isUnshadowedGlobal2(sourceCode, node) || node.type === AST_NODE_TYPES51.MemberExpression && node.object.type === AST_NODE_TYPES51.Identifier && (node.object.name === "window" || node.object.name === "globalThis") && isUnshadowedGlobal2(sourceCode, node.object) && ASTUtils28.getPropertyName(node) === "setInterval";
|
|
9843
10202
|
}
|
|
9844
10203
|
function isUnshadowedGlobal2(sourceCode, node) {
|
|
9845
|
-
const variable =
|
|
10204
|
+
const variable = ASTUtils28.findVariable(sourceCode.getScope(node), node.name);
|
|
9846
10205
|
return variable === null || variable.defs.length === 0;
|
|
9847
10206
|
}
|
|
9848
10207
|
var no_router_refresh_polling_default = createRule({
|
|
@@ -9865,7 +10224,7 @@ var no_router_refresh_polling_default = createRule({
|
|
|
9865
10224
|
if (node.source.value !== "next/navigation") return;
|
|
9866
10225
|
for (const specifier of node.specifiers) {
|
|
9867
10226
|
if (specifier.type === AST_NODE_TYPES51.ImportSpecifier && importedName4(specifier) === "useRouter") {
|
|
9868
|
-
const variable =
|
|
10227
|
+
const variable = ASTUtils28.findVariable(context.sourceCode.getScope(specifier.local), specifier.local.name);
|
|
9869
10228
|
if (variable !== null) routerHooks.add(variable);
|
|
9870
10229
|
}
|
|
9871
10230
|
}
|
|
@@ -9875,16 +10234,16 @@ var no_router_refresh_polling_default = createRule({
|
|
|
9875
10234
|
if (node.id.type === AST_NODE_TYPES51.Identifier && initializer?.type === AST_NODE_TYPES51.CallExpression) {
|
|
9876
10235
|
const hookCallee = unwrapExpression(initializer.callee);
|
|
9877
10236
|
if (hookCallee.type !== AST_NODE_TYPES51.Identifier) return;
|
|
9878
|
-
const hook =
|
|
9879
|
-
const router =
|
|
10237
|
+
const hook = ASTUtils28.findVariable(context.sourceCode.getScope(hookCallee), hookCallee.name);
|
|
10238
|
+
const router = ASTUtils28.findVariable(context.sourceCode.getScope(node.id), node.id.name);
|
|
9880
10239
|
if (hook !== null && router !== null && routerHooks.has(hook)) routers.add(router);
|
|
9881
10240
|
}
|
|
9882
10241
|
},
|
|
9883
10242
|
CallExpression(node) {
|
|
9884
10243
|
const unwrappedNodeCallee = unwrapExpression(node.callee);
|
|
9885
10244
|
const receiver = unwrappedNodeCallee.type === AST_NODE_TYPES51.MemberExpression ? unwrapExpression(unwrappedNodeCallee.object) : unwrappedNodeCallee;
|
|
9886
|
-
if (unwrappedNodeCallee.type !== AST_NODE_TYPES51.MemberExpression || receiver.type !== AST_NODE_TYPES51.Identifier ||
|
|
9887
|
-
const router =
|
|
10245
|
+
if (unwrappedNodeCallee.type !== AST_NODE_TYPES51.MemberExpression || receiver.type !== AST_NODE_TYPES51.Identifier || ASTUtils28.getPropertyName(unwrappedNodeCallee) === null || (ASTUtils28.getPropertyName(unwrappedNodeCallee) ?? "") !== "refresh") return;
|
|
10246
|
+
const router = ASTUtils28.findVariable(
|
|
9888
10247
|
context.sourceCode.getScope(receiver),
|
|
9889
10248
|
receiver.name
|
|
9890
10249
|
);
|
|
@@ -10447,7 +10806,7 @@ function proseTokens(text) {
|
|
|
10447
10806
|
}
|
|
10448
10807
|
|
|
10449
10808
|
// src/rules/no-secret-in-log.ts
|
|
10450
|
-
import { ASTUtils as
|
|
10809
|
+
import { ASTUtils as ASTUtils29 } from "@typescript-eslint/utils";
|
|
10451
10810
|
|
|
10452
10811
|
// src/rules/_secret-names.ts
|
|
10453
10812
|
var SECRET_WORDS = /* @__PURE__ */ new Set([
|
|
@@ -10670,7 +11029,7 @@ function hasRedactionMarker(name) {
|
|
|
10670
11029
|
}
|
|
10671
11030
|
function valueName(node) {
|
|
10672
11031
|
if (node.type === "Identifier") return node.name;
|
|
10673
|
-
return node.type === "MemberExpression" ?
|
|
11032
|
+
return node.type === "MemberExpression" ? ASTUtils29.getPropertyName(node) : null;
|
|
10674
11033
|
}
|
|
10675
11034
|
function isRawSecretValue(prop) {
|
|
10676
11035
|
if (prop.shorthand) {
|
|
@@ -10721,11 +11080,11 @@ function rawBlobValueName(value) {
|
|
|
10721
11080
|
return isRawBlobName(value.name) ? value.name : null;
|
|
10722
11081
|
}
|
|
10723
11082
|
if (value.type === "MemberExpression") {
|
|
10724
|
-
const name =
|
|
11083
|
+
const name = ASTUtils29.getPropertyName(value);
|
|
10725
11084
|
return name !== null && isRawBlobName(name) ? name : null;
|
|
10726
11085
|
}
|
|
10727
11086
|
if (value.type === "CallExpression" && value.arguments.length === 0 && unwrappedValueCallee?.type === "MemberExpression" && unwrappedValueCallee.object.type === "Identifier" && /^(?:res|response|\w+Response)$/.test(unwrappedValueCallee.object.name)) {
|
|
10728
|
-
const name =
|
|
11087
|
+
const name = ASTUtils29.getPropertyName(unwrappedValueCallee);
|
|
10729
11088
|
return name === "json" || name === "text" ? `${unwrappedValueCallee.object.name}.${name}()` : null;
|
|
10730
11089
|
}
|
|
10731
11090
|
return null;
|
|
@@ -10962,7 +11321,9 @@ var NO_SELECT_STAR_DOCUMENTATION = {
|
|
|
10962
11321
|
limitations: ["Only statically visible embedded SQL is checked; quoted strings (including PostgreSQL dollar strings), comments, function arguments such as COUNT(*), and stars inside EXISTS are excluded. This is a bounded lexical scan, not a complete SQL parser."],
|
|
10963
11322
|
examples: [
|
|
10964
11323
|
{ id: "explicit-projection", title: "Select the required columns", outcome: "no-match", files: [{ path: "src/runs.ts", source: "db.prepare(`SELECT id, status FROM runs`).all();" }], focusPath: "src/runs.ts", expectedCount: 0, public: true },
|
|
10965
|
-
{ id: "wildcard-projection", title: "Do not select every column", outcome: "match", files: [{ path: "src/runs.ts", source: "db.prepare(`SELECT * FROM runs`).all();" }], focusPath: "src/runs.ts", expectedCount: 1, public: true }
|
|
11324
|
+
{ id: "wildcard-projection", title: "Do not select every column", outcome: "match", files: [{ path: "src/runs.ts", source: "db.prepare(`SELECT * FROM runs`).all();" }], focusPath: "src/runs.ts", expectedCount: 1, public: true },
|
|
11325
|
+
{ id: "decoded-query", scenarioId: "native-decoded-sql", title: "Inspect native-decoded query text", outcome: "match", files: [{ path: "src/page.ts", source: 'db.query("SEL\\u0045CT * FROM runs");' }], focusPath: "src/page.ts", expectedCount: 1, public: true },
|
|
11326
|
+
{ id: "decoded-comment-data", scenarioId: "native-decoded-sql", title: "Ignore native-decoded comment data", outcome: "no-match", files: [{ path: "src/page.ts", source: 'db.query("SEL\\x45CT id FROM runs /* SELECT * FROM runs */");' }], focusPath: "src/page.ts", expectedCount: 0, public: true }
|
|
10966
11327
|
]
|
|
10967
11328
|
};
|
|
10968
11329
|
var QUERY_SHAPE = /\bSELECT\b[\s\S]*?\bFROM\b/i;
|
|
@@ -10970,7 +11331,6 @@ var SELECT_KEYWORD = /\bSELECT\b/gi;
|
|
|
10970
11331
|
var FROM_KEYWORD = /^FROM\b/i;
|
|
10971
11332
|
var EXISTS_BEFORE = /\bEXISTS\s*\(\s*$/i;
|
|
10972
11333
|
var QUALIFIED_PREFIX = /\w\.$/;
|
|
10973
|
-
var SELECT_GATE = /select/i;
|
|
10974
11334
|
function hasRealSelectStar(sql) {
|
|
10975
11335
|
const selects = [...sql.matchAll(SELECT_KEYWORD)].map((m) => m.index);
|
|
10976
11336
|
for (let pos = 0; pos < sql.length; pos++) {
|
|
@@ -11019,7 +11379,7 @@ var no_select_star_default = createRule({
|
|
|
11019
11379
|
},
|
|
11020
11380
|
defaultOptions: [],
|
|
11021
11381
|
create(context) {
|
|
11022
|
-
if (isTestFile(context.filename)
|
|
11382
|
+
if (isTestFile(context.filename)) {
|
|
11023
11383
|
return {};
|
|
11024
11384
|
}
|
|
11025
11385
|
return createSqlListener((sql, node) => {
|
|
@@ -11032,7 +11392,7 @@ var no_select_star_default = createRule({
|
|
|
11032
11392
|
});
|
|
11033
11393
|
|
|
11034
11394
|
// src/rules/no-sentinel-return-on-catch.ts
|
|
11035
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES55, ASTUtils as
|
|
11395
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES55, ASTUtils as ASTUtils30 } from "@typescript-eslint/utils";
|
|
11036
11396
|
var NO_SENTINEL_RETURN_ON_CATCH_DOCUMENTATION = {
|
|
11037
11397
|
summary: "Disallow swallowing a caught error by returning an empty sentinel unless the error is handled or the sentinel is part of the function contract.",
|
|
11038
11398
|
rationale: "An unreported fallback makes operational failure indistinguishable from a legitimate empty result.",
|
|
@@ -11186,8 +11546,8 @@ function argsIncludeBinding(args, caughtName) {
|
|
|
11186
11546
|
}
|
|
11187
11547
|
function isParseShapedNode(node) {
|
|
11188
11548
|
const unwrappedNodeCallee = node.type === "CallExpression" || node.type === "NewExpression" ? unwrapExpression(node.callee) : null;
|
|
11189
|
-
if (node.type === AST_NODE_TYPES55.CallExpression && unwrappedNodeCallee?.type === AST_NODE_TYPES55.MemberExpression &&
|
|
11190
|
-
return (
|
|
11549
|
+
if (node.type === AST_NODE_TYPES55.CallExpression && unwrappedNodeCallee?.type === AST_NODE_TYPES55.MemberExpression && ASTUtils30.getPropertyName(unwrappedNodeCallee) !== null) {
|
|
11550
|
+
return (ASTUtils30.getPropertyName(unwrappedNodeCallee) ?? "") === "parse";
|
|
11191
11551
|
}
|
|
11192
11552
|
if (node.type === AST_NODE_TYPES55.NewExpression && unwrappedNodeCallee?.type === AST_NODE_TYPES55.Identifier) {
|
|
11193
11553
|
return SAFE_PARSE_CONSTRUCTORS.has(unwrappedNodeCallee.name);
|
|
@@ -11201,21 +11561,21 @@ var SAFE_PARSE_CONSTRUCTORS = /* @__PURE__ */ new Set([
|
|
|
11201
11561
|
]);
|
|
11202
11562
|
function isBodyDecodeNode(node) {
|
|
11203
11563
|
const unwrappedNodeCallee = node.type === "CallExpression" || node.type === "NewExpression" ? unwrapExpression(node.callee) : null;
|
|
11204
|
-
return node.type === AST_NODE_TYPES55.CallExpression && unwrappedNodeCallee?.type === AST_NODE_TYPES55.MemberExpression &&
|
|
11564
|
+
return node.type === AST_NODE_TYPES55.CallExpression && unwrappedNodeCallee?.type === AST_NODE_TYPES55.MemberExpression && ASTUtils30.getPropertyName(unwrappedNodeCallee) !== null && BODY_DECODE_METHODS.has(ASTUtils30.getPropertyName(unwrappedNodeCallee) ?? "");
|
|
11205
11565
|
}
|
|
11206
11566
|
function isSafeParseSupportCall(node) {
|
|
11207
11567
|
const callee = unwrapExpression(node.callee);
|
|
11208
|
-
if (callee.type !== AST_NODE_TYPES55.MemberExpression ||
|
|
11568
|
+
if (callee.type !== AST_NODE_TYPES55.MemberExpression || ASTUtils30.getPropertyName(callee) === null) {
|
|
11209
11569
|
return false;
|
|
11210
11570
|
}
|
|
11211
|
-
if ((
|
|
11571
|
+
if ((ASTUtils30.getPropertyName(callee) ?? "") === "isArray" && callee.object.type === AST_NODE_TYPES55.Identifier && callee.object.name === "Array") {
|
|
11212
11572
|
return true;
|
|
11213
11573
|
}
|
|
11214
|
-
if ((
|
|
11574
|
+
if ((ASTUtils30.getPropertyName(callee) ?? "") !== "getItem") return false;
|
|
11215
11575
|
if (callee.object.type === AST_NODE_TYPES55.Identifier && (callee.object.name === "localStorage" || callee.object.name === "sessionStorage")) {
|
|
11216
11576
|
return true;
|
|
11217
11577
|
}
|
|
11218
|
-
return callee.object.type === AST_NODE_TYPES55.MemberExpression && callee.object.object.type === AST_NODE_TYPES55.Identifier && (callee.object.object.name === "window" || callee.object.object.name === "globalThis") &&
|
|
11578
|
+
return callee.object.type === AST_NODE_TYPES55.MemberExpression && callee.object.object.type === AST_NODE_TYPES55.Identifier && (callee.object.object.name === "window" || callee.object.object.name === "globalThis") && ASTUtils30.getPropertyName(callee.object) !== null && ((ASTUtils30.getPropertyName(callee.object) ?? "") === "localStorage" || (ASTUtils30.getPropertyName(callee.object) ?? "") === "sessionStorage");
|
|
11219
11579
|
}
|
|
11220
11580
|
var BODY_DECODE_METHODS = /* @__PURE__ */ new Set([
|
|
11221
11581
|
"json",
|
|
@@ -11427,7 +11787,7 @@ var no_sentinel_return_on_catch_default = createRule({
|
|
|
11427
11787
|
return;
|
|
11428
11788
|
}
|
|
11429
11789
|
const returned = unwrapSentinelExpression(last.argument);
|
|
11430
|
-
if (returned?.type === AST_NODE_TYPES55.Identifier && returned.name === "undefined" && (
|
|
11790
|
+
if (returned?.type === AST_NODE_TYPES55.Identifier && returned.name === "undefined" && (ASTUtils30.findVariable(context.sourceCode.getScope(returned), returned.name)?.defs.length ?? 0) > 0) return;
|
|
11431
11791
|
if (containsThrow(node.body)) {
|
|
11432
11792
|
return;
|
|
11433
11793
|
}
|
|
@@ -11470,16 +11830,18 @@ function isNonReadingProperty(current, key) {
|
|
|
11470
11830
|
}
|
|
11471
11831
|
|
|
11472
11832
|
// src/rules/no-silent-promise-catch.ts
|
|
11473
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES56, ASTUtils as
|
|
11833
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES56, ASTUtils as ASTUtils31 } from "@typescript-eslint/utils";
|
|
11474
11834
|
var NO_SILENT_PROMISE_CATCH_DOCUMENTATION = {
|
|
11475
11835
|
summary: "Disallow `.catch()` and second-argument `.then()` handlers that silently swallow a rejection; log, rethrow, or handle the error.",
|
|
11476
11836
|
rationale: "A swallowed rejection hides failures and gives callers an indistinguishable fallback value.",
|
|
11477
11837
|
remediation: "Log, rethrow, or explicitly recover from the rejection; explain intentional teardown suppression.",
|
|
11478
11838
|
category: "correctness",
|
|
11479
|
-
limitations: ["Test files, teardown calls, explanatory comments, non-function handlers, and handlers that consume or report the error are excluded.", "Recognized imported Zod construction chains and their stable local aliases are excluded. Other untyped catch-like APIs are not proven to be Promises."],
|
|
11839
|
+
limitations: ["Test files, teardown calls, explanatory comments, non-function handlers, and handlers that consume or report the error are excluded.", "Recognized imported Zod construction chains and their stable local aliases are excluded. Other untyped catch-like APIs are not proven to be Promises.", "Computed methods resolve literal syntax and stable local string aliases in lexical scope. Function-derived, object-derived and mutated computed keys remain unproven."],
|
|
11480
11840
|
examples: [
|
|
11481
11841
|
{ id: "reported-rejection", title: "Report the rejection", outcome: "no-match", files: [{ path: "src/load.ts", source: "load().catch((error) => logger.error({ error }, 'load failed'));" }], focusPath: "src/load.ts", expectedCount: 0, public: true },
|
|
11482
|
-
{ id: "silent-rejection", title: "Do not swallow the rejection", outcome: "match", files: [{ path: "src/load.ts", source: "load().catch(() => null);" }], focusPath: "src/load.ts", expectedCount: 1, public: true }
|
|
11842
|
+
{ id: "silent-rejection", title: "Do not swallow the rejection", outcome: "match", files: [{ path: "src/load.ts", source: "load().catch(() => null);" }], focusPath: "src/load.ts", expectedCount: 1, public: true },
|
|
11843
|
+
{ id: "stable-computed-catch", scenarioId: "computed-method-scope", title: "Report a rejection through a stable computed method", outcome: "match", files: [{ path: "src/load.ts", source: "const method = 'catch'; Promise.reject(new Error('lost'))[method](() => null);" }], focusPath: "src/load.ts", expectedCount: 1, public: true },
|
|
11844
|
+
{ id: "stable-computed-body-parser", scenarioId: "computed-method-scope", title: "Preserve a recognized optional body parse fallback", outcome: "no-match", files: [{ path: "src/load.ts", source: "const method = 'json'; new Response('')[method]().catch(() => null);" }], focusPath: "src/load.ts", expectedCount: 0, public: true }
|
|
11483
11845
|
]
|
|
11484
11846
|
};
|
|
11485
11847
|
var BODY_PARSE_METHODS = /* @__PURE__ */ new Set([
|
|
@@ -11527,9 +11889,11 @@ var ZOD_CHAIN_METHODS = /* @__PURE__ */ new Set([
|
|
|
11527
11889
|
"superRefine",
|
|
11528
11890
|
"transform"
|
|
11529
11891
|
]);
|
|
11530
|
-
function isBodyParseCall(node) {
|
|
11892
|
+
function isBodyParseCall(node, sourceCode) {
|
|
11531
11893
|
const unwrappedNodeCallee = node.type === "CallExpression" || node.type === "NewExpression" ? unwrapExpression(node.callee) : null;
|
|
11532
|
-
|
|
11894
|
+
if (node.type !== AST_NODE_TYPES56.CallExpression || node.arguments.length !== 0 || unwrappedNodeCallee?.type !== AST_NODE_TYPES56.MemberExpression) return false;
|
|
11895
|
+
const method = staticPropertyName(unwrappedNodeCallee, sourceCode);
|
|
11896
|
+
return method !== null && BODY_PARSE_METHODS.has(method);
|
|
11533
11897
|
}
|
|
11534
11898
|
var TEARDOWN_METHODS = /* @__PURE__ */ new Set([
|
|
11535
11899
|
"cancel",
|
|
@@ -11543,13 +11907,15 @@ var TEARDOWN_METHODS = /* @__PURE__ */ new Set([
|
|
|
11543
11907
|
]);
|
|
11544
11908
|
var DIRECTIVE_COMMENT_RE = /^\s*(eslint-|@ts-|prettier-ignore|biome-ignore|c8 |v8 |istanbul )/;
|
|
11545
11909
|
var isExplanatory = (comment) => !DIRECTIVE_COMMENT_RE.test(comment.value);
|
|
11546
|
-
function isTeardownCall(node) {
|
|
11910
|
+
function isTeardownCall(node, sourceCode) {
|
|
11547
11911
|
const unwrappedNodeCallee = node.type === "CallExpression" || node.type === "NewExpression" ? unwrapExpression(node.callee) : null;
|
|
11548
|
-
|
|
11912
|
+
if (node.type !== AST_NODE_TYPES56.CallExpression || unwrappedNodeCallee?.type !== AST_NODE_TYPES56.MemberExpression) return false;
|
|
11913
|
+
const method = staticPropertyName(unwrappedNodeCallee, sourceCode);
|
|
11914
|
+
return method !== null && TEARDOWN_METHODS.has(method);
|
|
11549
11915
|
}
|
|
11550
|
-
function isCancelledWebShare(node) {
|
|
11916
|
+
function isCancelledWebShare(node, sourceCode) {
|
|
11551
11917
|
const unwrappedNodeCallee = node.type === "CallExpression" || node.type === "NewExpression" ? unwrapExpression(node.callee) : null;
|
|
11552
|
-
return node.type === AST_NODE_TYPES56.CallExpression && unwrappedNodeCallee?.type === AST_NODE_TYPES56.MemberExpression && unwrappedNodeCallee.object.type === AST_NODE_TYPES56.Identifier && unwrappedNodeCallee.object.name === "navigator" &&
|
|
11918
|
+
return node.type === AST_NODE_TYPES56.CallExpression && unwrappedNodeCallee?.type === AST_NODE_TYPES56.MemberExpression && unwrappedNodeCallee.object.type === AST_NODE_TYPES56.Identifier && unwrappedNodeCallee.object.name === "navigator" && staticPropertyName(unwrappedNodeCallee, sourceCode) === "share";
|
|
11553
11919
|
}
|
|
11554
11920
|
function isSilentHandler(handler) {
|
|
11555
11921
|
const body2 = handler.body;
|
|
@@ -11608,16 +11974,16 @@ var no_silent_promise_catch_default = createRule({
|
|
|
11608
11974
|
if (seen.has(node)) return false;
|
|
11609
11975
|
seen.add(node);
|
|
11610
11976
|
if (node.type === AST_NODE_TYPES56.Identifier) {
|
|
11611
|
-
const binding =
|
|
11977
|
+
const binding = ASTUtils31.findVariable(context.sourceCode.getScope(node), node.name);
|
|
11612
11978
|
if (binding === null || binding.references.some((reference) => reference.isWrite() && reference.init !== true)) return false;
|
|
11613
11979
|
const [definition] = binding.defs;
|
|
11614
11980
|
return binding.defs.length === 1 && definition?.node.type === AST_NODE_TYPES56.VariableDeclarator && definition.node.init !== null && isZodSchema(definition.node.init, seen);
|
|
11615
11981
|
}
|
|
11616
|
-
if (node.type !== AST_NODE_TYPES56.CallExpression || unwrappedNodeCallee?.type !== AST_NODE_TYPES56.MemberExpression
|
|
11982
|
+
if (node.type !== AST_NODE_TYPES56.CallExpression || unwrappedNodeCallee?.type !== AST_NODE_TYPES56.MemberExpression) return false;
|
|
11617
11983
|
const { object } = unwrappedNodeCallee;
|
|
11618
|
-
const method =
|
|
11984
|
+
const method = staticPropertyName(unwrappedNodeCallee, context.sourceCode);
|
|
11619
11985
|
if (object.type === AST_NODE_TYPES56.Identifier && method !== null && ZOD_CONSTRUCTORS.has(method)) {
|
|
11620
|
-
const binding =
|
|
11986
|
+
const binding = ASTUtils31.findVariable(context.sourceCode.getScope(object), object.name);
|
|
11621
11987
|
if (binding?.defs.some((definition) => {
|
|
11622
11988
|
const specifier = definition.node;
|
|
11623
11989
|
return (specifier.type === AST_NODE_TYPES56.ImportNamespaceSpecifier || specifier.type === AST_NODE_TYPES56.ImportDefaultSpecifier || specifier.type === AST_NODE_TYPES56.ImportSpecifier && specifier.imported.type === AST_NODE_TYPES56.Identifier && specifier.imported.name === "z") && specifier.parent.type === AST_NODE_TYPES56.ImportDeclaration && isZodModule(String(specifier.parent.source.value));
|
|
@@ -11644,23 +12010,23 @@ var no_silent_promise_catch_default = createRule({
|
|
|
11644
12010
|
return {
|
|
11645
12011
|
CallExpression(node) {
|
|
11646
12012
|
const unwrappedNodeCallee = unwrapExpression(node.callee);
|
|
11647
|
-
if (unwrappedNodeCallee.type !== AST_NODE_TYPES56.MemberExpression
|
|
12013
|
+
if (unwrappedNodeCallee.type !== AST_NODE_TYPES56.MemberExpression) {
|
|
11648
12014
|
return;
|
|
11649
12015
|
}
|
|
11650
|
-
const method =
|
|
12016
|
+
const method = staticPropertyName(unwrappedNodeCallee, context.sourceCode);
|
|
11651
12017
|
const handlerIndex = method === "catch" ? 0 : method === "then" ? 1 : null;
|
|
11652
12018
|
if (handlerIndex === null) return;
|
|
11653
12019
|
if (method === "catch" && isZodSchema(unwrappedNodeCallee.object)) return;
|
|
11654
|
-
if (isBodyParseCall(unwrappedNodeCallee.object)) {
|
|
12020
|
+
if (isBodyParseCall(unwrappedNodeCallee.object, context.sourceCode)) {
|
|
11655
12021
|
return;
|
|
11656
12022
|
}
|
|
11657
|
-
if (isTeardownCall(unwrappedNodeCallee.object)) {
|
|
12023
|
+
if (isTeardownCall(unwrappedNodeCallee.object, context.sourceCode)) {
|
|
11658
12024
|
return;
|
|
11659
12025
|
}
|
|
11660
|
-
if (isCancelledWebShare(unwrappedNodeCallee.object)) {
|
|
12026
|
+
if (isCancelledWebShare(unwrappedNodeCallee.object, context.sourceCode)) {
|
|
11661
12027
|
return;
|
|
11662
12028
|
}
|
|
11663
|
-
if (node.parent.type === AST_NODE_TYPES56.MemberExpression && node.parent.object === node &&
|
|
12029
|
+
if (node.parent.type === AST_NODE_TYPES56.MemberExpression && node.parent.object === node && staticPropertyName(node.parent, context.sourceCode) === "then") {
|
|
11664
12030
|
return;
|
|
11665
12031
|
}
|
|
11666
12032
|
const expectedArguments = method === "catch" ? 1 : 2;
|
|
@@ -11685,7 +12051,7 @@ var no_silent_promise_catch_default = createRule({
|
|
|
11685
12051
|
});
|
|
11686
12052
|
|
|
11687
12053
|
// src/rules/no-sleep-in-test-body.ts
|
|
11688
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES57, ASTUtils as
|
|
12054
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES57, ASTUtils as ASTUtils32 } from "@typescript-eslint/utils";
|
|
11689
12055
|
var NO_SLEEP_IN_TEST_BODY_DOCUMENTATION = {
|
|
11690
12056
|
summary: "Avoid fixed timed sleeps directly in test bodies; synchronize on observable behavior or use controlled timers.",
|
|
11691
12057
|
rationale: "Wall-clock delays make test correctness depend on scheduler and machine speed.",
|
|
@@ -11772,7 +12138,7 @@ function testCallerName(callee, source) {
|
|
|
11772
12138
|
return name !== null && TEST_CALLERS2.has(name) ? name : null;
|
|
11773
12139
|
}
|
|
11774
12140
|
if (callee.type === AST_NODE_TYPES57.MemberExpression) {
|
|
11775
|
-
const member =
|
|
12141
|
+
const member = ASTUtils32.getPropertyName(callee);
|
|
11776
12142
|
return member !== null && TEST_MODIFIERS3.has(member) ? testCallerName(callee.object, source) : null;
|
|
11777
12143
|
}
|
|
11778
12144
|
if (callee.type === AST_NODE_TYPES57.CallExpression) return testCallerName(callee.callee, source);
|
|
@@ -11810,8 +12176,8 @@ var no_sleep_in_test_body_default = createRule({
|
|
|
11810
12176
|
return {
|
|
11811
12177
|
NewExpression(node) {
|
|
11812
12178
|
if (isPromiseSleep(node)) {
|
|
11813
|
-
const constructor =
|
|
11814
|
-
const timer =
|
|
12179
|
+
const constructor = ASTUtils32.findVariable(context.sourceCode.getScope(node), "Promise");
|
|
12180
|
+
const timer = ASTUtils32.findVariable(context.sourceCode.getScope(node), "setTimeout");
|
|
11815
12181
|
if ((constructor?.defs.length ?? 0) > 0 || (timer?.defs.length ?? 0) > 0) return;
|
|
11816
12182
|
report2(node);
|
|
11817
12183
|
}
|
|
@@ -11820,7 +12186,7 @@ var no_sleep_in_test_body_default = createRule({
|
|
|
11820
12186
|
const unwrappedNodeCallee = unwrapExpression(node.callee);
|
|
11821
12187
|
if (isHelperSleep(node)) {
|
|
11822
12188
|
if (unwrappedNodeCallee.type !== AST_NODE_TYPES57.Identifier) return;
|
|
11823
|
-
const variable =
|
|
12189
|
+
const variable = ASTUtils32.findVariable(context.sourceCode.getScope(node), unwrappedNodeCallee.name);
|
|
11824
12190
|
if (variable?.defs.some((definition) => definition.type !== "ImportBinding")) return;
|
|
11825
12191
|
report2(node);
|
|
11826
12192
|
}
|
|
@@ -11830,7 +12196,7 @@ var no_sleep_in_test_body_default = createRule({
|
|
|
11830
12196
|
});
|
|
11831
12197
|
|
|
11832
12198
|
// src/rules/no-storage-in-stateless-modules.ts
|
|
11833
|
-
import { ASTUtils as
|
|
12199
|
+
import { ASTUtils as ASTUtils33, AST_NODE_TYPES as AST_NODE_TYPES58 } from "@typescript-eslint/utils";
|
|
11834
12200
|
var DEFAULT_METHODS2 = [
|
|
11835
12201
|
"prepare",
|
|
11836
12202
|
"put",
|
|
@@ -11865,7 +12231,7 @@ function storageMethodName(node, methods) {
|
|
|
11865
12231
|
const callee = unwrapExpression(node.callee);
|
|
11866
12232
|
const calleeReceiver = callee.type === AST_NODE_TYPES58.MemberExpression ? unwrapExpression(callee.object) : callee;
|
|
11867
12233
|
if (callee.type !== AST_NODE_TYPES58.MemberExpression) return null;
|
|
11868
|
-
const name =
|
|
12234
|
+
const name = ASTUtils33.getPropertyName(callee);
|
|
11869
12235
|
if (name === null || !methods.has(name)) {
|
|
11870
12236
|
return null;
|
|
11871
12237
|
}
|
|
@@ -11886,7 +12252,7 @@ function isStorageLikeReceiver(node) {
|
|
|
11886
12252
|
if (node.type !== AST_NODE_TYPES58.MemberExpression) {
|
|
11887
12253
|
return false;
|
|
11888
12254
|
}
|
|
11889
|
-
const name =
|
|
12255
|
+
const name = ASTUtils33.getPropertyName(node);
|
|
11890
12256
|
if (name !== null && isStorageIdentifier(name)) {
|
|
11891
12257
|
return true;
|
|
11892
12258
|
}
|
|
@@ -11965,7 +12331,7 @@ function hasSqlPreparationEvidence(node, callee) {
|
|
|
11965
12331
|
if (!/^\s*(?:SELECT|WITH|INSERT|UPDATE|DELETE|REPLACE|CREATE|ALTER|DROP|PRAGMA|EXPLAIN)\b/iu.test(stripSqlNoise(text))) return false;
|
|
11966
12332
|
} else {
|
|
11967
12333
|
const receiver = callee.object;
|
|
11968
|
-
const receiverName = receiver.type === AST_NODE_TYPES58.Identifier ? receiver.name : receiver.type === AST_NODE_TYPES58.MemberExpression ?
|
|
12334
|
+
const receiverName = receiver.type === AST_NODE_TYPES58.Identifier ? receiver.name : receiver.type === AST_NODE_TYPES58.MemberExpression ? ASTUtils33.getPropertyName(receiver) ?? "" : "";
|
|
11969
12335
|
if (!/^(?:db|database|connection)$/iu.test(receiverName)) return false;
|
|
11970
12336
|
}
|
|
11971
12337
|
return true;
|
|
@@ -12228,7 +12594,7 @@ var no_string_concat_in_loop_default = createRule({
|
|
|
12228
12594
|
});
|
|
12229
12595
|
|
|
12230
12596
|
// src/rules/no-duplicate-test-case.ts
|
|
12231
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES59, ASTUtils as
|
|
12597
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES59, ASTUtils as ASTUtils34 } from "@typescript-eslint/utils";
|
|
12232
12598
|
var TEST_MODULES = /* @__PURE__ */ new Set(["vitest", "@jest/globals", "bun:test"]);
|
|
12233
12599
|
var TEST_NAMES2 = /* @__PURE__ */ new Set(["it", "test"]);
|
|
12234
12600
|
var MODIFIERS = /* @__PURE__ */ new Set(["only", "skip", "concurrent", "fails", "failing", "todo"]);
|
|
@@ -12250,15 +12616,15 @@ var NO_DUPLICATE_TEST_CASE_DOCUMENTATION = {
|
|
|
12250
12616
|
};
|
|
12251
12617
|
function frameworkEach(node, sourceCode) {
|
|
12252
12618
|
let callee = unwrapExpression(node.callee);
|
|
12253
|
-
if (callee.type !== AST_NODE_TYPES59.MemberExpression ||
|
|
12619
|
+
if (callee.type !== AST_NODE_TYPES59.MemberExpression || ASTUtils34.getPropertyName(callee) !== "each") return false;
|
|
12254
12620
|
callee = unwrapExpression(callee.object);
|
|
12255
12621
|
while (callee.type === AST_NODE_TYPES59.MemberExpression) {
|
|
12256
|
-
const name =
|
|
12622
|
+
const name = ASTUtils34.getPropertyName(callee);
|
|
12257
12623
|
if (name === null || !MODIFIERS.has(name)) return false;
|
|
12258
12624
|
callee = unwrapExpression(callee.object);
|
|
12259
12625
|
}
|
|
12260
12626
|
if (callee.type !== AST_NODE_TYPES59.Identifier) return false;
|
|
12261
|
-
const variable =
|
|
12627
|
+
const variable = ASTUtils34.findVariable(sourceCode.getScope(callee), callee.name);
|
|
12262
12628
|
if (variable === null || variable.defs.length === 0) return TEST_NAMES2.has(callee.name);
|
|
12263
12629
|
return variable.defs.length === 1 && variable.defs.every((definition) => {
|
|
12264
12630
|
if (definition.node.type !== AST_NODE_TYPES59.ImportSpecifier) return false;
|
|
@@ -12271,7 +12637,7 @@ function table(node, sourceCode) {
|
|
|
12271
12637
|
node = unwrapExpression(node);
|
|
12272
12638
|
if (node.type === AST_NODE_TYPES59.ArrayExpression) return node;
|
|
12273
12639
|
if (node.type !== AST_NODE_TYPES59.Identifier) return null;
|
|
12274
|
-
const variable =
|
|
12640
|
+
const variable = ASTUtils34.findVariable(sourceCode.getScope(node), node.name);
|
|
12275
12641
|
const definition = variable?.defs[0];
|
|
12276
12642
|
if (variable?.defs.length !== 1 || definition?.node.type !== AST_NODE_TYPES59.VariableDeclarator || definition.node.id.type !== AST_NODE_TYPES59.Identifier || definition.node.parent.kind !== "const" || definition.node.init === null || definition.node.init.range[1] > node.range[0]) return null;
|
|
12277
12643
|
if (!variable.references.every((reference) => {
|
|
@@ -12352,7 +12718,7 @@ var no_duplicate_test_case_default = createRule({
|
|
|
12352
12718
|
});
|
|
12353
12719
|
|
|
12354
12720
|
// src/rules/no-tautological-expect.ts
|
|
12355
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES60, ASTUtils as
|
|
12721
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES60, ASTUtils as ASTUtils35 } from "@typescript-eslint/utils";
|
|
12356
12722
|
var NO_TAUTOLOGICAL_EXPECT_DOCUMENTATION = {
|
|
12357
12723
|
summary: "Disallow supported assertions known to pass from literals or immutable scalar setup.",
|
|
12358
12724
|
rationale: "An assertion determined entirely by literals does not observe the code under test and can keep passing after that code is removed.",
|
|
@@ -12419,7 +12785,7 @@ function resolveLiteral(node, sourceCode, seen = /* @__PURE__ */ new Set()) {
|
|
|
12419
12785
|
if (isLiteral(node)) return node;
|
|
12420
12786
|
if (node.type !== AST_NODE_TYPES60.Identifier || seen.has(node)) return null;
|
|
12421
12787
|
seen.add(node);
|
|
12422
|
-
const variable =
|
|
12788
|
+
const variable = ASTUtils35.findVariable(sourceCode.getScope(node), node.name);
|
|
12423
12789
|
if (variable?.defs.length !== 1) return null;
|
|
12424
12790
|
const definition = variable.defs[0];
|
|
12425
12791
|
if (definition?.node.type !== AST_NODE_TYPES60.VariableDeclarator || definition.node.id.type !== AST_NODE_TYPES60.Identifier || definition.node.parent.kind !== "const" || definition.node.init === null || definition.node.init.range[1] > node.range[0] || variable.references.some((reference) => reference.isWrite() && !reference.init)) return null;
|
|
@@ -12519,13 +12885,13 @@ var no_tautological_expect_default = createRule({
|
|
|
12519
12885
|
CallExpression(node) {
|
|
12520
12886
|
const callee = unwrapExpression(node.callee);
|
|
12521
12887
|
if (callee.type !== AST_NODE_TYPES60.MemberExpression) return;
|
|
12522
|
-
const matcher =
|
|
12888
|
+
const matcher = ASTUtils35.getPropertyName(callee);
|
|
12523
12889
|
if (matcher === null) return;
|
|
12524
12890
|
const receiver = unwrapExpression(callee.object);
|
|
12525
12891
|
if (receiver.type !== AST_NODE_TYPES60.CallExpression) return;
|
|
12526
12892
|
const expectIdentifier = unwrapExpression(receiver.callee);
|
|
12527
12893
|
if (expectIdentifier.type !== AST_NODE_TYPES60.Identifier) return;
|
|
12528
|
-
const variable =
|
|
12894
|
+
const variable = ASTUtils35.findVariable(context.sourceCode.getScope(expectIdentifier), expectIdentifier.name);
|
|
12529
12895
|
if (variable !== null && variable.defs.some((definition) => {
|
|
12530
12896
|
if (definition.node.type !== AST_NODE_TYPES60.ImportSpecifier) return true;
|
|
12531
12897
|
const declaration = definition.node.parent;
|
|
@@ -13775,7 +14141,7 @@ var no_unnecessary_use_client_default = createRule({
|
|
|
13775
14141
|
// src/rules/no-unsafe-mock-casting.ts
|
|
13776
14142
|
import {
|
|
13777
14143
|
AST_NODE_TYPES as AST_NODE_TYPES66,
|
|
13778
|
-
ASTUtils as
|
|
14144
|
+
ASTUtils as ASTUtils36
|
|
13779
14145
|
} from "@typescript-eslint/utils";
|
|
13780
14146
|
var MOCK_TYPE_NAMES = /* @__PURE__ */ new Set([
|
|
13781
14147
|
"Mock",
|
|
@@ -13842,7 +14208,7 @@ var no_unsafe_mock_casting_default = createRule({
|
|
|
13842
14208
|
const directBindings = /* @__PURE__ */ new Set();
|
|
13843
14209
|
const namespaceBindings = /* @__PURE__ */ new Set();
|
|
13844
14210
|
function resolve2(identifier) {
|
|
13845
|
-
return
|
|
14211
|
+
return ASTUtils36.findVariable(
|
|
13846
14212
|
context.sourceCode.getScope(identifier),
|
|
13847
14213
|
identifier.name
|
|
13848
14214
|
);
|
|
@@ -13889,7 +14255,7 @@ var no_unsafe_mock_casting_default = createRule({
|
|
|
13889
14255
|
});
|
|
13890
14256
|
|
|
13891
14257
|
// src/rules/no-unsafe-test-double-cast.ts
|
|
13892
|
-
import { ASTUtils as
|
|
14258
|
+
import { ASTUtils as ASTUtils37, AST_NODE_TYPES as AST_NODE_TYPES67 } from "@typescript-eslint/utils";
|
|
13893
14259
|
var NO_UNSAFE_TEST_DOUBLE_CAST_DOCUMENTATION = {
|
|
13894
14260
|
summary: "Disallow mock-backed test doubles that bypass collaborator contracts through double assertions.",
|
|
13895
14261
|
rationale: "Casting a partial object through unknown hides missing or stale collaborator members, so production interface changes can compile while the test double silently drifts.",
|
|
@@ -13919,7 +14285,7 @@ function isMockFactory(node, source) {
|
|
|
13919
14285
|
const unwrappedNodeCallee = node.type === "CallExpression" || node.type === "NewExpression" ? unwrapExpression(node.callee) : null;
|
|
13920
14286
|
if (node.type !== AST_NODE_TYPES67.CallExpression || unwrappedNodeCallee?.type !== AST_NODE_TYPES67.MemberExpression) return false;
|
|
13921
14287
|
const receiver = unwrapExpression(unwrappedNodeCallee.object);
|
|
13922
|
-
return node.type === AST_NODE_TYPES67.CallExpression && unwrappedNodeCallee?.type === AST_NODE_TYPES67.MemberExpression && receiver.type === AST_NODE_TYPES67.Identifier && (importedTestMockNamespace(source, receiver) !== null || isUnshadowedTestMockGlobal(source, receiver)) &&
|
|
14288
|
+
return node.type === AST_NODE_TYPES67.CallExpression && unwrappedNodeCallee?.type === AST_NODE_TYPES67.MemberExpression && receiver.type === AST_NODE_TYPES67.Identifier && (importedTestMockNamespace(source, receiver) !== null || isUnshadowedTestMockGlobal(source, receiver)) && ASTUtils37.getPropertyName(unwrappedNodeCallee) !== null && ["fn", "spyOn"].includes(ASTUtils37.getPropertyName(unwrappedNodeCallee) ?? "");
|
|
13923
14289
|
}
|
|
13924
14290
|
var no_unsafe_test_double_cast_default = createRule({
|
|
13925
14291
|
name: "no-unsafe-test-double-cast",
|
|
@@ -13945,7 +14311,7 @@ var no_unsafe_test_double_cast_default = createRule({
|
|
|
13945
14311
|
});
|
|
13946
14312
|
|
|
13947
14313
|
// src/rules/no-first-party-module-mock.ts
|
|
13948
|
-
import { ASTUtils as
|
|
14314
|
+
import { ASTUtils as ASTUtils38, AST_NODE_TYPES as AST_NODE_TYPES68 } from "@typescript-eslint/utils";
|
|
13949
14315
|
var NO_FIRST_PARTY_MODULE_MOCK_DOCUMENTATION = {
|
|
13950
14316
|
summary: "Prefer injected collaborators over mocking maintained first-party modules in tests.",
|
|
13951
14317
|
rationale: "Replacing an owned module couples tests to its lookup path and can verify mock wiring while bypassing the real implementation contract.",
|
|
@@ -13976,7 +14342,7 @@ var no_first_party_module_mock_default = createRule({
|
|
|
13976
14342
|
CallExpression(node) {
|
|
13977
14343
|
const unwrappedNodeCallee = unwrapExpression(node.callee);
|
|
13978
14344
|
const receiver = unwrappedNodeCallee.type === AST_NODE_TYPES68.MemberExpression ? unwrapExpression(unwrappedNodeCallee.object) : unwrappedNodeCallee;
|
|
13979
|
-
if (unwrappedNodeCallee.type !== AST_NODE_TYPES68.MemberExpression || receiver.type !== AST_NODE_TYPES68.Identifier ||
|
|
14345
|
+
if (unwrappedNodeCallee.type !== AST_NODE_TYPES68.MemberExpression || receiver.type !== AST_NODE_TYPES68.Identifier || ASTUtils38.getPropertyName(unwrappedNodeCallee) === null || !["mock", "doMock"].includes(ASTUtils38.getPropertyName(unwrappedNodeCallee) ?? "")) return;
|
|
13980
14346
|
const framework = importedTestMockNamespace(context.sourceCode, receiver);
|
|
13981
14347
|
if (framework === null || framework === "jest" && mayBeVirtual(node.arguments[2])) return;
|
|
13982
14348
|
const argument = node.arguments[0] === void 0 ? void 0 : unwrapExpression(node.arguments[0]);
|
|
@@ -14002,7 +14368,7 @@ function mayBeVirtual(options) {
|
|
|
14002
14368
|
import {
|
|
14003
14369
|
ESLintUtils as ESLintUtils10,
|
|
14004
14370
|
AST_NODE_TYPES as AST_NODE_TYPES69,
|
|
14005
|
-
ASTUtils as
|
|
14371
|
+
ASTUtils as ASTUtils39
|
|
14006
14372
|
} from "@typescript-eslint/utils";
|
|
14007
14373
|
import * as ts9 from "typescript";
|
|
14008
14374
|
var NO_ZOD_NATIVE_ENUM_DOCUMENTATION = {
|
|
@@ -14109,7 +14475,7 @@ var no_zod_native_enum_default = createRule({
|
|
|
14109
14475
|
const zodImportedBindings = /* @__PURE__ */ new Map();
|
|
14110
14476
|
const zodNamespaceBindings = /* @__PURE__ */ new Set();
|
|
14111
14477
|
function resolvedBinding(identifier) {
|
|
14112
|
-
return
|
|
14478
|
+
return ASTUtils39.findVariable(
|
|
14113
14479
|
sourceCode.getScope(identifier),
|
|
14114
14480
|
identifier.name
|
|
14115
14481
|
);
|
|
@@ -14117,7 +14483,7 @@ var no_zod_native_enum_default = createRule({
|
|
|
14117
14483
|
function isZodMemberCall(node, api) {
|
|
14118
14484
|
const callee = unwrapExpression(node.callee);
|
|
14119
14485
|
const calleeReceiver = callee.type === AST_NODE_TYPES69.MemberExpression ? unwrapExpression(callee.object) : callee;
|
|
14120
|
-
if (callee.type === AST_NODE_TYPES69.MemberExpression && calleeReceiver.type === AST_NODE_TYPES69.Identifier &&
|
|
14486
|
+
if (callee.type === AST_NODE_TYPES69.MemberExpression && calleeReceiver.type === AST_NODE_TYPES69.Identifier && ASTUtils39.getPropertyName(callee) === api) {
|
|
14121
14487
|
const binding = resolvedBinding(calleeReceiver);
|
|
14122
14488
|
return binding !== null && zodNamespaceBindings.has(binding);
|
|
14123
14489
|
}
|
|
@@ -14176,7 +14542,7 @@ var no_zod_native_enum_default = createRule({
|
|
|
14176
14542
|
});
|
|
14177
14543
|
|
|
14178
14544
|
// src/rules/test-loops-over-literal-cases.ts
|
|
14179
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES70, ASTUtils as
|
|
14545
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES70, ASTUtils as ASTUtils40 } from "@typescript-eslint/utils";
|
|
14180
14546
|
var TEST_LOOPS_OVER_LITERAL_CASES_DOCUMENTATION = {
|
|
14181
14547
|
summary: "Disallow assertions over an inline literal case loop in a test; parameterization reports and names every case independently.",
|
|
14182
14548
|
rationale: "A loop is reported as one test, so failures hide the individual case name and may stop later cases from running.",
|
|
@@ -14329,7 +14695,7 @@ var test_loops_over_literal_cases_default = createRule({
|
|
|
14329
14695
|
}
|
|
14330
14696
|
const capturesSetup = walkOwnScope2(node.body, (current) => {
|
|
14331
14697
|
if (current.type !== AST_NODE_TYPES70.Identifier) return false;
|
|
14332
|
-
const variable =
|
|
14698
|
+
const variable = ASTUtils40.findVariable(context.sourceCode.getScope(current), current.name);
|
|
14333
14699
|
if (variable === null || !variable.references.some((reference) => reference.identifier === current)) return false;
|
|
14334
14700
|
return variable.defs.some((definition) => {
|
|
14335
14701
|
const declaration = definition.name;
|
|
@@ -14783,7 +15149,7 @@ var prefer_discriminated_union_default = createRule({
|
|
|
14783
15149
|
});
|
|
14784
15150
|
|
|
14785
15151
|
// src/rules/prefer-input-group-search.ts
|
|
14786
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES75, ASTUtils as
|
|
15152
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES75, ASTUtils as ASTUtils41 } from "@typescript-eslint/utils";
|
|
14787
15153
|
var PREFER_INPUT_GROUP_SEARCH_DOCUMENTATION = {
|
|
14788
15154
|
summary: "Require search icons and shared Input controls in the same visual wrapper to use InputGroup.",
|
|
14789
15155
|
rationale: "The shared compound control provides consistent spacing, focus behavior, and accessible composition.",
|
|
@@ -14907,7 +15273,7 @@ var prefer_input_group_search_default = createRule({
|
|
|
14907
15273
|
JSXOpeningElement(node) {
|
|
14908
15274
|
const name = elementName(node);
|
|
14909
15275
|
if (name === null) return;
|
|
14910
|
-
const binding =
|
|
15276
|
+
const binding = ASTUtils41.findVariable(context.sourceCode.getScope(node), name);
|
|
14911
15277
|
if (binding?.defs.length !== 1 || binding.defs[0]?.node.type !== AST_NODE_TYPES75.ImportSpecifier || binding.defs[0].node.importKind === "type") return;
|
|
14912
15278
|
const occurrence = {
|
|
14913
15279
|
ancestors: context.sourceCode.getAncestors(node),
|
|
@@ -14947,7 +15313,7 @@ var prefer_input_group_search_default = createRule({
|
|
|
14947
15313
|
|
|
14948
15314
|
// src/rules/prefer-millisecond-control-duration-schema.ts
|
|
14949
15315
|
import {
|
|
14950
|
-
ASTUtils as
|
|
15316
|
+
ASTUtils as ASTUtils42,
|
|
14951
15317
|
AST_NODE_TYPES as AST_NODE_TYPES77
|
|
14952
15318
|
} from "@typescript-eslint/utils";
|
|
14953
15319
|
|
|
@@ -15026,7 +15392,7 @@ var prefer_millisecond_control_duration_schema_default = createRule({
|
|
|
15026
15392
|
const objectFactories = /* @__PURE__ */ new Set();
|
|
15027
15393
|
const numberFactories = /* @__PURE__ */ new Set();
|
|
15028
15394
|
function binding(identifier) {
|
|
15029
|
-
return
|
|
15395
|
+
return ASTUtils42.findVariable(context.sourceCode.getScope(identifier), identifier.name);
|
|
15030
15396
|
}
|
|
15031
15397
|
function record(target, identifier) {
|
|
15032
15398
|
const variable = binding(identifier);
|
|
@@ -15039,7 +15405,7 @@ var prefer_millisecond_control_duration_schema_default = createRule({
|
|
|
15039
15405
|
const variable2 = binding(callee);
|
|
15040
15406
|
return variable2 !== null && objectFactories.has(variable2);
|
|
15041
15407
|
}
|
|
15042
|
-
if (callee.type !== AST_NODE_TYPES77.MemberExpression || calleeReceiver.type !== AST_NODE_TYPES77.Identifier ||
|
|
15408
|
+
if (callee.type !== AST_NODE_TYPES77.MemberExpression || calleeReceiver.type !== AST_NODE_TYPES77.Identifier || ASTUtils42.getPropertyName(callee) === null || (ASTUtils42.getPropertyName(callee) ?? "") !== "object" && (ASTUtils42.getPropertyName(callee) ?? "") !== "strictObject") {
|
|
15043
15409
|
return false;
|
|
15044
15410
|
}
|
|
15045
15411
|
const variable = binding(calleeReceiver);
|
|
@@ -15054,12 +15420,12 @@ var prefer_millisecond_control_duration_schema_default = createRule({
|
|
|
15054
15420
|
const variable = binding(callee);
|
|
15055
15421
|
return variable !== null && numberFactories.has(variable);
|
|
15056
15422
|
}
|
|
15057
|
-
if (callee.type !== AST_NODE_TYPES77.MemberExpression ||
|
|
15423
|
+
if (callee.type !== AST_NODE_TYPES77.MemberExpression || ASTUtils42.getPropertyName(callee) === null) return false;
|
|
15058
15424
|
if (calleeReceiver.type === AST_NODE_TYPES77.Identifier) {
|
|
15059
15425
|
const variable = binding(calleeReceiver);
|
|
15060
|
-
return (
|
|
15426
|
+
return (ASTUtils42.getPropertyName(callee) ?? "") === "number" && variable !== null && zodNamespaces.has(variable);
|
|
15061
15427
|
}
|
|
15062
|
-
return ["int", "min", "max", "positive", "nonnegative", "finite", "multipleOf", "optional", "nullable", "nullish", "default", "describe", "brand", "readonly"].includes(
|
|
15428
|
+
return ["int", "min", "max", "positive", "nonnegative", "finite", "multipleOf", "optional", "nullable", "nullish", "default", "describe", "brand", "readonly"].includes(ASTUtils42.getPropertyName(callee) ?? "") && isNumericSchema(calleeReceiver);
|
|
15063
15429
|
}
|
|
15064
15430
|
return {
|
|
15065
15431
|
ImportDeclaration(node) {
|
|
@@ -15092,7 +15458,7 @@ var prefer_millisecond_control_duration_schema_default = createRule({
|
|
|
15092
15458
|
});
|
|
15093
15459
|
|
|
15094
15460
|
// src/rules/prefer-immutable-module-constant.ts
|
|
15095
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES78, ASTUtils as
|
|
15461
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES78, ASTUtils as ASTUtils43 } from "@typescript-eslint/utils";
|
|
15096
15462
|
var PREFER_IMMUTABLE_MODULE_CONSTANT_DOCUMENTATION = {
|
|
15097
15463
|
summary: "Require module-level constant collections to expose readonly state.",
|
|
15098
15464
|
rationale: "A const binding prevents reassignment but does not stop callers from mutating its array, object, Set, or Map contents.",
|
|
@@ -15311,15 +15677,15 @@ var prefer_immutable_module_constant_default = createRule({
|
|
|
15311
15677
|
create(context) {
|
|
15312
15678
|
const sourceCode = context.sourceCode;
|
|
15313
15679
|
const isUnshadowedGlobal3 = (identifier) => {
|
|
15314
|
-
const variable =
|
|
15680
|
+
const variable = ASTUtils43.findVariable(sourceCode.getScope(identifier), identifier.name);
|
|
15315
15681
|
return variable === null || variable.defs.length === 0;
|
|
15316
15682
|
};
|
|
15317
15683
|
const isUnshadowedType = (identifier) => {
|
|
15318
|
-
const variable =
|
|
15684
|
+
const variable = ASTUtils43.findVariable(sourceCode.getScope(identifier), identifier.name);
|
|
15319
15685
|
return variable === null || !variable.defs.some((definition) => definition.isTypeDefinition);
|
|
15320
15686
|
};
|
|
15321
15687
|
const resolveLocalType = (identifier) => {
|
|
15322
|
-
const variable =
|
|
15688
|
+
const variable = ASTUtils43.findVariable(sourceCode.getScope(identifier), identifier.name);
|
|
15323
15689
|
const definitions = variable?.defs.filter((definition) => definition.isTypeDefinition) ?? [];
|
|
15324
15690
|
const declaration = definitions.length === 1 ? definitions[0]?.node : void 0;
|
|
15325
15691
|
return declaration?.type === AST_NODE_TYPES78.TSTypeAliasDeclaration || declaration?.type === AST_NODE_TYPES78.TSTypeParameter ? declaration : void 0;
|
|
@@ -15813,7 +16179,7 @@ function matchingAliasTargets(paths, alias) {
|
|
|
15813
16179
|
}
|
|
15814
16180
|
|
|
15815
16181
|
// src/rules/prefer-module-level-constant.ts
|
|
15816
|
-
import { ASTUtils as
|
|
16182
|
+
import { ASTUtils as ASTUtils44, AST_NODE_TYPES as AST_NODE_TYPES80 } from "@typescript-eslint/utils";
|
|
15817
16183
|
var PREFER_MODULE_LEVEL_CONSTANT_DOCUMENTATION = {
|
|
15818
16184
|
summary: "Hoist literal-only constant collections and regexes out of function bodies to module scope so they are allocated once.",
|
|
15819
16185
|
rationale: "Recreating immutable lookup data on every call wastes allocations and obscures its constant nature.",
|
|
@@ -15941,7 +16307,7 @@ function classify(init, checkRegex, sourceCode) {
|
|
|
15941
16307
|
function unwrapObjectFreeze(node, sourceCode) {
|
|
15942
16308
|
const inner = unwrap3(node);
|
|
15943
16309
|
const callee = inner.type === AST_NODE_TYPES80.CallExpression ? unwrapExpression(inner.callee) : null;
|
|
15944
|
-
if (inner.type === AST_NODE_TYPES80.CallExpression && callee?.type === AST_NODE_TYPES80.MemberExpression && !callee.computed && callee.object.type === AST_NODE_TYPES80.Identifier && callee.object.name === "Object" && (
|
|
16310
|
+
if (inner.type === AST_NODE_TYPES80.CallExpression && callee?.type === AST_NODE_TYPES80.MemberExpression && !callee.computed && callee.object.type === AST_NODE_TYPES80.Identifier && callee.object.name === "Object" && (ASTUtils44.findVariable(sourceCode.getScope(callee.object), "Object")?.defs.length ?? 0) === 0 && callee.property.type === AST_NODE_TYPES80.Identifier && callee.property.name === "freeze" && inner.arguments.length === 1 && inner.arguments[0] !== void 0 && inner.arguments[0].type !== AST_NODE_TYPES80.SpreadElement) {
|
|
15945
16311
|
return unwrap3(inner.arguments[0]);
|
|
15946
16312
|
}
|
|
15947
16313
|
return inner;
|
|
@@ -16140,14 +16506,14 @@ function isSafeMemberRead(identifier, parent) {
|
|
|
16140
16506
|
if (grandparent.type === AST_NODE_TYPES80.UnaryExpression && grandparent.operator === "delete") {
|
|
16141
16507
|
return false;
|
|
16142
16508
|
}
|
|
16143
|
-
if (grandparent.type === AST_NODE_TYPES80.CallExpression && grandparent.callee === usage && (
|
|
16509
|
+
if (grandparent.type === AST_NODE_TYPES80.CallExpression && grandparent.callee === usage && (ASTUtils44.getPropertyName(parent) === null || MUTATING_METHODS2.has(ASTUtils44.getPropertyName(parent) ?? ""))) {
|
|
16144
16510
|
return false;
|
|
16145
16511
|
}
|
|
16146
16512
|
return true;
|
|
16147
16513
|
}
|
|
16148
16514
|
|
|
16149
16515
|
// src/rules/prefer-module-level-schema.ts
|
|
16150
|
-
import { ASTUtils as
|
|
16516
|
+
import { ASTUtils as ASTUtils45, AST_NODE_TYPES as AST_NODE_TYPES81 } from "@typescript-eslint/utils";
|
|
16151
16517
|
var PREFER_MODULE_LEVEL_SCHEMA_DOCUMENTATION = {
|
|
16152
16518
|
summary: "Declare a Zod schema at module scope when it closes over nothing in the enclosing function",
|
|
16153
16519
|
rationale: "A schema created inside a function is rebuilt on each call. Module scope can enable reuse across callers; local schemas already support local type inference.",
|
|
@@ -16255,7 +16621,7 @@ function schemaExpression(node) {
|
|
|
16255
16621
|
if (parent === void 0) {
|
|
16256
16622
|
return current;
|
|
16257
16623
|
}
|
|
16258
|
-
if (parent.type === AST_NODE_TYPES81.MemberExpression && parent.object === current &&
|
|
16624
|
+
if (parent.type === AST_NODE_TYPES81.MemberExpression && parent.object === current && ASTUtils45.getPropertyName(parent) !== null && TERMINAL_METHODS.has(ASTUtils45.getPropertyName(parent) ?? "")) {
|
|
16259
16625
|
return current;
|
|
16260
16626
|
}
|
|
16261
16627
|
if (parent.type === AST_NODE_TYPES81.MemberExpression && parent.object === current || parent.type === AST_NODE_TYPES81.CallExpression && parent.callee === current || parent.type === AST_NODE_TYPES81.TSAsExpression && parent.expression === current || parent.type === AST_NODE_TYPES81.TSNonNullExpression && parent.expression === current) {
|
|
@@ -16393,14 +16759,14 @@ var prefer_module_level_schema_default = createRule({
|
|
|
16393
16759
|
const unwrappedNodeCallee = node.type === "CallExpression" || node.type === "NewExpression" ? unwrapExpression(node.callee) : null;
|
|
16394
16760
|
if (node.type !== AST_NODE_TYPES81.CallExpression || unwrappedNodeCallee?.type !== AST_NODE_TYPES81.MemberExpression) return false;
|
|
16395
16761
|
const receiver = unwrapExpression(unwrappedNodeCallee.object);
|
|
16396
|
-
return node.type === AST_NODE_TYPES81.CallExpression && unwrappedNodeCallee?.type === AST_NODE_TYPES81.MemberExpression &&
|
|
16762
|
+
return node.type === AST_NODE_TYPES81.CallExpression && unwrappedNodeCallee?.type === AST_NODE_TYPES81.MemberExpression && ASTUtils45.getPropertyName(unwrappedNodeCallee) !== null && receiver.type === AST_NODE_TYPES81.Identifier && zodNamespaces.has(receiver.name);
|
|
16397
16763
|
}
|
|
16398
16764
|
function isSchemaConstruction(node) {
|
|
16399
16765
|
const callee = unwrapExpression(node.callee);
|
|
16400
16766
|
const calleeReceiver = callee.type === AST_NODE_TYPES81.MemberExpression ? unwrapExpression(callee.object) : callee;
|
|
16401
|
-
if (callee.type !== AST_NODE_TYPES81.MemberExpression ||
|
|
16767
|
+
if (callee.type !== AST_NODE_TYPES81.MemberExpression || ASTUtils45.getPropertyName(callee) === null || TERMINAL_METHODS.has(ASTUtils45.getPropertyName(callee) ?? "")) return false;
|
|
16402
16768
|
if (calleeReceiver.type === AST_NODE_TYPES81.CallExpression) return isSchemaConstruction(calleeReceiver);
|
|
16403
|
-
return isZodCall(node) && CONSTRUCTION_FACTORIES.has(
|
|
16769
|
+
return isZodCall(node) && CONSTRUCTION_FACTORIES.has(ASTUtils45.getPropertyName(callee) ?? "");
|
|
16404
16770
|
}
|
|
16405
16771
|
function hasEagerComputation(node) {
|
|
16406
16772
|
return subtreeSome(node, (inner) => inner.type === AST_NODE_TYPES81.NewExpression || inner.type === AST_NODE_TYPES81.TaggedTemplateExpression || inner.type === AST_NODE_TYPES81.CallExpression && !isSchemaConstruction(inner), true);
|
|
@@ -16408,10 +16774,10 @@ var prefer_module_level_schema_default = createRule({
|
|
|
16408
16774
|
function isCovered(node) {
|
|
16409
16775
|
let current = node.parent ?? void 0;
|
|
16410
16776
|
while (current !== void 0) {
|
|
16411
|
-
if (current !== node && isZodCall(current) && current.callee.type === AST_NODE_TYPES81.MemberExpression &&
|
|
16777
|
+
if (current !== node && isZodCall(current) && current.callee.type === AST_NODE_TYPES81.MemberExpression && ASTUtils45.getPropertyName(current.callee) !== null && factories.has(ASTUtils45.getPropertyName(current.callee) ?? "")) {
|
|
16412
16778
|
return true;
|
|
16413
16779
|
}
|
|
16414
|
-
if (current.type === AST_NODE_TYPES81.CallExpression && (current.callee.type === AST_NODE_TYPES81.Identifier && memoCallees.has(current.callee.name) || current.callee.type === AST_NODE_TYPES81.MemberExpression &&
|
|
16780
|
+
if (current.type === AST_NODE_TYPES81.CallExpression && (current.callee.type === AST_NODE_TYPES81.Identifier && memoCallees.has(current.callee.name) || current.callee.type === AST_NODE_TYPES81.MemberExpression && ASTUtils45.getPropertyName(current.callee) !== null && memoCallees.has(ASTUtils45.getPropertyName(current.callee) ?? ""))) {
|
|
16415
16781
|
return true;
|
|
16416
16782
|
}
|
|
16417
16783
|
current = current.parent ?? void 0;
|
|
@@ -16440,7 +16806,7 @@ var prefer_module_level_schema_default = createRule({
|
|
|
16440
16806
|
}
|
|
16441
16807
|
function isSchemaComposition(node) {
|
|
16442
16808
|
const callee = unwrapExpression(node.callee);
|
|
16443
|
-
const isCombinator = callee.type === AST_NODE_TYPES81.MemberExpression &&
|
|
16809
|
+
const isCombinator = callee.type === AST_NODE_TYPES81.MemberExpression && ASTUtils45.getPropertyName(callee) !== null && ZOD_COMBINATOR_METHODS.has(ASTUtils45.getPropertyName(callee) ?? "");
|
|
16444
16810
|
return isCombinator || isZodCall(node);
|
|
16445
16811
|
}
|
|
16446
16812
|
function closesOverNothing(node, enclosing) {
|
|
@@ -16513,10 +16879,10 @@ var prefer_module_level_schema_default = createRule({
|
|
|
16513
16879
|
return;
|
|
16514
16880
|
}
|
|
16515
16881
|
const callee = unwrappedNodeCallee;
|
|
16516
|
-
if (
|
|
16882
|
+
if (ASTUtils45.getPropertyName(callee) === null) {
|
|
16517
16883
|
return;
|
|
16518
16884
|
}
|
|
16519
|
-
const factory =
|
|
16885
|
+
const factory = ASTUtils45.getPropertyName(callee) ?? "";
|
|
16520
16886
|
if (!factories.has(factory)) {
|
|
16521
16887
|
return;
|
|
16522
16888
|
}
|
|
@@ -16559,7 +16925,7 @@ var prefer_module_level_schema_default = createRule({
|
|
|
16559
16925
|
// src/rules/prefer-module-level-refined-schema.ts
|
|
16560
16926
|
import {
|
|
16561
16927
|
AST_NODE_TYPES as AST_NODE_TYPES82,
|
|
16562
|
-
ASTUtils as
|
|
16928
|
+
ASTUtils as ASTUtils46
|
|
16563
16929
|
} from "@typescript-eslint/utils";
|
|
16564
16930
|
var BENCHMARK_PATH_RE = /(^|[/\\])(?:benchmarks?|bench)[/\\]/;
|
|
16565
16931
|
var FACTORIES = /* @__PURE__ */ new Set([
|
|
@@ -16786,9 +17152,9 @@ function chainMemberNames(node) {
|
|
|
16786
17152
|
for (; ; ) {
|
|
16787
17153
|
current = unwrapExpression(current);
|
|
16788
17154
|
if (current.type === AST_NODE_TYPES82.MemberExpression) {
|
|
16789
|
-
if (
|
|
17155
|
+
if (ASTUtils46.getPropertyName(current) === null)
|
|
16790
17156
|
return [];
|
|
16791
|
-
names.push(
|
|
17157
|
+
names.push(ASTUtils46.getPropertyName(current) ?? "");
|
|
16792
17158
|
current = current.object;
|
|
16793
17159
|
continue;
|
|
16794
17160
|
}
|
|
@@ -16805,8 +17171,8 @@ function schemaExpression2(node) {
|
|
|
16805
17171
|
let current = node;
|
|
16806
17172
|
for (; ; ) {
|
|
16807
17173
|
const parent = current.parent ?? void 0;
|
|
16808
|
-
if (parent?.type === AST_NODE_TYPES82.MemberExpression && parent.object === current &&
|
|
16809
|
-
if (NON_SCHEMA_TERMINALS.has(
|
|
17174
|
+
if (parent?.type === AST_NODE_TYPES82.MemberExpression && parent.object === current && ASTUtils46.getPropertyName(parent) !== null && parent.parent?.type === AST_NODE_TYPES82.CallExpression && parent.parent.callee === parent) {
|
|
17175
|
+
if (NON_SCHEMA_TERMINALS.has(ASTUtils46.getPropertyName(parent) ?? "")) return current;
|
|
16810
17176
|
current = parent.parent;
|
|
16811
17177
|
continue;
|
|
16812
17178
|
}
|
|
@@ -16836,7 +17202,7 @@ var prefer_module_level_refined_schema_default = createRule({
|
|
|
16836
17202
|
return {};
|
|
16837
17203
|
const zodBindings = /* @__PURE__ */ new Set();
|
|
16838
17204
|
function resolvedBinding(identifier) {
|
|
16839
|
-
return
|
|
17205
|
+
return ASTUtils46.findVariable(
|
|
16840
17206
|
context.sourceCode.getScope(identifier),
|
|
16841
17207
|
identifier.name
|
|
16842
17208
|
);
|
|
@@ -16862,7 +17228,7 @@ var prefer_module_level_refined_schema_default = createRule({
|
|
|
16862
17228
|
function isSchemaConstruction(node) {
|
|
16863
17229
|
const callee = unwrapExpression(node.callee);
|
|
16864
17230
|
const calleeReceiver = callee.type === AST_NODE_TYPES82.MemberExpression ? unwrapExpression(callee.object) : callee;
|
|
16865
|
-
if (callee.type !== AST_NODE_TYPES82.MemberExpression ||
|
|
17231
|
+
if (callee.type !== AST_NODE_TYPES82.MemberExpression || ASTUtils46.getPropertyName(callee) === null || NON_SCHEMA_TERMINALS.has(ASTUtils46.getPropertyName(callee) ?? "")) return false;
|
|
16866
17232
|
if (calleeReceiver.type === AST_NODE_TYPES82.CallExpression) return isSchemaConstruction(calleeReceiver);
|
|
16867
17233
|
return factoryName(node, FACTORIES) !== null || factoryName(node, COMPOSITE_FACTORIES) !== null;
|
|
16868
17234
|
}
|
|
@@ -16889,7 +17255,7 @@ var prefer_module_level_refined_schema_default = createRule({
|
|
|
16889
17255
|
function isMemoized(node) {
|
|
16890
17256
|
let current = node.parent ?? void 0;
|
|
16891
17257
|
while (current !== void 0) {
|
|
16892
|
-
if (current.type === AST_NODE_TYPES82.CallExpression && (current.callee.type === AST_NODE_TYPES82.Identifier && MEMO_CALLEES2.has(current.callee.name) || current.callee.type === AST_NODE_TYPES82.MemberExpression &&
|
|
17258
|
+
if (current.type === AST_NODE_TYPES82.CallExpression && (current.callee.type === AST_NODE_TYPES82.Identifier && MEMO_CALLEES2.has(current.callee.name) || current.callee.type === AST_NODE_TYPES82.MemberExpression && ASTUtils46.getPropertyName(current.callee) !== null && MEMO_CALLEES2.has(ASTUtils46.getPropertyName(current.callee) ?? "")))
|
|
16893
17259
|
return true;
|
|
16894
17260
|
current = current.parent ?? void 0;
|
|
16895
17261
|
}
|
|
@@ -16952,7 +17318,7 @@ var prefer_module_level_refined_schema_default = createRule({
|
|
|
16952
17318
|
// src/rules/prefer-multi-value-zod-literal.ts
|
|
16953
17319
|
import {
|
|
16954
17320
|
AST_NODE_TYPES as AST_NODE_TYPES83,
|
|
16955
|
-
ASTUtils as
|
|
17321
|
+
ASTUtils as ASTUtils47
|
|
16956
17322
|
} from "@typescript-eslint/utils";
|
|
16957
17323
|
var PREFER_MULTI_VALUE_ZOD_LITERAL_DOCUMENTATION = {
|
|
16958
17324
|
defaultLevel: "warning",
|
|
@@ -17001,7 +17367,7 @@ function isStaticPrimitive(node, context) {
|
|
|
17001
17367
|
if (node.type === AST_NODE_TYPES83.TemplateLiteral && node.expressions.length === 0)
|
|
17002
17368
|
return true;
|
|
17003
17369
|
if (node.type === AST_NODE_TYPES83.Identifier && node.name === "undefined") {
|
|
17004
|
-
const binding =
|
|
17370
|
+
const binding = ASTUtils47.findVariable(
|
|
17005
17371
|
context.sourceCode.getScope(node),
|
|
17006
17372
|
node.name
|
|
17007
17373
|
);
|
|
@@ -17039,7 +17405,7 @@ var prefer_multi_value_zod_literal_default = createRule({
|
|
|
17039
17405
|
const zodBindings = /* @__PURE__ */ new Set();
|
|
17040
17406
|
const zod4Bindings = /* @__PURE__ */ new Set();
|
|
17041
17407
|
function resolvedBinding(identifier) {
|
|
17042
|
-
return
|
|
17408
|
+
return ASTUtils47.findVariable(
|
|
17043
17409
|
context.sourceCode.getScope(identifier),
|
|
17044
17410
|
identifier.name
|
|
17045
17411
|
);
|
|
@@ -17047,7 +17413,7 @@ var prefer_multi_value_zod_literal_default = createRule({
|
|
|
17047
17413
|
function directMemberCall(node, binding, method) {
|
|
17048
17414
|
const unwrappedNodeCallee = unwrapExpression(node.callee);
|
|
17049
17415
|
const receiver = unwrappedNodeCallee.type === AST_NODE_TYPES83.MemberExpression ? unwrapExpression(unwrappedNodeCallee.object) : unwrappedNodeCallee;
|
|
17050
|
-
if (unwrappedNodeCallee.type !== AST_NODE_TYPES83.MemberExpression || receiver.type !== AST_NODE_TYPES83.Identifier ||
|
|
17416
|
+
if (unwrappedNodeCallee.type !== AST_NODE_TYPES83.MemberExpression || receiver.type !== AST_NODE_TYPES83.Identifier || ASTUtils47.getPropertyName(unwrappedNodeCallee) === null || (ASTUtils47.getPropertyName(unwrappedNodeCallee) ?? "") !== method)
|
|
17051
17417
|
return false;
|
|
17052
17418
|
return resolvedBinding(receiver) === binding;
|
|
17053
17419
|
}
|
|
@@ -17097,7 +17463,7 @@ var prefer_multi_value_zod_literal_default = createRule({
|
|
|
17097
17463
|
});
|
|
17098
17464
|
|
|
17099
17465
|
// src/rules/prefer-nominal-id-types.ts
|
|
17100
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES84, ASTUtils as
|
|
17466
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES84, ASTUtils as ASTUtils48 } from "@typescript-eslint/utils";
|
|
17101
17467
|
var OPERATIONAL_ROLES = /* @__PURE__ */ new Set([
|
|
17102
17468
|
"request",
|
|
17103
17469
|
"trace",
|
|
@@ -17135,7 +17501,7 @@ function isNullish(node) {
|
|
|
17135
17501
|
}
|
|
17136
17502
|
function referenceCarrier(node, context, depth) {
|
|
17137
17503
|
if (node.typeName.type !== AST_NODE_TYPES84.Identifier) return void 0;
|
|
17138
|
-
const variable =
|
|
17504
|
+
const variable = ASTUtils48.findVariable(context.sourceCode.getScope(node), node.typeName.name);
|
|
17139
17505
|
const definitions = variable?.defs ?? [];
|
|
17140
17506
|
const args = node.typeArguments?.params;
|
|
17141
17507
|
if (definitions.length === 0 && ["Array", "ReadonlyArray"].includes(node.typeName.name) && args?.length === 1) {
|
|
@@ -17333,7 +17699,7 @@ var prefer_named_complex_return_type_default = createRule({
|
|
|
17333
17699
|
});
|
|
17334
17700
|
|
|
17335
17701
|
// src/rules/prefer-native-random-uuid.ts
|
|
17336
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES87, ASTUtils as
|
|
17702
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES87, ASTUtils as ASTUtils49 } from "@typescript-eslint/utils";
|
|
17337
17703
|
var PREFER_NATIVE_RANDOM_UUID_DOCUMENTATION = {
|
|
17338
17704
|
summary: "Prefer `globalThis.crypto.randomUUID()` over resolved zero-argument UUID v4 bindings from the `uuid` package.",
|
|
17339
17705
|
rationale: "The platform implementation avoids an unnecessary dependency for standard random UUID generation.",
|
|
@@ -17369,14 +17735,14 @@ var prefer_native_random_uuid_default = createRule({
|
|
|
17369
17735
|
const directBindings = /* @__PURE__ */ new Set();
|
|
17370
17736
|
const namespaceBindings = /* @__PURE__ */ new Set();
|
|
17371
17737
|
function resolve2(identifier) {
|
|
17372
|
-
return
|
|
17738
|
+
return ASTUtils49.findVariable(context.sourceCode.getScope(identifier), identifier.name);
|
|
17373
17739
|
}
|
|
17374
17740
|
function record(identifier, destination) {
|
|
17375
17741
|
const variable = resolve2(identifier);
|
|
17376
17742
|
if (variable !== null) destination.add(variable);
|
|
17377
17743
|
}
|
|
17378
17744
|
function report2(node) {
|
|
17379
|
-
const globalBinding =
|
|
17745
|
+
const globalBinding = ASTUtils49.findVariable(context.sourceCode.getScope(node), "globalThis");
|
|
17380
17746
|
const canSuggest = (globalBinding?.defs.length ?? 0) === 0 && context.sourceCode.getCommentsInside(node).length === 0;
|
|
17381
17747
|
context.report({
|
|
17382
17748
|
node,
|
|
@@ -17435,7 +17801,7 @@ var prefer_native_random_uuid_default = createRule({
|
|
|
17435
17801
|
});
|
|
17436
17802
|
|
|
17437
17803
|
// src/rules/prefer-node-crypto-hash.ts
|
|
17438
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES88, ASTUtils as
|
|
17804
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES88, ASTUtils as ASTUtils50 } from "@typescript-eslint/utils";
|
|
17439
17805
|
var PREFER_NODE_CRYPTO_HASH_DOCUMENTATION = {
|
|
17440
17806
|
defaultLevel: "warning",
|
|
17441
17807
|
summary: "Prefer the modern one-shot node:crypto hash API when streaming state is unnecessary.",
|
|
@@ -17463,7 +17829,7 @@ function isCryptoLoader(node, resolve2) {
|
|
|
17463
17829
|
if (unwrappedNodeCallee?.type === AST_NODE_TYPES88.Identifier) {
|
|
17464
17830
|
return unwrappedNodeCallee.name === "require" && isUnshadowedBuiltinIdentifier(unwrappedNodeCallee, resolve2);
|
|
17465
17831
|
}
|
|
17466
|
-
return unwrappedNodeCallee?.type === AST_NODE_TYPES88.MemberExpression && unwrappedNodeCallee.object.type === AST_NODE_TYPES88.Identifier && unwrappedNodeCallee.object.name === "process" && isUnshadowedBuiltinIdentifier(unwrappedNodeCallee.object, resolve2) &&
|
|
17832
|
+
return unwrappedNodeCallee?.type === AST_NODE_TYPES88.MemberExpression && unwrappedNodeCallee.object.type === AST_NODE_TYPES88.Identifier && unwrappedNodeCallee.object.name === "process" && isUnshadowedBuiltinIdentifier(unwrappedNodeCallee.object, resolve2) && ASTUtils50.getPropertyName(unwrappedNodeCallee) === "getBuiltinModule";
|
|
17467
17833
|
}
|
|
17468
17834
|
function isCryptoSpecifier(node) {
|
|
17469
17835
|
return node.type === AST_NODE_TYPES88.Literal && (node.value === "crypto" || node.value === "node:crypto");
|
|
@@ -17488,7 +17854,7 @@ var prefer_node_crypto_hash_default = createRule({
|
|
|
17488
17854
|
const directBindings = /* @__PURE__ */ new Set();
|
|
17489
17855
|
const namespaceBindings = /* @__PURE__ */ new Set();
|
|
17490
17856
|
function resolve2(identifier) {
|
|
17491
|
-
return
|
|
17857
|
+
return ASTUtils50.findVariable(
|
|
17492
17858
|
context.sourceCode.getScope(identifier),
|
|
17493
17859
|
identifier.name
|
|
17494
17860
|
);
|
|
@@ -17550,7 +17916,7 @@ function importedName5(node) {
|
|
|
17550
17916
|
}
|
|
17551
17917
|
function isMemberCall(node, name) {
|
|
17552
17918
|
const unwrappedNodeCallee = unwrapExpression(node.callee);
|
|
17553
|
-
return unwrappedNodeCallee.type === AST_NODE_TYPES88.MemberExpression &&
|
|
17919
|
+
return unwrappedNodeCallee.type === AST_NODE_TYPES88.MemberExpression && ASTUtils50.getPropertyName(unwrappedNodeCallee) === name;
|
|
17554
17920
|
}
|
|
17555
17921
|
function isCreateHashCall(node, directBindings, namespaceBindings, resolve2) {
|
|
17556
17922
|
const unwrappedNodeCallee = unwrapExpression(node.callee);
|
|
@@ -17558,7 +17924,7 @@ function isCreateHashCall(node, directBindings, namespaceBindings, resolve2) {
|
|
|
17558
17924
|
const variable2 = resolve2(unwrappedNodeCallee);
|
|
17559
17925
|
return variable2 !== null && directBindings.has(variable2);
|
|
17560
17926
|
}
|
|
17561
|
-
if (unwrappedNodeCallee.type !== AST_NODE_TYPES88.MemberExpression ||
|
|
17927
|
+
if (unwrappedNodeCallee.type !== AST_NODE_TYPES88.MemberExpression || ASTUtils50.getPropertyName(unwrappedNodeCallee) !== "createHash") {
|
|
17562
17928
|
return false;
|
|
17563
17929
|
}
|
|
17564
17930
|
if (isCryptoLoader(unwrappedNodeCallee.object, resolve2)) return true;
|
|
@@ -17568,7 +17934,7 @@ function isCreateHashCall(node, directBindings, namespaceBindings, resolve2) {
|
|
|
17568
17934
|
}
|
|
17569
17935
|
|
|
17570
17936
|
// src/rules/prefer-node-fs-promises.ts
|
|
17571
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES89, ASTUtils as
|
|
17937
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES89, ASTUtils as ASTUtils51 } from "@typescript-eslint/utils";
|
|
17572
17938
|
var PREFER_NODE_FS_PROMISES_DOCUMENTATION = {
|
|
17573
17939
|
defaultLevel: "warning",
|
|
17574
17940
|
summary: "Prefer promise-based Node.js filesystem APIs over synchronous calls in production modules.",
|
|
@@ -17630,7 +17996,7 @@ var prefer_node_fs_promises_default = createRule({
|
|
|
17630
17996
|
if (isTestFile(context.filename) || isGeneratedFile(context.filename, context.sourceCode.text) || normalizedFilename.includes("src/rules/"))
|
|
17631
17997
|
return {};
|
|
17632
17998
|
const namespaces = /* @__PURE__ */ new Set();
|
|
17633
|
-
const bindingOf = (node) =>
|
|
17999
|
+
const bindingOf = (node) => ASTUtils51.findVariable(context.sourceCode.getScope(node), node.name);
|
|
17634
18000
|
const isGlobal = (node) => {
|
|
17635
18001
|
const binding = bindingOf(node);
|
|
17636
18002
|
return binding === null || binding.defs.length === 0;
|
|
@@ -17696,7 +18062,7 @@ var prefer_node_fs_promises_default = createRule({
|
|
|
17696
18062
|
});
|
|
17697
18063
|
|
|
17698
18064
|
// src/rules/prefer-non-nullable-collection.ts
|
|
17699
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES90, ASTUtils as
|
|
18065
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES90, ASTUtils as ASTUtils52 } from "@typescript-eslint/utils";
|
|
17700
18066
|
var PREFER_NON_NULLABLE_COLLECTION_DOCUMENTATION = {
|
|
17701
18067
|
summary: "Suggest reviewing nullish arrays that use local empty-array defaults or a shared null-or-empty guard.",
|
|
17702
18068
|
rationale: "A redundant nullish collection state spreads defaults and guards through consumers without carrying information.",
|
|
@@ -17821,14 +18187,14 @@ function directlyCoalesced(node) {
|
|
|
17821
18187
|
return parent?.type === AST_NODE_TYPES90.LogicalExpression && parent.left === node && (parent.operator === "??" || parent.operator === "||") && emptyArray(parent.right);
|
|
17822
18188
|
}
|
|
17823
18189
|
function identifierIsOnlyCoalesced(context, binding, fn) {
|
|
17824
|
-
const variable =
|
|
18190
|
+
const variable = ASTUtils52.findVariable(context.sourceCode.getScope(binding), binding.name);
|
|
17825
18191
|
if (variable === null || variable.references.length === 0) return false;
|
|
17826
18192
|
return variable.references.every(
|
|
17827
18193
|
(reference) => belongsToFunction(reference.identifier, fn) && directlyCoalesced(reference.identifier)
|
|
17828
18194
|
);
|
|
17829
18195
|
}
|
|
17830
18196
|
function memberIsOnlyCoalesced(context, object, property, fn) {
|
|
17831
|
-
const variable =
|
|
18197
|
+
const variable = ASTUtils52.findVariable(context.sourceCode.getScope(object), object.name);
|
|
17832
18198
|
if (variable === null) return false;
|
|
17833
18199
|
const accesses = variable.references.flatMap((reference) => {
|
|
17834
18200
|
if (!belongsToFunction(reference.identifier, fn)) return [null];
|
|
@@ -17896,7 +18262,7 @@ var prefer_non_nullable_collection_default = createRule({
|
|
|
17896
18262
|
function checkDestructuredProperties(parameter, properties) {
|
|
17897
18263
|
for (const property of properties) {
|
|
17898
18264
|
const bindingProperty = parameter.properties.find(
|
|
17899
|
-
(entry) => entry.type === AST_NODE_TYPES90.Property && !entry.computed &&
|
|
18265
|
+
(entry) => entry.type === AST_NODE_TYPES90.Property && !entry.computed && ASTUtils52.getPropertyName(entry) === property.name
|
|
17900
18266
|
);
|
|
17901
18267
|
if (bindingProperty === void 0) continue;
|
|
17902
18268
|
const value = bindingProperty.value;
|
|
@@ -17944,7 +18310,7 @@ var prefer_non_nullable_collection_default = createRule({
|
|
|
17944
18310
|
// src/rules/prefer-nullish-filter-predicate.ts
|
|
17945
18311
|
import {
|
|
17946
18312
|
AST_NODE_TYPES as AST_NODE_TYPES91,
|
|
17947
|
-
ASTUtils as
|
|
18313
|
+
ASTUtils as ASTUtils53,
|
|
17948
18314
|
ESLintUtils as ESLintUtils12
|
|
17949
18315
|
} from "@typescript-eslint/utils";
|
|
17950
18316
|
import ts10 from "typescript";
|
|
@@ -17990,7 +18356,7 @@ var PREFER_NULLISH_FILTER_PREDICATE_DOCUMENTATION = {
|
|
|
17990
18356
|
]
|
|
17991
18357
|
};
|
|
17992
18358
|
function isUnshadowedBoolean(node, context) {
|
|
17993
|
-
const variable =
|
|
18359
|
+
const variable = ASTUtils53.findVariable(context.sourceCode.getScope(node), node.name);
|
|
17994
18360
|
return variable === null || variable.defs.length === 0;
|
|
17995
18361
|
}
|
|
17996
18362
|
function isBuiltinArrayFilter(node, services) {
|
|
@@ -18049,7 +18415,7 @@ function isProvablyTruthy(type, checker) {
|
|
|
18049
18415
|
}
|
|
18050
18416
|
function availableParameterName(node, context) {
|
|
18051
18417
|
for (const name of ["value", "item", "element", "candidate"]) {
|
|
18052
|
-
if (
|
|
18418
|
+
if (ASTUtils53.findVariable(context.sourceCode.getScope(node), name) === null) return name;
|
|
18053
18419
|
}
|
|
18054
18420
|
return null;
|
|
18055
18421
|
}
|
|
@@ -18080,7 +18446,7 @@ var prefer_nullish_filter_predicate_default = createRule({
|
|
|
18080
18446
|
CallExpression(node) {
|
|
18081
18447
|
const callee = unwrapExpression(node.callee);
|
|
18082
18448
|
const callback = node.arguments[0] === void 0 ? void 0 : unwrapExpression(node.arguments[0]);
|
|
18083
|
-
if (node.arguments.length !== 1 || callback?.type !== AST_NODE_TYPES91.Identifier || callback.name !== "Boolean" || callee.type !== AST_NODE_TYPES91.MemberExpression ||
|
|
18449
|
+
if (node.arguments.length !== 1 || callback?.type !== AST_NODE_TYPES91.Identifier || callback.name !== "Boolean" || callee.type !== AST_NODE_TYPES91.MemberExpression || ASTUtils53.getPropertyName(callee) === null || (ASTUtils53.getPropertyName(callee) ?? "") !== "filter" || !isUnshadowedBoolean(callback, context) || !isBuiltinArrayFilter(callee, services)) return;
|
|
18084
18450
|
const elementType = arrayElementType(callee.object, services);
|
|
18085
18451
|
const checker = services.program.getTypeChecker();
|
|
18086
18452
|
if (elementType === null || !isNullishPlusTruthy(elementType, checker)) return;
|
|
@@ -18103,7 +18469,7 @@ var prefer_nullish_filter_predicate_default = createRule({
|
|
|
18103
18469
|
|
|
18104
18470
|
// src/rules/prefer-await-in-async-return.ts
|
|
18105
18471
|
import {
|
|
18106
|
-
ASTUtils as
|
|
18472
|
+
ASTUtils as ASTUtils54,
|
|
18107
18473
|
ESLintUtils as ESLintUtils13,
|
|
18108
18474
|
AST_NODE_TYPES as AST_NODE_TYPES92
|
|
18109
18475
|
} from "@typescript-eslint/utils";
|
|
@@ -18166,7 +18532,7 @@ function isRuntimeFunction(node) {
|
|
|
18166
18532
|
}
|
|
18167
18533
|
function promiseThenReceiver(node) {
|
|
18168
18534
|
const callee = unwrapExpression(node.callee);
|
|
18169
|
-
if (callee.type !== AST_NODE_TYPES92.MemberExpression || callee.optional ||
|
|
18535
|
+
if (callee.type !== AST_NODE_TYPES92.MemberExpression || callee.optional || ASTUtils54.getPropertyName(callee) === null || (ASTUtils54.getPropertyName(callee) ?? "") !== "then" || node.optional || node.arguments.length !== 1) {
|
|
18170
18536
|
return null;
|
|
18171
18537
|
}
|
|
18172
18538
|
const argument = node.arguments[0];
|
|
@@ -18236,7 +18602,7 @@ var prefer_await_in_async_return_default = createRule({
|
|
|
18236
18602
|
if (services === null) return {};
|
|
18237
18603
|
const frameworkLoaders = /* @__PURE__ */ new Set();
|
|
18238
18604
|
const rememberFrameworkLoader = (identifier) => {
|
|
18239
|
-
const variable =
|
|
18605
|
+
const variable = ASTUtils54.findVariable(context.sourceCode.getScope(identifier), identifier.name);
|
|
18240
18606
|
if (variable !== null) frameworkLoaders.add(variable);
|
|
18241
18607
|
};
|
|
18242
18608
|
const isFrameworkLoaderCallback = (owner) => {
|
|
@@ -18244,7 +18610,7 @@ var prefer_await_in_async_return_default = createRule({
|
|
|
18244
18610
|
if (parent === null || parent.arguments[0] !== outerExpression(owner)) return false;
|
|
18245
18611
|
const callee = unwrapExpression(parent.callee);
|
|
18246
18612
|
if (callee.type !== AST_NODE_TYPES92.Identifier) return false;
|
|
18247
|
-
const variable =
|
|
18613
|
+
const variable = ASTUtils54.findVariable(context.sourceCode.getScope(callee), callee.name);
|
|
18248
18614
|
return variable !== null && frameworkLoaders.has(variable);
|
|
18249
18615
|
};
|
|
18250
18616
|
return {
|
|
@@ -18281,7 +18647,7 @@ var prefer_await_in_async_return_default = createRule({
|
|
|
18281
18647
|
});
|
|
18282
18648
|
|
|
18283
18649
|
// src/rules/prefer-schema-for-api-payload.ts
|
|
18284
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES93, ASTUtils as
|
|
18650
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES93, ASTUtils as ASTUtils55 } from "@typescript-eslint/utils";
|
|
18285
18651
|
var PREFER_SCHEMA_FOR_API_PAYLOAD_DOCUMENTATION = {
|
|
18286
18652
|
summary: "Require Zod (or similar) schema validation on `response.json()` / `JSON.parse()` results before property access.",
|
|
18287
18653
|
rationale: "External JSON is untrusted at runtime even when its expected TypeScript shape is known statically.",
|
|
@@ -18318,7 +18684,7 @@ var PROMISE_CHAIN_METHODS = /* @__PURE__ */ new Set([
|
|
|
18318
18684
|
]);
|
|
18319
18685
|
var isSchemaParseReference = (node) => {
|
|
18320
18686
|
const inner = unwrap5(node);
|
|
18321
|
-
return inner !== null && inner.type === AST_NODE_TYPES93.MemberExpression &&
|
|
18687
|
+
return inner !== null && inner.type === AST_NODE_TYPES93.MemberExpression && ASTUtils55.getPropertyName(inner) !== null && ((ASTUtils55.getPropertyName(inner) ?? "") === "parse" || (ASTUtils55.getPropertyName(inner) ?? "") === "safeParse");
|
|
18322
18688
|
};
|
|
18323
18689
|
var isRawPayloadSource = (node, context, isKnownLocalText) => {
|
|
18324
18690
|
let current = unwrap5(node);
|
|
@@ -18333,7 +18699,7 @@ var isRawPayloadSource = (node, context, isKnownLocalText) => {
|
|
|
18333
18699
|
if (callee === null || callee.type !== AST_NODE_TYPES93.MemberExpression) {
|
|
18334
18700
|
return false;
|
|
18335
18701
|
}
|
|
18336
|
-
const property =
|
|
18702
|
+
const property = ASTUtils55.getPropertyName(callee);
|
|
18337
18703
|
if (property === null) {
|
|
18338
18704
|
return false;
|
|
18339
18705
|
}
|
|
@@ -18345,19 +18711,19 @@ var isRawPayloadSource = (node, context, isKnownLocalText) => {
|
|
|
18345
18711
|
}
|
|
18346
18712
|
const object = unwrap5(callee.object);
|
|
18347
18713
|
const input = unwrap5(current.arguments[0]);
|
|
18348
|
-
if (input?.type === AST_NODE_TYPES93.CallExpression && input.arguments.length === 1 && input.callee.type === AST_NODE_TYPES93.MemberExpression && input.callee.object.type === AST_NODE_TYPES93.Identifier && input.callee.object.name === "JSON" &&
|
|
18349
|
-
return property === "parse" && object !== null && object.type === AST_NODE_TYPES93.Identifier && object.name === "JSON" && (
|
|
18714
|
+
if (input?.type === AST_NODE_TYPES93.CallExpression && input.arguments.length === 1 && input.callee.type === AST_NODE_TYPES93.MemberExpression && input.callee.object.type === AST_NODE_TYPES93.Identifier && input.callee.object.name === "JSON" && ASTUtils55.getPropertyName(input.callee) === "stringify" && (ASTUtils55.findVariable(context.sourceCode.getScope(input.callee.object), "JSON")?.defs.length ?? 0) === 0) return false;
|
|
18715
|
+
return property === "parse" && object !== null && object.type === AST_NODE_TYPES93.Identifier && object.name === "JSON" && (ASTUtils55.findVariable(context.sourceCode.getScope(object), "JSON")?.defs.length ?? 0) === 0 && !isLocalFileRead(current.arguments[0]) && isKnownLocalText?.(current.arguments[0]) !== true;
|
|
18350
18716
|
};
|
|
18351
18717
|
var isResponseSource = (node, context, seen = /* @__PURE__ */ new Set()) => {
|
|
18352
18718
|
let current = unwrap5(node);
|
|
18353
18719
|
if (current?.type === AST_NODE_TYPES93.AwaitExpression) current = unwrap5(current.argument);
|
|
18354
18720
|
if (current === null || seen.has(current)) return false;
|
|
18355
18721
|
seen.add(current);
|
|
18356
|
-
const isGlobal = (identifier) => (
|
|
18722
|
+
const isGlobal = (identifier) => (ASTUtils55.findVariable(context.sourceCode.getScope(identifier), identifier.name)?.defs.length ?? 0) === 0;
|
|
18357
18723
|
if (current.type === AST_NODE_TYPES93.CallExpression) return current.callee.type === AST_NODE_TYPES93.Identifier && current.callee.name === "fetch" && isGlobal(current.callee);
|
|
18358
18724
|
if (current.type === AST_NODE_TYPES93.NewExpression) return current.callee.type === AST_NODE_TYPES93.Identifier && ["Request", "Response"].includes(current.callee.name) && isGlobal(current.callee);
|
|
18359
18725
|
if (current.type !== AST_NODE_TYPES93.Identifier) return false;
|
|
18360
|
-
const binding =
|
|
18726
|
+
const binding = ASTUtils55.findVariable(context.sourceCode.getScope(current), current.name);
|
|
18361
18727
|
if (binding?.defs.length !== 1 || binding.references.some((reference) => reference.isWrite() && reference.init !== true)) return false;
|
|
18362
18728
|
const definition = binding.defs[0];
|
|
18363
18729
|
const annotation = definition?.name.type === AST_NODE_TYPES93.Identifier ? definition.name.typeAnnotation?.typeAnnotation : void 0;
|
|
@@ -18372,7 +18738,7 @@ var isDirectLocalFileRead = (node) => {
|
|
|
18372
18738
|
}
|
|
18373
18739
|
if (current?.type !== AST_NODE_TYPES93.CallExpression) return false;
|
|
18374
18740
|
const callee = unwrap5(current.callee);
|
|
18375
|
-
const name = callee?.type === AST_NODE_TYPES93.Identifier ? callee.name : callee?.type === AST_NODE_TYPES93.MemberExpression &&
|
|
18741
|
+
const name = callee?.type === AST_NODE_TYPES93.Identifier ? callee.name : callee?.type === AST_NODE_TYPES93.MemberExpression && ASTUtils55.getPropertyName(callee) !== null ? ASTUtils55.getPropertyName(callee) ?? "" : null;
|
|
18376
18742
|
return name !== null && FILE_READ_RE.test(name);
|
|
18377
18743
|
};
|
|
18378
18744
|
var isLocalFileRead = (node) => {
|
|
@@ -18433,7 +18799,7 @@ var isValidationRead = (node) => {
|
|
|
18433
18799
|
return false;
|
|
18434
18800
|
}
|
|
18435
18801
|
const callee = parent.callee;
|
|
18436
|
-
if (callee.type === AST_NODE_TYPES93.MemberExpression && callee.object.type === AST_NODE_TYPES93.Identifier && callee.object.name === "Array" &&
|
|
18802
|
+
if (callee.type === AST_NODE_TYPES93.MemberExpression && callee.object.type === AST_NODE_TYPES93.Identifier && callee.object.name === "Array" && ASTUtils55.getPropertyName(callee) === "isArray") {
|
|
18437
18803
|
return parent.arguments.length === 1;
|
|
18438
18804
|
}
|
|
18439
18805
|
return callee.type === AST_NODE_TYPES93.Identifier && GUARD_NAME_RE.test(callee.name);
|
|
@@ -18461,11 +18827,11 @@ var bindingValidationPolarity = (test, bindingName) => {
|
|
|
18461
18827
|
}
|
|
18462
18828
|
return test.operator === "!==" || test.operator === "!=" ? "valid-when-false" : null;
|
|
18463
18829
|
}
|
|
18464
|
-
return test.type === AST_NODE_TYPES93.CallExpression && test.arguments.length === 1 && test.arguments[0]?.type === AST_NODE_TYPES93.Identifier && test.arguments[0].name === bindingName && test.callee.type === AST_NODE_TYPES93.MemberExpression && test.callee.object.type === AST_NODE_TYPES93.Identifier && test.callee.object.name === "Array" &&
|
|
18830
|
+
return test.type === AST_NODE_TYPES93.CallExpression && test.arguments.length === 1 && test.arguments[0]?.type === AST_NODE_TYPES93.Identifier && test.arguments[0].name === bindingName && test.callee.type === AST_NODE_TYPES93.MemberExpression && test.callee.object.type === AST_NODE_TYPES93.Identifier && test.callee.object.name === "Array" && ASTUtils55.getPropertyName(test.callee) === "isArray" ? "valid-when-true" : null;
|
|
18465
18831
|
};
|
|
18466
18832
|
var plainMemberAccess = (node) => {
|
|
18467
18833
|
if (node.type !== AST_NODE_TYPES93.MemberExpression || node.object.type !== AST_NODE_TYPES93.Identifier) return null;
|
|
18468
|
-
const property =
|
|
18834
|
+
const property = ASTUtils55.getPropertyName(node);
|
|
18469
18835
|
return property === null ? null : { object: node.object.name, property };
|
|
18470
18836
|
};
|
|
18471
18837
|
var isSamePlainMember = (node, access) => {
|
|
@@ -18529,7 +18895,7 @@ var memberValidationPolarity = (test, access) => {
|
|
|
18529
18895
|
}
|
|
18530
18896
|
return test.operator === "!==" || test.operator === "!=" ? "valid-when-false" : null;
|
|
18531
18897
|
}
|
|
18532
|
-
return test.type === AST_NODE_TYPES93.CallExpression && test.arguments.length === 1 && test.arguments[0] !== void 0 && test.arguments[0].type !== AST_NODE_TYPES93.SpreadElement && isSamePlainMember(test.arguments[0], access) && test.callee.type === AST_NODE_TYPES93.MemberExpression && test.callee.object.type === AST_NODE_TYPES93.Identifier && test.callee.object.name === "Array" &&
|
|
18898
|
+
return test.type === AST_NODE_TYPES93.CallExpression && test.arguments.length === 1 && test.arguments[0] !== void 0 && test.arguments[0].type !== AST_NODE_TYPES93.SpreadElement && isSamePlainMember(test.arguments[0], access) && test.callee.type === AST_NODE_TYPES93.MemberExpression && test.callee.object.type === AST_NODE_TYPES93.Identifier && test.callee.object.name === "Array" && ASTUtils55.getPropertyName(test.callee) === "isArray" ? "valid-when-true" : null;
|
|
18533
18899
|
};
|
|
18534
18900
|
var isFullyValidatedExtractedBinding = (member, source, context) => {
|
|
18535
18901
|
const isValidationReference = (identifier) => {
|
|
@@ -18812,7 +19178,7 @@ var prefer_schema_for_api_payload_default = createRule({
|
|
|
18812
19178
|
(candidate2) => localFileTextRef(candidate2, scope) !== null
|
|
18813
19179
|
)) {
|
|
18814
19180
|
const parent = node.parent;
|
|
18815
|
-
const method =
|
|
19181
|
+
const method = ASTUtils55.getPropertyName(node);
|
|
18816
19182
|
if (parent.type === AST_NODE_TYPES93.CallExpression && parent.callee === node && method !== null && (method === "parse" || method === "safeParse" || PROMISE_CHAIN_METHODS.has(method))) {
|
|
18817
19183
|
return;
|
|
18818
19184
|
}
|
|
@@ -18865,7 +19231,7 @@ function ifGuardDominates(use, branch, positive) {
|
|
|
18865
19231
|
}
|
|
18866
19232
|
|
|
18867
19233
|
// src/rules/prefer-shared-zod-enum.ts
|
|
18868
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES94, ASTUtils as
|
|
19234
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES94, ASTUtils as ASTUtils56 } from "@typescript-eslint/utils";
|
|
18869
19235
|
var PREFER_SHARED_ZOD_ENUM_DOCUMENTATION = {
|
|
18870
19236
|
defaultLevel: "warning",
|
|
18871
19237
|
summary: "Give repeated literal Zod enum domains one reusable module-level schema.",
|
|
@@ -18915,7 +19281,7 @@ var prefer_shared_zod_enum_default = createRule({
|
|
|
18915
19281
|
create(context) {
|
|
18916
19282
|
if (isTestFile(context.filename) || isGeneratedFile(context.filename, context.sourceCode.text)) return {};
|
|
18917
19283
|
const zodBindings = /* @__PURE__ */ new Set();
|
|
18918
|
-
const bindingOf = (node) =>
|
|
19284
|
+
const bindingOf = (node) => ASTUtils56.findVariable(context.sourceCode.getScope(node), node.name);
|
|
18919
19285
|
const candidates = /* @__PURE__ */ new Map();
|
|
18920
19286
|
return {
|
|
18921
19287
|
ImportDeclaration(node) {
|
|
@@ -18930,7 +19296,7 @@ var prefer_shared_zod_enum_default = createRule({
|
|
|
18930
19296
|
CallExpression(node) {
|
|
18931
19297
|
const unwrappedNodeCallee = unwrapExpression(node.callee);
|
|
18932
19298
|
const receiver = unwrappedNodeCallee.type === AST_NODE_TYPES94.MemberExpression ? unwrapExpression(unwrappedNodeCallee.object) : unwrappedNodeCallee;
|
|
18933
|
-
if (unwrappedNodeCallee.type !== AST_NODE_TYPES94.MemberExpression || receiver.type !== AST_NODE_TYPES94.Identifier ||
|
|
19299
|
+
if (unwrappedNodeCallee.type !== AST_NODE_TYPES94.MemberExpression || receiver.type !== AST_NODE_TYPES94.Identifier || ASTUtils56.getPropertyName(unwrappedNodeCallee) === null || (ASTUtils56.getPropertyName(unwrappedNodeCallee) ?? "") !== "enum") return;
|
|
18934
19300
|
const binding = bindingOf(receiver);
|
|
18935
19301
|
if (binding === null || !zodBindings.has(binding)) return;
|
|
18936
19302
|
const domain = literalDomain(node);
|
|
@@ -18970,16 +19336,20 @@ var PREFER_SWITCH_FOR_REPEATED_EQUALITY_DOCUMENTATION = {
|
|
|
18970
19336
|
],
|
|
18971
19337
|
examples: [
|
|
18972
19338
|
{ id: "switch-dispatch", title: "Make finite dispatch explicit", outcome: "no-match", files: [{ path: "src/render.ts", source: "switch (kind) { case 'a': return a(); case 'b': return b(); case 'c': return c(); default: return fallback(); }" }], focusPath: "src/render.ts", expectedCount: 0, public: true },
|
|
18973
|
-
{ id: "repeated-equality", title: "Avoid repeating the discriminant", outcome: "match", files: [{ path: "src/render.ts", source: "if (kind === 'a') return a(); else if (kind === 'b') return b(); else if (kind === 'c') return c();" }], focusPath: "src/render.ts", expectedCount: 1, public: true }
|
|
19339
|
+
{ id: "repeated-equality", title: "Avoid repeating the discriminant", outcome: "match", files: [{ path: "src/render.ts", source: "if (kind === 'a') return a(); else if (kind === 'b') return b(); else if (kind === 'c') return c();" }], focusPath: "src/render.ts", expectedCount: 1, public: true },
|
|
19340
|
+
{ id: "escaped-middle", scenarioId: "native-discriminant", title: "Use native identifier identity", outcome: "match", files: [{ path: "src/dispatch.ts", source: `function probe(kind){if(kind==='a')return 1;else if(\\u006bind==='b')return 2;else if(kind==='c')return 3;return 0;}
|
|
19341
|
+
console.log(JSON.stringify(["a","b","c","d"].map(probe)));` }], focusPath: "src/dispatch.ts", expectedCount: 1, public: true },
|
|
19342
|
+
{ id: "different-discriminants", scenarioId: "native-discriminant", title: "Use native identifier identity", outcome: "no-match", files: [{ path: "src/dispatch.ts", source: `function probe(kind){const other="other";if(kind==='a')return 1;else if(other==='b')return 2;else if(kind==='c')return 3;return 0;}
|
|
19343
|
+
console.log(JSON.stringify(["a","b","c","d"].map(probe)));` }], focusPath: "src/dispatch.ts", expectedCount: 0, public: true }
|
|
18974
19344
|
]
|
|
18975
19345
|
};
|
|
18976
|
-
function
|
|
19346
|
+
function discriminantName(test) {
|
|
18977
19347
|
if (test.type !== AST_NODE_TYPES95.BinaryExpression || test.operator !== "===") return null;
|
|
18978
19348
|
const leftIsCase = isCaseValue(test.left);
|
|
18979
19349
|
const rightIsCase = isCaseValue(test.right);
|
|
18980
19350
|
if (leftIsCase === rightIsCase) return null;
|
|
18981
19351
|
const discriminant = leftIsCase ? test.right : test.left;
|
|
18982
|
-
return discriminant.type === AST_NODE_TYPES95.Identifier ?
|
|
19352
|
+
return discriminant.type === AST_NODE_TYPES95.Identifier ? discriminant.name : null;
|
|
18983
19353
|
}
|
|
18984
19354
|
function isCaseValue(node) {
|
|
18985
19355
|
if (node.type === AST_NODE_TYPES95.Literal) return true;
|
|
@@ -19003,12 +19373,12 @@ var prefer_switch_for_repeated_equality_default = createRule({
|
|
|
19003
19373
|
return {
|
|
19004
19374
|
IfStatement(node) {
|
|
19005
19375
|
if (node.parent.type === AST_NODE_TYPES95.IfStatement && node.parent.alternate === node) return;
|
|
19006
|
-
const first =
|
|
19376
|
+
const first = discriminantName(node.test);
|
|
19007
19377
|
if (first === null) return;
|
|
19008
19378
|
let count = 1;
|
|
19009
19379
|
let current = node.alternate;
|
|
19010
19380
|
while (current?.type === AST_NODE_TYPES95.IfStatement) {
|
|
19011
|
-
if (
|
|
19381
|
+
if (discriminantName(current.test) !== first) return;
|
|
19012
19382
|
count += 1;
|
|
19013
19383
|
current = current.alternate;
|
|
19014
19384
|
}
|
|
@@ -19548,7 +19918,7 @@ function packageWorkspaceGlobs(parsed) {
|
|
|
19548
19918
|
}
|
|
19549
19919
|
|
|
19550
19920
|
// src/rules/prefer-server-actions.ts
|
|
19551
|
-
import { ASTUtils as
|
|
19921
|
+
import { ASTUtils as ASTUtils57 } from "@typescript-eslint/utils";
|
|
19552
19922
|
var PREFER_SERVER_ACTIONS_DOCUMENTATION = {
|
|
19553
19923
|
summary: "Prefer Next.js Server Actions over same-origin API mutations.",
|
|
19554
19924
|
rationale: "Server Actions can remove a hand-written internal API wrapper while retaining typed application calls. Client invocations still cross a network and serialization boundary.",
|
|
@@ -19581,7 +19951,7 @@ function resolveNode(node, context) {
|
|
|
19581
19951
|
node = node == null ? node : unwrapExpression(node);
|
|
19582
19952
|
if (!node) return null;
|
|
19583
19953
|
if (node.type !== "Identifier") return node;
|
|
19584
|
-
const variable =
|
|
19954
|
+
const variable = ASTUtils57.findVariable(getScope(context, node), node.name);
|
|
19585
19955
|
const definition = variable?.defs.length === 1 ? variable.defs[0] : void 0;
|
|
19586
19956
|
if (definition?.type !== "Variable" || definition.parent.kind !== "const" || definition.node.init === null || variable?.references.some((reference) => reference.isWrite() && reference.init !== true)) return node;
|
|
19587
19957
|
if (definition.node.init.type === "ObjectExpression" && variable?.references.some((reference) => reference.identifier !== node && reference.init !== true)) return node;
|
|
@@ -19590,7 +19960,7 @@ function resolveNode(node, context) {
|
|
|
19590
19960
|
function isAxiosClient(node, context, seen = /* @__PURE__ */ new Set()) {
|
|
19591
19961
|
if (node.type !== "Identifier" || seen.has(node)) return false;
|
|
19592
19962
|
seen.add(node);
|
|
19593
|
-
const variable =
|
|
19963
|
+
const variable = ASTUtils57.findVariable(getScope(context, node), node.name);
|
|
19594
19964
|
const definition = variable?.defs.length === 1 ? variable.defs[0] : void 0;
|
|
19595
19965
|
if (definition === void 0 || variable?.references.some((reference) => reference.isWrite() && reference.init !== true)) return false;
|
|
19596
19966
|
if (variable?.references.some((reference) => {
|
|
@@ -19674,10 +20044,10 @@ function isFunctionArgument(node, context) {
|
|
|
19674
20044
|
}
|
|
19675
20045
|
function getPropertyNode(objNode, propName2) {
|
|
19676
20046
|
if (!objNode || objNode.type !== "ObjectExpression") return null;
|
|
19677
|
-
if (objNode.properties.some((property) => property.type === "SpreadElement" ||
|
|
20047
|
+
if (objNode.properties.some((property) => property.type === "SpreadElement" || ASTUtils57.getPropertyName(property) === null)) return null;
|
|
19678
20048
|
for (const prop of [...objNode.properties].reverse()) {
|
|
19679
20049
|
if (prop.type !== "Property") continue;
|
|
19680
|
-
const keyName =
|
|
20050
|
+
const keyName = ASTUtils57.getPropertyName(prop);
|
|
19681
20051
|
if (keyName === propName2) {
|
|
19682
20052
|
if (prop.value.type === "AssignmentPattern" || prop.value.type === "ArrayPattern" || prop.value.type === "ObjectPattern") {
|
|
19683
20053
|
return null;
|
|
@@ -19801,7 +20171,7 @@ var prefer_server_actions_default = createRule({
|
|
|
19801
20171
|
});
|
|
19802
20172
|
|
|
19803
20173
|
// src/rules/prefer-whole-object-assertion.ts
|
|
19804
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES97, ASTUtils as
|
|
20174
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES97, ASTUtils as ASTUtils58 } from "@typescript-eslint/utils";
|
|
19805
20175
|
var MERGEABLE_MATCHERS = /* @__PURE__ */ new Set(["toBe", "toEqual", "toStrictEqual"]);
|
|
19806
20176
|
var SYNTHETIC_LITERAL_MATCHERS = /* @__PURE__ */ new Map([
|
|
19807
20177
|
["toBeNull", "null"]
|
|
@@ -19866,7 +20236,7 @@ function propertyAccess(node) {
|
|
|
19866
20236
|
const path = [];
|
|
19867
20237
|
let current = node;
|
|
19868
20238
|
while (current.type === AST_NODE_TYPES97.MemberExpression && !current.optional) {
|
|
19869
|
-
const name =
|
|
20239
|
+
const name = ASTUtils58.getPropertyName(current);
|
|
19870
20240
|
if (name === null || COLLECTION_PROPERTIES.has(name) || LITERAL_KEY_HAZARDS.has(name)) return null;
|
|
19871
20241
|
path.unshift(name);
|
|
19872
20242
|
current = unwrapExpression(current.object);
|
|
@@ -20013,7 +20383,7 @@ var prefer_whole_object_assertion_default = createRule({
|
|
|
20013
20383
|
const callee = unwrapExpression(call.callee);
|
|
20014
20384
|
const calleeReceiver = callee.type === AST_NODE_TYPES97.MemberExpression ? unwrapExpression(callee.object) : callee;
|
|
20015
20385
|
if (callee.type !== AST_NODE_TYPES97.MemberExpression) return null;
|
|
20016
|
-
const matcher =
|
|
20386
|
+
const matcher = ASTUtils58.getPropertyName(callee);
|
|
20017
20387
|
if (matcher === null) return null;
|
|
20018
20388
|
const expectCall = calleeReceiver;
|
|
20019
20389
|
const expectCallee = expectCall.type === AST_NODE_TYPES97.CallExpression ? unwrapExpression(expectCall.callee) : null;
|
|
@@ -20043,7 +20413,7 @@ var prefer_whole_object_assertion_default = createRule({
|
|
|
20043
20413
|
return assertionExpectation(statement, call, receiver, key, matcher);
|
|
20044
20414
|
}
|
|
20045
20415
|
function isTestExpect(callee) {
|
|
20046
|
-
const variable =
|
|
20416
|
+
const variable = ASTUtils58.findVariable(sourceCode.getScope(callee), callee.name);
|
|
20047
20417
|
if (variable !== null && variable.defs.some((definition) => {
|
|
20048
20418
|
if (definition.node.type !== AST_NODE_TYPES97.ImportSpecifier) return true;
|
|
20049
20419
|
const declaration = definition.node.parent;
|
|
@@ -20086,7 +20456,7 @@ var prefer_whole_object_assertion_default = createRule({
|
|
|
20086
20456
|
});
|
|
20087
20457
|
|
|
20088
20458
|
// src/rules/repeated-static-call-cases.ts
|
|
20089
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES98, ASTUtils as
|
|
20459
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES98, ASTUtils as ASTUtils59 } from "@typescript-eslint/utils";
|
|
20090
20460
|
var REPEATED_STATIC_CALL_CASES_DOCUMENTATION = {
|
|
20091
20461
|
summary: "Review three or more consecutive static-input call assertions as potential named cases.",
|
|
20092
20462
|
rationale: "Copy-pasted cases obscure the input table, and a thrown assertion can stop later cases from being reported.",
|
|
@@ -20107,7 +20477,7 @@ var EXPECT_MODIFIERS = /* @__PURE__ */ new Set(["not", "rejects", "resolves"]);
|
|
|
20107
20477
|
var SNAPSHOT_MATCHERS = /snapshot/iu;
|
|
20108
20478
|
var MIN_CASES2 = 3;
|
|
20109
20479
|
function importedName6(identifier, context, modules) {
|
|
20110
|
-
const variable =
|
|
20480
|
+
const variable = ASTUtils59.findVariable(context.sourceCode.getScope(identifier), identifier.name);
|
|
20111
20481
|
if (variable === null || variable.defs.length === 0) return identifier.name;
|
|
20112
20482
|
for (const definition of variable.defs) {
|
|
20113
20483
|
if (definition.node.type !== AST_NODE_TYPES98.ImportSpecifier) continue;
|
|
@@ -20129,7 +20499,7 @@ function testRoot2(callee) {
|
|
|
20129
20499
|
callee = unwrapExpression(callee);
|
|
20130
20500
|
if (callee.type === AST_NODE_TYPES98.Identifier) return callee;
|
|
20131
20501
|
if (callee.type !== AST_NODE_TYPES98.MemberExpression) return null;
|
|
20132
|
-
const modifier =
|
|
20502
|
+
const modifier = ASTUtils59.getPropertyName(callee);
|
|
20133
20503
|
return modifier !== null && TEST_MODIFIERS5.has(modifier) ? testRoot2(callee.object) : null;
|
|
20134
20504
|
}
|
|
20135
20505
|
function isStatic(input) {
|
|
@@ -20175,8 +20545,8 @@ function assertionShape(statement, context, callback) {
|
|
|
20175
20545
|
const matcherCall = unwrapExpression(statement.expression);
|
|
20176
20546
|
if (matcherCall.type !== AST_NODE_TYPES98.CallExpression) return null;
|
|
20177
20547
|
const matcherCallee = unwrapExpression(matcherCall.callee);
|
|
20178
|
-
if (matcherCallee.type !== AST_NODE_TYPES98.MemberExpression ||
|
|
20179
|
-
const matcher =
|
|
20548
|
+
if (matcherCallee.type !== AST_NODE_TYPES98.MemberExpression || ASTUtils59.getPropertyName(matcherCallee) === null || matcherCall.arguments.length !== 1) return null;
|
|
20549
|
+
const matcher = ASTUtils59.getPropertyName(matcherCallee) ?? "";
|
|
20180
20550
|
if (SNAPSHOT_MATCHERS.test(matcher)) return null;
|
|
20181
20551
|
const chain = expectCallFromMatcher(matcherCallee);
|
|
20182
20552
|
const expectCallee = chain === null ? null : unwrapExpression(chain.call.callee);
|
|
@@ -20186,7 +20556,7 @@ function assertionShape(statement, context, callback) {
|
|
|
20186
20556
|
const observedCallee = observed?.type === AST_NODE_TYPES98.CallExpression ? unwrapExpression(observed.callee) : null;
|
|
20187
20557
|
if (observed?.type !== AST_NODE_TYPES98.CallExpression || observedCallee?.type !== AST_NODE_TYPES98.Identifier || observed.arguments.length === 0 || observed.arguments.some((arg) => arg.type === AST_NODE_TYPES98.SpreadElement || !isStatic(arg)) || expected?.type === AST_NODE_TYPES98.SpreadElement || expected === void 0 || !isStatic(expected)) return null;
|
|
20188
20558
|
const skeleton = `${observedCallee.name}/${observed.arguments.map((item) => staticShape(item)).join(",")}/${chain.modifiers.join(".")}/${matcher}/${staticShape(expected)}`;
|
|
20189
|
-
const binding =
|
|
20559
|
+
const binding = ASTUtils59.findVariable(context.sourceCode.getScope(observedCallee), observedCallee.name);
|
|
20190
20560
|
if (binding?.defs.some(
|
|
20191
20561
|
(definition) => definition.node.range[0] >= callback.range[0] && definition.node.range[1] <= callback.range[1]
|
|
20192
20562
|
)) return null;
|
|
@@ -20197,7 +20567,7 @@ function expectCallFromMatcher(node) {
|
|
|
20197
20567
|
const modifiers = [];
|
|
20198
20568
|
let receiver = node.object;
|
|
20199
20569
|
while (receiver.type === AST_NODE_TYPES98.MemberExpression) {
|
|
20200
|
-
const modifier =
|
|
20570
|
+
const modifier = ASTUtils59.getPropertyName(receiver);
|
|
20201
20571
|
if (modifier === null || !EXPECT_MODIFIERS.has(modifier)) return null;
|
|
20202
20572
|
modifiers.unshift(modifier);
|
|
20203
20573
|
receiver = receiver.object;
|
|
@@ -20273,7 +20643,7 @@ var repeated_static_call_cases_default = createRule({
|
|
|
20273
20643
|
});
|
|
20274
20644
|
|
|
20275
20645
|
// src/rules/prefer-zod-infer.ts
|
|
20276
|
-
import { ASTUtils as
|
|
20646
|
+
import { ASTUtils as ASTUtils60, AST_NODE_TYPES as AST_NODE_TYPES99 } from "@typescript-eslint/utils";
|
|
20277
20647
|
var PREFER_ZOD_INFER_DOCUMENTATION = {
|
|
20278
20648
|
summary: "Derive a type from its Zod schema with `z.infer` instead of hand-writing a twin declaration beside it.",
|
|
20279
20649
|
rationale: "A derived type stays synchronized when the runtime schema changes.",
|
|
@@ -20591,7 +20961,7 @@ function twinCallChain(node, zodNamespaces) {
|
|
|
20591
20961
|
while (current.type === AST_NODE_TYPES99.CallExpression) {
|
|
20592
20962
|
const callee = unwrapExpression(current.callee);
|
|
20593
20963
|
const calleeReceiver = callee.type === AST_NODE_TYPES99.MemberExpression ? unwrapExpression(callee.object) : callee;
|
|
20594
|
-
if (callee.type !== AST_NODE_TYPES99.MemberExpression ||
|
|
20964
|
+
if (callee.type !== AST_NODE_TYPES99.MemberExpression || ASTUtils60.getPropertyName(callee) === null) {
|
|
20595
20965
|
return null;
|
|
20596
20966
|
}
|
|
20597
20967
|
chain.push(current);
|
|
@@ -20604,7 +20974,7 @@ function twinCallChain(node, zodNamespaces) {
|
|
|
20604
20974
|
}
|
|
20605
20975
|
function twinMethodName(call) {
|
|
20606
20976
|
const callee = unwrapExpression(call.callee);
|
|
20607
|
-
return callee.type === AST_NODE_TYPES99.MemberExpression &&
|
|
20977
|
+
return callee.type === AST_NODE_TYPES99.MemberExpression && ASTUtils60.getPropertyName(callee) !== null ? ASTUtils60.getPropertyName(callee) ?? "" : "";
|
|
20608
20978
|
}
|
|
20609
20979
|
function twinSchemaFields(initializer, zodNamespaces) {
|
|
20610
20980
|
const chain = twinCallChain(initializer, zodNamespaces);
|
|
@@ -20619,7 +20989,7 @@ function twinSchemaFields(initializer, zodNamespaces) {
|
|
|
20619
20989
|
const fields = /* @__PURE__ */ new Map();
|
|
20620
20990
|
for (const property of shape.properties) {
|
|
20621
20991
|
if (property.type !== AST_NODE_TYPES99.Property) return null;
|
|
20622
|
-
const name =
|
|
20992
|
+
const name = ASTUtils60.getPropertyName(property);
|
|
20623
20993
|
if (name === null) return null;
|
|
20624
20994
|
fields.set(name, twinSchemaField(property.value, zodNamespaces));
|
|
20625
20995
|
}
|
|
@@ -20633,16 +21003,16 @@ function twinSchemaField(node, zodNamespaces) {
|
|
|
20633
21003
|
while (current.type === AST_NODE_TYPES99.CallExpression) {
|
|
20634
21004
|
const callee = unwrapExpression(current.callee);
|
|
20635
21005
|
const calleeReceiver = callee.type === AST_NODE_TYPES99.MemberExpression ? unwrapExpression(callee.object) : callee;
|
|
20636
|
-
if (callee.type !== AST_NODE_TYPES99.MemberExpression ||
|
|
21006
|
+
if (callee.type !== AST_NODE_TYPES99.MemberExpression || ASTUtils60.getPropertyName(callee) === null) {
|
|
20637
21007
|
break;
|
|
20638
21008
|
}
|
|
20639
21009
|
const receiver = calleeReceiver;
|
|
20640
21010
|
if (receiver.type === AST_NODE_TYPES99.Identifier && zodNamespaces.has(receiver.name)) {
|
|
20641
|
-
leaf =
|
|
21011
|
+
leaf = ASTUtils60.getPropertyName(callee) ?? "";
|
|
20642
21012
|
leafCall = current;
|
|
20643
21013
|
break;
|
|
20644
21014
|
}
|
|
20645
|
-
modifiers.push(
|
|
21015
|
+
modifiers.push(ASTUtils60.getPropertyName(callee) ?? "");
|
|
20646
21016
|
current = receiver;
|
|
20647
21017
|
}
|
|
20648
21018
|
return {
|
|
@@ -20845,7 +21215,7 @@ var prefer_zod_infer_default = createRule({
|
|
|
20845
21215
|
},
|
|
20846
21216
|
/** Records `XSchema.transform(...)` and equivalent module-level reshaping. */
|
|
20847
21217
|
"MemberExpression"(node) {
|
|
20848
|
-
if (node.object.type === AST_NODE_TYPES99.Identifier &&
|
|
21218
|
+
if (node.object.type === AST_NODE_TYPES99.Identifier && ASTUtils60.getPropertyName(node) !== null && isPreferZodInferModuleReshaper(ASTUtils60.getPropertyName(node) ?? "")) {
|
|
20849
21219
|
reshapedSchemaNames.add(node.object.name);
|
|
20850
21220
|
}
|
|
20851
21221
|
},
|
|
@@ -21003,7 +21373,7 @@ function staticFieldName(key) {
|
|
|
21003
21373
|
|
|
21004
21374
|
// src/rules/prefer-zod-parse-output-type.ts
|
|
21005
21375
|
import {
|
|
21006
|
-
ASTUtils as
|
|
21376
|
+
ASTUtils as ASTUtils61,
|
|
21007
21377
|
AST_NODE_TYPES as AST_NODE_TYPES100,
|
|
21008
21378
|
ESLintUtils as ESLintUtils14
|
|
21009
21379
|
} from "@typescript-eslint/utils";
|
|
@@ -21073,11 +21443,11 @@ function isLocalZodObjectSchema(node, namespaces) {
|
|
|
21073
21443
|
while (current.type === AST_NODE_TYPES100.CallExpression) {
|
|
21074
21444
|
const callee = unwrapExpression(current.callee);
|
|
21075
21445
|
const calleeReceiver = callee.type === AST_NODE_TYPES100.MemberExpression ? unwrapExpression(callee.object) : callee;
|
|
21076
|
-
if (callee.type !== AST_NODE_TYPES100.MemberExpression ||
|
|
21446
|
+
if (callee.type !== AST_NODE_TYPES100.MemberExpression || ASTUtils61.getPropertyName(callee) === null) {
|
|
21077
21447
|
return false;
|
|
21078
21448
|
}
|
|
21079
21449
|
if (calleeReceiver.type === AST_NODE_TYPES100.Identifier) {
|
|
21080
|
-
return namespaces.has(calleeReceiver.name) && ((
|
|
21450
|
+
return namespaces.has(calleeReceiver.name) && ((ASTUtils61.getPropertyName(callee) ?? "") === "object" || (ASTUtils61.getPropertyName(callee) ?? "") === "strictObject");
|
|
21081
21451
|
}
|
|
21082
21452
|
current = calleeReceiver;
|
|
21083
21453
|
}
|
|
@@ -21086,10 +21456,10 @@ function isLocalZodObjectSchema(node, namespaces) {
|
|
|
21086
21456
|
function zodParseCall(node) {
|
|
21087
21457
|
const callee = unwrapExpression(node.callee);
|
|
21088
21458
|
const calleeReceiver = callee.type === AST_NODE_TYPES100.MemberExpression ? unwrapExpression(callee.object) : callee;
|
|
21089
|
-
if (callee.type !== AST_NODE_TYPES100.MemberExpression || calleeReceiver.type !== AST_NODE_TYPES100.Identifier ||
|
|
21459
|
+
if (callee.type !== AST_NODE_TYPES100.MemberExpression || calleeReceiver.type !== AST_NODE_TYPES100.Identifier || ASTUtils61.getPropertyName(callee) === null) {
|
|
21090
21460
|
return null;
|
|
21091
21461
|
}
|
|
21092
|
-
const method =
|
|
21462
|
+
const method = ASTUtils61.getPropertyName(callee);
|
|
21093
21463
|
if (method !== "parse" && method !== "safeParse") return null;
|
|
21094
21464
|
return {
|
|
21095
21465
|
call: node,
|
|
@@ -21131,7 +21501,7 @@ function localParseReturnCandidates(node, sourceCode) {
|
|
|
21131
21501
|
for (const reference of variable.references) {
|
|
21132
21502
|
const identifier = reference.identifier;
|
|
21133
21503
|
const parent = identifier.parent;
|
|
21134
|
-
const output = parsed.method === "parse" ? identifier : parent.type === AST_NODE_TYPES100.MemberExpression && parent.object === identifier &&
|
|
21504
|
+
const output = parsed.method === "parse" ? identifier : parent.type === AST_NODE_TYPES100.MemberExpression && parent.object === identifier && ASTUtils61.getPropertyName(parent) !== null && (ASTUtils61.getPropertyName(parent) ?? "") === "data" ? parent : null;
|
|
21135
21505
|
if (output === null) continue;
|
|
21136
21506
|
const candidate2 = returnedOutputCandidate(parsed, output);
|
|
21137
21507
|
if (candidate2 !== null) candidates.push(candidate2);
|
|
@@ -21514,7 +21884,7 @@ var require_assert_never_default = createRule({
|
|
|
21514
21884
|
});
|
|
21515
21885
|
|
|
21516
21886
|
// src/rules/require-fetch-timeout.ts
|
|
21517
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES102, ASTUtils as
|
|
21887
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES102, ASTUtils as ASTUtils62 } from "@typescript-eslint/utils";
|
|
21518
21888
|
var REQUIRE_FETCH_TIMEOUT_DOCUMENTATION = {
|
|
21519
21889
|
summary: "Require an explicit abort signal on locally analyzable global fetch calls.",
|
|
21520
21890
|
rationale: "An unbounded request can occupy work indefinitely when an upstream stalls.",
|
|
@@ -21598,7 +21968,7 @@ var require_fetch_timeout_default = createRule({
|
|
|
21598
21968
|
}
|
|
21599
21969
|
function resolvesToGlobal(identifier) {
|
|
21600
21970
|
const scope = context.sourceCode.getScope(identifier);
|
|
21601
|
-
const variable =
|
|
21971
|
+
const variable = ASTUtils62.findVariable(scope, identifier.name);
|
|
21602
21972
|
return variable === null || variable.defs.length === 0;
|
|
21603
21973
|
}
|
|
21604
21974
|
function isGlobalFetchCall2(callee) {
|
|
@@ -21608,7 +21978,7 @@ var require_fetch_timeout_default = createRule({
|
|
|
21608
21978
|
return callee.type === AST_NODE_TYPES102.MemberExpression && !callee.computed && callee.property.type === AST_NODE_TYPES102.Identifier && callee.property.name === "fetch" && callee.object.type === AST_NODE_TYPES102.Identifier && GLOBAL_OBJECTS2.has(callee.object.name) && resolvesToGlobal(callee.object);
|
|
21609
21979
|
}
|
|
21610
21980
|
function localConstInitProvablyLacksSignal(identifier) {
|
|
21611
|
-
const variable =
|
|
21981
|
+
const variable = ASTUtils62.findVariable(
|
|
21612
21982
|
context.sourceCode.getScope(identifier),
|
|
21613
21983
|
identifier.name
|
|
21614
21984
|
);
|
|
@@ -21630,7 +22000,7 @@ var require_fetch_timeout_default = createRule({
|
|
|
21630
22000
|
function isForwardedRequest(argument) {
|
|
21631
22001
|
let value = argument;
|
|
21632
22002
|
if (value.type === AST_NODE_TYPES102.Identifier) {
|
|
21633
|
-
const binding =
|
|
22003
|
+
const binding = ASTUtils62.findVariable(context.sourceCode.getScope(value), value.name);
|
|
21634
22004
|
const definition = binding?.defs.length === 1 ? binding.defs[0] : void 0;
|
|
21635
22005
|
if (definition?.type !== "Variable" || definition.parent.kind !== "const" || definition.node.init === null || binding?.references.some((reference) => reference.isWrite() && reference.init !== true)) return false;
|
|
21636
22006
|
value = definition.node.init;
|
|
@@ -21805,7 +22175,7 @@ function exportedClasses(program, classes) {
|
|
|
21805
22175
|
}
|
|
21806
22176
|
|
|
21807
22177
|
// src/rules/require-sql-access-class.ts
|
|
21808
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES104, ASTUtils as
|
|
22178
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES104, ASTUtils as ASTUtils63 } from "@typescript-eslint/utils";
|
|
21809
22179
|
var DIRECT_EXECUTION_METHODS = /* @__PURE__ */ new Set([
|
|
21810
22180
|
"all",
|
|
21811
22181
|
"batch",
|
|
@@ -21912,7 +22282,7 @@ function databaseReceiver(node) {
|
|
|
21912
22282
|
if (node.type === AST_NODE_TYPES104.Identifier)
|
|
21913
22283
|
return DATABASE_NAMES.test(node.name);
|
|
21914
22284
|
if (node.type !== AST_NODE_TYPES104.MemberExpression) return false;
|
|
21915
|
-
const name =
|
|
22285
|
+
const name = ASTUtils63.getPropertyName(node);
|
|
21916
22286
|
return name === "DB" || name !== null && DATABASE_NAMES.test(name);
|
|
21917
22287
|
}
|
|
21918
22288
|
function databaseRootMember(node) {
|
|
@@ -21930,7 +22300,7 @@ function databaseRootMember(node) {
|
|
|
21930
22300
|
}
|
|
21931
22301
|
if (current.type === AST_NODE_TYPES104.MemberExpression) {
|
|
21932
22302
|
if (current.object.type === AST_NODE_TYPES104.ThisExpression)
|
|
21933
|
-
return
|
|
22303
|
+
return ASTUtils63.getPropertyName(current);
|
|
21934
22304
|
current = current.object;
|
|
21935
22305
|
continue;
|
|
21936
22306
|
}
|
|
@@ -21951,7 +22321,7 @@ function expressionHasDatabaseMarker(node) {
|
|
|
21951
22321
|
continue;
|
|
21952
22322
|
}
|
|
21953
22323
|
if (current.type === AST_NODE_TYPES104.MemberExpression) {
|
|
21954
|
-
const name =
|
|
22324
|
+
const name = ASTUtils63.getPropertyName(current);
|
|
21955
22325
|
if (name === "DB" || name !== null && DATABASE_NAMES.test(name))
|
|
21956
22326
|
return true;
|
|
21957
22327
|
current = current.object;
|
|
@@ -21970,7 +22340,7 @@ function expressionCallsBuilder(node) {
|
|
|
21970
22340
|
}
|
|
21971
22341
|
if (current.type === AST_NODE_TYPES104.CallExpression) {
|
|
21972
22342
|
if (current.callee.type !== AST_NODE_TYPES104.MemberExpression) return false;
|
|
21973
|
-
const name =
|
|
22343
|
+
const name = ASTUtils63.getPropertyName(current.callee);
|
|
21974
22344
|
if (name !== null && BUILDER_METHODS.has(name)) return true;
|
|
21975
22345
|
current = current.callee.object;
|
|
21976
22346
|
continue;
|
|
@@ -22021,7 +22391,7 @@ function thisRootMember(node) {
|
|
|
22021
22391
|
let current = node;
|
|
22022
22392
|
let root = null;
|
|
22023
22393
|
while (current.type === AST_NODE_TYPES104.MemberExpression) {
|
|
22024
|
-
const name =
|
|
22394
|
+
const name = ASTUtils63.getPropertyName(current);
|
|
22025
22395
|
if (name === null) return null;
|
|
22026
22396
|
root = name;
|
|
22027
22397
|
current = current.object;
|
|
@@ -22065,19 +22435,19 @@ var require_sql_access_class_default = createRule({
|
|
|
22065
22435
|
if (seen.has(node)) return false;
|
|
22066
22436
|
seen.add(node);
|
|
22067
22437
|
if (node.type === AST_NODE_TYPES104.Identifier) {
|
|
22068
|
-
const binding =
|
|
22438
|
+
const binding = ASTUtils63.findVariable(context.sourceCode.getScope(node), node.name);
|
|
22069
22439
|
if (binding?.defs.length !== 1 || binding.references.some((reference) => reference.isWrite() && reference.init !== true)) return false;
|
|
22070
22440
|
const definition = binding.defs[0];
|
|
22071
22441
|
return definition?.type === "Variable" && definition.node.init !== null && knownNonDatabase(definition.node.init, seen);
|
|
22072
22442
|
}
|
|
22073
|
-
return node.type === AST_NODE_TYPES104.NewExpression && unwrappedNodeCallee?.type === AST_NODE_TYPES104.Identifier && ["Map", "WeakMap", "URLSearchParams"].includes(unwrappedNodeCallee.name) && (
|
|
22443
|
+
return node.type === AST_NODE_TYPES104.NewExpression && unwrappedNodeCallee?.type === AST_NODE_TYPES104.Identifier && ["Map", "WeakMap", "URLSearchParams"].includes(unwrappedNodeCallee.name) && (ASTUtils63.findVariable(context.sourceCode.getScope(unwrappedNodeCallee), unwrappedNodeCallee.name)?.defs.length ?? 0) === 0;
|
|
22074
22444
|
}
|
|
22075
22445
|
return {
|
|
22076
22446
|
CallExpression(node) {
|
|
22077
22447
|
const unwrappedNodeCallee = unwrapExpression(node.callee);
|
|
22078
22448
|
if (unwrappedNodeCallee.type !== AST_NODE_TYPES104.MemberExpression)
|
|
22079
22449
|
return;
|
|
22080
|
-
const method =
|
|
22450
|
+
const method = ASTUtils63.getPropertyName(unwrappedNodeCallee);
|
|
22081
22451
|
if (knownNonDatabase(unwrappedNodeCallee.object)) return;
|
|
22082
22452
|
if (method === null || !isDatabaseOperation(method, unwrappedNodeCallee.object))
|
|
22083
22453
|
return;
|
|
@@ -22177,7 +22547,7 @@ var require_static_next_matcher_default = createRule({
|
|
|
22177
22547
|
});
|
|
22178
22548
|
|
|
22179
22549
|
// src/rules/require-use-form-default-values.ts
|
|
22180
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES106, ASTUtils as
|
|
22550
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES106, ASTUtils as ASTUtils64 } from "@typescript-eslint/utils";
|
|
22181
22551
|
var REQUIRE_USE_FORM_DEFAULT_VALUES_DOCUMENTATION = {
|
|
22182
22552
|
summary: "Require explicit form-level initialization or a field default for directly bound Controller fields.",
|
|
22183
22553
|
rationale: "React Hook Form exposes form-level defaultValues/values and field-level defaultValue as its explicit initialization mechanisms. A directly bound controlled field should not omit both mechanisms.",
|
|
@@ -22208,7 +22578,7 @@ var REQUIRE_USE_FORM_DEFAULT_VALUES_DOCUMENTATION = {
|
|
|
22208
22578
|
}
|
|
22209
22579
|
]
|
|
22210
22580
|
};
|
|
22211
|
-
function
|
|
22581
|
+
function staticPropertyName2(property) {
|
|
22212
22582
|
if (property.computed) return null;
|
|
22213
22583
|
if (property.key.type === AST_NODE_TYPES106.Identifier) return property.key.name;
|
|
22214
22584
|
if (property.key.type === AST_NODE_TYPES106.Literal && typeof property.key.value === "string") return property.key.value;
|
|
@@ -22228,7 +22598,7 @@ var require_use_form_default_values_default = createRule({
|
|
|
22228
22598
|
const imported = /* @__PURE__ */ new Map();
|
|
22229
22599
|
const uninitializedForms = /* @__PURE__ */ new Set();
|
|
22230
22600
|
const uninitializedControls = /* @__PURE__ */ new Set();
|
|
22231
|
-
const bindingNamed = (node, name) =>
|
|
22601
|
+
const bindingNamed = (node, name) => ASTUtils64.findVariable(context.sourceCode.getScope(node), name);
|
|
22232
22602
|
const bindingOf = (node) => bindingNamed(node, node.name);
|
|
22233
22603
|
const stable = (variable) => !variable.references.some((reference) => reference.isWrite() && reference.init !== true);
|
|
22234
22604
|
const importedKind = (node) => {
|
|
@@ -22257,7 +22627,7 @@ var require_use_form_default_values_default = createRule({
|
|
|
22257
22627
|
for (const property of node.properties) {
|
|
22258
22628
|
if (property.type === AST_NODE_TYPES106.SpreadElement || property.computed) return "unknown";
|
|
22259
22629
|
if (property.type !== AST_NODE_TYPES106.Property) continue;
|
|
22260
|
-
const name =
|
|
22630
|
+
const name = staticPropertyName2(property);
|
|
22261
22631
|
if (name === "defaultValues" || name === "values") initialization.set(name, !isDefinitelyUndefined(property.value));
|
|
22262
22632
|
}
|
|
22263
22633
|
return [...initialization.values()].some(Boolean) ? "initialized" : "uninitialized";
|
|
@@ -22274,7 +22644,7 @@ var require_use_form_default_values_default = createRule({
|
|
|
22274
22644
|
const variable = bindingOf(node);
|
|
22275
22645
|
return variable !== null && stable(variable) && uninitializedControls.has(variable);
|
|
22276
22646
|
}
|
|
22277
|
-
return node.type === AST_NODE_TYPES106.MemberExpression &&
|
|
22647
|
+
return node.type === AST_NODE_TYPES106.MemberExpression && ASTUtils64.getPropertyName(node) !== null && (ASTUtils64.getPropertyName(node) ?? "") === "control" && isUninitializedForm(node.object);
|
|
22278
22648
|
};
|
|
22279
22649
|
const fieldOptionsNeedDefault = (node) => {
|
|
22280
22650
|
if (node?.type !== AST_NODE_TYPES106.ObjectExpression) return false;
|
|
@@ -22283,7 +22653,7 @@ var require_use_form_default_values_default = createRule({
|
|
|
22283
22653
|
for (const property of node.properties) {
|
|
22284
22654
|
if (property.type === AST_NODE_TYPES106.SpreadElement || property.computed) return false;
|
|
22285
22655
|
if (property.type !== AST_NODE_TYPES106.Property) continue;
|
|
22286
|
-
const name =
|
|
22656
|
+
const name = staticPropertyName2(property);
|
|
22287
22657
|
if (name === "control") control = property.value;
|
|
22288
22658
|
if (name === "defaultValue") hasDefault = !isDefinitelyUndefined(property.value);
|
|
22289
22659
|
}
|
|
@@ -22299,7 +22669,7 @@ var require_use_form_default_values_default = createRule({
|
|
|
22299
22669
|
};
|
|
22300
22670
|
const trackDestructuredControl = (pattern) => {
|
|
22301
22671
|
for (const property of pattern.properties) {
|
|
22302
|
-
if (property.type !== AST_NODE_TYPES106.Property ||
|
|
22672
|
+
if (property.type !== AST_NODE_TYPES106.Property || staticPropertyName2(property) !== "control" || property.value.type !== AST_NODE_TYPES106.Identifier) continue;
|
|
22303
22673
|
const variable = bindingOf(property.value);
|
|
22304
22674
|
if (variable !== null) uninitializedControls.add(variable);
|
|
22305
22675
|
}
|
|
@@ -22330,7 +22700,7 @@ var require_use_form_default_values_default = createRule({
|
|
|
22330
22700
|
trackDestructuredControl(node.id);
|
|
22331
22701
|
return;
|
|
22332
22702
|
}
|
|
22333
|
-
if (node.id.type === AST_NODE_TYPES106.Identifier && node.init.type === AST_NODE_TYPES106.MemberExpression &&
|
|
22703
|
+
if (node.id.type === AST_NODE_TYPES106.Identifier && node.init.type === AST_NODE_TYPES106.MemberExpression && ASTUtils64.getPropertyName(node.init) !== null && (ASTUtils64.getPropertyName(node.init) ?? "") === "control" && isUninitializedForm(node.init.object)) {
|
|
22334
22704
|
const variable = bindingOf(node.id);
|
|
22335
22705
|
if (variable !== null) uninitializedControls.add(variable);
|
|
22336
22706
|
}
|
|
@@ -22423,7 +22793,7 @@ var require_use_server_in_actions_file_default = createRule({
|
|
|
22423
22793
|
// src/rules/require-zod-form-validation.ts
|
|
22424
22794
|
import {
|
|
22425
22795
|
AST_NODE_TYPES as AST_NODE_TYPES107,
|
|
22426
|
-
ASTUtils as
|
|
22796
|
+
ASTUtils as ASTUtils65
|
|
22427
22797
|
} from "@typescript-eslint/utils";
|
|
22428
22798
|
var REQUIRE_ZOD_FORM_VALIDATION_DOCUMENTATION = {
|
|
22429
22799
|
summary: "Require Zod validation (`Schema.parse(...)` / `Schema.safeParse(...)`) when reading values out of a `FormData` object.",
|
|
@@ -22471,7 +22841,7 @@ var isFormDataMethodCall = (node) => {
|
|
|
22471
22841
|
}
|
|
22472
22842
|
if (current.type !== AST_NODE_TYPES107.CallExpression) return false;
|
|
22473
22843
|
const callee = unwrapExpression(current.callee);
|
|
22474
|
-
return callee.type === AST_NODE_TYPES107.MemberExpression &&
|
|
22844
|
+
return callee.type === AST_NODE_TYPES107.MemberExpression && ASTUtils65.getPropertyName(callee) === "formData";
|
|
22475
22845
|
};
|
|
22476
22846
|
var require_zod_form_validation_default = createRule({
|
|
22477
22847
|
name: "require-zod-form-validation",
|
|
@@ -22492,7 +22862,7 @@ var require_zod_form_validation_default = createRule({
|
|
|
22492
22862
|
return {};
|
|
22493
22863
|
}
|
|
22494
22864
|
const zodBindings = /* @__PURE__ */ new Set();
|
|
22495
|
-
const resolvedBinding = (identifier) =>
|
|
22865
|
+
const resolvedBinding = (identifier) => ASTUtils65.findVariable(
|
|
22496
22866
|
context.sourceCode.getScope(identifier),
|
|
22497
22867
|
identifier.name
|
|
22498
22868
|
);
|
|
@@ -22500,7 +22870,7 @@ var require_zod_form_validation_default = createRule({
|
|
|
22500
22870
|
const callee = unwrapExpression(node.callee);
|
|
22501
22871
|
const calleeReceiver = callee.type === AST_NODE_TYPES107.MemberExpression ? unwrapExpression(callee.object) : callee;
|
|
22502
22872
|
if (callee.type !== AST_NODE_TYPES107.MemberExpression) return false;
|
|
22503
|
-
if (
|
|
22873
|
+
if (ASTUtils65.getPropertyName(callee) === null || !FORM_VALUE_METHODS.has(ASTUtils65.getPropertyName(callee) ?? "")) {
|
|
22504
22874
|
return false;
|
|
22505
22875
|
}
|
|
22506
22876
|
return isFormSourceIdentifier(calleeReceiver);
|
|
@@ -22531,7 +22901,7 @@ var require_zod_form_validation_default = createRule({
|
|
|
22531
22901
|
parent = parent.parent;
|
|
22532
22902
|
continue;
|
|
22533
22903
|
}
|
|
22534
|
-
if (parent.type === AST_NODE_TYPES107.CallExpression && parent.callee.type === AST_NODE_TYPES107.MemberExpression && parent.callee.object.type === AST_NODE_TYPES107.Identifier && parent.callee.object.name === "Object" &&
|
|
22904
|
+
if (parent.type === AST_NODE_TYPES107.CallExpression && parent.callee.type === AST_NODE_TYPES107.MemberExpression && parent.callee.object.type === AST_NODE_TYPES107.Identifier && parent.callee.object.name === "Object" && ASTUtils65.getPropertyName(parent.callee) === "fromEntries" && (resolvedBinding(parent.callee.object)?.defs.length ?? 0) === 0) {
|
|
22535
22905
|
parent = parent.parent;
|
|
22536
22906
|
continue;
|
|
22537
22907
|
}
|
|
@@ -22544,7 +22914,7 @@ var require_zod_form_validation_default = createRule({
|
|
|
22544
22914
|
if (node.type !== AST_NODE_TYPES107.CallExpression) return false;
|
|
22545
22915
|
const callee = unwrapExpression(node.callee);
|
|
22546
22916
|
const calleeReceiver = callee.type === AST_NODE_TYPES107.MemberExpression ? unwrapExpression(callee.object) : callee;
|
|
22547
|
-
if (callee.type !== AST_NODE_TYPES107.MemberExpression ||
|
|
22917
|
+
if (callee.type !== AST_NODE_TYPES107.MemberExpression || ASTUtils65.getPropertyName(callee) === null || !ZOD_PARSE_METHODS.has(ASTUtils65.getPropertyName(callee) ?? "")) {
|
|
22548
22918
|
return false;
|
|
22549
22919
|
}
|
|
22550
22920
|
const root = zodReceiverRoot(calleeReceiver);
|
|
@@ -22630,7 +23000,7 @@ var require_zod_form_validation_default = createRule({
|
|
|
22630
23000
|
};
|
|
22631
23001
|
const zodParseMethod = (call) => {
|
|
22632
23002
|
const callee = unwrapExpression(call.callee);
|
|
22633
|
-
return callee.type === AST_NODE_TYPES107.MemberExpression &&
|
|
23003
|
+
return callee.type === AST_NODE_TYPES107.MemberExpression && ASTUtils65.getPropertyName(callee) !== null ? ASTUtils65.getPropertyName(callee) ?? "" : null;
|
|
22634
23004
|
};
|
|
22635
23005
|
const isSafePrevalidationInspection = (identifier) => {
|
|
22636
23006
|
const parent = identifier.parent;
|
|
@@ -22746,7 +23116,9 @@ var STORE_INSERT_REQUIRES_ON_CONFLICT_DOCUMENTATION = {
|
|
|
22746
23116
|
limitations: ["Only the nearest statically named callable is considered; top-level inserts and anonymous callbacks are excluded. Recognized conflict syntax does not prove idempotence or concurrency safety: WHERE NOT EXISTS can race, and INSERT OR REPLACE can delete an existing row. Review unique constraints and dialect semantics manually."],
|
|
22747
23117
|
examples: [
|
|
22748
23118
|
{ id: "conflict-safe-insert", title: "Review the conflict policy for a replayed insert", outcome: "no-match", files: [{ path: "src/store.ts", source: "function seed() { db.prepare(`INSERT INTO runs (id) VALUES (?) ON CONFLICT(id) DO NOTHING`).run(); }" }], focusPath: "src/store.ts", expectedCount: 0, public: true },
|
|
22749
|
-
{ id: "bare-insert", title: "Review a bare insert in a replay-named callable", outcome: "match", files: [{ path: "src/store.ts", source: "function seed() { db.prepare(`INSERT INTO runs (id) VALUES (?)`).run(); }" }], focusPath: "src/store.ts", expectedCount: 1, public: true }
|
|
23119
|
+
{ id: "bare-insert", title: "Review a bare insert in a replay-named callable", outcome: "match", files: [{ path: "src/store.ts", source: "function seed() { db.prepare(`INSERT INTO runs (id) VALUES (?)`).run(); }" }], focusPath: "src/store.ts", expectedCount: 1, public: true },
|
|
23120
|
+
{ id: "decoded-query", scenarioId: "native-decoded-sql", title: "Inspect native-decoded query text", outcome: "match", files: [{ path: "src/page.ts", source: `function seed(){db.query("INS\\u0045RT INTO runs(id,note) VALUES(4,'new')");}` }], focusPath: "src/page.ts", expectedCount: 1, public: true },
|
|
23121
|
+
{ id: "decoded-comment-data", scenarioId: "native-decoded-sql", title: "Ignore native-decoded comment data", outcome: "no-match", files: [{ path: "src/page.ts", source: `function seed(){db.query("SELECT id FROM runs /* INS\\x45RT INTO runs(id,note) VALUES(4,'new') */");}` }], focusPath: "src/page.ts", expectedCount: 0, public: true }
|
|
22750
23122
|
]
|
|
22751
23123
|
};
|
|
22752
23124
|
var INSERT_WRITE = /\bINSERT\s+(?:OR\s+\w+\s+)?INTO\s+[\w."'`?$:@-]+\s*(?:\([^)]*\)\s*)?(?:VALUES|SELECT|DEFAULT\s+VALUES)\b/i;
|
|
@@ -22766,7 +23138,6 @@ function owningCallableName(node) {
|
|
|
22766
23138
|
}
|
|
22767
23139
|
return null;
|
|
22768
23140
|
}
|
|
22769
|
-
var INSERT_GATE = /insert/i;
|
|
22770
23141
|
var store_insert_requires_on_conflict_default = createRule({
|
|
22771
23142
|
name: "store-insert-requires-on-conflict",
|
|
22772
23143
|
documentation: STORE_INSERT_REQUIRES_ON_CONFLICT_DOCUMENTATION,
|
|
@@ -22782,7 +23153,7 @@ var store_insert_requires_on_conflict_default = createRule({
|
|
|
22782
23153
|
},
|
|
22783
23154
|
defaultOptions: [],
|
|
22784
23155
|
create(context) {
|
|
22785
|
-
if (isTestFile(context.filename)
|
|
23156
|
+
if (isTestFile(context.filename)) {
|
|
22786
23157
|
return {};
|
|
22787
23158
|
}
|
|
22788
23159
|
return createSqlListener((sql, node) => {
|
|
@@ -22805,7 +23176,7 @@ function expressionCallableName(current) {
|
|
|
22805
23176
|
}
|
|
22806
23177
|
|
|
22807
23178
|
// src/rules/stepdown.ts
|
|
22808
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES108, ASTUtils as
|
|
23179
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES108, ASTUtils as ASTUtils66 } from "@typescript-eslint/utils";
|
|
22809
23180
|
var STEPDOWN_DOCUMENTATION = {
|
|
22810
23181
|
summary: "Place a private helper below its sole direct same-scope caller.",
|
|
22811
23182
|
rationale: "Caller-first ordering lets a reader follow the main flow before descending into implementation details.",
|
|
@@ -23105,7 +23476,7 @@ function receiverOrigin(context, object, receivers) {
|
|
|
23105
23476
|
while (true) {
|
|
23106
23477
|
const unwrapped = unwrapExpression4(current);
|
|
23107
23478
|
if (unwrapped.type !== AST_NODE_TYPES108.Identifier) return unwrapped;
|
|
23108
|
-
const variable =
|
|
23479
|
+
const variable = ASTUtils66.findVariable(context.sourceCode.getScope(unwrapped), unwrapped.name);
|
|
23109
23480
|
if (variable === null) return null;
|
|
23110
23481
|
const known = receivers.get(variable);
|
|
23111
23482
|
if (known !== void 0) return known;
|
|
@@ -23286,11 +23657,11 @@ function classScope(context, node, computedReferences) {
|
|
|
23286
23657
|
function classReceiverBindings(context, node) {
|
|
23287
23658
|
const classReceivers = /* @__PURE__ */ new Map();
|
|
23288
23659
|
if (node.id !== null) {
|
|
23289
|
-
const internal =
|
|
23660
|
+
const internal = ASTUtils66.findVariable(context.sourceCode.getScope(node), node.id.name);
|
|
23290
23661
|
if (internal !== null && stableVariable(internal)) classReceivers.set(internal, true);
|
|
23291
23662
|
}
|
|
23292
23663
|
if (node.type === AST_NODE_TYPES108.ClassExpression && node.parent.type === AST_NODE_TYPES108.VariableDeclarator && node.parent.id.type === AST_NODE_TYPES108.Identifier && node.parent.parent.type === AST_NODE_TYPES108.VariableDeclaration && node.parent.parent.kind === "const") {
|
|
23293
|
-
const outer =
|
|
23664
|
+
const outer = ASTUtils66.findVariable(context.sourceCode.getScope(node.parent), node.parent.id.name);
|
|
23294
23665
|
if (outer !== null && stableVariable(outer)) classReceivers.set(outer, true);
|
|
23295
23666
|
}
|
|
23296
23667
|
return classReceivers;
|
|
@@ -23376,7 +23747,7 @@ function classMethodCounts(body2, methods) {
|
|
|
23376
23747
|
}
|
|
23377
23748
|
|
|
23378
23749
|
// src/rules/source-coupled-test.ts
|
|
23379
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES109, ASTUtils as
|
|
23750
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES109, ASTUtils as ASTUtils67 } from "@typescript-eslint/utils";
|
|
23380
23751
|
var GENERAL_SOURCE_SUFFIX_RE = /\.(?:bash|sh|ya?ml|jsonc?|toml|py|[cm]?[jt]s)$/iu;
|
|
23381
23752
|
var FS_MODULES = /* @__PURE__ */ new Set(["fs", "node:fs", "fs/promises", "node:fs/promises"]);
|
|
23382
23753
|
var FS_READERS = /* @__PURE__ */ new Set(["readFile", "readFileSync"]);
|
|
@@ -23493,7 +23864,7 @@ function createSourceCoupledRule(name, documentation, sourceSuffixRe) {
|
|
|
23493
23864
|
const scopes = [newScope()];
|
|
23494
23865
|
const reportedOrigins = /* @__PURE__ */ new Set();
|
|
23495
23866
|
const currentScope = () => scopes.at(-1) ?? scopes[0];
|
|
23496
|
-
const bindingOf = (node) =>
|
|
23867
|
+
const bindingOf = (node) => ASTUtils67.findVariable(context.sourceCode.getScope(node), node.name);
|
|
23497
23868
|
const assertionKind = (node) => {
|
|
23498
23869
|
const binding = bindingOf(node);
|
|
23499
23870
|
if (binding === null || binding.defs.length === 0) {
|
|
@@ -23546,7 +23917,7 @@ function createSourceCoupledRule(name, documentation, sourceSuffixRe) {
|
|
|
23546
23917
|
return visible("fsReaders", callee) && sourcePath(current.arguments[0]);
|
|
23547
23918
|
}
|
|
23548
23919
|
if (callee.type !== AST_NODE_TYPES109.MemberExpression) return false;
|
|
23549
|
-
const name2 =
|
|
23920
|
+
const name2 = ASTUtils67.getPropertyName(callee);
|
|
23550
23921
|
const object = unwrap6(calleeReceiver);
|
|
23551
23922
|
return name2 !== null && FS_READERS.has(name2) && object.type === AST_NODE_TYPES109.Identifier && visible("fsObjects", object) && sourcePath(current.arguments[0]);
|
|
23552
23923
|
};
|
|
@@ -23555,12 +23926,12 @@ function createSourceCoupledRule(name, documentation, sourceSuffixRe) {
|
|
|
23555
23926
|
if (current.type === AST_NODE_TYPES109.Identifier) return visibleRawOrigins(current);
|
|
23556
23927
|
if (rawRead(current)) return /* @__PURE__ */ new Set([`${current.range[0]}:${current.range[1]}`]);
|
|
23557
23928
|
if (current.type === AST_NODE_TYPES109.BinaryExpression && current.operator === "+") return /* @__PURE__ */ new Set([...rawOrigins(current.left), ...rawOrigins(current.right)]);
|
|
23558
|
-
if (current.type === AST_NODE_TYPES109.MemberExpression &&
|
|
23929
|
+
if (current.type === AST_NODE_TYPES109.MemberExpression && ASTUtils67.getPropertyName(current) === "length") return rawOrigins(current.object);
|
|
23559
23930
|
if (current.type !== AST_NODE_TYPES109.CallExpression) return /* @__PURE__ */ new Set();
|
|
23560
23931
|
const callee = unwrap6(current.callee);
|
|
23561
23932
|
const calleeReceiver = callee.type === AST_NODE_TYPES109.MemberExpression ? unwrapExpression(callee.object) : callee;
|
|
23562
23933
|
if (callee.type !== AST_NODE_TYPES109.MemberExpression) return /* @__PURE__ */ new Set();
|
|
23563
|
-
const name2 =
|
|
23934
|
+
const name2 = ASTUtils67.getPropertyName(callee);
|
|
23564
23935
|
return name2 !== null && TEXT_TRANSFORMS.has(name2) ? rawOrigins(calleeReceiver) : /* @__PURE__ */ new Set();
|
|
23565
23936
|
};
|
|
23566
23937
|
const evidenceOrigins = (node) => {
|
|
@@ -23573,7 +23944,7 @@ function createSourceCoupledRule(name, documentation, sourceSuffixRe) {
|
|
|
23573
23944
|
const callee = unwrap6(current.callee);
|
|
23574
23945
|
const calleeReceiver = callee.type === AST_NODE_TYPES109.MemberExpression ? unwrapExpression(callee.object) : callee;
|
|
23575
23946
|
if (callee.type !== AST_NODE_TYPES109.MemberExpression) return /* @__PURE__ */ new Set();
|
|
23576
|
-
const name2 =
|
|
23947
|
+
const name2 = ASTUtils67.getPropertyName(callee);
|
|
23577
23948
|
if (name2 !== null && TEXT_PREDICATES.has(name2)) return rawOrigins(calleeReceiver);
|
|
23578
23949
|
if (name2 !== null && REGEXP_PREDICATES.has(name2)) return new Set(current.arguments.flatMap((argument) => argument.type === AST_NODE_TYPES109.SpreadElement ? [] : [...rawOrigins(argument)]));
|
|
23579
23950
|
return /* @__PURE__ */ new Set();
|
|
@@ -23585,10 +23956,10 @@ function createSourceCoupledRule(name, documentation, sourceSuffixRe) {
|
|
|
23585
23956
|
return new Set(node.arguments.flatMap((argument) => argument.type === AST_NODE_TYPES109.SpreadElement ? [] : [...evidenceOrigins(argument)]));
|
|
23586
23957
|
}
|
|
23587
23958
|
if (callee.type !== AST_NODE_TYPES109.MemberExpression) return /* @__PURE__ */ new Set();
|
|
23588
|
-
const matcher =
|
|
23959
|
+
const matcher = ASTUtils67.getPropertyName(callee);
|
|
23589
23960
|
if (matcher === null) return /* @__PURE__ */ new Set();
|
|
23590
23961
|
let receiver = unwrap6(calleeReceiver);
|
|
23591
|
-
while (receiver.type === AST_NODE_TYPES109.MemberExpression && EXPECT_MODIFIERS2.has(
|
|
23962
|
+
while (receiver.type === AST_NODE_TYPES109.MemberExpression && EXPECT_MODIFIERS2.has(ASTUtils67.getPropertyName(receiver) ?? "")) receiver = unwrap6(receiver.object);
|
|
23592
23963
|
const expectCallee = receiver.type === AST_NODE_TYPES109.CallExpression ? unwrapExpression(receiver.callee) : null;
|
|
23593
23964
|
if (receiver.type === AST_NODE_TYPES109.CallExpression && expectCallee?.type === AST_NODE_TYPES109.Identifier && assertionKind(expectCallee) === "expect") {
|
|
23594
23965
|
if (!EXPECT_MATCHERS.has(matcher)) return /* @__PURE__ */ new Set();
|
|
@@ -23871,7 +24242,7 @@ var iac_source_coupled_test_default = createSourceCoupledRule(
|
|
|
23871
24242
|
// src/rules/require-pascal-case-zod-schema-name.ts
|
|
23872
24243
|
import {
|
|
23873
24244
|
AST_NODE_TYPES as AST_NODE_TYPES111,
|
|
23874
|
-
ASTUtils as
|
|
24245
|
+
ASTUtils as ASTUtils68
|
|
23875
24246
|
} from "@typescript-eslint/utils";
|
|
23876
24247
|
var REQUIRE_PASCAL_CASE_ZOD_SCHEMA_NAME_DOCUMENTATION = {
|
|
23877
24248
|
summary: "Require confirmed module-level Zod schema contracts to use PascalCase with a `Schema` suffix.",
|
|
@@ -24004,7 +24375,7 @@ var SCHEMA_RETURNING_METHODS = /* @__PURE__ */ new Set([
|
|
|
24004
24375
|
"superRefine",
|
|
24005
24376
|
"transform"
|
|
24006
24377
|
]);
|
|
24007
|
-
var terminalMethodName = (callee) =>
|
|
24378
|
+
var terminalMethodName = (callee) => ASTUtils68.getPropertyName(callee) !== null ? ASTUtils68.getPropertyName(callee) ?? "" : null;
|
|
24008
24379
|
var calleeChainRoot2 = (node) => {
|
|
24009
24380
|
let current = node;
|
|
24010
24381
|
for (; ; ) {
|
|
@@ -24029,8 +24400,8 @@ var chainMemberNames2 = (node) => {
|
|
|
24029
24400
|
for (; ; ) {
|
|
24030
24401
|
current = unwrapExpression(current);
|
|
24031
24402
|
if (current.type === AST_NODE_TYPES111.MemberExpression) {
|
|
24032
|
-
if (
|
|
24033
|
-
names.push(
|
|
24403
|
+
if (ASTUtils68.getPropertyName(current) === null) return [];
|
|
24404
|
+
names.push(ASTUtils68.getPropertyName(current) ?? "");
|
|
24034
24405
|
current = current.object;
|
|
24035
24406
|
continue;
|
|
24036
24407
|
}
|
|
@@ -24067,7 +24438,7 @@ var require_pascal_case_zod_schema_name_default = createRule({
|
|
|
24067
24438
|
const zodBindings = /* @__PURE__ */ new Set();
|
|
24068
24439
|
const schemaBindings = /* @__PURE__ */ new Set();
|
|
24069
24440
|
function resolvedBinding(identifier) {
|
|
24070
|
-
return
|
|
24441
|
+
return ASTUtils68.findVariable(
|
|
24071
24442
|
context.sourceCode.getScope(identifier),
|
|
24072
24443
|
identifier.name
|
|
24073
24444
|
);
|
|
@@ -24338,7 +24709,7 @@ var RULES = {
|
|
|
24338
24709
|
};
|
|
24339
24710
|
var meta = {
|
|
24340
24711
|
name: "@sarj/eslint-plugin",
|
|
24341
|
-
version:
|
|
24712
|
+
version: package_default.version
|
|
24342
24713
|
};
|
|
24343
24714
|
var APPLICATION_ONLY_RULES = [];
|
|
24344
24715
|
var LIBRARY_IMPORT_POLICY = ["error", {
|