@sarj/eslint-plugin 11.0.1 → 11.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +392 -74
- package/dist/index.d.cts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +392 -74
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -827,6 +827,7 @@ var BANNER_RUN_RE = /={4,}|-{4,}|#{4,}|\*{4,}|~{4,}|[\u2500-\u257f]{4,}/;
|
|
|
827
827
|
var REGION_MARKER_RE = /^#?(?:end)?region\b(.*)$/i;
|
|
828
828
|
var REGION_TITLE_RE = /^[\s:\-\u2013\u2014]*\w[\w \-/&+]*$/;
|
|
829
829
|
var REGION_TITLE_MAX_WORDS = 5;
|
|
830
|
+
var REGION_PROSE_VERB_RE = /^(?:is|are|was|were|comes?|defaults?|derives?|inherits?|depends?|uses?|maps?|resolves?)\b/i;
|
|
830
831
|
function stripCommentMarker(line) {
|
|
831
832
|
return line.replace(/^\s*\/{1,2}/, "").replace(/^\s*\*+/, "").trim();
|
|
832
833
|
}
|
|
@@ -888,7 +889,9 @@ var CALL_RE = /^[A-Za-z_$][\w.$]*\([^)]*\)\s*;?\s*$/;
|
|
|
888
889
|
var ASSERTION_CODE_RE = /^(?:await\s+)?(?:expect(?:TypeOf)?|assert(?:\.\w+)?)\s*\(/;
|
|
889
890
|
var HTTP_CONTRACT_RE = /\b(?:GET|HEAD|OPTIONS|PATCH|POST|PUT|DELETE)\s+(?:https?:\/\/|\/|\{[A-Za-z_$])/;
|
|
890
891
|
var PROSE_ASSIGNMENT_RE = /^[A-Za-z_$][\w.$[\]]*\s*=\s*[A-Za-z][A-Za-z '-]{2,}\s+\((?:how|what|when|where|which|who|why)\b[^)]*\)[.!]?$/i;
|
|
891
|
-
var PSEUDOCODE_RE = /%\w+%|\[opt\]|(?:^|\s)<[A-Za-z]\w
|
|
892
|
+
var PSEUDOCODE_RE = /%\w+%|\[opt\]|(?:^|\s)<[A-Za-z]\w*>|\b[A-Za-z_$][\w$]*\s+x\d+\b|…|\.\.\./;
|
|
893
|
+
var CALL_LABEL_RE = /^([A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*)\([^;{}]*\)$/;
|
|
894
|
+
var MULTIPLIER_PSEUDOCODE_RE = /\b[A-Za-z_$][\w$]*\s+x\d+\b/;
|
|
892
895
|
function isBanner(text) {
|
|
893
896
|
const t = text.trim();
|
|
894
897
|
if (!t) return false;
|
|
@@ -900,6 +903,7 @@ function isRegionMarker(text) {
|
|
|
900
903
|
if (match === null) return false;
|
|
901
904
|
const title = (match[1] ?? "").trim();
|
|
902
905
|
if (title.length === 0) return true;
|
|
906
|
+
if (REGION_PROSE_VERB_RE.test(title)) return false;
|
|
903
907
|
if (!REGION_TITLE_RE.test(title)) return false;
|
|
904
908
|
return title.split(/\s+/).length <= REGION_TITLE_MAX_WORDS;
|
|
905
909
|
}
|
|
@@ -915,6 +919,15 @@ function looksLikeCode(text, allowCall = true) {
|
|
|
915
919
|
function hasPseudocode(text) {
|
|
916
920
|
return PSEUDOCODE_RE.test(text);
|
|
917
921
|
}
|
|
922
|
+
function testCallMatrixStems(comments) {
|
|
923
|
+
const stems = /* @__PURE__ */ new Set();
|
|
924
|
+
for (const comment of comments) {
|
|
925
|
+
const body2 = stripCommentMarker(comment.value);
|
|
926
|
+
const stem3 = CALL_LABEL_RE.exec(body2)?.[1];
|
|
927
|
+
if (stem3 !== void 0 && MULTIPLIER_PSEUDOCODE_RE.test(body2)) stems.add(stem3);
|
|
928
|
+
}
|
|
929
|
+
return stems;
|
|
930
|
+
}
|
|
918
931
|
function isEnumeratedProseItem(text) {
|
|
919
932
|
const t = text.trim();
|
|
920
933
|
return ENUMERATED_ITEM_RE.test(t) && t.split(/\s+/).length >= ENUMERATED_ITEM_MIN_WORDS;
|
|
@@ -1203,6 +1216,7 @@ var no_comment_cruft_default = createRule({
|
|
|
1203
1216
|
return {
|
|
1204
1217
|
Program() {
|
|
1205
1218
|
const comments = sourceCode.getAllComments();
|
|
1219
|
+
const callMatrixStems = isTestFile(context.filename) ? testCallMatrixStems(comments) : /* @__PURE__ */ new Set();
|
|
1206
1220
|
const walls = findCommentWalls(comments);
|
|
1207
1221
|
const wallByLeader = new Map(walls.map((wall) => [wall.leader, wall]));
|
|
1208
1222
|
const wallMembers = new Set(walls.flatMap((wall) => [...wall.members]));
|
|
@@ -1240,6 +1254,8 @@ var no_comment_cruft_default = createRule({
|
|
|
1240
1254
|
continue;
|
|
1241
1255
|
}
|
|
1242
1256
|
const firstText = texts[0];
|
|
1257
|
+
const firstTextStem = firstText === void 0 ? void 0 : CALL_LABEL_RE.exec(firstText)?.[1];
|
|
1258
|
+
if (firstTextStem !== void 0 && texts.length === 1 && callMatrixStems.has(firstTextStem)) continue;
|
|
1243
1259
|
if (firstText !== void 0 && /^(?:todo|fixme)\b/i.test(firstText)) {
|
|
1244
1260
|
if (!runCitesAReference(comments, i)) {
|
|
1245
1261
|
context.report({
|
|
@@ -2169,6 +2185,20 @@ var PURE_METHODS = /* @__PURE__ */ new Set([
|
|
|
2169
2185
|
"startsWith",
|
|
2170
2186
|
"endsWith"
|
|
2171
2187
|
]);
|
|
2188
|
+
var SYNC_CALLBACK_METHODS = /* @__PURE__ */ new Set([
|
|
2189
|
+
"every",
|
|
2190
|
+
"filter",
|
|
2191
|
+
"findIndex",
|
|
2192
|
+
"findLast",
|
|
2193
|
+
"findLastIndex",
|
|
2194
|
+
"flatMap",
|
|
2195
|
+
"forEach",
|
|
2196
|
+
"map",
|
|
2197
|
+
"reduce",
|
|
2198
|
+
"reduceRight",
|
|
2199
|
+
"some",
|
|
2200
|
+
"sort"
|
|
2201
|
+
]);
|
|
2172
2202
|
var PURE_NAMESPACES = /* @__PURE__ */ new Set([
|
|
2173
2203
|
"Object",
|
|
2174
2204
|
"Array",
|
|
@@ -2218,7 +2248,17 @@ function isPureCall(node) {
|
|
|
2218
2248
|
if (callee.object.type === AST_NODE_TYPES10.Identifier && PURE_NAMESPACES.has(callee.object.name)) {
|
|
2219
2249
|
return !IMPURE_NAMESPACE_METHODS.has(`${callee.object.name}.${property.name}`);
|
|
2220
2250
|
}
|
|
2221
|
-
return PURE_METHODS.has(property.name);
|
|
2251
|
+
return PURE_METHODS.has(property.name) && (!SYNC_CALLBACK_METHODS.has(property.name) || !synchronousCallbackCanThrow(node));
|
|
2252
|
+
}
|
|
2253
|
+
function synchronousCallbackCanThrow(node) {
|
|
2254
|
+
return node.arguments.some((argument) => {
|
|
2255
|
+
if (argument.type !== AST_NODE_TYPES10.ArrowFunctionExpression && argument.type !== AST_NODE_TYPES10.FunctionExpression) return false;
|
|
2256
|
+
if (argument.async) return false;
|
|
2257
|
+
return subtreeMatches2(
|
|
2258
|
+
argument.body,
|
|
2259
|
+
(current) => current.type === AST_NODE_TYPES10.ThrowStatement || current.type === AST_NODE_TYPES10.CallExpression && current.callee.type === AST_NODE_TYPES10.MemberExpression && !current.callee.computed && current.callee.object.type === AST_NODE_TYPES10.Identifier && current.callee.object.name === "JSON" && current.callee.property.type === AST_NODE_TYPES10.Identifier && current.callee.property.name === "parse"
|
|
2260
|
+
);
|
|
2261
|
+
});
|
|
2222
2262
|
}
|
|
2223
2263
|
function isPureNew(node) {
|
|
2224
2264
|
return node.callee.type === AST_NODE_TYPES10.Identifier && PURE_CONSTRUCTORS.has(node.callee.name);
|
|
@@ -2899,6 +2939,16 @@ var PAYLOAD_PROPS = /* @__PURE__ */ new Set([
|
|
|
2899
2939
|
"metadata",
|
|
2900
2940
|
"context"
|
|
2901
2941
|
]);
|
|
2942
|
+
var BUILTIN_ERROR_CONSTRUCTORS = /* @__PURE__ */ new Set([
|
|
2943
|
+
"AggregateError",
|
|
2944
|
+
"Error",
|
|
2945
|
+
"EvalError",
|
|
2946
|
+
"RangeError",
|
|
2947
|
+
"ReferenceError",
|
|
2948
|
+
"SyntaxError",
|
|
2949
|
+
"TypeError",
|
|
2950
|
+
"URIError"
|
|
2951
|
+
]);
|
|
2902
2952
|
function isCatchBinding(scope, name) {
|
|
2903
2953
|
let current = scope;
|
|
2904
2954
|
while (current) {
|
|
@@ -3013,6 +3063,48 @@ function nodeWithin(node, container) {
|
|
|
3013
3063
|
function isJsonStringify(callee) {
|
|
3014
3064
|
return callee.type === "MemberExpression" && !callee.computed && callee.object.type === "Identifier" && callee.object.name === "JSON" && callee.property.type === "Identifier" && callee.property.name === "stringify";
|
|
3015
3065
|
}
|
|
3066
|
+
function directLiteralValues(argument) {
|
|
3067
|
+
if (argument.type === "ObjectExpression") {
|
|
3068
|
+
return argument.properties.flatMap((property) => {
|
|
3069
|
+
if (property.type !== "Property" || property.computed) return [];
|
|
3070
|
+
const value = property.value;
|
|
3071
|
+
if (value.type === "AssignmentPattern" || value.type === "ArrayPattern" || value.type === "ObjectPattern" || value.type === "TSEmptyBodyFunctionExpression") {
|
|
3072
|
+
return [];
|
|
3073
|
+
}
|
|
3074
|
+
return [value];
|
|
3075
|
+
});
|
|
3076
|
+
}
|
|
3077
|
+
if (argument.type === "ArrayExpression") {
|
|
3078
|
+
return argument.elements.flatMap(
|
|
3079
|
+
(element) => element !== null && element.type !== "SpreadElement" ? [element] : []
|
|
3080
|
+
);
|
|
3081
|
+
}
|
|
3082
|
+
return argument.type === "SpreadElement" ? [] : [argument];
|
|
3083
|
+
}
|
|
3084
|
+
function expressionSuggestsError(expression, scope) {
|
|
3085
|
+
if (expression.type === "Identifier") {
|
|
3086
|
+
return ERROR_NAME_PATTERN.test(expression.name) || isCatchBinding(scope, expression.name);
|
|
3087
|
+
}
|
|
3088
|
+
return expression.type === "MemberExpression" && memberSuggestsError(expression, scope);
|
|
3089
|
+
}
|
|
3090
|
+
function nestedExpressionSuggestsError(expression, scope) {
|
|
3091
|
+
if (expression.type === "Identifier") {
|
|
3092
|
+
if (isCatchBinding(scope, expression.name)) return true;
|
|
3093
|
+
let current = scope;
|
|
3094
|
+
while (current !== null && !current.set.has(expression.name)) {
|
|
3095
|
+
current = current.upper;
|
|
3096
|
+
}
|
|
3097
|
+
const variable = current?.set.get(expression.name);
|
|
3098
|
+
if (variable === void 0 || variable.defs.length !== 1) return false;
|
|
3099
|
+
const definition = variable.defs[0];
|
|
3100
|
+
if (definition?.type !== "Variable") return false;
|
|
3101
|
+
const initializer = definition.node.init;
|
|
3102
|
+
return initializer?.type === "NewExpression" && initializer.callee.type === "Identifier" && BUILTIN_ERROR_CONSTRUCTORS.has(initializer.callee.name) && variable.references.every(
|
|
3103
|
+
(reference) => !reference.isWrite() || reference.init === true
|
|
3104
|
+
);
|
|
3105
|
+
}
|
|
3106
|
+
return expression.type === "MemberExpression" && memberSuggestsError(expression, scope);
|
|
3107
|
+
}
|
|
3016
3108
|
var no_json_stringify_error_default = createRule({
|
|
3017
3109
|
name: "no-json-stringify-error",
|
|
3018
3110
|
meta: {
|
|
@@ -3037,18 +3129,11 @@ var no_json_stringify_error_default = createRule({
|
|
|
3037
3129
|
return;
|
|
3038
3130
|
}
|
|
3039
3131
|
const scope = context.sourceCode.getScope(firstArg);
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
} else {
|
|
3046
|
-
return;
|
|
3047
|
-
}
|
|
3048
|
-
if (!suggestsError) {
|
|
3049
|
-
return;
|
|
3050
|
-
}
|
|
3051
|
-
if (isGuardedByInstanceofError(node, firstArg, context.sourceCode) || isNarrowedByEarlyReturn(node, firstArg, context.sourceCode)) {
|
|
3132
|
+
const isNestedLiteral = firstArg.type === "ObjectExpression" || firstArg.type === "ArrayExpression";
|
|
3133
|
+
const unsafeValue = directLiteralValues(firstArg).find(
|
|
3134
|
+
(value) => (isNestedLiteral ? nestedExpressionSuggestsError(value, scope) : expressionSuggestsError(value, scope)) && !isGuardedByInstanceofError(node, value, context.sourceCode) && !isNarrowedByEarlyReturn(node, value, context.sourceCode)
|
|
3135
|
+
);
|
|
3136
|
+
if (unsafeValue === void 0) {
|
|
3052
3137
|
return;
|
|
3053
3138
|
}
|
|
3054
3139
|
context.report({
|
|
@@ -3435,6 +3520,8 @@ function typedFunction(node) {
|
|
|
3435
3520
|
|
|
3436
3521
|
// src/rules/no-long-comment.ts
|
|
3437
3522
|
var EXCESSIVE_SENTENCE_COUNT = 8;
|
|
3523
|
+
var EXCESSIVE_WORD_COUNT = 120;
|
|
3524
|
+
var PROSE_WORD_RE = /[\p{L}\p{N}][\p{L}\p{N}'’-]*/gu;
|
|
3438
3525
|
var VERSIONED_DEPENDENCY_TREE_RE = /(?:^|\/)lib\/[^/]*-?v?\d+\.\d+(?:\.\d+)?[^/]*\//iu;
|
|
3439
3526
|
function documentsTypeOrMember(sourceCode, comment) {
|
|
3440
3527
|
const token = sourceCode.getTokenAfter(comment, { includeComments: false });
|
|
@@ -3446,6 +3533,9 @@ function documentsTypeOrMember(sourceCode, comment) {
|
|
|
3446
3533
|
}
|
|
3447
3534
|
return false;
|
|
3448
3535
|
}
|
|
3536
|
+
function wordUnits(text) {
|
|
3537
|
+
return text.match(PROSE_WORD_RE)?.length ?? 0;
|
|
3538
|
+
}
|
|
3449
3539
|
var no_long_comment_default = createRule({
|
|
3450
3540
|
name: "no-long-comment",
|
|
3451
3541
|
meta: {
|
|
@@ -3463,7 +3553,7 @@ var no_long_comment_default = createRule({
|
|
|
3463
3553
|
return {
|
|
3464
3554
|
Program() {
|
|
3465
3555
|
for (const group of proseGroups(context.filename, context.sourceCode)) {
|
|
3466
|
-
if (group.comment.type !== "Block" || !group.comment.value.startsWith("*") || group.hasTypedTags || hasDocumentationStructure(group.text) || hasTechnicalAnchor(group.text) || documentsTypedFunction(context.sourceCode, group.comment) || documentsTypeOrMember(context.sourceCode, group.comment) || sentenceUnits(group.text) < EXCESSIVE_SENTENCE_COUNT) continue;
|
|
3556
|
+
if (group.comment.type !== "Block" || !group.comment.value.startsWith("*") || group.hasTypedTags || hasDocumentationStructure(group.text) || hasTechnicalAnchor(group.text) || documentsTypedFunction(context.sourceCode, group.comment) || documentsTypeOrMember(context.sourceCode, group.comment) || sentenceUnits(group.text) < EXCESSIVE_SENTENCE_COUNT && wordUnits(group.text) < EXCESSIVE_WORD_COUNT) continue;
|
|
3467
3557
|
context.report({ node: group.comment, messageId: "tooLong" });
|
|
3468
3558
|
}
|
|
3469
3559
|
}
|
|
@@ -5118,50 +5208,59 @@ var no_select_star_default = createRule({
|
|
|
5118
5208
|
|
|
5119
5209
|
// src/rules/no-sentinel-return-on-catch.ts
|
|
5120
5210
|
import { AST_NODE_TYPES as AST_NODE_TYPES23 } from "@typescript-eslint/utils";
|
|
5211
|
+
function unwrapSentinelExpression(arg) {
|
|
5212
|
+
let current = arg;
|
|
5213
|
+
while (current?.type === AST_NODE_TYPES23.TSAsExpression || current?.type === AST_NODE_TYPES23.TSTypeAssertion || current?.type === AST_NODE_TYPES23.TSSatisfiesExpression) {
|
|
5214
|
+
current = current.expression;
|
|
5215
|
+
}
|
|
5216
|
+
return current;
|
|
5217
|
+
}
|
|
5121
5218
|
function sentinelKind(arg) {
|
|
5122
|
-
|
|
5219
|
+
const value = unwrapSentinelExpression(arg);
|
|
5220
|
+
if (value === null) {
|
|
5123
5221
|
return null;
|
|
5124
5222
|
}
|
|
5125
|
-
if (
|
|
5126
|
-
if (
|
|
5223
|
+
if (value.type === AST_NODE_TYPES23.Literal) {
|
|
5224
|
+
if (value.value === null) {
|
|
5127
5225
|
return "nullish";
|
|
5128
5226
|
}
|
|
5129
|
-
if (typeof
|
|
5227
|
+
if (typeof value.value === "boolean") {
|
|
5130
5228
|
return "boolean";
|
|
5131
5229
|
}
|
|
5132
|
-
if (typeof
|
|
5230
|
+
if (typeof value.value === "string") {
|
|
5133
5231
|
return "string";
|
|
5134
5232
|
}
|
|
5135
5233
|
return null;
|
|
5136
5234
|
}
|
|
5137
|
-
if (
|
|
5235
|
+
if (value.type === AST_NODE_TYPES23.Identifier && value.name === "undefined") {
|
|
5138
5236
|
return "nullish";
|
|
5139
5237
|
}
|
|
5140
|
-
if (
|
|
5238
|
+
if (value.type === AST_NODE_TYPES23.ArrayExpression) {
|
|
5141
5239
|
return "array";
|
|
5142
5240
|
}
|
|
5143
|
-
if (
|
|
5241
|
+
if (value.type === AST_NODE_TYPES23.ObjectExpression) {
|
|
5144
5242
|
return "object";
|
|
5145
5243
|
}
|
|
5146
5244
|
return null;
|
|
5147
5245
|
}
|
|
5148
5246
|
function isSentinelArgument(arg) {
|
|
5149
|
-
|
|
5247
|
+
const value = unwrapSentinelExpression(arg);
|
|
5248
|
+
if (value === null) {
|
|
5150
5249
|
return false;
|
|
5151
5250
|
}
|
|
5152
|
-
if (
|
|
5251
|
+
if (value.type === AST_NODE_TYPES23.Literal && value.value === null) {
|
|
5153
5252
|
return true;
|
|
5154
5253
|
}
|
|
5155
|
-
if (
|
|
5254
|
+
if (value.type === AST_NODE_TYPES23.Literal && value.value === false) {
|
|
5156
5255
|
return true;
|
|
5157
5256
|
}
|
|
5158
|
-
if (
|
|
5257
|
+
if (value.type === AST_NODE_TYPES23.Identifier && value.name === "undefined") {
|
|
5159
5258
|
return true;
|
|
5160
5259
|
}
|
|
5161
|
-
if (
|
|
5260
|
+
if (value.type === AST_NODE_TYPES23.ArrayExpression && value.elements.length === 0) {
|
|
5162
5261
|
return true;
|
|
5163
5262
|
}
|
|
5164
|
-
if (
|
|
5263
|
+
if (value.type === AST_NODE_TYPES23.ObjectExpression && value.properties.length === 0) {
|
|
5165
5264
|
return true;
|
|
5166
5265
|
}
|
|
5167
5266
|
return false;
|
|
@@ -5359,6 +5458,16 @@ function tryReturnsSafeParse(catchNode) {
|
|
|
5359
5458
|
const only = tryBlock.body.length === 1 ? tryBlock.body[0] : void 0;
|
|
5360
5459
|
return only !== void 0 && returnsMatching(only, isBodyDecodeNode);
|
|
5361
5460
|
}
|
|
5461
|
+
function isIntentionalStackCapture(catchNode, caughtName) {
|
|
5462
|
+
if (caughtName === null) return false;
|
|
5463
|
+
const tryBody = tryBlockOf(catchNode).body;
|
|
5464
|
+
const only = tryBody.length === 1 ? tryBody[0] : void 0;
|
|
5465
|
+
if (only?.type !== AST_NODE_TYPES23.ThrowStatement) return false;
|
|
5466
|
+
const thrown = unwrapSentinelExpression(only.argument);
|
|
5467
|
+
const constructsError = (thrown?.type === AST_NODE_TYPES23.CallExpression || thrown?.type === AST_NODE_TYPES23.NewExpression) && thrown.callee.type === AST_NODE_TYPES23.Identifier && thrown.callee.name === "Error";
|
|
5468
|
+
if (!constructsError) return false;
|
|
5469
|
+
return catchNode.body.body.slice(0, -1).some((statement) => subtreeReadsName(statement, caughtName));
|
|
5470
|
+
}
|
|
5362
5471
|
function tryBlockOf(catchNode) {
|
|
5363
5472
|
return catchNode.parent.block;
|
|
5364
5473
|
}
|
|
@@ -5479,6 +5588,9 @@ var no_sentinel_return_on_catch_default = createRule({
|
|
|
5479
5588
|
if (tryReturnsSafeParse(node)) {
|
|
5480
5589
|
return;
|
|
5481
5590
|
}
|
|
5591
|
+
if (isIntentionalStackCapture(node, caughtName)) {
|
|
5592
|
+
return;
|
|
5593
|
+
}
|
|
5482
5594
|
const kind = sentinelKind(last.argument);
|
|
5483
5595
|
if (kind !== null && isNamedBooleanPredicate(node, kind)) {
|
|
5484
5596
|
return;
|
|
@@ -5557,11 +5669,11 @@ var no_silent_promise_catch_default = createRule({
|
|
|
5557
5669
|
meta: {
|
|
5558
5670
|
type: "problem",
|
|
5559
5671
|
docs: {
|
|
5560
|
-
description: "Disallow `.catch()` handlers that silently swallow
|
|
5672
|
+
description: "Disallow `.catch()` and second-argument `.then()` handlers that silently swallow a rejection; log, rethrow, or handle the error."
|
|
5561
5673
|
},
|
|
5562
5674
|
schema: [],
|
|
5563
5675
|
messages: {
|
|
5564
|
-
silentCatch: "This
|
|
5676
|
+
silentCatch: "This rejection handler swallows the error without logging, rethrowing, or handling it \u2014 failures become invisible and callers get an indistinguishable sentinel. Log the error (and only then map to a fallback), or let it propagate."
|
|
5565
5677
|
}
|
|
5566
5678
|
},
|
|
5567
5679
|
defaultOptions: [],
|
|
@@ -5587,9 +5699,12 @@ var no_silent_promise_catch_default = createRule({
|
|
|
5587
5699
|
};
|
|
5588
5700
|
return {
|
|
5589
5701
|
CallExpression(node) {
|
|
5590
|
-
if (node.callee.type !== AST_NODE_TYPES24.MemberExpression || node.callee.computed || node.callee.property.type !== AST_NODE_TYPES24.Identifier
|
|
5702
|
+
if (node.callee.type !== AST_NODE_TYPES24.MemberExpression || node.callee.computed || node.callee.property.type !== AST_NODE_TYPES24.Identifier) {
|
|
5591
5703
|
return;
|
|
5592
5704
|
}
|
|
5705
|
+
const method = node.callee.property.name;
|
|
5706
|
+
const handlerIndex = method === "catch" ? 0 : method === "then" ? 1 : null;
|
|
5707
|
+
if (handlerIndex === null) return;
|
|
5593
5708
|
if (isBodyParseCall(node.callee.object)) {
|
|
5594
5709
|
return;
|
|
5595
5710
|
}
|
|
@@ -5599,10 +5714,11 @@ var no_silent_promise_catch_default = createRule({
|
|
|
5599
5714
|
if (node.parent.type === AST_NODE_TYPES24.MemberExpression && node.parent.object === node) {
|
|
5600
5715
|
return;
|
|
5601
5716
|
}
|
|
5602
|
-
|
|
5717
|
+
const expectedArguments = method === "catch" ? 1 : 2;
|
|
5718
|
+
if (node.arguments.length !== expectedArguments) {
|
|
5603
5719
|
return;
|
|
5604
5720
|
}
|
|
5605
|
-
const handler = node.arguments[
|
|
5721
|
+
const handler = node.arguments[handlerIndex];
|
|
5606
5722
|
if (handler === void 0 || handler.type !== AST_NODE_TYPES24.ArrowFunctionExpression && handler.type !== AST_NODE_TYPES24.FunctionExpression) {
|
|
5607
5723
|
return;
|
|
5608
5724
|
}
|
|
@@ -5865,6 +5981,11 @@ function isStringLiteralInit(node) {
|
|
|
5865
5981
|
return false;
|
|
5866
5982
|
}
|
|
5867
5983
|
function isConcatOntoTarget(rhs, target) {
|
|
5984
|
+
if (rhs.type === "TemplateLiteral") {
|
|
5985
|
+
return rhs.expressions.some(
|
|
5986
|
+
(expression) => expression.type === "Identifier" && expression.name === target
|
|
5987
|
+
);
|
|
5988
|
+
}
|
|
5868
5989
|
if (rhs.type !== "BinaryExpression" || rhs.operator !== "+") {
|
|
5869
5990
|
return false;
|
|
5870
5991
|
}
|
|
@@ -7420,6 +7541,15 @@ var SUCCESS_PAYLOAD_MEMBER_NAMES = /* @__PURE__ */ new Set([
|
|
|
7420
7541
|
"value"
|
|
7421
7542
|
]);
|
|
7422
7543
|
var REQUIRED_STATUS_MEMBER_COUNT = 1;
|
|
7544
|
+
var FUNCTION_RETURN_OWNER_TYPES = /* @__PURE__ */ new Set([
|
|
7545
|
+
AST_NODE_TYPES37.ArrowFunctionExpression,
|
|
7546
|
+
AST_NODE_TYPES37.FunctionDeclaration,
|
|
7547
|
+
AST_NODE_TYPES37.FunctionExpression,
|
|
7548
|
+
AST_NODE_TYPES37.TSDeclareFunction,
|
|
7549
|
+
AST_NODE_TYPES37.TSEmptyBodyFunctionExpression,
|
|
7550
|
+
AST_NODE_TYPES37.TSFunctionType,
|
|
7551
|
+
AST_NODE_TYPES37.TSMethodSignature
|
|
7552
|
+
]);
|
|
7423
7553
|
function looksLikeMutuallyExclusiveState(typeLiteral) {
|
|
7424
7554
|
let statusMemberCount = 0;
|
|
7425
7555
|
let hasFailurePayload = false;
|
|
@@ -7460,6 +7590,17 @@ function getMemberName(member) {
|
|
|
7460
7590
|
function isBooleanTyped(member) {
|
|
7461
7591
|
return member.typeAnnotation?.typeAnnotation.type === AST_NODE_TYPES37.TSBooleanKeyword;
|
|
7462
7592
|
}
|
|
7593
|
+
function inlineReturnTypeLiteral(node) {
|
|
7594
|
+
let annotation = null;
|
|
7595
|
+
if (node.parent.type === AST_NODE_TYPES37.TSTypeAnnotation) {
|
|
7596
|
+
annotation = node.parent;
|
|
7597
|
+
} else if (node.parent.type === AST_NODE_TYPES37.TSTypeParameterInstantiation && node.parent.params.length === 1 && node.parent.params[0] === node && node.parent.parent.type === AST_NODE_TYPES37.TSTypeReference && node.parent.parent.typeName.type === AST_NODE_TYPES37.Identifier && node.parent.parent.typeName.name === "Promise" && node.parent.parent.parent.type === AST_NODE_TYPES37.TSTypeAnnotation) {
|
|
7598
|
+
annotation = node.parent.parent.parent;
|
|
7599
|
+
}
|
|
7600
|
+
if (annotation === null) return null;
|
|
7601
|
+
const owner = annotation.parent;
|
|
7602
|
+
return FUNCTION_RETURN_OWNER_TYPES.has(owner.type) && "returnType" in owner && owner.returnType === annotation ? annotation : null;
|
|
7603
|
+
}
|
|
7463
7604
|
var prefer_discriminated_union_default = createRule({
|
|
7464
7605
|
name: "prefer-discriminated-union",
|
|
7465
7606
|
meta: {
|
|
@@ -7499,6 +7640,10 @@ var prefer_discriminated_union_default = createRule({
|
|
|
7499
7640
|
},
|
|
7500
7641
|
"TSTypeAliasDeclaration > TSTypeLiteral"(node) {
|
|
7501
7642
|
checkTypeLiteral(node, node.parent);
|
|
7643
|
+
},
|
|
7644
|
+
TSTypeLiteral(node) {
|
|
7645
|
+
const annotation = inlineReturnTypeLiteral(node);
|
|
7646
|
+
if (annotation !== null) checkTypeLiteral(node, annotation);
|
|
7502
7647
|
}
|
|
7503
7648
|
};
|
|
7504
7649
|
}
|
|
@@ -8415,6 +8560,11 @@ var prefer_module_level_schema_default = createRule({
|
|
|
8415
8560
|
type: "boolean",
|
|
8416
8561
|
description: "Skip test files, where a fixture schema belongs next to its assertion."
|
|
8417
8562
|
},
|
|
8563
|
+
memoCallees: {
|
|
8564
|
+
type: "array",
|
|
8565
|
+
items: { type: "string" },
|
|
8566
|
+
description: "Wrappers that construct their callback at most once. Defaults to lazy, memo, once, and useMemo."
|
|
8567
|
+
},
|
|
8418
8568
|
minProperties: {
|
|
8419
8569
|
type: "number",
|
|
8420
8570
|
minimum: 0,
|
|
@@ -8432,6 +8582,7 @@ var prefer_module_level_schema_default = createRule({
|
|
|
8432
8582
|
create(context, [options]) {
|
|
8433
8583
|
const factories = new Set(options?.factories ?? DEFAULT_FACTORIES);
|
|
8434
8584
|
const ignoreTestFiles = options?.ignoreTestFiles ?? true;
|
|
8585
|
+
const memoCallees = new Set(options?.memoCallees ?? MEMO_CALLEES);
|
|
8435
8586
|
const minProperties = options?.minProperties ?? DEFAULT_MIN_PROPERTIES;
|
|
8436
8587
|
const sourceCode = context.sourceCode;
|
|
8437
8588
|
const filename = context.filename;
|
|
@@ -8451,7 +8602,7 @@ var prefer_module_level_schema_default = createRule({
|
|
|
8451
8602
|
if (current !== node && isZodCall(current) && current.callee.type === AST_NODE_TYPES42.MemberExpression && current.callee.property.type === AST_NODE_TYPES42.Identifier && factories.has(current.callee.property.name)) {
|
|
8452
8603
|
return true;
|
|
8453
8604
|
}
|
|
8454
|
-
if (current.type === AST_NODE_TYPES42.CallExpression && (current.callee.type === AST_NODE_TYPES42.Identifier &&
|
|
8605
|
+
if (current.type === AST_NODE_TYPES42.CallExpression && (current.callee.type === AST_NODE_TYPES42.Identifier && memoCallees.has(current.callee.name) || current.callee.type === AST_NODE_TYPES42.MemberExpression && !current.callee.computed && current.callee.property.type === AST_NODE_TYPES42.Identifier && memoCallees.has(current.callee.property.name))) {
|
|
8455
8606
|
return true;
|
|
8456
8607
|
}
|
|
8457
8608
|
current = current.parent ?? void 0;
|
|
@@ -8501,6 +8652,9 @@ var prefer_module_level_schema_default = createRule({
|
|
|
8501
8652
|
if (definition.type === "ImportBinding") {
|
|
8502
8653
|
continue;
|
|
8503
8654
|
}
|
|
8655
|
+
if (definition.node.type === AST_NODE_TYPES42.VariableDeclarator && definition.node.parent.type === AST_NODE_TYPES42.VariableDeclaration && definition.node.parent.kind !== "const") {
|
|
8656
|
+
return false;
|
|
8657
|
+
}
|
|
8504
8658
|
const [defStart, defEnd] = definition.node.range;
|
|
8505
8659
|
if (defStart >= schemaStart && defEnd <= schemaEnd) {
|
|
8506
8660
|
continue;
|
|
@@ -8735,7 +8889,7 @@ function sameAccess(node, access) {
|
|
|
8735
8889
|
return node.type === AST_NODE_TYPES44.MemberExpression && !node.computed && node.object.type === AST_NODE_TYPES44.Identifier && node.object.name === access.object && node.property.type === AST_NODE_TYPES44.Identifier && node.property.name === access.property;
|
|
8736
8890
|
}
|
|
8737
8891
|
function isNullGuard(node, access) {
|
|
8738
|
-
if (node.type === AST_NODE_TYPES44.UnaryExpression && node.operator === "!" && sameAccess(node.argument, access)) return true;
|
|
8892
|
+
if (node.type === AST_NODE_TYPES44.UnaryExpression && node.operator === "!" && (sameAccess(node.argument, access) || optionalMemberLengthOf(node.argument, access))) return true;
|
|
8739
8893
|
if (node.type !== AST_NODE_TYPES44.BinaryExpression || !["==", "==="].includes(node.operator)) {
|
|
8740
8894
|
return false;
|
|
8741
8895
|
}
|
|
@@ -8751,7 +8905,11 @@ function isEmptyGuard(node, access) {
|
|
|
8751
8905
|
return memberLengthOf(node.left, access) && zero(node.right) || memberLengthOf(node.right, access) && zero(node.left);
|
|
8752
8906
|
}
|
|
8753
8907
|
function memberLengthOf(node, access) {
|
|
8754
|
-
|
|
8908
|
+
const target = node.type === AST_NODE_TYPES44.ChainExpression ? node.expression : node;
|
|
8909
|
+
return target.type === AST_NODE_TYPES44.MemberExpression && !target.computed && target.property.type === AST_NODE_TYPES44.Identifier && target.property.name === "length" && sameAccess(target.object, access);
|
|
8910
|
+
}
|
|
8911
|
+
function optionalMemberLengthOf(node, access) {
|
|
8912
|
+
return node.type === AST_NODE_TYPES44.ChainExpression && node.expression.type === AST_NODE_TYPES44.MemberExpression && node.expression.optional && memberLengthOf(node, access);
|
|
8755
8913
|
}
|
|
8756
8914
|
function hasEquivalentLeadingGuard(fn, access, visitorKeys) {
|
|
8757
8915
|
if (fn.body.type !== AST_NODE_TYPES44.BlockStatement) return false;
|
|
@@ -8759,6 +8917,7 @@ function hasEquivalentLeadingGuard(fn, access, visitorKeys) {
|
|
|
8759
8917
|
if (first?.type !== AST_NODE_TYPES44.IfStatement) return false;
|
|
8760
8918
|
const terminating = first.consequent.type === AST_NODE_TYPES44.ReturnStatement || first.consequent.type === AST_NODE_TYPES44.ThrowStatement || first.consequent.type === AST_NODE_TYPES44.BlockStatement && first.consequent.body.length === 1 && (first.consequent.body[0]?.type === AST_NODE_TYPES44.ReturnStatement || first.consequent.body[0]?.type === AST_NODE_TYPES44.ThrowStatement);
|
|
8761
8919
|
if (!terminating) return false;
|
|
8920
|
+
if (contains(first.consequent, visitorKeys, (node) => sameAccess(node, access))) return false;
|
|
8762
8921
|
return contains(first.test, visitorKeys, (node) => isNullGuard(node, access)) && contains(first.test, visitorKeys, (node) => isEmptyGuard(node, access));
|
|
8763
8922
|
}
|
|
8764
8923
|
function contains(node, visitorKeys, predicate) {
|
|
@@ -8921,7 +9080,7 @@ var isSchemaParseReference = (node) => {
|
|
|
8921
9080
|
const inner = unwrap4(node);
|
|
8922
9081
|
return inner !== null && inner.type === AST_NODE_TYPES45.MemberExpression && !inner.computed && inner.property.type === AST_NODE_TYPES45.Identifier && (inner.property.name === "parse" || inner.property.name === "safeParse");
|
|
8923
9082
|
};
|
|
8924
|
-
var isRawPayloadSource = (node) => {
|
|
9083
|
+
var isRawPayloadSource = (node, isKnownLocalText) => {
|
|
8925
9084
|
let current = unwrap4(node);
|
|
8926
9085
|
if (current === null) return false;
|
|
8927
9086
|
if (current.type === AST_NODE_TYPES45.AwaitExpression) {
|
|
@@ -8945,20 +9104,26 @@ var isRawPayloadSource = (node) => {
|
|
|
8945
9104
|
return !current.arguments.some(isSchemaParseReference) && isRawPayloadSource(callee.object);
|
|
8946
9105
|
}
|
|
8947
9106
|
const object = unwrap4(callee.object);
|
|
8948
|
-
return property.name === "parse" && object !== null && object.type === AST_NODE_TYPES45.Identifier && object.name === "JSON" && !isLocalFileRead(current.arguments[0]);
|
|
9107
|
+
return property.name === "parse" && object !== null && object.type === AST_NODE_TYPES45.Identifier && object.name === "JSON" && !isLocalFileRead(current.arguments[0]) && isKnownLocalText?.(current.arguments[0]) !== true;
|
|
8949
9108
|
};
|
|
8950
9109
|
var FILE_READ_RE = /^(readFile|readFileSync|readJson|readJsonSync|readJSON)$/;
|
|
9110
|
+
var isDirectLocalFileRead = (node) => {
|
|
9111
|
+
let current = unwrap4(node);
|
|
9112
|
+
if (current?.type === AST_NODE_TYPES45.AwaitExpression) {
|
|
9113
|
+
current = unwrap4(current.argument);
|
|
9114
|
+
}
|
|
9115
|
+
if (current?.type !== AST_NODE_TYPES45.CallExpression) return false;
|
|
9116
|
+
const callee = unwrap4(current.callee);
|
|
9117
|
+
const name = callee?.type === AST_NODE_TYPES45.Identifier ? callee.name : callee?.type === AST_NODE_TYPES45.MemberExpression && !callee.computed && callee.property.type === AST_NODE_TYPES45.Identifier ? callee.property.name : null;
|
|
9118
|
+
return name !== null && FILE_READ_RE.test(name);
|
|
9119
|
+
};
|
|
8951
9120
|
var isLocalFileRead = (node) => {
|
|
8952
9121
|
let found = false;
|
|
8953
9122
|
const visit = (current) => {
|
|
8954
9123
|
if (found || current === null || current === void 0) return;
|
|
8955
|
-
if (current
|
|
8956
|
-
|
|
8957
|
-
|
|
8958
|
-
if (name !== null && FILE_READ_RE.test(name)) {
|
|
8959
|
-
found = true;
|
|
8960
|
-
return;
|
|
8961
|
-
}
|
|
9124
|
+
if (isDirectLocalFileRead(current)) {
|
|
9125
|
+
found = true;
|
|
9126
|
+
return;
|
|
8962
9127
|
}
|
|
8963
9128
|
for (const key of Object.keys(current)) {
|
|
8964
9129
|
if (key === "parent") continue;
|
|
@@ -9020,6 +9185,87 @@ var isValidationRead = (node) => {
|
|
|
9020
9185
|
}
|
|
9021
9186
|
return callee.type === AST_NODE_TYPES45.Identifier && GUARD_NAME_RE.test(callee.name);
|
|
9022
9187
|
};
|
|
9188
|
+
var PRIMITIVE_TYPEOF_RESULTS = /* @__PURE__ */ new Set([
|
|
9189
|
+
"bigint",
|
|
9190
|
+
"boolean",
|
|
9191
|
+
"number",
|
|
9192
|
+
"string",
|
|
9193
|
+
"symbol",
|
|
9194
|
+
"undefined"
|
|
9195
|
+
]);
|
|
9196
|
+
var bindingValidationPolarity = (test, bindingName) => {
|
|
9197
|
+
if (test.type === AST_NODE_TYPES45.UnaryExpression && test.operator === "!") {
|
|
9198
|
+
const inner = bindingValidationPolarity(test.argument, bindingName);
|
|
9199
|
+
return inner === "valid-when-true" ? "valid-when-false" : inner === "valid-when-false" ? "valid-when-true" : null;
|
|
9200
|
+
}
|
|
9201
|
+
if (test.type === AST_NODE_TYPES45.BinaryExpression) {
|
|
9202
|
+
const typeofName = (node) => node.type === AST_NODE_TYPES45.UnaryExpression && node.operator === "typeof" && node.argument.type === AST_NODE_TYPES45.Identifier ? node.argument.name : null;
|
|
9203
|
+
const literalType = (node) => node.type === AST_NODE_TYPES45.Literal && typeof node.value === "string" && PRIMITIVE_TYPEOF_RESULTS.has(node.value) ? node.value : null;
|
|
9204
|
+
const matches = typeofName(test.left) === bindingName && literalType(test.right) !== null || typeofName(test.right) === bindingName && literalType(test.left) !== null;
|
|
9205
|
+
if (!matches) return null;
|
|
9206
|
+
if (test.operator === "===" || test.operator === "==") {
|
|
9207
|
+
return "valid-when-true";
|
|
9208
|
+
}
|
|
9209
|
+
return test.operator === "!==" || test.operator === "!=" ? "valid-when-false" : null;
|
|
9210
|
+
}
|
|
9211
|
+
return test.type === AST_NODE_TYPES45.CallExpression && test.arguments.length === 1 && test.arguments[0]?.type === AST_NODE_TYPES45.Identifier && test.arguments[0].name === bindingName && test.callee.type === AST_NODE_TYPES45.MemberExpression && !test.callee.computed && test.callee.object.type === AST_NODE_TYPES45.Identifier && test.callee.object.name === "Array" && test.callee.property.type === AST_NODE_TYPES45.Identifier && test.callee.property.name === "isArray" ? "valid-when-true" : null;
|
|
9212
|
+
};
|
|
9213
|
+
var nodeWithin2 = (node, container) => node.range[0] >= container.range[0] && node.range[1] <= container.range[1];
|
|
9214
|
+
var isFullyValidatedExtractedBinding = (member, source, context) => {
|
|
9215
|
+
const isValidationReference = (identifier) => {
|
|
9216
|
+
for (let current = identifier.parent; current !== void 0 && current !== null; current = current.parent) {
|
|
9217
|
+
if ((current.type === AST_NODE_TYPES45.BinaryExpression || current.type === AST_NODE_TYPES45.CallExpression || current.type === AST_NODE_TYPES45.UnaryExpression) && bindingValidationPolarity(current, identifier.name) !== null) {
|
|
9218
|
+
return true;
|
|
9219
|
+
}
|
|
9220
|
+
if (current.type !== AST_NODE_TYPES45.UnaryExpression && current.type !== AST_NODE_TYPES45.MemberExpression && current.type !== AST_NODE_TYPES45.CallExpression) {
|
|
9221
|
+
return false;
|
|
9222
|
+
}
|
|
9223
|
+
}
|
|
9224
|
+
return false;
|
|
9225
|
+
};
|
|
9226
|
+
const isGuardedUse = (identifier) => {
|
|
9227
|
+
for (let current = identifier.parent; current !== void 0 && current !== null; current = current.parent) {
|
|
9228
|
+
if (current.type === AST_NODE_TYPES45.ConditionalExpression) {
|
|
9229
|
+
const polarity = bindingValidationPolarity(current.test, identifier.name);
|
|
9230
|
+
if (polarity === "valid-when-true" && nodeWithin2(identifier, current.consequent)) {
|
|
9231
|
+
return true;
|
|
9232
|
+
}
|
|
9233
|
+
if (polarity === "valid-when-false" && nodeWithin2(identifier, current.alternate)) {
|
|
9234
|
+
return true;
|
|
9235
|
+
}
|
|
9236
|
+
}
|
|
9237
|
+
if (current.type === AST_NODE_TYPES45.IfStatement) {
|
|
9238
|
+
const polarity = bindingValidationPolarity(current.test, identifier.name);
|
|
9239
|
+
if (polarity === "valid-when-true" && nodeWithin2(identifier, current.consequent)) {
|
|
9240
|
+
return true;
|
|
9241
|
+
}
|
|
9242
|
+
if (polarity === "valid-when-false" && current.alternate !== null && nodeWithin2(identifier, current.alternate)) {
|
|
9243
|
+
return true;
|
|
9244
|
+
}
|
|
9245
|
+
}
|
|
9246
|
+
if (current.type === AST_NODE_TYPES45.FunctionDeclaration || current.type === AST_NODE_TYPES45.FunctionExpression || current.type === AST_NODE_TYPES45.ArrowFunctionExpression) {
|
|
9247
|
+
return false;
|
|
9248
|
+
}
|
|
9249
|
+
}
|
|
9250
|
+
return false;
|
|
9251
|
+
};
|
|
9252
|
+
const declarator = member.parent;
|
|
9253
|
+
if (declarator.type !== AST_NODE_TYPES45.VariableDeclarator || declarator.init !== member || declarator.id.type !== AST_NODE_TYPES45.Identifier || declarator.parent.type !== AST_NODE_TYPES45.VariableDeclaration || declarator.parent.kind !== "const") {
|
|
9254
|
+
return false;
|
|
9255
|
+
}
|
|
9256
|
+
const extracted = context.sourceCode.getDeclaredVariables(declarator)[0];
|
|
9257
|
+
if (extracted === void 0 || extracted.scope !== source.scope) return false;
|
|
9258
|
+
let hasValueUse = false;
|
|
9259
|
+
for (const reference of extracted.references) {
|
|
9260
|
+
const identifier = reference.identifier;
|
|
9261
|
+
if (identifier.type !== AST_NODE_TYPES45.Identifier) return false;
|
|
9262
|
+
if (nodeWithin2(identifier, declarator)) continue;
|
|
9263
|
+
if (isValidationReference(identifier)) continue;
|
|
9264
|
+
hasValueUse = true;
|
|
9265
|
+
if (!isGuardedUse(identifier)) return false;
|
|
9266
|
+
}
|
|
9267
|
+
return hasValueUse;
|
|
9268
|
+
};
|
|
9023
9269
|
var isGuardTestPosition = (node) => {
|
|
9024
9270
|
let current = node;
|
|
9025
9271
|
let parent = current.parent;
|
|
@@ -9043,13 +9289,13 @@ var isGuardTestPosition = (node) => {
|
|
|
9043
9289
|
}
|
|
9044
9290
|
return false;
|
|
9045
9291
|
};
|
|
9046
|
-
var
|
|
9292
|
+
var unvalidatedVariableRef = (node, scope, tracked) => {
|
|
9047
9293
|
const unwrapped = unwrap4(node);
|
|
9048
9294
|
if (unwrapped === null || unwrapped.type !== AST_NODE_TYPES45.Identifier) {
|
|
9049
|
-
return
|
|
9295
|
+
return null;
|
|
9050
9296
|
}
|
|
9051
9297
|
const variable = findVariable2(scope, unwrapped.name);
|
|
9052
|
-
return variable !== null && tracked.has(variable);
|
|
9298
|
+
return variable !== null && tracked.has(variable) ? variable : null;
|
|
9053
9299
|
};
|
|
9054
9300
|
var prefer_schema_for_api_payload_default = createRule({
|
|
9055
9301
|
name: "prefer-schema-for-api-payload",
|
|
@@ -9069,6 +9315,56 @@ var prefer_schema_for_api_payload_default = createRule({
|
|
|
9069
9315
|
return {};
|
|
9070
9316
|
}
|
|
9071
9317
|
const unvalidatedVariables = /* @__PURE__ */ new Set();
|
|
9318
|
+
const aliasGroups = /* @__PURE__ */ new Map();
|
|
9319
|
+
const localFileTextVariables = /* @__PURE__ */ new Set();
|
|
9320
|
+
const localFileTextRef = (node, scope) => {
|
|
9321
|
+
const unwrapped = unwrap4(node);
|
|
9322
|
+
if (unwrapped?.type !== AST_NODE_TYPES45.Identifier) return null;
|
|
9323
|
+
const variable = findVariable2(scope, unwrapped.name);
|
|
9324
|
+
return variable !== null && localFileTextVariables.has(variable) ? variable : null;
|
|
9325
|
+
};
|
|
9326
|
+
const updateLocalFileText = (target, value, scope) => {
|
|
9327
|
+
const source = localFileTextRef(value, scope);
|
|
9328
|
+
if (isDirectLocalFileRead(value) || source !== null && source.scope === target.scope) {
|
|
9329
|
+
localFileTextVariables.add(target);
|
|
9330
|
+
} else {
|
|
9331
|
+
localFileTextVariables.delete(target);
|
|
9332
|
+
}
|
|
9333
|
+
};
|
|
9334
|
+
const clearBinding = (variable) => {
|
|
9335
|
+
unvalidatedVariables.delete(variable);
|
|
9336
|
+
const group = aliasGroups.get(variable);
|
|
9337
|
+
aliasGroups.delete(variable);
|
|
9338
|
+
group?.delete(variable);
|
|
9339
|
+
};
|
|
9340
|
+
const clearAliasGroup = (variable) => {
|
|
9341
|
+
const group = aliasGroups.get(variable);
|
|
9342
|
+
if (group === void 0) {
|
|
9343
|
+
unvalidatedVariables.delete(variable);
|
|
9344
|
+
return;
|
|
9345
|
+
}
|
|
9346
|
+
for (const alias of group) {
|
|
9347
|
+
unvalidatedVariables.delete(alias);
|
|
9348
|
+
aliasGroups.delete(alias);
|
|
9349
|
+
}
|
|
9350
|
+
group.clear();
|
|
9351
|
+
};
|
|
9352
|
+
const trackRawBinding = (variable) => {
|
|
9353
|
+
clearBinding(variable);
|
|
9354
|
+
const group = /* @__PURE__ */ new Set([variable]);
|
|
9355
|
+
unvalidatedVariables.add(variable);
|
|
9356
|
+
aliasGroups.set(variable, group);
|
|
9357
|
+
};
|
|
9358
|
+
const trackAlias = (target, source) => {
|
|
9359
|
+
if (target === source) return;
|
|
9360
|
+
const group = aliasGroups.get(source) ?? /* @__PURE__ */ new Set([source]);
|
|
9361
|
+
if (aliasGroups.get(target) === group) return;
|
|
9362
|
+
clearBinding(target);
|
|
9363
|
+
unvalidatedVariables.add(target);
|
|
9364
|
+
group.add(target);
|
|
9365
|
+
aliasGroups.set(source, group);
|
|
9366
|
+
aliasGroups.set(target, group);
|
|
9367
|
+
};
|
|
9072
9368
|
const isFullyNarrowedPattern = (declarator) => {
|
|
9073
9369
|
const declared = context.sourceCode.getDeclaredVariables(declarator);
|
|
9074
9370
|
return declared.length > 0 && declared.every(
|
|
@@ -9077,29 +9373,40 @@ var prefer_schema_for_api_payload_default = createRule({
|
|
|
9077
9373
|
)
|
|
9078
9374
|
);
|
|
9079
9375
|
};
|
|
9080
|
-
const trackInitializer = (declarator) => {
|
|
9081
|
-
if (!isRawPayloadSource(declarator.init)) return;
|
|
9376
|
+
const trackInitializer = (declarator, scope) => {
|
|
9082
9377
|
const declaredVars = context.sourceCode.getDeclaredVariables(declarator);
|
|
9083
9378
|
const variable = declaredVars[0];
|
|
9084
|
-
if (variable
|
|
9085
|
-
|
|
9379
|
+
if (variable === void 0) return;
|
|
9380
|
+
const localText = (candidate) => localFileTextRef(candidate, scope) !== null;
|
|
9381
|
+
if (isRawPayloadSource(declarator.init, localText)) {
|
|
9382
|
+
trackRawBinding(variable);
|
|
9383
|
+
return;
|
|
9086
9384
|
}
|
|
9385
|
+
const source = unvalidatedVariableRef(declarator.init, scope, unvalidatedVariables);
|
|
9386
|
+
if (source !== null) trackAlias(variable, source);
|
|
9087
9387
|
};
|
|
9088
9388
|
return {
|
|
9089
9389
|
VariableDeclarator(node) {
|
|
9090
9390
|
const scope = context.sourceCode.getScope(node);
|
|
9091
9391
|
if (node.id.type === AST_NODE_TYPES45.Identifier) {
|
|
9092
|
-
|
|
9392
|
+
const variable = context.sourceCode.getDeclaredVariables(node)[0];
|
|
9393
|
+
if (variable !== void 0) {
|
|
9394
|
+
updateLocalFileText(variable, node.init, scope);
|
|
9395
|
+
}
|
|
9396
|
+
trackInitializer(node, scope);
|
|
9093
9397
|
return;
|
|
9094
9398
|
}
|
|
9095
9399
|
if (node.id.type === AST_NODE_TYPES45.ObjectPattern || node.id.type === AST_NODE_TYPES45.ArrayPattern) {
|
|
9096
|
-
if (isRawPayloadSource(
|
|
9400
|
+
if (isRawPayloadSource(
|
|
9401
|
+
node.init,
|
|
9402
|
+
(candidate) => localFileTextRef(candidate, scope) !== null
|
|
9403
|
+
)) {
|
|
9097
9404
|
if (!isFullyNarrowedPattern(node)) {
|
|
9098
9405
|
context.report({ node: node.id, messageId: "unparsedJsonAccess" });
|
|
9099
9406
|
}
|
|
9100
9407
|
return;
|
|
9101
9408
|
}
|
|
9102
|
-
if (
|
|
9409
|
+
if (unvalidatedVariableRef(node.init, scope, unvalidatedVariables) !== null) {
|
|
9103
9410
|
context.report({ node: node.id, messageId: "unparsedJsonAccess" });
|
|
9104
9411
|
}
|
|
9105
9412
|
}
|
|
@@ -9109,22 +9416,29 @@ var prefer_schema_for_api_payload_default = createRule({
|
|
|
9109
9416
|
if (node.left.type === AST_NODE_TYPES45.Identifier) {
|
|
9110
9417
|
const variable = findVariable2(scope, node.left.name);
|
|
9111
9418
|
if (variable === null) return;
|
|
9112
|
-
|
|
9113
|
-
|
|
9419
|
+
const isLocalText = (candidate) => localFileTextRef(candidate, scope) !== null;
|
|
9420
|
+
updateLocalFileText(variable, node.right, scope);
|
|
9421
|
+
if (isRawPayloadSource(node.right, isLocalText)) {
|
|
9422
|
+
trackRawBinding(variable);
|
|
9114
9423
|
} else {
|
|
9115
|
-
unvalidatedVariables
|
|
9424
|
+
const source = unvalidatedVariableRef(node.right, scope, unvalidatedVariables);
|
|
9425
|
+
if (source === null) clearBinding(variable);
|
|
9426
|
+
else trackAlias(variable, source);
|
|
9116
9427
|
}
|
|
9117
9428
|
return;
|
|
9118
9429
|
}
|
|
9119
9430
|
if (node.left.type === AST_NODE_TYPES45.ObjectPattern || node.left.type === AST_NODE_TYPES45.ArrayPattern) {
|
|
9120
|
-
if (isRawPayloadSource(
|
|
9431
|
+
if (isRawPayloadSource(
|
|
9432
|
+
node.right,
|
|
9433
|
+
(candidate) => localFileTextRef(candidate, scope) !== null
|
|
9434
|
+
)) {
|
|
9121
9435
|
context.report({
|
|
9122
9436
|
node: node.left,
|
|
9123
9437
|
messageId: "unparsedJsonAccess"
|
|
9124
9438
|
});
|
|
9125
9439
|
return;
|
|
9126
9440
|
}
|
|
9127
|
-
if (
|
|
9441
|
+
if (unvalidatedVariableRef(node.right, scope, unvalidatedVariables) !== null) {
|
|
9128
9442
|
context.report({
|
|
9129
9443
|
node: node.left,
|
|
9130
9444
|
messageId: "unparsedJsonAccess"
|
|
@@ -9145,7 +9459,7 @@ var prefer_schema_for_api_payload_default = createRule({
|
|
|
9145
9459
|
continue;
|
|
9146
9460
|
}
|
|
9147
9461
|
const variable = findVariable2(scope, unwrapped.name);
|
|
9148
|
-
if (variable !== null)
|
|
9462
|
+
if (variable !== null) clearAliasGroup(variable);
|
|
9149
9463
|
}
|
|
9150
9464
|
},
|
|
9151
9465
|
MemberExpression(node) {
|
|
@@ -9153,7 +9467,10 @@ var prefer_schema_for_api_payload_default = createRule({
|
|
|
9153
9467
|
if (isValidationRead(node)) return;
|
|
9154
9468
|
const scope = context.sourceCode.getScope(node);
|
|
9155
9469
|
const obj = unwrap4(node.object);
|
|
9156
|
-
if (isRawPayloadSource(
|
|
9470
|
+
if (isRawPayloadSource(
|
|
9471
|
+
obj,
|
|
9472
|
+
(candidate) => localFileTextRef(candidate, scope) !== null
|
|
9473
|
+
)) {
|
|
9157
9474
|
const parent = node.parent;
|
|
9158
9475
|
if (parent.type === AST_NODE_TYPES45.CallExpression && parent.callee === node && node.property.type === AST_NODE_TYPES45.Identifier && (node.property.name === "parse" || node.property.name === "safeParse" || PROMISE_CHAIN_METHODS.has(node.property.name))) {
|
|
9159
9476
|
return;
|
|
@@ -9161,12 +9478,13 @@ var prefer_schema_for_api_payload_default = createRule({
|
|
|
9161
9478
|
context.report({ node, messageId: "unparsedJsonAccess" });
|
|
9162
9479
|
return;
|
|
9163
9480
|
}
|
|
9164
|
-
|
|
9165
|
-
|
|
9166
|
-
|
|
9167
|
-
|
|
9168
|
-
unvalidatedVariables.delete(variable);
|
|
9481
|
+
const variable = obj?.type === AST_NODE_TYPES45.Identifier ? unvalidatedVariableRef(obj, scope, unvalidatedVariables) : null;
|
|
9482
|
+
if (variable !== null) {
|
|
9483
|
+
if (isFullyValidatedExtractedBinding(node, variable, context)) {
|
|
9484
|
+
return;
|
|
9169
9485
|
}
|
|
9486
|
+
context.report({ node, messageId: "unparsedJsonAccess" });
|
|
9487
|
+
clearAliasGroup(variable);
|
|
9170
9488
|
}
|
|
9171
9489
|
}
|
|
9172
9490
|
};
|
|
@@ -10933,8 +11251,8 @@ function initProvablyLacksSignal(init) {
|
|
|
10933
11251
|
}
|
|
10934
11252
|
return true;
|
|
10935
11253
|
}
|
|
10936
|
-
function
|
|
10937
|
-
return node.type === AST_NODE_TYPES52.Literal && typeof node.value === "string" || node.type === AST_NODE_TYPES52.TemplateLiteral;
|
|
11254
|
+
function isInlineUrl(node, resolvesToGlobal) {
|
|
11255
|
+
return node.type === AST_NODE_TYPES52.Literal && typeof node.value === "string" || node.type === AST_NODE_TYPES52.TemplateLiteral || node.type === AST_NODE_TYPES52.NewExpression && node.callee.type === AST_NODE_TYPES52.Identifier && node.callee.name === "URL" && resolvesToGlobal(node.callee);
|
|
10938
11256
|
}
|
|
10939
11257
|
var require_fetch_timeout_default = createRule({
|
|
10940
11258
|
name: "require-fetch-timeout",
|
|
@@ -10986,7 +11304,7 @@ var require_fetch_timeout_default = createRule({
|
|
|
10986
11304
|
return;
|
|
10987
11305
|
}
|
|
10988
11306
|
const [first, init] = node.arguments;
|
|
10989
|
-
if (node.arguments.length === 1 && first !== void 0 && !
|
|
11307
|
+
if (node.arguments.length === 1 && first !== void 0 && !isInlineUrl(first, resolvesToGlobal)) {
|
|
10990
11308
|
return;
|
|
10991
11309
|
}
|
|
10992
11310
|
if (init === void 0 || initProvablyLacksSignal(init)) {
|
|
@@ -11003,7 +11321,7 @@ var CONFIGISH_TYPE_RE = /(?:Options|Opts|Config|Configuration|Settings|Params|Pr
|
|
|
11003
11321
|
var CONFIGISH_NAME_RE = /^(?:options|opts|config|configuration|settings|params|props|args|env|environment|callbacks|flags|logger|log|clock)$/i;
|
|
11004
11322
|
var HTTP_TRANSPORT_TYPE_RE = /^(?:KyInstance|AxiosInstance|Session)$/;
|
|
11005
11323
|
var BUILTIN_CONTAINER_TYPE_RE = /^(?:Record|Map|WeakMap|Set|WeakSet|Array|ReadonlyArray|ReadonlyMap|ReadonlySet|Promise|Partial|Required|Readonly|Pick|Omit|Exclude|Extract|NonNullable|Awaited|Parameters|ReturnType|InstanceType)$/;
|
|
11006
|
-
var VALUE_TYPE_RE = /^(?:ArrayBuffer|Blob|Buffer|Date|RegExp|URL|URLSearchParams)$/;
|
|
11324
|
+
var VALUE_TYPE_RE = /^(?:ArrayBuffer|Blob|Buffer|Date|NodePath|RegExp|URL|URLSearchParams)$/;
|
|
11007
11325
|
var TRANSPORT_WRAPPER_NAME_RE = /(?:Client$|^Http[A-Z])/;
|
|
11008
11326
|
var ERROR_VALUE_NAME_RE = /Error$/;
|
|
11009
11327
|
var FLUENT_BUILDER_NAME_RE = /Builder$/;
|
|
@@ -11467,7 +11785,7 @@ var require_interface_for_injected_service_default = createRule({
|
|
|
11467
11785
|
if (node.abstract === true) return;
|
|
11468
11786
|
if (node.decorators.length > 0) return;
|
|
11469
11787
|
const ctor = node.body.body.find(
|
|
11470
|
-
(member) => member.type === AST_NODE_TYPES53.MethodDefinition && member.kind === "constructor"
|
|
11788
|
+
(member) => member.type === AST_NODE_TYPES53.MethodDefinition && member.kind === "constructor" && member.value.body !== null && member.value.body !== void 0
|
|
11471
11789
|
);
|
|
11472
11790
|
if (ctor === void 0) return;
|
|
11473
11791
|
const constructorFacts = readConstructor(
|
|
@@ -12346,7 +12664,7 @@ var rules = {
|
|
|
12346
12664
|
};
|
|
12347
12665
|
var meta = {
|
|
12348
12666
|
name: "@sarj/eslint-plugin",
|
|
12349
|
-
version: "11.0
|
|
12667
|
+
version: "11.2.0"
|
|
12350
12668
|
};
|
|
12351
12669
|
var applicationOnlyRules = [
|
|
12352
12670
|
"no-restricted-library-load",
|