@sarj/eslint-plugin 15.8.2 → 15.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +207 -94
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +223 -109
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -4718,11 +4718,11 @@ var no_offset_pagination_default = createRule({
|
|
|
4718
4718
|
// src/rules/no-positional-tuple-return.ts
|
|
4719
4719
|
var import_utils24 = require("@typescript-eslint/utils");
|
|
4720
4720
|
var noPositionalTupleReturnDocumentation = {
|
|
4721
|
-
summary: "Disallow returning a multi-field tuple from
|
|
4722
|
-
rationale: "
|
|
4721
|
+
summary: "Disallow returning a multi-field tuple from a named function; return a named object so call sites cannot mismatch slots.",
|
|
4722
|
+
rationale: "Tuple fields are identified only by position, so reordering can preserve types while changing meaning.",
|
|
4723
4723
|
remediation: "Return an object whose property names describe each value.",
|
|
4724
4724
|
category: "maintainability",
|
|
4725
|
-
limitations: ["
|
|
4725
|
+
limitations: ["Declared or syntax-proven multi-field tuple returns on named functions and public type surfaces are inspected; anonymous inline callbacks and syntax-proven TanStack Query key factories are excluded."],
|
|
4726
4726
|
examples: [
|
|
4727
4727
|
{ id: "named-object-return", title: "Return named fields", outcome: "no-match", files: [{ path: "src/download.ts", source: "export function download(): { body: string; status: number } { return impl(); }" }], focusPath: "src/download.ts", expectedCount: 0, public: true },
|
|
4728
4728
|
{ id: "tuple-return", title: "Do not expose positional fields", outcome: "match", files: [{ path: "src/download.ts", source: "export function download(): [string, number] { return impl(); }" }], focusPath: "src/download.ts", expectedCount: 1, public: true }
|
|
@@ -4760,6 +4760,16 @@ function tupleReturnType(node, aliases, resolving = /* @__PURE__ */ new Set()) {
|
|
|
4760
4760
|
}
|
|
4761
4761
|
return null;
|
|
4762
4762
|
}
|
|
4763
|
+
function tupleExpression(node, aliases) {
|
|
4764
|
+
if (node.type !== import_utils24.AST_NODE_TYPES.TSAsExpression && node.type !== import_utils24.AST_NODE_TYPES.TSSatisfiesExpression) {
|
|
4765
|
+
return null;
|
|
4766
|
+
}
|
|
4767
|
+
if (node.expression.type !== import_utils24.AST_NODE_TYPES.ArrayExpression || node.expression.elements.length < MIN_ELEMENTS) {
|
|
4768
|
+
return null;
|
|
4769
|
+
}
|
|
4770
|
+
if (node.type === import_utils24.AST_NODE_TYPES.TSAsExpression && node.typeAnnotation.type === import_utils24.AST_NODE_TYPES.TSTypeReference && node.typeAnnotation.typeName.type === import_utils24.AST_NODE_TYPES.Identifier && node.typeAnnotation.typeName.name === "const") return node.expression;
|
|
4771
|
+
return tupleReturnType(node.typeAnnotation, aliases) === null ? null : node.expression;
|
|
4772
|
+
}
|
|
4763
4773
|
function functionName(node) {
|
|
4764
4774
|
if (node.type === import_utils24.AST_NODE_TYPES.FunctionDeclaration) {
|
|
4765
4775
|
if (node.id !== null) return node.id.name;
|
|
@@ -4775,60 +4785,25 @@ function functionName(node) {
|
|
|
4775
4785
|
return parent.id.name;
|
|
4776
4786
|
}
|
|
4777
4787
|
if ((parent?.type === import_utils24.AST_NODE_TYPES.MethodDefinition || parent?.type === import_utils24.AST_NODE_TYPES.TSAbstractMethodDefinition || parent?.type === import_utils24.AST_NODE_TYPES.PropertyDefinition || parent?.type === import_utils24.AST_NODE_TYPES.Property) && parent.key.type === import_utils24.AST_NODE_TYPES.Identifier) {
|
|
4778
|
-
if ((parent.type === import_utils24.AST_NODE_TYPES.MethodDefinition || parent.type === import_utils24.AST_NODE_TYPES.TSAbstractMethodDefinition || parent.type === import_utils24.AST_NODE_TYPES.PropertyDefinition) && (parent.accessibility === "private" || parent.accessibility === "protected")) return null;
|
|
4779
4788
|
return parent.key.name;
|
|
4780
4789
|
}
|
|
4781
4790
|
return null;
|
|
4782
4791
|
}
|
|
4783
|
-
function
|
|
4784
|
-
|
|
4785
|
-
|
|
4786
|
-
|
|
4787
|
-
|
|
4788
|
-
|
|
4789
|
-
|
|
4790
|
-
|
|
4791
|
-
return false;
|
|
4792
|
-
|
|
4793
|
-
|
|
4794
|
-
|
|
4795
|
-
|
|
4796
|
-
|
|
4797
|
-
}
|
|
4798
|
-
if (current.parent?.type !== import_utils24.AST_NODE_TYPES.Program) {
|
|
4799
|
-
return null;
|
|
4800
|
-
}
|
|
4801
|
-
let topLevel = current;
|
|
4802
|
-
if (current.type === import_utils24.AST_NODE_TYPES.ExportNamedDeclaration || current.type === import_utils24.AST_NODE_TYPES.ExportDefaultDeclaration) {
|
|
4803
|
-
topLevel = current.declaration;
|
|
4804
|
-
}
|
|
4805
|
-
if (topLevel === null) return null;
|
|
4806
|
-
if (topLevel.type === import_utils24.AST_NODE_TYPES.FunctionDeclaration) {
|
|
4807
|
-
if (topLevel !== node) return null;
|
|
4808
|
-
return topLevel.id?.name ?? (current.type === import_utils24.AST_NODE_TYPES.ExportDefaultDeclaration ? "default" : null);
|
|
4809
|
-
}
|
|
4810
|
-
if ((topLevel.type === import_utils24.AST_NODE_TYPES.ArrowFunctionExpression || topLevel.type === import_utils24.AST_NODE_TYPES.FunctionExpression) && topLevel === node && current.type === import_utils24.AST_NODE_TYPES.ExportDefaultDeclaration) {
|
|
4811
|
-
return "default";
|
|
4812
|
-
}
|
|
4813
|
-
if (topLevel.type === import_utils24.AST_NODE_TYPES.ClassDeclaration) {
|
|
4814
|
-
let owner = node.parent;
|
|
4815
|
-
while (owner != null && owner.parent !== topLevel.body) owner = owner.parent;
|
|
4816
|
-
return (owner?.type === import_utils24.AST_NODE_TYPES.MethodDefinition || owner?.type === import_utils24.AST_NODE_TYPES.TSAbstractMethodDefinition || owner?.type === import_utils24.AST_NODE_TYPES.PropertyDefinition) && owner.value === node ? topLevel.id?.name ?? (current.type === import_utils24.AST_NODE_TYPES.ExportDefaultDeclaration ? "default" : null) : null;
|
|
4817
|
-
}
|
|
4818
|
-
if (topLevel.type === import_utils24.AST_NODE_TYPES.VariableDeclaration) {
|
|
4819
|
-
for (const declarator of topLevel.declarations) {
|
|
4820
|
-
let initializer = declarator.init;
|
|
4821
|
-
while (initializer?.type === import_utils24.AST_NODE_TYPES.TSAsExpression || initializer?.type === import_utils24.AST_NODE_TYPES.TSSatisfiesExpression || initializer?.type === import_utils24.AST_NODE_TYPES.TSNonNullExpression) initializer = initializer.expression;
|
|
4822
|
-
if (declarator.id.type === import_utils24.AST_NODE_TYPES.Identifier && initializer === node) return declarator.id.name;
|
|
4823
|
-
if (declarator.id.type === import_utils24.AST_NODE_TYPES.Identifier && (initializer?.type === import_utils24.AST_NODE_TYPES.ClassExpression || initializer?.type === import_utils24.AST_NODE_TYPES.ObjectExpression)) {
|
|
4824
|
-
let owner = node.parent;
|
|
4825
|
-
const container = initializer.type === import_utils24.AST_NODE_TYPES.ClassExpression ? initializer.body : initializer;
|
|
4826
|
-
while (owner != null && owner.parent !== container) owner = owner.parent;
|
|
4827
|
-
if ((owner?.type === import_utils24.AST_NODE_TYPES.MethodDefinition || owner?.type === import_utils24.AST_NODE_TYPES.PropertyDefinition || owner?.type === import_utils24.AST_NODE_TYPES.Property) && owner.value === node) return declarator.id.name;
|
|
4828
|
-
}
|
|
4829
|
-
}
|
|
4830
|
-
}
|
|
4831
|
-
return null;
|
|
4792
|
+
function isQueryKeyFactory(node) {
|
|
4793
|
+
let wrapped = node;
|
|
4794
|
+
while ((wrapped.parent?.type === import_utils24.AST_NODE_TYPES.TSAsExpression || wrapped.parent?.type === import_utils24.AST_NODE_TYPES.TSSatisfiesExpression || wrapped.parent?.type === import_utils24.AST_NODE_TYPES.TSNonNullExpression) && wrapped.parent.expression === wrapped) wrapped = wrapped.parent;
|
|
4795
|
+
const property = wrapped.parent;
|
|
4796
|
+
if (property?.type !== import_utils24.AST_NODE_TYPES.Property || property.value !== wrapped) return false;
|
|
4797
|
+
const object = property.parent;
|
|
4798
|
+
if (object.type !== import_utils24.AST_NODE_TYPES.ObjectExpression) return false;
|
|
4799
|
+
const assertion = object.parent;
|
|
4800
|
+
if (assertion.type !== import_utils24.AST_NODE_TYPES.TSAsExpression || assertion.expression !== object || assertion.typeAnnotation.type !== import_utils24.AST_NODE_TYPES.TSTypeReference || assertion.typeAnnotation.typeName.type !== import_utils24.AST_NODE_TYPES.Identifier || assertion.typeAnnotation.typeName.name !== "const") return false;
|
|
4801
|
+
const declarator = assertion.parent;
|
|
4802
|
+
if (declarator.type !== import_utils24.AST_NODE_TYPES.VariableDeclarator || declarator.id.type !== import_utils24.AST_NODE_TYPES.Identifier || !/Keys$/i.test(declarator.id.name) || declarator.parent.type !== import_utils24.AST_NODE_TYPES.VariableDeclaration || declarator.parent.kind !== "const") return false;
|
|
4803
|
+
return object.properties.some((candidate) => {
|
|
4804
|
+
if (candidate.type !== import_utils24.AST_NODE_TYPES.Property || staticMemberName3(candidate.key) !== "all") return false;
|
|
4805
|
+
return candidate.value.type === import_utils24.AST_NODE_TYPES.TSAsExpression && candidate.value.expression.type === import_utils24.AST_NODE_TYPES.ArrayExpression && candidate.value.typeAnnotation.type === import_utils24.AST_NODE_TYPES.TSTypeReference && candidate.value.typeAnnotation.typeName.type === import_utils24.AST_NODE_TYPES.Identifier && candidate.value.typeAnnotation.typeName.name === "const";
|
|
4806
|
+
});
|
|
4832
4807
|
}
|
|
4833
4808
|
function specifierExportedNames(program) {
|
|
4834
4809
|
const names = /* @__PURE__ */ new Set();
|
|
@@ -4937,18 +4912,52 @@ function isExportedClass(node, specifierExports) {
|
|
|
4937
4912
|
if (node.parent.type === import_utils24.AST_NODE_TYPES.VariableDeclarator && node.parent.id.type === import_utils24.AST_NODE_TYPES.Identifier) return specifierExports.has(node.parent.id.name) || isInlineExported(node);
|
|
4938
4913
|
return false;
|
|
4939
4914
|
}
|
|
4940
|
-
function
|
|
4941
|
-
|
|
4915
|
+
function isInlineExported(node) {
|
|
4916
|
+
if (moduleScopeBindingName(node) === null) return false;
|
|
4917
|
+
for (let current = node; current != null; current = current.parent) {
|
|
4918
|
+
const parent = current.parent;
|
|
4919
|
+
if (parent?.type === import_utils24.AST_NODE_TYPES.ExportNamedDeclaration || parent?.type === import_utils24.AST_NODE_TYPES.ExportDefaultDeclaration) {
|
|
4920
|
+
return true;
|
|
4921
|
+
}
|
|
4922
|
+
}
|
|
4923
|
+
return false;
|
|
4942
4924
|
}
|
|
4943
|
-
function
|
|
4944
|
-
|
|
4945
|
-
|
|
4925
|
+
function moduleScopeBindingName(node) {
|
|
4926
|
+
let current = node;
|
|
4927
|
+
while (current.parent != null && current.parent.type !== import_utils24.AST_NODE_TYPES.Program) {
|
|
4928
|
+
current = current.parent;
|
|
4946
4929
|
}
|
|
4947
|
-
if (
|
|
4948
|
-
|
|
4930
|
+
if (current.parent?.type !== import_utils24.AST_NODE_TYPES.Program) return null;
|
|
4931
|
+
let topLevel = current;
|
|
4932
|
+
if (current.type === import_utils24.AST_NODE_TYPES.ExportNamedDeclaration || current.type === import_utils24.AST_NODE_TYPES.ExportDefaultDeclaration) topLevel = current.declaration;
|
|
4933
|
+
if (topLevel === null) return null;
|
|
4934
|
+
if (topLevel.type === import_utils24.AST_NODE_TYPES.FunctionDeclaration) {
|
|
4935
|
+
if (topLevel !== node) return null;
|
|
4936
|
+
return topLevel.id?.name ?? (current.type === import_utils24.AST_NODE_TYPES.ExportDefaultDeclaration ? "default" : null);
|
|
4937
|
+
}
|
|
4938
|
+
if ((topLevel.type === import_utils24.AST_NODE_TYPES.ArrowFunctionExpression || topLevel.type === import_utils24.AST_NODE_TYPES.FunctionExpression) && topLevel === node && current.type === import_utils24.AST_NODE_TYPES.ExportDefaultDeclaration) return "default";
|
|
4939
|
+
if (topLevel.type === import_utils24.AST_NODE_TYPES.ClassDeclaration) {
|
|
4940
|
+
let owner = node.parent;
|
|
4941
|
+
while (owner != null && owner.parent !== topLevel.body) owner = owner.parent;
|
|
4942
|
+
return (owner?.type === import_utils24.AST_NODE_TYPES.MethodDefinition || owner?.type === import_utils24.AST_NODE_TYPES.TSAbstractMethodDefinition || owner?.type === import_utils24.AST_NODE_TYPES.PropertyDefinition) && owner.value === node ? topLevel.id?.name ?? (current.type === import_utils24.AST_NODE_TYPES.ExportDefaultDeclaration ? "default" : null) : null;
|
|
4943
|
+
}
|
|
4944
|
+
if (topLevel.type === import_utils24.AST_NODE_TYPES.VariableDeclaration) {
|
|
4945
|
+
for (const declarator of topLevel.declarations) {
|
|
4946
|
+
let initializer = declarator.init;
|
|
4947
|
+
while (initializer?.type === import_utils24.AST_NODE_TYPES.TSAsExpression || initializer?.type === import_utils24.AST_NODE_TYPES.TSSatisfiesExpression || initializer?.type === import_utils24.AST_NODE_TYPES.TSNonNullExpression) initializer = initializer.expression;
|
|
4948
|
+
if (declarator.id.type === import_utils24.AST_NODE_TYPES.Identifier && initializer === node) return declarator.id.name;
|
|
4949
|
+
if (declarator.id.type === import_utils24.AST_NODE_TYPES.Identifier && (initializer?.type === import_utils24.AST_NODE_TYPES.ClassExpression || initializer?.type === import_utils24.AST_NODE_TYPES.ObjectExpression)) {
|
|
4950
|
+
let owner = node.parent;
|
|
4951
|
+
const container = initializer.type === import_utils24.AST_NODE_TYPES.ClassExpression ? initializer.body : initializer;
|
|
4952
|
+
while (owner != null && owner.parent !== container) owner = owner.parent;
|
|
4953
|
+
if ((owner?.type === import_utils24.AST_NODE_TYPES.MethodDefinition || owner?.type === import_utils24.AST_NODE_TYPES.PropertyDefinition || owner?.type === import_utils24.AST_NODE_TYPES.Property) && owner.value === node) return declarator.id.name;
|
|
4954
|
+
}
|
|
4955
|
+
}
|
|
4949
4956
|
}
|
|
4950
|
-
|
|
4951
|
-
|
|
4957
|
+
return null;
|
|
4958
|
+
}
|
|
4959
|
+
function isExportedInterface(node, exports2) {
|
|
4960
|
+
return node.parent.type === import_utils24.AST_NODE_TYPES.ExportNamedDeclaration || node.parent.type === import_utils24.AST_NODE_TYPES.ExportDefaultDeclaration || node.parent.type === import_utils24.AST_NODE_TYPES.Program && exports2.has(node.id.name);
|
|
4952
4961
|
}
|
|
4953
4962
|
var no_positional_tuple_return_default = createRule({
|
|
4954
4963
|
name: "no-positional-tuple-return",
|
|
@@ -4956,11 +4965,11 @@ var no_positional_tuple_return_default = createRule({
|
|
|
4956
4965
|
meta: {
|
|
4957
4966
|
type: "suggestion",
|
|
4958
4967
|
docs: {
|
|
4959
|
-
description: "Disallow returning a multi-field tuple from
|
|
4968
|
+
description: "Disallow returning a multi-field tuple from a named function; return a named object so call sites cannot mismatch slots."
|
|
4960
4969
|
},
|
|
4961
4970
|
schema: [],
|
|
4962
4971
|
messages: {
|
|
4963
|
-
noPositionalTupleReturn: "
|
|
4972
|
+
noPositionalTupleReturn: "`{{name}}` returns a {{count}}-field tuple, so callers depend on positional slots that can be reordered silently. Return a named object instead."
|
|
4964
4973
|
}
|
|
4965
4974
|
},
|
|
4966
4975
|
defaultOptions: [],
|
|
@@ -4972,6 +4981,8 @@ var no_positional_tuple_return_default = createRule({
|
|
|
4972
4981
|
exportedTypeNames(context.sourceCode.ast)
|
|
4973
4982
|
);
|
|
4974
4983
|
const aliases = typeAliases(context.sourceCode.ast);
|
|
4984
|
+
const reportedFunctions = /* @__PURE__ */ new WeakSet();
|
|
4985
|
+
const functionStack = [];
|
|
4975
4986
|
const report = (annotation, name) => {
|
|
4976
4987
|
const tuple = tupleReturnType(annotation, aliases);
|
|
4977
4988
|
if (tuple === null || tuple.elementTypes.length < MIN_ELEMENTS) return;
|
|
@@ -4981,25 +4992,54 @@ var no_positional_tuple_return_default = createRule({
|
|
|
4981
4992
|
data: { name, count: String(tuple.elementTypes.length) }
|
|
4982
4993
|
});
|
|
4983
4994
|
};
|
|
4995
|
+
const reportExpression = (node, expression) => {
|
|
4996
|
+
if (reportedFunctions.has(node)) return;
|
|
4997
|
+
const tuple = tupleExpression(expression, aliases);
|
|
4998
|
+
const name = functionName(node);
|
|
4999
|
+
if (tuple === null || name === null) return;
|
|
5000
|
+
reportedFunctions.add(node);
|
|
5001
|
+
context.report({
|
|
5002
|
+
node: tuple,
|
|
5003
|
+
messageId: "noPositionalTupleReturn",
|
|
5004
|
+
data: { name, count: String(tuple.elements.length) }
|
|
5005
|
+
});
|
|
5006
|
+
};
|
|
4984
5007
|
const check = (node) => {
|
|
5008
|
+
if (isQueryKeyFactory(node)) return;
|
|
4985
5009
|
const annotation = node.returnType?.typeAnnotation;
|
|
4986
5010
|
if (annotation === void 0) {
|
|
5011
|
+
if (node.type === import_utils24.AST_NODE_TYPES.ArrowFunctionExpression && node.expression) {
|
|
5012
|
+
reportExpression(node, node.body);
|
|
5013
|
+
}
|
|
4987
5014
|
return;
|
|
4988
5015
|
}
|
|
4989
5016
|
const name = functionName(node);
|
|
4990
5017
|
if (name === null) {
|
|
4991
5018
|
return;
|
|
4992
5019
|
}
|
|
4993
|
-
if (!isExported(node, specifierExports)) {
|
|
4994
|
-
return;
|
|
4995
|
-
}
|
|
4996
5020
|
report(annotation, name);
|
|
4997
5021
|
};
|
|
5022
|
+
const enterFunction = (node) => {
|
|
5023
|
+
functionStack.push(node);
|
|
5024
|
+
check(node);
|
|
5025
|
+
};
|
|
5026
|
+
const exitFunction = () => {
|
|
5027
|
+
functionStack.pop();
|
|
5028
|
+
};
|
|
4998
5029
|
return {
|
|
4999
|
-
FunctionDeclaration:
|
|
5000
|
-
|
|
5001
|
-
|
|
5002
|
-
|
|
5030
|
+
FunctionDeclaration: enterFunction,
|
|
5031
|
+
"FunctionDeclaration:exit": exitFunction,
|
|
5032
|
+
FunctionExpression: enterFunction,
|
|
5033
|
+
"FunctionExpression:exit": exitFunction,
|
|
5034
|
+
ArrowFunctionExpression: enterFunction,
|
|
5035
|
+
"ArrowFunctionExpression:exit": exitFunction,
|
|
5036
|
+
TSEmptyBodyFunctionExpression: enterFunction,
|
|
5037
|
+
"TSEmptyBodyFunctionExpression:exit": exitFunction,
|
|
5038
|
+
ReturnStatement(node) {
|
|
5039
|
+
const owner = functionStack.at(-1);
|
|
5040
|
+
if (owner === void 0 || owner.returnType !== void 0 || node.argument === null) return;
|
|
5041
|
+
reportExpression(owner, node.argument);
|
|
5042
|
+
},
|
|
5003
5043
|
TSDeclareFunction(node) {
|
|
5004
5044
|
if (node.id === null || node.returnType === void 0 || node.parent.type !== import_utils24.AST_NODE_TYPES.ExportNamedDeclaration && node.parent.type !== import_utils24.AST_NODE_TYPES.ExportDefaultDeclaration && !specifierExports.has(node.id.name)) return;
|
|
5005
5045
|
report(node.returnType.typeAnnotation, node.id.name);
|
|
@@ -11180,7 +11220,8 @@ var preferAwaitInAsyncReturnDocumentation = {
|
|
|
11180
11220
|
since: "15.6.3",
|
|
11181
11221
|
limitations: [
|
|
11182
11222
|
"Only a single directly returned `.then` call with an inline callback is checked.",
|
|
11183
|
-
"The receiver must be proven Promise-like by TypeScript; untyped files and larger chains are intentionally ignored."
|
|
11223
|
+
"The receiver must be proven Promise-like by TypeScript; untyped files and larger chains are intentionally ignored.",
|
|
11224
|
+
"Direct loader callbacks passed to resolved `React.lazy` and `next/dynamic` imports are excluded because returning the module Promise is their framework contract."
|
|
11184
11225
|
],
|
|
11185
11226
|
examples: [
|
|
11186
11227
|
{
|
|
@@ -11209,19 +11250,19 @@ var preferAwaitInAsyncReturnDocumentation = {
|
|
|
11209
11250
|
}
|
|
11210
11251
|
]
|
|
11211
11252
|
};
|
|
11212
|
-
function
|
|
11253
|
+
function directAsyncReturnOwner(node) {
|
|
11213
11254
|
const parent = node.parent;
|
|
11214
11255
|
if (parent.type === import_utils59.AST_NODE_TYPES.ArrowFunctionExpression && parent.body === node) {
|
|
11215
|
-
return parent.async && !parent.generator;
|
|
11256
|
+
return parent.async && !parent.generator ? parent : null;
|
|
11216
11257
|
}
|
|
11217
11258
|
if (parent.type !== import_utils59.AST_NODE_TYPES.ReturnStatement || parent.argument !== node) {
|
|
11218
|
-
return
|
|
11259
|
+
return null;
|
|
11219
11260
|
}
|
|
11220
11261
|
let owner = parent.parent;
|
|
11221
11262
|
while (owner !== void 0 && !isRuntimeFunction(owner)) {
|
|
11222
11263
|
owner = owner.parent;
|
|
11223
11264
|
}
|
|
11224
|
-
return owner !== void 0 && owner.async && !owner.generator;
|
|
11265
|
+
return owner !== void 0 && owner.async && !owner.generator ? owner : null;
|
|
11225
11266
|
}
|
|
11226
11267
|
function isRuntimeFunction(node) {
|
|
11227
11268
|
return node.type === import_utils59.AST_NODE_TYPES.ArrowFunctionExpression || node.type === import_utils59.AST_NODE_TYPES.FunctionDeclaration || node.type === import_utils59.AST_NODE_TYPES.FunctionExpression;
|
|
@@ -11278,9 +11319,33 @@ var prefer_await_in_async_return_default = createRule({
|
|
|
11278
11319
|
services = null;
|
|
11279
11320
|
}
|
|
11280
11321
|
if (services === null) return {};
|
|
11322
|
+
const frameworkLoaders = /* @__PURE__ */ new Set();
|
|
11323
|
+
const rememberFrameworkLoader = (identifier) => {
|
|
11324
|
+
const variable = import_utils59.ASTUtils.findVariable(context.sourceCode.getScope(identifier), identifier.name);
|
|
11325
|
+
if (variable !== null) frameworkLoaders.add(variable);
|
|
11326
|
+
};
|
|
11327
|
+
const isFrameworkLoaderCallback = (owner) => {
|
|
11328
|
+
const parent = owner.parent;
|
|
11329
|
+
if (parent.type !== import_utils59.AST_NODE_TYPES.CallExpression || parent.arguments[0] !== owner || parent.callee.type !== import_utils59.AST_NODE_TYPES.Identifier) return false;
|
|
11330
|
+
const variable = import_utils59.ASTUtils.findVariable(context.sourceCode.getScope(parent.callee), parent.callee.name);
|
|
11331
|
+
return variable !== null && frameworkLoaders.has(variable);
|
|
11332
|
+
};
|
|
11281
11333
|
return {
|
|
11334
|
+
ImportDeclaration(node) {
|
|
11335
|
+
if (node.source.value === "react") {
|
|
11336
|
+
for (const specifier of node.specifiers) {
|
|
11337
|
+
if (specifier.type === import_utils59.AST_NODE_TYPES.ImportSpecifier && (specifier.imported.type === import_utils59.AST_NODE_TYPES.Identifier ? specifier.imported.name : specifier.imported.value) === "lazy") rememberFrameworkLoader(specifier.local);
|
|
11338
|
+
}
|
|
11339
|
+
}
|
|
11340
|
+
if (node.source.value === "next/dynamic") {
|
|
11341
|
+
for (const specifier of node.specifiers) {
|
|
11342
|
+
if (specifier.type === import_utils59.AST_NODE_TYPES.ImportDefaultSpecifier) rememberFrameworkLoader(specifier.local);
|
|
11343
|
+
}
|
|
11344
|
+
}
|
|
11345
|
+
},
|
|
11282
11346
|
CallExpression(node) {
|
|
11283
|
-
|
|
11347
|
+
const owner = directAsyncReturnOwner(node);
|
|
11348
|
+
if (owner === null || isFrameworkLoaderCallback(owner)) return;
|
|
11284
11349
|
const receiver = promiseThenReceiver(node);
|
|
11285
11350
|
if (receiver === null || !isProvenPromiseLike(receiver, services)) {
|
|
11286
11351
|
return;
|
|
@@ -12489,6 +12554,16 @@ function literalIndex(node) {
|
|
|
12489
12554
|
}
|
|
12490
12555
|
return Number.isInteger(node.value) && node.value >= 0 ? node.value : null;
|
|
12491
12556
|
}
|
|
12557
|
+
function propertyAccess(node) {
|
|
12558
|
+
const path = [];
|
|
12559
|
+
let current = node;
|
|
12560
|
+
while (current.type === import_utils63.AST_NODE_TYPES.MemberExpression && !current.computed && !current.optional) {
|
|
12561
|
+
if (current.property.type !== import_utils63.AST_NODE_TYPES.Identifier || COLLECTION_PROPERTIES.has(current.property.name) || LITERAL_KEY_HAZARDS.has(current.property.name)) return null;
|
|
12562
|
+
path.unshift(current.property.name);
|
|
12563
|
+
current = current.object;
|
|
12564
|
+
}
|
|
12565
|
+
return path.length > 0 && isPureReceiver(current) ? { receiver: current, path } : null;
|
|
12566
|
+
}
|
|
12492
12567
|
var prefer_whole_object_assertion_default = createRule({
|
|
12493
12568
|
name: "prefer-whole-object-assertion",
|
|
12494
12569
|
documentation: preferWholeObjectAssertionDocumentation,
|
|
@@ -12535,21 +12610,23 @@ var prefer_whole_object_assertion_default = createRule({
|
|
|
12535
12610
|
return null;
|
|
12536
12611
|
}
|
|
12537
12612
|
let key;
|
|
12613
|
+
let receiver;
|
|
12538
12614
|
if (actual.computed) {
|
|
12539
12615
|
const index = literalIndex(actual.property);
|
|
12540
12616
|
if (index === null) {
|
|
12541
12617
|
return null;
|
|
12542
12618
|
}
|
|
12543
12619
|
key = { kind: "index", index };
|
|
12620
|
+
receiver = actual.object;
|
|
12544
12621
|
} else {
|
|
12545
|
-
|
|
12546
|
-
|
|
12547
|
-
}
|
|
12548
|
-
|
|
12622
|
+
const access = propertyAccess(actual);
|
|
12623
|
+
if (access === null) return null;
|
|
12624
|
+
key = { kind: "property", path: access.path };
|
|
12625
|
+
receiver = access.receiver;
|
|
12549
12626
|
}
|
|
12550
12627
|
const synthetic = SYNTHETIC_LITERAL_MATCHERS.get(matcher);
|
|
12551
12628
|
if (synthetic !== void 0 && call.arguments.length === 0) {
|
|
12552
|
-
return { statement, receiver
|
|
12629
|
+
return { statement, receiver, key, matcher, expectedText: synthetic, expectedIsLiteral: true };
|
|
12553
12630
|
}
|
|
12554
12631
|
if (!MERGEABLE_MATCHERS.has(matcher)) {
|
|
12555
12632
|
return null;
|
|
@@ -12561,7 +12638,7 @@ var prefer_whole_object_assertion_default = createRule({
|
|
|
12561
12638
|
const literal = literalText(expected, (node) => sourceCode.getText(node));
|
|
12562
12639
|
return {
|
|
12563
12640
|
statement,
|
|
12564
|
-
receiver
|
|
12641
|
+
receiver,
|
|
12565
12642
|
key,
|
|
12566
12643
|
matcher,
|
|
12567
12644
|
expectedText: literal ?? sourceCode.getText(expected),
|
|
@@ -12574,7 +12651,8 @@ var prefer_whole_object_assertion_default = createRule({
|
|
|
12574
12651
|
);
|
|
12575
12652
|
}
|
|
12576
12653
|
function reportPropertyRun(run) {
|
|
12577
|
-
const
|
|
12654
|
+
const tree = /* @__PURE__ */ new Map();
|
|
12655
|
+
const paths = [];
|
|
12578
12656
|
for (const assertion of run) {
|
|
12579
12657
|
if (assertion.key.kind !== "property" || !assertion.expectedIsLiteral) {
|
|
12580
12658
|
return;
|
|
@@ -12582,19 +12660,44 @@ var prefer_whole_object_assertion_default = createRule({
|
|
|
12582
12660
|
if (!MERGEABLE_MATCHERS.has(assertion.matcher) && !SYNTHETIC_LITERAL_MATCHERS.has(assertion.matcher)) {
|
|
12583
12661
|
return;
|
|
12584
12662
|
}
|
|
12585
|
-
|
|
12586
|
-
|
|
12663
|
+
paths.push([...assertion.key.path]);
|
|
12664
|
+
}
|
|
12665
|
+
const commonPrefix = [];
|
|
12666
|
+
for (let index = 0; ; index += 1) {
|
|
12667
|
+
const candidate = paths[0]?.[index];
|
|
12668
|
+
if (candidate === void 0 || paths.some((path) => path[index] !== candidate || path.length === index + 1)) {
|
|
12669
|
+
break;
|
|
12670
|
+
}
|
|
12671
|
+
commonPrefix.push(candidate);
|
|
12672
|
+
}
|
|
12673
|
+
for (const [assertionIndex, assertion] of run.entries()) {
|
|
12674
|
+
if (assertion.key.kind !== "property") return;
|
|
12675
|
+
let branch = tree;
|
|
12676
|
+
const relativePath = paths[assertionIndex]?.slice(commonPrefix.length) ?? [];
|
|
12677
|
+
for (const [index, name] of relativePath.entries()) {
|
|
12678
|
+
const leaf = index === relativePath.length - 1;
|
|
12679
|
+
const existing = branch.get(name);
|
|
12680
|
+
if (leaf) {
|
|
12681
|
+
if (existing !== void 0) return;
|
|
12682
|
+
branch.set(name, assertion.expectedText);
|
|
12683
|
+
} else if (existing === void 0) {
|
|
12684
|
+
const nested = /* @__PURE__ */ new Map();
|
|
12685
|
+
branch.set(name, nested);
|
|
12686
|
+
branch = nested;
|
|
12687
|
+
} else if (existing instanceof Map) {
|
|
12688
|
+
branch = existing;
|
|
12689
|
+
} else {
|
|
12690
|
+
return;
|
|
12691
|
+
}
|
|
12587
12692
|
}
|
|
12588
|
-
names.add(assertion.key.name);
|
|
12589
12693
|
}
|
|
12590
12694
|
const first = run[0];
|
|
12591
12695
|
if (first === void 0) {
|
|
12592
12696
|
return;
|
|
12593
12697
|
}
|
|
12594
|
-
const receiverText = sourceCode.getText(first.receiver)
|
|
12595
|
-
const
|
|
12596
|
-
|
|
12597
|
-
).join(", ");
|
|
12698
|
+
const receiverText = `${sourceCode.getText(first.receiver)}${commonPrefix.map((name) => `.${name}`).join("")}`;
|
|
12699
|
+
const renderTree = (value) => [...value.entries()].map(([name, child]) => `${name}: ${child instanceof Map ? `{ ${renderTree(child)} }` : child}`).join(", ");
|
|
12700
|
+
const properties = renderTree(tree);
|
|
12598
12701
|
context.report({
|
|
12599
12702
|
node: first.statement,
|
|
12600
12703
|
messageId: "combineAssertions",
|
|
@@ -15222,7 +15325,7 @@ var stepdown_default = createRule({
|
|
|
15222
15325
|
|
|
15223
15326
|
// src/rules/source-coupled-test.ts
|
|
15224
15327
|
var import_utils73 = require("@typescript-eslint/utils");
|
|
15225
|
-
var GENERAL_SOURCE_SUFFIX_RE = /\.(?:bash|sh|ya?ml|py|[cm]?[jt]s)$/iu;
|
|
15328
|
+
var GENERAL_SOURCE_SUFFIX_RE = /\.(?:bash|sh|ya?ml|jsonc|py|[cm]?[jt]s)$/iu;
|
|
15226
15329
|
var FS_MODULES = /* @__PURE__ */ new Set(["fs", "node:fs", "fs/promises", "node:fs/promises"]);
|
|
15227
15330
|
var FS_READERS = /* @__PURE__ */ new Set(["readFile", "readFileSync"]);
|
|
15228
15331
|
var TEXT_TRANSFORMS = /* @__PURE__ */ new Set([
|
|
@@ -15417,6 +15520,13 @@ function createSourceCoupledRule(name, documentation, sourceSuffixRe) {
|
|
|
15417
15520
|
if (receiver.type !== import_utils73.AST_NODE_TYPES.Identifier || receiver.name !== "assert" || !ASSERT_MATCHERS.has(matcher)) return /* @__PURE__ */ new Set();
|
|
15418
15521
|
return new Set(node.arguments.flatMap((argument) => argument.type === import_utils73.AST_NODE_TYPES.SpreadElement ? [] : [...evidenceOrigins(argument)]));
|
|
15419
15522
|
};
|
|
15523
|
+
const rawRegexExtractionOrigins = (node) => {
|
|
15524
|
+
const callee = unwrap5(node.callee);
|
|
15525
|
+
if (callee.type !== import_utils73.AST_NODE_TYPES.MemberExpression || staticMemberName7(callee) !== "matchAll" || node.arguments.length !== 1) return /* @__PURE__ */ new Set();
|
|
15526
|
+
const argument = node.arguments[0];
|
|
15527
|
+
if (argument?.type !== import_utils73.AST_NODE_TYPES.Literal || !(argument.value instanceof RegExp)) return /* @__PURE__ */ new Set();
|
|
15528
|
+
return rawOrigins(callee.object);
|
|
15529
|
+
};
|
|
15420
15530
|
const declare = (name2, state) => {
|
|
15421
15531
|
const scope = currentScope();
|
|
15422
15532
|
scope.declared.add(name2);
|
|
@@ -15496,7 +15606,10 @@ function createSourceCoupledRule(name, documentation, sourceSuffixRe) {
|
|
|
15496
15606
|
if (collection && left?.type === import_utils73.AST_NODE_TYPES.Identifier) declare(left.name, { path: true });
|
|
15497
15607
|
},
|
|
15498
15608
|
CallExpression(node) {
|
|
15499
|
-
const origins =
|
|
15609
|
+
const origins = /* @__PURE__ */ new Set([
|
|
15610
|
+
...rawAssertionOrigins(node),
|
|
15611
|
+
...rawRegexExtractionOrigins(node)
|
|
15612
|
+
]);
|
|
15500
15613
|
if (origins.size === 0 || [...origins].every((origin) => reportedOrigins.has(origin))) return;
|
|
15501
15614
|
for (const origin of origins) reportedOrigins.add(origin);
|
|
15502
15615
|
context.report({ node, messageId: "rawSourceOracle" });
|
|
@@ -15844,7 +15957,7 @@ var rules = {
|
|
|
15844
15957
|
};
|
|
15845
15958
|
var meta = {
|
|
15846
15959
|
name: "@sarj/eslint-plugin",
|
|
15847
|
-
version: "15.
|
|
15960
|
+
version: "15.9.0"
|
|
15848
15961
|
};
|
|
15849
15962
|
var applicationOnlyRules = [
|
|
15850
15963
|
"no-restricted-library-load",
|
package/dist/index.d.cts
CHANGED
|
@@ -435,7 +435,7 @@ type FlatPreset = {
|
|
|
435
435
|
declare const plugin: {
|
|
436
436
|
readonly meta: {
|
|
437
437
|
readonly name: "@sarj/eslint-plugin";
|
|
438
|
-
readonly version: "15.
|
|
438
|
+
readonly version: "15.9.0";
|
|
439
439
|
};
|
|
440
440
|
readonly rules: {
|
|
441
441
|
readonly "iac-source-coupled-test": DocumentedRule<readonly [], "rawSourceOracle">;
|
package/dist/index.d.ts
CHANGED
|
@@ -435,7 +435,7 @@ type FlatPreset = {
|
|
|
435
435
|
declare const plugin: {
|
|
436
436
|
readonly meta: {
|
|
437
437
|
readonly name: "@sarj/eslint-plugin";
|
|
438
|
-
readonly version: "15.
|
|
438
|
+
readonly version: "15.9.0";
|
|
439
439
|
};
|
|
440
440
|
readonly rules: {
|
|
441
441
|
readonly "iac-source-coupled-test": DocumentedRule<readonly [], "rawSourceOracle">;
|
package/dist/index.js
CHANGED
|
@@ -4679,11 +4679,11 @@ var no_offset_pagination_default = createRule({
|
|
|
4679
4679
|
// src/rules/no-positional-tuple-return.ts
|
|
4680
4680
|
import { AST_NODE_TYPES as AST_NODE_TYPES18 } from "@typescript-eslint/utils";
|
|
4681
4681
|
var noPositionalTupleReturnDocumentation = {
|
|
4682
|
-
summary: "Disallow returning a multi-field tuple from
|
|
4683
|
-
rationale: "
|
|
4682
|
+
summary: "Disallow returning a multi-field tuple from a named function; return a named object so call sites cannot mismatch slots.",
|
|
4683
|
+
rationale: "Tuple fields are identified only by position, so reordering can preserve types while changing meaning.",
|
|
4684
4684
|
remediation: "Return an object whose property names describe each value.",
|
|
4685
4685
|
category: "maintainability",
|
|
4686
|
-
limitations: ["
|
|
4686
|
+
limitations: ["Declared or syntax-proven multi-field tuple returns on named functions and public type surfaces are inspected; anonymous inline callbacks and syntax-proven TanStack Query key factories are excluded."],
|
|
4687
4687
|
examples: [
|
|
4688
4688
|
{ id: "named-object-return", title: "Return named fields", outcome: "no-match", files: [{ path: "src/download.ts", source: "export function download(): { body: string; status: number } { return impl(); }" }], focusPath: "src/download.ts", expectedCount: 0, public: true },
|
|
4689
4689
|
{ id: "tuple-return", title: "Do not expose positional fields", outcome: "match", files: [{ path: "src/download.ts", source: "export function download(): [string, number] { return impl(); }" }], focusPath: "src/download.ts", expectedCount: 1, public: true }
|
|
@@ -4721,6 +4721,16 @@ function tupleReturnType(node, aliases, resolving = /* @__PURE__ */ new Set()) {
|
|
|
4721
4721
|
}
|
|
4722
4722
|
return null;
|
|
4723
4723
|
}
|
|
4724
|
+
function tupleExpression(node, aliases) {
|
|
4725
|
+
if (node.type !== AST_NODE_TYPES18.TSAsExpression && node.type !== AST_NODE_TYPES18.TSSatisfiesExpression) {
|
|
4726
|
+
return null;
|
|
4727
|
+
}
|
|
4728
|
+
if (node.expression.type !== AST_NODE_TYPES18.ArrayExpression || node.expression.elements.length < MIN_ELEMENTS) {
|
|
4729
|
+
return null;
|
|
4730
|
+
}
|
|
4731
|
+
if (node.type === AST_NODE_TYPES18.TSAsExpression && node.typeAnnotation.type === AST_NODE_TYPES18.TSTypeReference && node.typeAnnotation.typeName.type === AST_NODE_TYPES18.Identifier && node.typeAnnotation.typeName.name === "const") return node.expression;
|
|
4732
|
+
return tupleReturnType(node.typeAnnotation, aliases) === null ? null : node.expression;
|
|
4733
|
+
}
|
|
4724
4734
|
function functionName(node) {
|
|
4725
4735
|
if (node.type === AST_NODE_TYPES18.FunctionDeclaration) {
|
|
4726
4736
|
if (node.id !== null) return node.id.name;
|
|
@@ -4736,60 +4746,25 @@ function functionName(node) {
|
|
|
4736
4746
|
return parent.id.name;
|
|
4737
4747
|
}
|
|
4738
4748
|
if ((parent?.type === AST_NODE_TYPES18.MethodDefinition || parent?.type === AST_NODE_TYPES18.TSAbstractMethodDefinition || parent?.type === AST_NODE_TYPES18.PropertyDefinition || parent?.type === AST_NODE_TYPES18.Property) && parent.key.type === AST_NODE_TYPES18.Identifier) {
|
|
4739
|
-
if ((parent.type === AST_NODE_TYPES18.MethodDefinition || parent.type === AST_NODE_TYPES18.TSAbstractMethodDefinition || parent.type === AST_NODE_TYPES18.PropertyDefinition) && (parent.accessibility === "private" || parent.accessibility === "protected")) return null;
|
|
4740
4749
|
return parent.key.name;
|
|
4741
4750
|
}
|
|
4742
4751
|
return null;
|
|
4743
4752
|
}
|
|
4744
|
-
function
|
|
4745
|
-
|
|
4746
|
-
|
|
4747
|
-
|
|
4748
|
-
|
|
4749
|
-
|
|
4750
|
-
|
|
4751
|
-
|
|
4752
|
-
return false;
|
|
4753
|
-
|
|
4754
|
-
|
|
4755
|
-
|
|
4756
|
-
|
|
4757
|
-
|
|
4758
|
-
}
|
|
4759
|
-
if (current.parent?.type !== AST_NODE_TYPES18.Program) {
|
|
4760
|
-
return null;
|
|
4761
|
-
}
|
|
4762
|
-
let topLevel = current;
|
|
4763
|
-
if (current.type === AST_NODE_TYPES18.ExportNamedDeclaration || current.type === AST_NODE_TYPES18.ExportDefaultDeclaration) {
|
|
4764
|
-
topLevel = current.declaration;
|
|
4765
|
-
}
|
|
4766
|
-
if (topLevel === null) return null;
|
|
4767
|
-
if (topLevel.type === AST_NODE_TYPES18.FunctionDeclaration) {
|
|
4768
|
-
if (topLevel !== node) return null;
|
|
4769
|
-
return topLevel.id?.name ?? (current.type === AST_NODE_TYPES18.ExportDefaultDeclaration ? "default" : null);
|
|
4770
|
-
}
|
|
4771
|
-
if ((topLevel.type === AST_NODE_TYPES18.ArrowFunctionExpression || topLevel.type === AST_NODE_TYPES18.FunctionExpression) && topLevel === node && current.type === AST_NODE_TYPES18.ExportDefaultDeclaration) {
|
|
4772
|
-
return "default";
|
|
4773
|
-
}
|
|
4774
|
-
if (topLevel.type === AST_NODE_TYPES18.ClassDeclaration) {
|
|
4775
|
-
let owner = node.parent;
|
|
4776
|
-
while (owner != null && owner.parent !== topLevel.body) owner = owner.parent;
|
|
4777
|
-
return (owner?.type === AST_NODE_TYPES18.MethodDefinition || owner?.type === AST_NODE_TYPES18.TSAbstractMethodDefinition || owner?.type === AST_NODE_TYPES18.PropertyDefinition) && owner.value === node ? topLevel.id?.name ?? (current.type === AST_NODE_TYPES18.ExportDefaultDeclaration ? "default" : null) : null;
|
|
4778
|
-
}
|
|
4779
|
-
if (topLevel.type === AST_NODE_TYPES18.VariableDeclaration) {
|
|
4780
|
-
for (const declarator of topLevel.declarations) {
|
|
4781
|
-
let initializer = declarator.init;
|
|
4782
|
-
while (initializer?.type === AST_NODE_TYPES18.TSAsExpression || initializer?.type === AST_NODE_TYPES18.TSSatisfiesExpression || initializer?.type === AST_NODE_TYPES18.TSNonNullExpression) initializer = initializer.expression;
|
|
4783
|
-
if (declarator.id.type === AST_NODE_TYPES18.Identifier && initializer === node) return declarator.id.name;
|
|
4784
|
-
if (declarator.id.type === AST_NODE_TYPES18.Identifier && (initializer?.type === AST_NODE_TYPES18.ClassExpression || initializer?.type === AST_NODE_TYPES18.ObjectExpression)) {
|
|
4785
|
-
let owner = node.parent;
|
|
4786
|
-
const container = initializer.type === AST_NODE_TYPES18.ClassExpression ? initializer.body : initializer;
|
|
4787
|
-
while (owner != null && owner.parent !== container) owner = owner.parent;
|
|
4788
|
-
if ((owner?.type === AST_NODE_TYPES18.MethodDefinition || owner?.type === AST_NODE_TYPES18.PropertyDefinition || owner?.type === AST_NODE_TYPES18.Property) && owner.value === node) return declarator.id.name;
|
|
4789
|
-
}
|
|
4790
|
-
}
|
|
4791
|
-
}
|
|
4792
|
-
return null;
|
|
4753
|
+
function isQueryKeyFactory(node) {
|
|
4754
|
+
let wrapped = node;
|
|
4755
|
+
while ((wrapped.parent?.type === AST_NODE_TYPES18.TSAsExpression || wrapped.parent?.type === AST_NODE_TYPES18.TSSatisfiesExpression || wrapped.parent?.type === AST_NODE_TYPES18.TSNonNullExpression) && wrapped.parent.expression === wrapped) wrapped = wrapped.parent;
|
|
4756
|
+
const property = wrapped.parent;
|
|
4757
|
+
if (property?.type !== AST_NODE_TYPES18.Property || property.value !== wrapped) return false;
|
|
4758
|
+
const object = property.parent;
|
|
4759
|
+
if (object.type !== AST_NODE_TYPES18.ObjectExpression) return false;
|
|
4760
|
+
const assertion = object.parent;
|
|
4761
|
+
if (assertion.type !== AST_NODE_TYPES18.TSAsExpression || assertion.expression !== object || assertion.typeAnnotation.type !== AST_NODE_TYPES18.TSTypeReference || assertion.typeAnnotation.typeName.type !== AST_NODE_TYPES18.Identifier || assertion.typeAnnotation.typeName.name !== "const") return false;
|
|
4762
|
+
const declarator = assertion.parent;
|
|
4763
|
+
if (declarator.type !== AST_NODE_TYPES18.VariableDeclarator || declarator.id.type !== AST_NODE_TYPES18.Identifier || !/Keys$/i.test(declarator.id.name) || declarator.parent.type !== AST_NODE_TYPES18.VariableDeclaration || declarator.parent.kind !== "const") return false;
|
|
4764
|
+
return object.properties.some((candidate) => {
|
|
4765
|
+
if (candidate.type !== AST_NODE_TYPES18.Property || staticMemberName3(candidate.key) !== "all") return false;
|
|
4766
|
+
return candidate.value.type === AST_NODE_TYPES18.TSAsExpression && candidate.value.expression.type === AST_NODE_TYPES18.ArrayExpression && candidate.value.typeAnnotation.type === AST_NODE_TYPES18.TSTypeReference && candidate.value.typeAnnotation.typeName.type === AST_NODE_TYPES18.Identifier && candidate.value.typeAnnotation.typeName.name === "const";
|
|
4767
|
+
});
|
|
4793
4768
|
}
|
|
4794
4769
|
function specifierExportedNames(program) {
|
|
4795
4770
|
const names = /* @__PURE__ */ new Set();
|
|
@@ -4898,18 +4873,52 @@ function isExportedClass(node, specifierExports) {
|
|
|
4898
4873
|
if (node.parent.type === AST_NODE_TYPES18.VariableDeclarator && node.parent.id.type === AST_NODE_TYPES18.Identifier) return specifierExports.has(node.parent.id.name) || isInlineExported(node);
|
|
4899
4874
|
return false;
|
|
4900
4875
|
}
|
|
4901
|
-
function
|
|
4902
|
-
|
|
4876
|
+
function isInlineExported(node) {
|
|
4877
|
+
if (moduleScopeBindingName(node) === null) return false;
|
|
4878
|
+
for (let current = node; current != null; current = current.parent) {
|
|
4879
|
+
const parent = current.parent;
|
|
4880
|
+
if (parent?.type === AST_NODE_TYPES18.ExportNamedDeclaration || parent?.type === AST_NODE_TYPES18.ExportDefaultDeclaration) {
|
|
4881
|
+
return true;
|
|
4882
|
+
}
|
|
4883
|
+
}
|
|
4884
|
+
return false;
|
|
4903
4885
|
}
|
|
4904
|
-
function
|
|
4905
|
-
|
|
4906
|
-
|
|
4886
|
+
function moduleScopeBindingName(node) {
|
|
4887
|
+
let current = node;
|
|
4888
|
+
while (current.parent != null && current.parent.type !== AST_NODE_TYPES18.Program) {
|
|
4889
|
+
current = current.parent;
|
|
4907
4890
|
}
|
|
4908
|
-
if (
|
|
4909
|
-
|
|
4891
|
+
if (current.parent?.type !== AST_NODE_TYPES18.Program) return null;
|
|
4892
|
+
let topLevel = current;
|
|
4893
|
+
if (current.type === AST_NODE_TYPES18.ExportNamedDeclaration || current.type === AST_NODE_TYPES18.ExportDefaultDeclaration) topLevel = current.declaration;
|
|
4894
|
+
if (topLevel === null) return null;
|
|
4895
|
+
if (topLevel.type === AST_NODE_TYPES18.FunctionDeclaration) {
|
|
4896
|
+
if (topLevel !== node) return null;
|
|
4897
|
+
return topLevel.id?.name ?? (current.type === AST_NODE_TYPES18.ExportDefaultDeclaration ? "default" : null);
|
|
4898
|
+
}
|
|
4899
|
+
if ((topLevel.type === AST_NODE_TYPES18.ArrowFunctionExpression || topLevel.type === AST_NODE_TYPES18.FunctionExpression) && topLevel === node && current.type === AST_NODE_TYPES18.ExportDefaultDeclaration) return "default";
|
|
4900
|
+
if (topLevel.type === AST_NODE_TYPES18.ClassDeclaration) {
|
|
4901
|
+
let owner = node.parent;
|
|
4902
|
+
while (owner != null && owner.parent !== topLevel.body) owner = owner.parent;
|
|
4903
|
+
return (owner?.type === AST_NODE_TYPES18.MethodDefinition || owner?.type === AST_NODE_TYPES18.TSAbstractMethodDefinition || owner?.type === AST_NODE_TYPES18.PropertyDefinition) && owner.value === node ? topLevel.id?.name ?? (current.type === AST_NODE_TYPES18.ExportDefaultDeclaration ? "default" : null) : null;
|
|
4904
|
+
}
|
|
4905
|
+
if (topLevel.type === AST_NODE_TYPES18.VariableDeclaration) {
|
|
4906
|
+
for (const declarator of topLevel.declarations) {
|
|
4907
|
+
let initializer = declarator.init;
|
|
4908
|
+
while (initializer?.type === AST_NODE_TYPES18.TSAsExpression || initializer?.type === AST_NODE_TYPES18.TSSatisfiesExpression || initializer?.type === AST_NODE_TYPES18.TSNonNullExpression) initializer = initializer.expression;
|
|
4909
|
+
if (declarator.id.type === AST_NODE_TYPES18.Identifier && initializer === node) return declarator.id.name;
|
|
4910
|
+
if (declarator.id.type === AST_NODE_TYPES18.Identifier && (initializer?.type === AST_NODE_TYPES18.ClassExpression || initializer?.type === AST_NODE_TYPES18.ObjectExpression)) {
|
|
4911
|
+
let owner = node.parent;
|
|
4912
|
+
const container = initializer.type === AST_NODE_TYPES18.ClassExpression ? initializer.body : initializer;
|
|
4913
|
+
while (owner != null && owner.parent !== container) owner = owner.parent;
|
|
4914
|
+
if ((owner?.type === AST_NODE_TYPES18.MethodDefinition || owner?.type === AST_NODE_TYPES18.PropertyDefinition || owner?.type === AST_NODE_TYPES18.Property) && owner.value === node) return declarator.id.name;
|
|
4915
|
+
}
|
|
4916
|
+
}
|
|
4910
4917
|
}
|
|
4911
|
-
|
|
4912
|
-
|
|
4918
|
+
return null;
|
|
4919
|
+
}
|
|
4920
|
+
function isExportedInterface(node, exports) {
|
|
4921
|
+
return node.parent.type === AST_NODE_TYPES18.ExportNamedDeclaration || node.parent.type === AST_NODE_TYPES18.ExportDefaultDeclaration || node.parent.type === AST_NODE_TYPES18.Program && exports.has(node.id.name);
|
|
4913
4922
|
}
|
|
4914
4923
|
var no_positional_tuple_return_default = createRule({
|
|
4915
4924
|
name: "no-positional-tuple-return",
|
|
@@ -4917,11 +4926,11 @@ var no_positional_tuple_return_default = createRule({
|
|
|
4917
4926
|
meta: {
|
|
4918
4927
|
type: "suggestion",
|
|
4919
4928
|
docs: {
|
|
4920
|
-
description: "Disallow returning a multi-field tuple from
|
|
4929
|
+
description: "Disallow returning a multi-field tuple from a named function; return a named object so call sites cannot mismatch slots."
|
|
4921
4930
|
},
|
|
4922
4931
|
schema: [],
|
|
4923
4932
|
messages: {
|
|
4924
|
-
noPositionalTupleReturn: "
|
|
4933
|
+
noPositionalTupleReturn: "`{{name}}` returns a {{count}}-field tuple, so callers depend on positional slots that can be reordered silently. Return a named object instead."
|
|
4925
4934
|
}
|
|
4926
4935
|
},
|
|
4927
4936
|
defaultOptions: [],
|
|
@@ -4933,6 +4942,8 @@ var no_positional_tuple_return_default = createRule({
|
|
|
4933
4942
|
exportedTypeNames(context.sourceCode.ast)
|
|
4934
4943
|
);
|
|
4935
4944
|
const aliases = typeAliases(context.sourceCode.ast);
|
|
4945
|
+
const reportedFunctions = /* @__PURE__ */ new WeakSet();
|
|
4946
|
+
const functionStack = [];
|
|
4936
4947
|
const report = (annotation, name) => {
|
|
4937
4948
|
const tuple = tupleReturnType(annotation, aliases);
|
|
4938
4949
|
if (tuple === null || tuple.elementTypes.length < MIN_ELEMENTS) return;
|
|
@@ -4942,25 +4953,54 @@ var no_positional_tuple_return_default = createRule({
|
|
|
4942
4953
|
data: { name, count: String(tuple.elementTypes.length) }
|
|
4943
4954
|
});
|
|
4944
4955
|
};
|
|
4956
|
+
const reportExpression = (node, expression) => {
|
|
4957
|
+
if (reportedFunctions.has(node)) return;
|
|
4958
|
+
const tuple = tupleExpression(expression, aliases);
|
|
4959
|
+
const name = functionName(node);
|
|
4960
|
+
if (tuple === null || name === null) return;
|
|
4961
|
+
reportedFunctions.add(node);
|
|
4962
|
+
context.report({
|
|
4963
|
+
node: tuple,
|
|
4964
|
+
messageId: "noPositionalTupleReturn",
|
|
4965
|
+
data: { name, count: String(tuple.elements.length) }
|
|
4966
|
+
});
|
|
4967
|
+
};
|
|
4945
4968
|
const check = (node) => {
|
|
4969
|
+
if (isQueryKeyFactory(node)) return;
|
|
4946
4970
|
const annotation = node.returnType?.typeAnnotation;
|
|
4947
4971
|
if (annotation === void 0) {
|
|
4972
|
+
if (node.type === AST_NODE_TYPES18.ArrowFunctionExpression && node.expression) {
|
|
4973
|
+
reportExpression(node, node.body);
|
|
4974
|
+
}
|
|
4948
4975
|
return;
|
|
4949
4976
|
}
|
|
4950
4977
|
const name = functionName(node);
|
|
4951
4978
|
if (name === null) {
|
|
4952
4979
|
return;
|
|
4953
4980
|
}
|
|
4954
|
-
if (!isExported(node, specifierExports)) {
|
|
4955
|
-
return;
|
|
4956
|
-
}
|
|
4957
4981
|
report(annotation, name);
|
|
4958
4982
|
};
|
|
4983
|
+
const enterFunction = (node) => {
|
|
4984
|
+
functionStack.push(node);
|
|
4985
|
+
check(node);
|
|
4986
|
+
};
|
|
4987
|
+
const exitFunction = () => {
|
|
4988
|
+
functionStack.pop();
|
|
4989
|
+
};
|
|
4959
4990
|
return {
|
|
4960
|
-
FunctionDeclaration:
|
|
4961
|
-
|
|
4962
|
-
|
|
4963
|
-
|
|
4991
|
+
FunctionDeclaration: enterFunction,
|
|
4992
|
+
"FunctionDeclaration:exit": exitFunction,
|
|
4993
|
+
FunctionExpression: enterFunction,
|
|
4994
|
+
"FunctionExpression:exit": exitFunction,
|
|
4995
|
+
ArrowFunctionExpression: enterFunction,
|
|
4996
|
+
"ArrowFunctionExpression:exit": exitFunction,
|
|
4997
|
+
TSEmptyBodyFunctionExpression: enterFunction,
|
|
4998
|
+
"TSEmptyBodyFunctionExpression:exit": exitFunction,
|
|
4999
|
+
ReturnStatement(node) {
|
|
5000
|
+
const owner = functionStack.at(-1);
|
|
5001
|
+
if (owner === void 0 || owner.returnType !== void 0 || node.argument === null) return;
|
|
5002
|
+
reportExpression(owner, node.argument);
|
|
5003
|
+
},
|
|
4964
5004
|
TSDeclareFunction(node) {
|
|
4965
5005
|
if (node.id === null || node.returnType === void 0 || node.parent.type !== AST_NODE_TYPES18.ExportNamedDeclaration && node.parent.type !== AST_NODE_TYPES18.ExportDefaultDeclaration && !specifierExports.has(node.id.name)) return;
|
|
4966
5006
|
report(node.returnType.typeAnnotation, node.id.name);
|
|
@@ -11139,6 +11179,7 @@ var prefer_non_nullable_collection_default = createRule({
|
|
|
11139
11179
|
|
|
11140
11180
|
// src/rules/prefer-await-in-async-return.ts
|
|
11141
11181
|
import {
|
|
11182
|
+
ASTUtils as ASTUtils14,
|
|
11142
11183
|
ESLintUtils as ESLintUtils3,
|
|
11143
11184
|
AST_NODE_TYPES as AST_NODE_TYPES46
|
|
11144
11185
|
} from "@typescript-eslint/utils";
|
|
@@ -11151,7 +11192,8 @@ var preferAwaitInAsyncReturnDocumentation = {
|
|
|
11151
11192
|
since: "15.6.3",
|
|
11152
11193
|
limitations: [
|
|
11153
11194
|
"Only a single directly returned `.then` call with an inline callback is checked.",
|
|
11154
|
-
"The receiver must be proven Promise-like by TypeScript; untyped files and larger chains are intentionally ignored."
|
|
11195
|
+
"The receiver must be proven Promise-like by TypeScript; untyped files and larger chains are intentionally ignored.",
|
|
11196
|
+
"Direct loader callbacks passed to resolved `React.lazy` and `next/dynamic` imports are excluded because returning the module Promise is their framework contract."
|
|
11155
11197
|
],
|
|
11156
11198
|
examples: [
|
|
11157
11199
|
{
|
|
@@ -11180,19 +11222,19 @@ var preferAwaitInAsyncReturnDocumentation = {
|
|
|
11180
11222
|
}
|
|
11181
11223
|
]
|
|
11182
11224
|
};
|
|
11183
|
-
function
|
|
11225
|
+
function directAsyncReturnOwner(node) {
|
|
11184
11226
|
const parent = node.parent;
|
|
11185
11227
|
if (parent.type === AST_NODE_TYPES46.ArrowFunctionExpression && parent.body === node) {
|
|
11186
|
-
return parent.async && !parent.generator;
|
|
11228
|
+
return parent.async && !parent.generator ? parent : null;
|
|
11187
11229
|
}
|
|
11188
11230
|
if (parent.type !== AST_NODE_TYPES46.ReturnStatement || parent.argument !== node) {
|
|
11189
|
-
return
|
|
11231
|
+
return null;
|
|
11190
11232
|
}
|
|
11191
11233
|
let owner = parent.parent;
|
|
11192
11234
|
while (owner !== void 0 && !isRuntimeFunction(owner)) {
|
|
11193
11235
|
owner = owner.parent;
|
|
11194
11236
|
}
|
|
11195
|
-
return owner !== void 0 && owner.async && !owner.generator;
|
|
11237
|
+
return owner !== void 0 && owner.async && !owner.generator ? owner : null;
|
|
11196
11238
|
}
|
|
11197
11239
|
function isRuntimeFunction(node) {
|
|
11198
11240
|
return node.type === AST_NODE_TYPES46.ArrowFunctionExpression || node.type === AST_NODE_TYPES46.FunctionDeclaration || node.type === AST_NODE_TYPES46.FunctionExpression;
|
|
@@ -11249,9 +11291,33 @@ var prefer_await_in_async_return_default = createRule({
|
|
|
11249
11291
|
services = null;
|
|
11250
11292
|
}
|
|
11251
11293
|
if (services === null) return {};
|
|
11294
|
+
const frameworkLoaders = /* @__PURE__ */ new Set();
|
|
11295
|
+
const rememberFrameworkLoader = (identifier) => {
|
|
11296
|
+
const variable = ASTUtils14.findVariable(context.sourceCode.getScope(identifier), identifier.name);
|
|
11297
|
+
if (variable !== null) frameworkLoaders.add(variable);
|
|
11298
|
+
};
|
|
11299
|
+
const isFrameworkLoaderCallback = (owner) => {
|
|
11300
|
+
const parent = owner.parent;
|
|
11301
|
+
if (parent.type !== AST_NODE_TYPES46.CallExpression || parent.arguments[0] !== owner || parent.callee.type !== AST_NODE_TYPES46.Identifier) return false;
|
|
11302
|
+
const variable = ASTUtils14.findVariable(context.sourceCode.getScope(parent.callee), parent.callee.name);
|
|
11303
|
+
return variable !== null && frameworkLoaders.has(variable);
|
|
11304
|
+
};
|
|
11252
11305
|
return {
|
|
11306
|
+
ImportDeclaration(node) {
|
|
11307
|
+
if (node.source.value === "react") {
|
|
11308
|
+
for (const specifier of node.specifiers) {
|
|
11309
|
+
if (specifier.type === AST_NODE_TYPES46.ImportSpecifier && (specifier.imported.type === AST_NODE_TYPES46.Identifier ? specifier.imported.name : specifier.imported.value) === "lazy") rememberFrameworkLoader(specifier.local);
|
|
11310
|
+
}
|
|
11311
|
+
}
|
|
11312
|
+
if (node.source.value === "next/dynamic") {
|
|
11313
|
+
for (const specifier of node.specifiers) {
|
|
11314
|
+
if (specifier.type === AST_NODE_TYPES46.ImportDefaultSpecifier) rememberFrameworkLoader(specifier.local);
|
|
11315
|
+
}
|
|
11316
|
+
}
|
|
11317
|
+
},
|
|
11253
11318
|
CallExpression(node) {
|
|
11254
|
-
|
|
11319
|
+
const owner = directAsyncReturnOwner(node);
|
|
11320
|
+
if (owner === null || isFrameworkLoaderCallback(owner)) return;
|
|
11255
11321
|
const receiver = promiseThenReceiver(node);
|
|
11256
11322
|
if (receiver === null || !isProvenPromiseLike(receiver, services)) {
|
|
11257
11323
|
return;
|
|
@@ -12460,6 +12526,16 @@ function literalIndex(node) {
|
|
|
12460
12526
|
}
|
|
12461
12527
|
return Number.isInteger(node.value) && node.value >= 0 ? node.value : null;
|
|
12462
12528
|
}
|
|
12529
|
+
function propertyAccess(node) {
|
|
12530
|
+
const path = [];
|
|
12531
|
+
let current = node;
|
|
12532
|
+
while (current.type === AST_NODE_TYPES49.MemberExpression && !current.computed && !current.optional) {
|
|
12533
|
+
if (current.property.type !== AST_NODE_TYPES49.Identifier || COLLECTION_PROPERTIES.has(current.property.name) || LITERAL_KEY_HAZARDS.has(current.property.name)) return null;
|
|
12534
|
+
path.unshift(current.property.name);
|
|
12535
|
+
current = current.object;
|
|
12536
|
+
}
|
|
12537
|
+
return path.length > 0 && isPureReceiver(current) ? { receiver: current, path } : null;
|
|
12538
|
+
}
|
|
12463
12539
|
var prefer_whole_object_assertion_default = createRule({
|
|
12464
12540
|
name: "prefer-whole-object-assertion",
|
|
12465
12541
|
documentation: preferWholeObjectAssertionDocumentation,
|
|
@@ -12506,21 +12582,23 @@ var prefer_whole_object_assertion_default = createRule({
|
|
|
12506
12582
|
return null;
|
|
12507
12583
|
}
|
|
12508
12584
|
let key;
|
|
12585
|
+
let receiver;
|
|
12509
12586
|
if (actual.computed) {
|
|
12510
12587
|
const index = literalIndex(actual.property);
|
|
12511
12588
|
if (index === null) {
|
|
12512
12589
|
return null;
|
|
12513
12590
|
}
|
|
12514
12591
|
key = { kind: "index", index };
|
|
12592
|
+
receiver = actual.object;
|
|
12515
12593
|
} else {
|
|
12516
|
-
|
|
12517
|
-
|
|
12518
|
-
}
|
|
12519
|
-
|
|
12594
|
+
const access = propertyAccess(actual);
|
|
12595
|
+
if (access === null) return null;
|
|
12596
|
+
key = { kind: "property", path: access.path };
|
|
12597
|
+
receiver = access.receiver;
|
|
12520
12598
|
}
|
|
12521
12599
|
const synthetic = SYNTHETIC_LITERAL_MATCHERS.get(matcher);
|
|
12522
12600
|
if (synthetic !== void 0 && call.arguments.length === 0) {
|
|
12523
|
-
return { statement, receiver
|
|
12601
|
+
return { statement, receiver, key, matcher, expectedText: synthetic, expectedIsLiteral: true };
|
|
12524
12602
|
}
|
|
12525
12603
|
if (!MERGEABLE_MATCHERS.has(matcher)) {
|
|
12526
12604
|
return null;
|
|
@@ -12532,7 +12610,7 @@ var prefer_whole_object_assertion_default = createRule({
|
|
|
12532
12610
|
const literal = literalText(expected, (node) => sourceCode.getText(node));
|
|
12533
12611
|
return {
|
|
12534
12612
|
statement,
|
|
12535
|
-
receiver
|
|
12613
|
+
receiver,
|
|
12536
12614
|
key,
|
|
12537
12615
|
matcher,
|
|
12538
12616
|
expectedText: literal ?? sourceCode.getText(expected),
|
|
@@ -12545,7 +12623,8 @@ var prefer_whole_object_assertion_default = createRule({
|
|
|
12545
12623
|
);
|
|
12546
12624
|
}
|
|
12547
12625
|
function reportPropertyRun(run) {
|
|
12548
|
-
const
|
|
12626
|
+
const tree = /* @__PURE__ */ new Map();
|
|
12627
|
+
const paths = [];
|
|
12549
12628
|
for (const assertion of run) {
|
|
12550
12629
|
if (assertion.key.kind !== "property" || !assertion.expectedIsLiteral) {
|
|
12551
12630
|
return;
|
|
@@ -12553,19 +12632,44 @@ var prefer_whole_object_assertion_default = createRule({
|
|
|
12553
12632
|
if (!MERGEABLE_MATCHERS.has(assertion.matcher) && !SYNTHETIC_LITERAL_MATCHERS.has(assertion.matcher)) {
|
|
12554
12633
|
return;
|
|
12555
12634
|
}
|
|
12556
|
-
|
|
12557
|
-
|
|
12635
|
+
paths.push([...assertion.key.path]);
|
|
12636
|
+
}
|
|
12637
|
+
const commonPrefix = [];
|
|
12638
|
+
for (let index = 0; ; index += 1) {
|
|
12639
|
+
const candidate = paths[0]?.[index];
|
|
12640
|
+
if (candidate === void 0 || paths.some((path) => path[index] !== candidate || path.length === index + 1)) {
|
|
12641
|
+
break;
|
|
12642
|
+
}
|
|
12643
|
+
commonPrefix.push(candidate);
|
|
12644
|
+
}
|
|
12645
|
+
for (const [assertionIndex, assertion] of run.entries()) {
|
|
12646
|
+
if (assertion.key.kind !== "property") return;
|
|
12647
|
+
let branch = tree;
|
|
12648
|
+
const relativePath = paths[assertionIndex]?.slice(commonPrefix.length) ?? [];
|
|
12649
|
+
for (const [index, name] of relativePath.entries()) {
|
|
12650
|
+
const leaf = index === relativePath.length - 1;
|
|
12651
|
+
const existing = branch.get(name);
|
|
12652
|
+
if (leaf) {
|
|
12653
|
+
if (existing !== void 0) return;
|
|
12654
|
+
branch.set(name, assertion.expectedText);
|
|
12655
|
+
} else if (existing === void 0) {
|
|
12656
|
+
const nested = /* @__PURE__ */ new Map();
|
|
12657
|
+
branch.set(name, nested);
|
|
12658
|
+
branch = nested;
|
|
12659
|
+
} else if (existing instanceof Map) {
|
|
12660
|
+
branch = existing;
|
|
12661
|
+
} else {
|
|
12662
|
+
return;
|
|
12663
|
+
}
|
|
12558
12664
|
}
|
|
12559
|
-
names.add(assertion.key.name);
|
|
12560
12665
|
}
|
|
12561
12666
|
const first = run[0];
|
|
12562
12667
|
if (first === void 0) {
|
|
12563
12668
|
return;
|
|
12564
12669
|
}
|
|
12565
|
-
const receiverText = sourceCode.getText(first.receiver)
|
|
12566
|
-
const
|
|
12567
|
-
|
|
12568
|
-
).join(", ");
|
|
12670
|
+
const receiverText = `${sourceCode.getText(first.receiver)}${commonPrefix.map((name) => `.${name}`).join("")}`;
|
|
12671
|
+
const renderTree = (value) => [...value.entries()].map(([name, child]) => `${name}: ${child instanceof Map ? `{ ${renderTree(child)} }` : child}`).join(", ");
|
|
12672
|
+
const properties = renderTree(tree);
|
|
12569
12673
|
context.report({
|
|
12570
12674
|
node: first.statement,
|
|
12571
12675
|
messageId: "combineAssertions",
|
|
@@ -12641,7 +12745,7 @@ var prefer_whole_object_assertion_default = createRule({
|
|
|
12641
12745
|
});
|
|
12642
12746
|
|
|
12643
12747
|
// src/rules/repeated-static-call-cases.ts
|
|
12644
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES50, ASTUtils as
|
|
12748
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES50, ASTUtils as ASTUtils15 } from "@typescript-eslint/utils";
|
|
12645
12749
|
var repeatedStaticCallCasesDocumentation = {
|
|
12646
12750
|
summary: "Report three or more consecutive literal call assertions that should be independently named test cases.",
|
|
12647
12751
|
rationale: "Copy-pasted cases obscure the input table and stop later cases from being reported after the first failure.",
|
|
@@ -12667,7 +12771,7 @@ function staticMemberName5(node) {
|
|
|
12667
12771
|
return null;
|
|
12668
12772
|
}
|
|
12669
12773
|
function importedName3(identifier, context, modules) {
|
|
12670
|
-
const variable =
|
|
12774
|
+
const variable = ASTUtils15.findVariable(context.sourceCode.getScope(identifier), identifier.name);
|
|
12671
12775
|
if (variable === null || variable.defs.length === 0) return identifier.name;
|
|
12672
12776
|
for (const definition of variable.defs) {
|
|
12673
12777
|
if (definition.node.type !== AST_NODE_TYPES50.ImportSpecifier) continue;
|
|
@@ -13668,7 +13772,7 @@ var require_assert_never_default = createRule({
|
|
|
13668
13772
|
});
|
|
13669
13773
|
|
|
13670
13774
|
// src/rules/require-fetch-timeout.ts
|
|
13671
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES53, ASTUtils as
|
|
13775
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES53, ASTUtils as ASTUtils16 } from "@typescript-eslint/utils";
|
|
13672
13776
|
var requireFetchTimeoutDocumentation = {
|
|
13673
13777
|
summary: "Require an abort `signal` (e.g. `AbortSignal.timeout(ms)`) on global `fetch()` calls so stalled upstreams cannot hang the caller forever.",
|
|
13674
13778
|
rationale: "An unbounded request can occupy work indefinitely when an upstream stalls.",
|
|
@@ -13749,7 +13853,7 @@ var require_fetch_timeout_default = createRule({
|
|
|
13749
13853
|
}
|
|
13750
13854
|
function resolvesToGlobal(identifier) {
|
|
13751
13855
|
const scope = context.sourceCode.getScope(identifier);
|
|
13752
|
-
const variable =
|
|
13856
|
+
const variable = ASTUtils16.findVariable(scope, identifier.name);
|
|
13753
13857
|
return variable === null || variable.defs.length === 0;
|
|
13754
13858
|
}
|
|
13755
13859
|
function isGlobalFetchCall2(callee) {
|
|
@@ -13759,7 +13863,7 @@ var require_fetch_timeout_default = createRule({
|
|
|
13759
13863
|
return callee.type === AST_NODE_TYPES53.MemberExpression && !callee.computed && callee.property.type === AST_NODE_TYPES53.Identifier && callee.property.name === "fetch" && callee.object.type === AST_NODE_TYPES53.Identifier && GLOBAL_OBJECTS2.has(callee.object.name) && resolvesToGlobal(callee.object);
|
|
13760
13864
|
}
|
|
13761
13865
|
function localConstInitProvablyLacksSignal(identifier) {
|
|
13762
|
-
const variable =
|
|
13866
|
+
const variable = ASTUtils16.findVariable(
|
|
13763
13867
|
context.sourceCode.getScope(identifier),
|
|
13764
13868
|
identifier.name
|
|
13765
13869
|
);
|
|
@@ -14403,7 +14507,7 @@ var require_static_next_matcher_default = createRule({
|
|
|
14403
14507
|
// src/rules/require-zod-form-validation.ts
|
|
14404
14508
|
import {
|
|
14405
14509
|
AST_NODE_TYPES as AST_NODE_TYPES56,
|
|
14406
|
-
ASTUtils as
|
|
14510
|
+
ASTUtils as ASTUtils17
|
|
14407
14511
|
} from "@typescript-eslint/utils";
|
|
14408
14512
|
var requireZodFormValidationDocumentation = {
|
|
14409
14513
|
summary: "Require Zod validation (`Schema.parse(...)` / `Schema.safeParse(...)`) when reading values out of a `FormData` object.",
|
|
@@ -14471,7 +14575,7 @@ var require_zod_form_validation_default = createRule({
|
|
|
14471
14575
|
return {};
|
|
14472
14576
|
}
|
|
14473
14577
|
const zodBindings = /* @__PURE__ */ new Set();
|
|
14474
|
-
const resolvedBinding = (identifier) =>
|
|
14578
|
+
const resolvedBinding = (identifier) => ASTUtils17.findVariable(
|
|
14475
14579
|
context.sourceCode.getScope(identifier),
|
|
14476
14580
|
identifier.name
|
|
14477
14581
|
);
|
|
@@ -14768,7 +14872,7 @@ var store_insert_requires_on_conflict_default = createRule({
|
|
|
14768
14872
|
});
|
|
14769
14873
|
|
|
14770
14874
|
// src/rules/stepdown.ts
|
|
14771
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES57, ASTUtils as
|
|
14875
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES57, ASTUtils as ASTUtils18 } from "@typescript-eslint/utils";
|
|
14772
14876
|
var stepdownDocumentation = {
|
|
14773
14877
|
summary: "Place a private helper below its sole direct same-scope caller.",
|
|
14774
14878
|
rationale: "Caller-first ordering lets a reader follow the main flow before descending into implementation details.",
|
|
@@ -14968,7 +15072,7 @@ function methodName(node) {
|
|
|
14968
15072
|
return !node.computed && node.key.type === AST_NODE_TYPES57.Identifier ? node.key.name : null;
|
|
14969
15073
|
}
|
|
14970
15074
|
function referencedMethod(context, node, classVariables) {
|
|
14971
|
-
const objectVariable = node.object.type === AST_NODE_TYPES57.Identifier ?
|
|
15075
|
+
const objectVariable = node.object.type === AST_NODE_TYPES57.Identifier ? ASTUtils18.findVariable(context.sourceCode.getScope(node.object), node.object.name) : null;
|
|
14972
15076
|
const isClassReference = objectVariable !== null && classVariables.has(objectVariable);
|
|
14973
15077
|
if (node.object.type !== AST_NODE_TYPES57.ThisExpression && !isClassReference) return null;
|
|
14974
15078
|
if (node.property.type === AST_NODE_TYPES57.PrivateIdentifier) return `#${node.property.name}`;
|
|
@@ -15021,11 +15125,11 @@ function classScope(context, node, computedReferenceNames) {
|
|
|
15021
15125
|
const pinned = /* @__PURE__ */ new Set();
|
|
15022
15126
|
const classVariables = /* @__PURE__ */ new Set();
|
|
15023
15127
|
if (node.id !== null) {
|
|
15024
|
-
const internal =
|
|
15128
|
+
const internal = ASTUtils18.findVariable(context.sourceCode.getScope(node), node.id.name);
|
|
15025
15129
|
if (internal !== null) classVariables.add(internal);
|
|
15026
15130
|
}
|
|
15027
15131
|
if (node.type === AST_NODE_TYPES57.ClassExpression && node.parent.type === AST_NODE_TYPES57.VariableDeclarator && node.parent.id.type === AST_NODE_TYPES57.Identifier) {
|
|
15028
|
-
const outer =
|
|
15132
|
+
const outer = ASTUtils18.findVariable(context.sourceCode.getScope(node.parent), node.parent.id.name);
|
|
15029
15133
|
if (outer !== null) classVariables.add(outer);
|
|
15030
15134
|
}
|
|
15031
15135
|
for (const method of methods) {
|
|
@@ -15061,7 +15165,7 @@ function classScope(context, node, computedReferenceNames) {
|
|
|
15061
15165
|
return;
|
|
15062
15166
|
}
|
|
15063
15167
|
if (binding.type !== AST_NODE_TYPES57.Identifier) return;
|
|
15064
|
-
const variable =
|
|
15168
|
+
const variable = ASTUtils18.findVariable(context.sourceCode.getScope(binding), binding.name);
|
|
15065
15169
|
if (variable !== null) {
|
|
15066
15170
|
methodClassVariables.add(variable);
|
|
15067
15171
|
methodAliases.add(variable);
|
|
@@ -15091,7 +15195,7 @@ function classScope(context, node, computedReferenceNames) {
|
|
|
15091
15195
|
return;
|
|
15092
15196
|
}
|
|
15093
15197
|
if (!privateNames.has(target)) return;
|
|
15094
|
-
const objectVariable = current.object.type === AST_NODE_TYPES57.Identifier ?
|
|
15198
|
+
const objectVariable = current.object.type === AST_NODE_TYPES57.Identifier ? ASTUtils18.findVariable(context.sourceCode.getScope(current.object), current.object.name) : null;
|
|
15095
15199
|
if (objectVariable !== null && methodAliases.has(objectVariable)) {
|
|
15096
15200
|
pinned.add(target);
|
|
15097
15201
|
return;
|
|
@@ -15199,7 +15303,7 @@ var stepdown_default = createRule({
|
|
|
15199
15303
|
|
|
15200
15304
|
// src/rules/source-coupled-test.ts
|
|
15201
15305
|
import { AST_NODE_TYPES as AST_NODE_TYPES58 } from "@typescript-eslint/utils";
|
|
15202
|
-
var GENERAL_SOURCE_SUFFIX_RE = /\.(?:bash|sh|ya?ml|py|[cm]?[jt]s)$/iu;
|
|
15306
|
+
var GENERAL_SOURCE_SUFFIX_RE = /\.(?:bash|sh|ya?ml|jsonc|py|[cm]?[jt]s)$/iu;
|
|
15203
15307
|
var FS_MODULES = /* @__PURE__ */ new Set(["fs", "node:fs", "fs/promises", "node:fs/promises"]);
|
|
15204
15308
|
var FS_READERS = /* @__PURE__ */ new Set(["readFile", "readFileSync"]);
|
|
15205
15309
|
var TEXT_TRANSFORMS = /* @__PURE__ */ new Set([
|
|
@@ -15394,6 +15498,13 @@ function createSourceCoupledRule(name, documentation, sourceSuffixRe) {
|
|
|
15394
15498
|
if (receiver.type !== AST_NODE_TYPES58.Identifier || receiver.name !== "assert" || !ASSERT_MATCHERS.has(matcher)) return /* @__PURE__ */ new Set();
|
|
15395
15499
|
return new Set(node.arguments.flatMap((argument) => argument.type === AST_NODE_TYPES58.SpreadElement ? [] : [...evidenceOrigins(argument)]));
|
|
15396
15500
|
};
|
|
15501
|
+
const rawRegexExtractionOrigins = (node) => {
|
|
15502
|
+
const callee = unwrap5(node.callee);
|
|
15503
|
+
if (callee.type !== AST_NODE_TYPES58.MemberExpression || staticMemberName7(callee) !== "matchAll" || node.arguments.length !== 1) return /* @__PURE__ */ new Set();
|
|
15504
|
+
const argument = node.arguments[0];
|
|
15505
|
+
if (argument?.type !== AST_NODE_TYPES58.Literal || !(argument.value instanceof RegExp)) return /* @__PURE__ */ new Set();
|
|
15506
|
+
return rawOrigins(callee.object);
|
|
15507
|
+
};
|
|
15397
15508
|
const declare = (name2, state) => {
|
|
15398
15509
|
const scope = currentScope();
|
|
15399
15510
|
scope.declared.add(name2);
|
|
@@ -15473,7 +15584,10 @@ function createSourceCoupledRule(name, documentation, sourceSuffixRe) {
|
|
|
15473
15584
|
if (collection && left?.type === AST_NODE_TYPES58.Identifier) declare(left.name, { path: true });
|
|
15474
15585
|
},
|
|
15475
15586
|
CallExpression(node) {
|
|
15476
|
-
const origins =
|
|
15587
|
+
const origins = /* @__PURE__ */ new Set([
|
|
15588
|
+
...rawAssertionOrigins(node),
|
|
15589
|
+
...rawRegexExtractionOrigins(node)
|
|
15590
|
+
]);
|
|
15477
15591
|
if (origins.size === 0 || [...origins].every((origin) => reportedOrigins.has(origin))) return;
|
|
15478
15592
|
for (const origin of origins) reportedOrigins.add(origin);
|
|
15479
15593
|
context.report({ node, messageId: "rawSourceOracle" });
|
|
@@ -15529,7 +15643,7 @@ var iac_source_coupled_test_default = createSourceCoupledRule(
|
|
|
15529
15643
|
// src/rules/zod-naming-convention.ts
|
|
15530
15644
|
import {
|
|
15531
15645
|
AST_NODE_TYPES as AST_NODE_TYPES59,
|
|
15532
|
-
ASTUtils as
|
|
15646
|
+
ASTUtils as ASTUtils19
|
|
15533
15647
|
} from "@typescript-eslint/utils";
|
|
15534
15648
|
var zodNamingConventionDocumentation = {
|
|
15535
15649
|
summary: "Enforce a consistent Zod schema naming convention \u2014 a `Z` prefix (`ZUser`) or a `Schema` suffix (`userSchema`); both are accepted by default.",
|
|
@@ -15622,7 +15736,7 @@ var zod_naming_convention_default = createRule({
|
|
|
15622
15736
|
const acceptsSchemaWord = convention !== "prefix";
|
|
15623
15737
|
const zodBindings = /* @__PURE__ */ new Set();
|
|
15624
15738
|
function resolvedBinding(identifier) {
|
|
15625
|
-
return
|
|
15739
|
+
return ASTUtils19.findVariable(
|
|
15626
15740
|
context.sourceCode.getScope(identifier),
|
|
15627
15741
|
identifier.name
|
|
15628
15742
|
);
|
|
@@ -15824,7 +15938,7 @@ var rules = {
|
|
|
15824
15938
|
};
|
|
15825
15939
|
var meta = {
|
|
15826
15940
|
name: "@sarj/eslint-plugin",
|
|
15827
|
-
version: "15.
|
|
15941
|
+
version: "15.9.0"
|
|
15828
15942
|
};
|
|
15829
15943
|
var applicationOnlyRules = [
|
|
15830
15944
|
"no-restricted-library-load",
|