@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.cjs
CHANGED
|
@@ -869,6 +869,7 @@ var BANNER_RUN_RE = /={4,}|-{4,}|#{4,}|\*{4,}|~{4,}|[\u2500-\u257f]{4,}/;
|
|
|
869
869
|
var REGION_MARKER_RE = /^#?(?:end)?region\b(.*)$/i;
|
|
870
870
|
var REGION_TITLE_RE = /^[\s:\-\u2013\u2014]*\w[\w \-/&+]*$/;
|
|
871
871
|
var REGION_TITLE_MAX_WORDS = 5;
|
|
872
|
+
var REGION_PROSE_VERB_RE = /^(?:is|are|was|were|comes?|defaults?|derives?|inherits?|depends?|uses?|maps?|resolves?)\b/i;
|
|
872
873
|
function stripCommentMarker(line) {
|
|
873
874
|
return line.replace(/^\s*\/{1,2}/, "").replace(/^\s*\*+/, "").trim();
|
|
874
875
|
}
|
|
@@ -930,7 +931,9 @@ var CALL_RE = /^[A-Za-z_$][\w.$]*\([^)]*\)\s*;?\s*$/;
|
|
|
930
931
|
var ASSERTION_CODE_RE = /^(?:await\s+)?(?:expect(?:TypeOf)?|assert(?:\.\w+)?)\s*\(/;
|
|
931
932
|
var HTTP_CONTRACT_RE = /\b(?:GET|HEAD|OPTIONS|PATCH|POST|PUT|DELETE)\s+(?:https?:\/\/|\/|\{[A-Za-z_$])/;
|
|
932
933
|
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;
|
|
933
|
-
var PSEUDOCODE_RE = /%\w+%|\[opt\]|(?:^|\s)<[A-Za-z]\w
|
|
934
|
+
var PSEUDOCODE_RE = /%\w+%|\[opt\]|(?:^|\s)<[A-Za-z]\w*>|\b[A-Za-z_$][\w$]*\s+x\d+\b|…|\.\.\./;
|
|
935
|
+
var CALL_LABEL_RE = /^([A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*)\([^;{}]*\)$/;
|
|
936
|
+
var MULTIPLIER_PSEUDOCODE_RE = /\b[A-Za-z_$][\w$]*\s+x\d+\b/;
|
|
934
937
|
function isBanner(text) {
|
|
935
938
|
const t = text.trim();
|
|
936
939
|
if (!t) return false;
|
|
@@ -942,6 +945,7 @@ function isRegionMarker(text) {
|
|
|
942
945
|
if (match === null) return false;
|
|
943
946
|
const title = (match[1] ?? "").trim();
|
|
944
947
|
if (title.length === 0) return true;
|
|
948
|
+
if (REGION_PROSE_VERB_RE.test(title)) return false;
|
|
945
949
|
if (!REGION_TITLE_RE.test(title)) return false;
|
|
946
950
|
return title.split(/\s+/).length <= REGION_TITLE_MAX_WORDS;
|
|
947
951
|
}
|
|
@@ -957,6 +961,15 @@ function looksLikeCode(text, allowCall = true) {
|
|
|
957
961
|
function hasPseudocode(text) {
|
|
958
962
|
return PSEUDOCODE_RE.test(text);
|
|
959
963
|
}
|
|
964
|
+
function testCallMatrixStems(comments) {
|
|
965
|
+
const stems = /* @__PURE__ */ new Set();
|
|
966
|
+
for (const comment of comments) {
|
|
967
|
+
const body2 = stripCommentMarker(comment.value);
|
|
968
|
+
const stem3 = CALL_LABEL_RE.exec(body2)?.[1];
|
|
969
|
+
if (stem3 !== void 0 && MULTIPLIER_PSEUDOCODE_RE.test(body2)) stems.add(stem3);
|
|
970
|
+
}
|
|
971
|
+
return stems;
|
|
972
|
+
}
|
|
960
973
|
function isEnumeratedProseItem(text) {
|
|
961
974
|
const t = text.trim();
|
|
962
975
|
return ENUMERATED_ITEM_RE.test(t) && t.split(/\s+/).length >= ENUMERATED_ITEM_MIN_WORDS;
|
|
@@ -1245,6 +1258,7 @@ var no_comment_cruft_default = createRule({
|
|
|
1245
1258
|
return {
|
|
1246
1259
|
Program() {
|
|
1247
1260
|
const comments = sourceCode.getAllComments();
|
|
1261
|
+
const callMatrixStems = isTestFile(context.filename) ? testCallMatrixStems(comments) : /* @__PURE__ */ new Set();
|
|
1248
1262
|
const walls = findCommentWalls(comments);
|
|
1249
1263
|
const wallByLeader = new Map(walls.map((wall) => [wall.leader, wall]));
|
|
1250
1264
|
const wallMembers = new Set(walls.flatMap((wall) => [...wall.members]));
|
|
@@ -1282,6 +1296,8 @@ var no_comment_cruft_default = createRule({
|
|
|
1282
1296
|
continue;
|
|
1283
1297
|
}
|
|
1284
1298
|
const firstText = texts[0];
|
|
1299
|
+
const firstTextStem = firstText === void 0 ? void 0 : CALL_LABEL_RE.exec(firstText)?.[1];
|
|
1300
|
+
if (firstTextStem !== void 0 && texts.length === 1 && callMatrixStems.has(firstTextStem)) continue;
|
|
1285
1301
|
if (firstText !== void 0 && /^(?:todo|fixme)\b/i.test(firstText)) {
|
|
1286
1302
|
if (!runCitesAReference(comments, i)) {
|
|
1287
1303
|
context.report({
|
|
@@ -2211,6 +2227,20 @@ var PURE_METHODS = /* @__PURE__ */ new Set([
|
|
|
2211
2227
|
"startsWith",
|
|
2212
2228
|
"endsWith"
|
|
2213
2229
|
]);
|
|
2230
|
+
var SYNC_CALLBACK_METHODS = /* @__PURE__ */ new Set([
|
|
2231
|
+
"every",
|
|
2232
|
+
"filter",
|
|
2233
|
+
"findIndex",
|
|
2234
|
+
"findLast",
|
|
2235
|
+
"findLastIndex",
|
|
2236
|
+
"flatMap",
|
|
2237
|
+
"forEach",
|
|
2238
|
+
"map",
|
|
2239
|
+
"reduce",
|
|
2240
|
+
"reduceRight",
|
|
2241
|
+
"some",
|
|
2242
|
+
"sort"
|
|
2243
|
+
]);
|
|
2214
2244
|
var PURE_NAMESPACES = /* @__PURE__ */ new Set([
|
|
2215
2245
|
"Object",
|
|
2216
2246
|
"Array",
|
|
@@ -2260,7 +2290,17 @@ function isPureCall(node) {
|
|
|
2260
2290
|
if (callee.object.type === import_utils13.AST_NODE_TYPES.Identifier && PURE_NAMESPACES.has(callee.object.name)) {
|
|
2261
2291
|
return !IMPURE_NAMESPACE_METHODS.has(`${callee.object.name}.${property.name}`);
|
|
2262
2292
|
}
|
|
2263
|
-
return PURE_METHODS.has(property.name);
|
|
2293
|
+
return PURE_METHODS.has(property.name) && (!SYNC_CALLBACK_METHODS.has(property.name) || !synchronousCallbackCanThrow(node));
|
|
2294
|
+
}
|
|
2295
|
+
function synchronousCallbackCanThrow(node) {
|
|
2296
|
+
return node.arguments.some((argument) => {
|
|
2297
|
+
if (argument.type !== import_utils13.AST_NODE_TYPES.ArrowFunctionExpression && argument.type !== import_utils13.AST_NODE_TYPES.FunctionExpression) return false;
|
|
2298
|
+
if (argument.async) return false;
|
|
2299
|
+
return subtreeMatches2(
|
|
2300
|
+
argument.body,
|
|
2301
|
+
(current) => current.type === import_utils13.AST_NODE_TYPES.ThrowStatement || current.type === import_utils13.AST_NODE_TYPES.CallExpression && current.callee.type === import_utils13.AST_NODE_TYPES.MemberExpression && !current.callee.computed && current.callee.object.type === import_utils13.AST_NODE_TYPES.Identifier && current.callee.object.name === "JSON" && current.callee.property.type === import_utils13.AST_NODE_TYPES.Identifier && current.callee.property.name === "parse"
|
|
2302
|
+
);
|
|
2303
|
+
});
|
|
2264
2304
|
}
|
|
2265
2305
|
function isPureNew(node) {
|
|
2266
2306
|
return node.callee.type === import_utils13.AST_NODE_TYPES.Identifier && PURE_CONSTRUCTORS.has(node.callee.name);
|
|
@@ -2941,6 +2981,16 @@ var PAYLOAD_PROPS = /* @__PURE__ */ new Set([
|
|
|
2941
2981
|
"metadata",
|
|
2942
2982
|
"context"
|
|
2943
2983
|
]);
|
|
2984
|
+
var BUILTIN_ERROR_CONSTRUCTORS = /* @__PURE__ */ new Set([
|
|
2985
|
+
"AggregateError",
|
|
2986
|
+
"Error",
|
|
2987
|
+
"EvalError",
|
|
2988
|
+
"RangeError",
|
|
2989
|
+
"ReferenceError",
|
|
2990
|
+
"SyntaxError",
|
|
2991
|
+
"TypeError",
|
|
2992
|
+
"URIError"
|
|
2993
|
+
]);
|
|
2944
2994
|
function isCatchBinding(scope, name) {
|
|
2945
2995
|
let current = scope;
|
|
2946
2996
|
while (current) {
|
|
@@ -3055,6 +3105,48 @@ function nodeWithin(node, container) {
|
|
|
3055
3105
|
function isJsonStringify(callee) {
|
|
3056
3106
|
return callee.type === "MemberExpression" && !callee.computed && callee.object.type === "Identifier" && callee.object.name === "JSON" && callee.property.type === "Identifier" && callee.property.name === "stringify";
|
|
3057
3107
|
}
|
|
3108
|
+
function directLiteralValues(argument) {
|
|
3109
|
+
if (argument.type === "ObjectExpression") {
|
|
3110
|
+
return argument.properties.flatMap((property) => {
|
|
3111
|
+
if (property.type !== "Property" || property.computed) return [];
|
|
3112
|
+
const value = property.value;
|
|
3113
|
+
if (value.type === "AssignmentPattern" || value.type === "ArrayPattern" || value.type === "ObjectPattern" || value.type === "TSEmptyBodyFunctionExpression") {
|
|
3114
|
+
return [];
|
|
3115
|
+
}
|
|
3116
|
+
return [value];
|
|
3117
|
+
});
|
|
3118
|
+
}
|
|
3119
|
+
if (argument.type === "ArrayExpression") {
|
|
3120
|
+
return argument.elements.flatMap(
|
|
3121
|
+
(element) => element !== null && element.type !== "SpreadElement" ? [element] : []
|
|
3122
|
+
);
|
|
3123
|
+
}
|
|
3124
|
+
return argument.type === "SpreadElement" ? [] : [argument];
|
|
3125
|
+
}
|
|
3126
|
+
function expressionSuggestsError(expression, scope) {
|
|
3127
|
+
if (expression.type === "Identifier") {
|
|
3128
|
+
return ERROR_NAME_PATTERN.test(expression.name) || isCatchBinding(scope, expression.name);
|
|
3129
|
+
}
|
|
3130
|
+
return expression.type === "MemberExpression" && memberSuggestsError(expression, scope);
|
|
3131
|
+
}
|
|
3132
|
+
function nestedExpressionSuggestsError(expression, scope) {
|
|
3133
|
+
if (expression.type === "Identifier") {
|
|
3134
|
+
if (isCatchBinding(scope, expression.name)) return true;
|
|
3135
|
+
let current = scope;
|
|
3136
|
+
while (current !== null && !current.set.has(expression.name)) {
|
|
3137
|
+
current = current.upper;
|
|
3138
|
+
}
|
|
3139
|
+
const variable = current?.set.get(expression.name);
|
|
3140
|
+
if (variable === void 0 || variable.defs.length !== 1) return false;
|
|
3141
|
+
const definition = variable.defs[0];
|
|
3142
|
+
if (definition?.type !== "Variable") return false;
|
|
3143
|
+
const initializer = definition.node.init;
|
|
3144
|
+
return initializer?.type === "NewExpression" && initializer.callee.type === "Identifier" && BUILTIN_ERROR_CONSTRUCTORS.has(initializer.callee.name) && variable.references.every(
|
|
3145
|
+
(reference) => !reference.isWrite() || reference.init === true
|
|
3146
|
+
);
|
|
3147
|
+
}
|
|
3148
|
+
return expression.type === "MemberExpression" && memberSuggestsError(expression, scope);
|
|
3149
|
+
}
|
|
3058
3150
|
var no_json_stringify_error_default = createRule({
|
|
3059
3151
|
name: "no-json-stringify-error",
|
|
3060
3152
|
meta: {
|
|
@@ -3079,18 +3171,11 @@ var no_json_stringify_error_default = createRule({
|
|
|
3079
3171
|
return;
|
|
3080
3172
|
}
|
|
3081
3173
|
const scope = context.sourceCode.getScope(firstArg);
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
} else {
|
|
3088
|
-
return;
|
|
3089
|
-
}
|
|
3090
|
-
if (!suggestsError) {
|
|
3091
|
-
return;
|
|
3092
|
-
}
|
|
3093
|
-
if (isGuardedByInstanceofError(node, firstArg, context.sourceCode) || isNarrowedByEarlyReturn(node, firstArg, context.sourceCode)) {
|
|
3174
|
+
const isNestedLiteral = firstArg.type === "ObjectExpression" || firstArg.type === "ArrayExpression";
|
|
3175
|
+
const unsafeValue = directLiteralValues(firstArg).find(
|
|
3176
|
+
(value) => (isNestedLiteral ? nestedExpressionSuggestsError(value, scope) : expressionSuggestsError(value, scope)) && !isGuardedByInstanceofError(node, value, context.sourceCode) && !isNarrowedByEarlyReturn(node, value, context.sourceCode)
|
|
3177
|
+
);
|
|
3178
|
+
if (unsafeValue === void 0) {
|
|
3094
3179
|
return;
|
|
3095
3180
|
}
|
|
3096
3181
|
context.report({
|
|
@@ -3477,6 +3562,8 @@ function typedFunction(node) {
|
|
|
3477
3562
|
|
|
3478
3563
|
// src/rules/no-long-comment.ts
|
|
3479
3564
|
var EXCESSIVE_SENTENCE_COUNT = 8;
|
|
3565
|
+
var EXCESSIVE_WORD_COUNT = 120;
|
|
3566
|
+
var PROSE_WORD_RE = /[\p{L}\p{N}][\p{L}\p{N}'’-]*/gu;
|
|
3480
3567
|
var VERSIONED_DEPENDENCY_TREE_RE = /(?:^|\/)lib\/[^/]*-?v?\d+\.\d+(?:\.\d+)?[^/]*\//iu;
|
|
3481
3568
|
function documentsTypeOrMember(sourceCode, comment) {
|
|
3482
3569
|
const token = sourceCode.getTokenAfter(comment, { includeComments: false });
|
|
@@ -3488,6 +3575,9 @@ function documentsTypeOrMember(sourceCode, comment) {
|
|
|
3488
3575
|
}
|
|
3489
3576
|
return false;
|
|
3490
3577
|
}
|
|
3578
|
+
function wordUnits(text) {
|
|
3579
|
+
return text.match(PROSE_WORD_RE)?.length ?? 0;
|
|
3580
|
+
}
|
|
3491
3581
|
var no_long_comment_default = createRule({
|
|
3492
3582
|
name: "no-long-comment",
|
|
3493
3583
|
meta: {
|
|
@@ -3505,7 +3595,7 @@ var no_long_comment_default = createRule({
|
|
|
3505
3595
|
return {
|
|
3506
3596
|
Program() {
|
|
3507
3597
|
for (const group of proseGroups(context.filename, context.sourceCode)) {
|
|
3508
|
-
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;
|
|
3598
|
+
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;
|
|
3509
3599
|
context.report({ node: group.comment, messageId: "tooLong" });
|
|
3510
3600
|
}
|
|
3511
3601
|
}
|
|
@@ -5160,50 +5250,59 @@ var no_select_star_default = createRule({
|
|
|
5160
5250
|
|
|
5161
5251
|
// src/rules/no-sentinel-return-on-catch.ts
|
|
5162
5252
|
var import_utils33 = require("@typescript-eslint/utils");
|
|
5253
|
+
function unwrapSentinelExpression(arg) {
|
|
5254
|
+
let current = arg;
|
|
5255
|
+
while (current?.type === import_utils33.AST_NODE_TYPES.TSAsExpression || current?.type === import_utils33.AST_NODE_TYPES.TSTypeAssertion || current?.type === import_utils33.AST_NODE_TYPES.TSSatisfiesExpression) {
|
|
5256
|
+
current = current.expression;
|
|
5257
|
+
}
|
|
5258
|
+
return current;
|
|
5259
|
+
}
|
|
5163
5260
|
function sentinelKind(arg) {
|
|
5164
|
-
|
|
5261
|
+
const value = unwrapSentinelExpression(arg);
|
|
5262
|
+
if (value === null) {
|
|
5165
5263
|
return null;
|
|
5166
5264
|
}
|
|
5167
|
-
if (
|
|
5168
|
-
if (
|
|
5265
|
+
if (value.type === import_utils33.AST_NODE_TYPES.Literal) {
|
|
5266
|
+
if (value.value === null) {
|
|
5169
5267
|
return "nullish";
|
|
5170
5268
|
}
|
|
5171
|
-
if (typeof
|
|
5269
|
+
if (typeof value.value === "boolean") {
|
|
5172
5270
|
return "boolean";
|
|
5173
5271
|
}
|
|
5174
|
-
if (typeof
|
|
5272
|
+
if (typeof value.value === "string") {
|
|
5175
5273
|
return "string";
|
|
5176
5274
|
}
|
|
5177
5275
|
return null;
|
|
5178
5276
|
}
|
|
5179
|
-
if (
|
|
5277
|
+
if (value.type === import_utils33.AST_NODE_TYPES.Identifier && value.name === "undefined") {
|
|
5180
5278
|
return "nullish";
|
|
5181
5279
|
}
|
|
5182
|
-
if (
|
|
5280
|
+
if (value.type === import_utils33.AST_NODE_TYPES.ArrayExpression) {
|
|
5183
5281
|
return "array";
|
|
5184
5282
|
}
|
|
5185
|
-
if (
|
|
5283
|
+
if (value.type === import_utils33.AST_NODE_TYPES.ObjectExpression) {
|
|
5186
5284
|
return "object";
|
|
5187
5285
|
}
|
|
5188
5286
|
return null;
|
|
5189
5287
|
}
|
|
5190
5288
|
function isSentinelArgument(arg) {
|
|
5191
|
-
|
|
5289
|
+
const value = unwrapSentinelExpression(arg);
|
|
5290
|
+
if (value === null) {
|
|
5192
5291
|
return false;
|
|
5193
5292
|
}
|
|
5194
|
-
if (
|
|
5293
|
+
if (value.type === import_utils33.AST_NODE_TYPES.Literal && value.value === null) {
|
|
5195
5294
|
return true;
|
|
5196
5295
|
}
|
|
5197
|
-
if (
|
|
5296
|
+
if (value.type === import_utils33.AST_NODE_TYPES.Literal && value.value === false) {
|
|
5198
5297
|
return true;
|
|
5199
5298
|
}
|
|
5200
|
-
if (
|
|
5299
|
+
if (value.type === import_utils33.AST_NODE_TYPES.Identifier && value.name === "undefined") {
|
|
5201
5300
|
return true;
|
|
5202
5301
|
}
|
|
5203
|
-
if (
|
|
5302
|
+
if (value.type === import_utils33.AST_NODE_TYPES.ArrayExpression && value.elements.length === 0) {
|
|
5204
5303
|
return true;
|
|
5205
5304
|
}
|
|
5206
|
-
if (
|
|
5305
|
+
if (value.type === import_utils33.AST_NODE_TYPES.ObjectExpression && value.properties.length === 0) {
|
|
5207
5306
|
return true;
|
|
5208
5307
|
}
|
|
5209
5308
|
return false;
|
|
@@ -5401,6 +5500,16 @@ function tryReturnsSafeParse(catchNode) {
|
|
|
5401
5500
|
const only = tryBlock.body.length === 1 ? tryBlock.body[0] : void 0;
|
|
5402
5501
|
return only !== void 0 && returnsMatching(only, isBodyDecodeNode);
|
|
5403
5502
|
}
|
|
5503
|
+
function isIntentionalStackCapture(catchNode, caughtName) {
|
|
5504
|
+
if (caughtName === null) return false;
|
|
5505
|
+
const tryBody = tryBlockOf(catchNode).body;
|
|
5506
|
+
const only = tryBody.length === 1 ? tryBody[0] : void 0;
|
|
5507
|
+
if (only?.type !== import_utils33.AST_NODE_TYPES.ThrowStatement) return false;
|
|
5508
|
+
const thrown = unwrapSentinelExpression(only.argument);
|
|
5509
|
+
const constructsError = (thrown?.type === import_utils33.AST_NODE_TYPES.CallExpression || thrown?.type === import_utils33.AST_NODE_TYPES.NewExpression) && thrown.callee.type === import_utils33.AST_NODE_TYPES.Identifier && thrown.callee.name === "Error";
|
|
5510
|
+
if (!constructsError) return false;
|
|
5511
|
+
return catchNode.body.body.slice(0, -1).some((statement) => subtreeReadsName(statement, caughtName));
|
|
5512
|
+
}
|
|
5404
5513
|
function tryBlockOf(catchNode) {
|
|
5405
5514
|
return catchNode.parent.block;
|
|
5406
5515
|
}
|
|
@@ -5521,6 +5630,9 @@ var no_sentinel_return_on_catch_default = createRule({
|
|
|
5521
5630
|
if (tryReturnsSafeParse(node)) {
|
|
5522
5631
|
return;
|
|
5523
5632
|
}
|
|
5633
|
+
if (isIntentionalStackCapture(node, caughtName)) {
|
|
5634
|
+
return;
|
|
5635
|
+
}
|
|
5524
5636
|
const kind = sentinelKind(last.argument);
|
|
5525
5637
|
if (kind !== null && isNamedBooleanPredicate(node, kind)) {
|
|
5526
5638
|
return;
|
|
@@ -5599,11 +5711,11 @@ var no_silent_promise_catch_default = createRule({
|
|
|
5599
5711
|
meta: {
|
|
5600
5712
|
type: "problem",
|
|
5601
5713
|
docs: {
|
|
5602
|
-
description: "Disallow `.catch()` handlers that silently swallow
|
|
5714
|
+
description: "Disallow `.catch()` and second-argument `.then()` handlers that silently swallow a rejection; log, rethrow, or handle the error."
|
|
5603
5715
|
},
|
|
5604
5716
|
schema: [],
|
|
5605
5717
|
messages: {
|
|
5606
|
-
silentCatch: "This
|
|
5718
|
+
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."
|
|
5607
5719
|
}
|
|
5608
5720
|
},
|
|
5609
5721
|
defaultOptions: [],
|
|
@@ -5629,9 +5741,12 @@ var no_silent_promise_catch_default = createRule({
|
|
|
5629
5741
|
};
|
|
5630
5742
|
return {
|
|
5631
5743
|
CallExpression(node) {
|
|
5632
|
-
if (node.callee.type !== import_utils34.AST_NODE_TYPES.MemberExpression || node.callee.computed || node.callee.property.type !== import_utils34.AST_NODE_TYPES.Identifier
|
|
5744
|
+
if (node.callee.type !== import_utils34.AST_NODE_TYPES.MemberExpression || node.callee.computed || node.callee.property.type !== import_utils34.AST_NODE_TYPES.Identifier) {
|
|
5633
5745
|
return;
|
|
5634
5746
|
}
|
|
5747
|
+
const method = node.callee.property.name;
|
|
5748
|
+
const handlerIndex = method === "catch" ? 0 : method === "then" ? 1 : null;
|
|
5749
|
+
if (handlerIndex === null) return;
|
|
5635
5750
|
if (isBodyParseCall(node.callee.object)) {
|
|
5636
5751
|
return;
|
|
5637
5752
|
}
|
|
@@ -5641,10 +5756,11 @@ var no_silent_promise_catch_default = createRule({
|
|
|
5641
5756
|
if (node.parent.type === import_utils34.AST_NODE_TYPES.MemberExpression && node.parent.object === node) {
|
|
5642
5757
|
return;
|
|
5643
5758
|
}
|
|
5644
|
-
|
|
5759
|
+
const expectedArguments = method === "catch" ? 1 : 2;
|
|
5760
|
+
if (node.arguments.length !== expectedArguments) {
|
|
5645
5761
|
return;
|
|
5646
5762
|
}
|
|
5647
|
-
const handler = node.arguments[
|
|
5763
|
+
const handler = node.arguments[handlerIndex];
|
|
5648
5764
|
if (handler === void 0 || handler.type !== import_utils34.AST_NODE_TYPES.ArrowFunctionExpression && handler.type !== import_utils34.AST_NODE_TYPES.FunctionExpression) {
|
|
5649
5765
|
return;
|
|
5650
5766
|
}
|
|
@@ -5907,6 +6023,11 @@ function isStringLiteralInit(node) {
|
|
|
5907
6023
|
return false;
|
|
5908
6024
|
}
|
|
5909
6025
|
function isConcatOntoTarget(rhs, target) {
|
|
6026
|
+
if (rhs.type === "TemplateLiteral") {
|
|
6027
|
+
return rhs.expressions.some(
|
|
6028
|
+
(expression) => expression.type === "Identifier" && expression.name === target
|
|
6029
|
+
);
|
|
6030
|
+
}
|
|
5910
6031
|
if (rhs.type !== "BinaryExpression" || rhs.operator !== "+") {
|
|
5911
6032
|
return false;
|
|
5912
6033
|
}
|
|
@@ -7459,6 +7580,15 @@ var SUCCESS_PAYLOAD_MEMBER_NAMES = /* @__PURE__ */ new Set([
|
|
|
7459
7580
|
"value"
|
|
7460
7581
|
]);
|
|
7461
7582
|
var REQUIRED_STATUS_MEMBER_COUNT = 1;
|
|
7583
|
+
var FUNCTION_RETURN_OWNER_TYPES = /* @__PURE__ */ new Set([
|
|
7584
|
+
import_utils51.AST_NODE_TYPES.ArrowFunctionExpression,
|
|
7585
|
+
import_utils51.AST_NODE_TYPES.FunctionDeclaration,
|
|
7586
|
+
import_utils51.AST_NODE_TYPES.FunctionExpression,
|
|
7587
|
+
import_utils51.AST_NODE_TYPES.TSDeclareFunction,
|
|
7588
|
+
import_utils51.AST_NODE_TYPES.TSEmptyBodyFunctionExpression,
|
|
7589
|
+
import_utils51.AST_NODE_TYPES.TSFunctionType,
|
|
7590
|
+
import_utils51.AST_NODE_TYPES.TSMethodSignature
|
|
7591
|
+
]);
|
|
7462
7592
|
function looksLikeMutuallyExclusiveState(typeLiteral) {
|
|
7463
7593
|
let statusMemberCount = 0;
|
|
7464
7594
|
let hasFailurePayload = false;
|
|
@@ -7499,6 +7629,17 @@ function getMemberName(member) {
|
|
|
7499
7629
|
function isBooleanTyped(member) {
|
|
7500
7630
|
return member.typeAnnotation?.typeAnnotation.type === import_utils51.AST_NODE_TYPES.TSBooleanKeyword;
|
|
7501
7631
|
}
|
|
7632
|
+
function inlineReturnTypeLiteral(node) {
|
|
7633
|
+
let annotation = null;
|
|
7634
|
+
if (node.parent.type === import_utils51.AST_NODE_TYPES.TSTypeAnnotation) {
|
|
7635
|
+
annotation = node.parent;
|
|
7636
|
+
} else if (node.parent.type === import_utils51.AST_NODE_TYPES.TSTypeParameterInstantiation && node.parent.params.length === 1 && node.parent.params[0] === node && node.parent.parent.type === import_utils51.AST_NODE_TYPES.TSTypeReference && node.parent.parent.typeName.type === import_utils51.AST_NODE_TYPES.Identifier && node.parent.parent.typeName.name === "Promise" && node.parent.parent.parent.type === import_utils51.AST_NODE_TYPES.TSTypeAnnotation) {
|
|
7637
|
+
annotation = node.parent.parent.parent;
|
|
7638
|
+
}
|
|
7639
|
+
if (annotation === null) return null;
|
|
7640
|
+
const owner = annotation.parent;
|
|
7641
|
+
return FUNCTION_RETURN_OWNER_TYPES.has(owner.type) && "returnType" in owner && owner.returnType === annotation ? annotation : null;
|
|
7642
|
+
}
|
|
7502
7643
|
var prefer_discriminated_union_default = createRule({
|
|
7503
7644
|
name: "prefer-discriminated-union",
|
|
7504
7645
|
meta: {
|
|
@@ -7538,6 +7679,10 @@ var prefer_discriminated_union_default = createRule({
|
|
|
7538
7679
|
},
|
|
7539
7680
|
"TSTypeAliasDeclaration > TSTypeLiteral"(node) {
|
|
7540
7681
|
checkTypeLiteral(node, node.parent);
|
|
7682
|
+
},
|
|
7683
|
+
TSTypeLiteral(node) {
|
|
7684
|
+
const annotation = inlineReturnTypeLiteral(node);
|
|
7685
|
+
if (annotation !== null) checkTypeLiteral(node, annotation);
|
|
7541
7686
|
}
|
|
7542
7687
|
};
|
|
7543
7688
|
}
|
|
@@ -8454,6 +8599,11 @@ var prefer_module_level_schema_default = createRule({
|
|
|
8454
8599
|
type: "boolean",
|
|
8455
8600
|
description: "Skip test files, where a fixture schema belongs next to its assertion."
|
|
8456
8601
|
},
|
|
8602
|
+
memoCallees: {
|
|
8603
|
+
type: "array",
|
|
8604
|
+
items: { type: "string" },
|
|
8605
|
+
description: "Wrappers that construct their callback at most once. Defaults to lazy, memo, once, and useMemo."
|
|
8606
|
+
},
|
|
8457
8607
|
minProperties: {
|
|
8458
8608
|
type: "number",
|
|
8459
8609
|
minimum: 0,
|
|
@@ -8471,6 +8621,7 @@ var prefer_module_level_schema_default = createRule({
|
|
|
8471
8621
|
create(context, [options]) {
|
|
8472
8622
|
const factories = new Set(options?.factories ?? DEFAULT_FACTORIES);
|
|
8473
8623
|
const ignoreTestFiles = options?.ignoreTestFiles ?? true;
|
|
8624
|
+
const memoCallees = new Set(options?.memoCallees ?? MEMO_CALLEES);
|
|
8474
8625
|
const minProperties = options?.minProperties ?? DEFAULT_MIN_PROPERTIES;
|
|
8475
8626
|
const sourceCode = context.sourceCode;
|
|
8476
8627
|
const filename = context.filename;
|
|
@@ -8490,7 +8641,7 @@ var prefer_module_level_schema_default = createRule({
|
|
|
8490
8641
|
if (current !== node && isZodCall(current) && current.callee.type === import_utils56.AST_NODE_TYPES.MemberExpression && current.callee.property.type === import_utils56.AST_NODE_TYPES.Identifier && factories.has(current.callee.property.name)) {
|
|
8491
8642
|
return true;
|
|
8492
8643
|
}
|
|
8493
|
-
if (current.type === import_utils56.AST_NODE_TYPES.CallExpression && (current.callee.type === import_utils56.AST_NODE_TYPES.Identifier &&
|
|
8644
|
+
if (current.type === import_utils56.AST_NODE_TYPES.CallExpression && (current.callee.type === import_utils56.AST_NODE_TYPES.Identifier && memoCallees.has(current.callee.name) || current.callee.type === import_utils56.AST_NODE_TYPES.MemberExpression && !current.callee.computed && current.callee.property.type === import_utils56.AST_NODE_TYPES.Identifier && memoCallees.has(current.callee.property.name))) {
|
|
8494
8645
|
return true;
|
|
8495
8646
|
}
|
|
8496
8647
|
current = current.parent ?? void 0;
|
|
@@ -8540,6 +8691,9 @@ var prefer_module_level_schema_default = createRule({
|
|
|
8540
8691
|
if (definition.type === "ImportBinding") {
|
|
8541
8692
|
continue;
|
|
8542
8693
|
}
|
|
8694
|
+
if (definition.node.type === import_utils56.AST_NODE_TYPES.VariableDeclarator && definition.node.parent.type === import_utils56.AST_NODE_TYPES.VariableDeclaration && definition.node.parent.kind !== "const") {
|
|
8695
|
+
return false;
|
|
8696
|
+
}
|
|
8543
8697
|
const [defStart, defEnd] = definition.node.range;
|
|
8544
8698
|
if (defStart >= schemaStart && defEnd <= schemaEnd) {
|
|
8545
8699
|
continue;
|
|
@@ -8774,7 +8928,7 @@ function sameAccess(node, access) {
|
|
|
8774
8928
|
return node.type === import_utils58.AST_NODE_TYPES.MemberExpression && !node.computed && node.object.type === import_utils58.AST_NODE_TYPES.Identifier && node.object.name === access.object && node.property.type === import_utils58.AST_NODE_TYPES.Identifier && node.property.name === access.property;
|
|
8775
8929
|
}
|
|
8776
8930
|
function isNullGuard(node, access) {
|
|
8777
|
-
if (node.type === import_utils58.AST_NODE_TYPES.UnaryExpression && node.operator === "!" && sameAccess(node.argument, access)) return true;
|
|
8931
|
+
if (node.type === import_utils58.AST_NODE_TYPES.UnaryExpression && node.operator === "!" && (sameAccess(node.argument, access) || optionalMemberLengthOf(node.argument, access))) return true;
|
|
8778
8932
|
if (node.type !== import_utils58.AST_NODE_TYPES.BinaryExpression || !["==", "==="].includes(node.operator)) {
|
|
8779
8933
|
return false;
|
|
8780
8934
|
}
|
|
@@ -8790,7 +8944,11 @@ function isEmptyGuard(node, access) {
|
|
|
8790
8944
|
return memberLengthOf(node.left, access) && zero(node.right) || memberLengthOf(node.right, access) && zero(node.left);
|
|
8791
8945
|
}
|
|
8792
8946
|
function memberLengthOf(node, access) {
|
|
8793
|
-
|
|
8947
|
+
const target = node.type === import_utils58.AST_NODE_TYPES.ChainExpression ? node.expression : node;
|
|
8948
|
+
return target.type === import_utils58.AST_NODE_TYPES.MemberExpression && !target.computed && target.property.type === import_utils58.AST_NODE_TYPES.Identifier && target.property.name === "length" && sameAccess(target.object, access);
|
|
8949
|
+
}
|
|
8950
|
+
function optionalMemberLengthOf(node, access) {
|
|
8951
|
+
return node.type === import_utils58.AST_NODE_TYPES.ChainExpression && node.expression.type === import_utils58.AST_NODE_TYPES.MemberExpression && node.expression.optional && memberLengthOf(node, access);
|
|
8794
8952
|
}
|
|
8795
8953
|
function hasEquivalentLeadingGuard(fn, access, visitorKeys) {
|
|
8796
8954
|
if (fn.body.type !== import_utils58.AST_NODE_TYPES.BlockStatement) return false;
|
|
@@ -8798,6 +8956,7 @@ function hasEquivalentLeadingGuard(fn, access, visitorKeys) {
|
|
|
8798
8956
|
if (first?.type !== import_utils58.AST_NODE_TYPES.IfStatement) return false;
|
|
8799
8957
|
const terminating = first.consequent.type === import_utils58.AST_NODE_TYPES.ReturnStatement || first.consequent.type === import_utils58.AST_NODE_TYPES.ThrowStatement || first.consequent.type === import_utils58.AST_NODE_TYPES.BlockStatement && first.consequent.body.length === 1 && (first.consequent.body[0]?.type === import_utils58.AST_NODE_TYPES.ReturnStatement || first.consequent.body[0]?.type === import_utils58.AST_NODE_TYPES.ThrowStatement);
|
|
8800
8958
|
if (!terminating) return false;
|
|
8959
|
+
if (contains(first.consequent, visitorKeys, (node) => sameAccess(node, access))) return false;
|
|
8801
8960
|
return contains(first.test, visitorKeys, (node) => isNullGuard(node, access)) && contains(first.test, visitorKeys, (node) => isEmptyGuard(node, access));
|
|
8802
8961
|
}
|
|
8803
8962
|
function contains(node, visitorKeys, predicate) {
|
|
@@ -8960,7 +9119,7 @@ var isSchemaParseReference = (node) => {
|
|
|
8960
9119
|
const inner = unwrap4(node);
|
|
8961
9120
|
return inner !== null && inner.type === import_utils59.AST_NODE_TYPES.MemberExpression && !inner.computed && inner.property.type === import_utils59.AST_NODE_TYPES.Identifier && (inner.property.name === "parse" || inner.property.name === "safeParse");
|
|
8962
9121
|
};
|
|
8963
|
-
var isRawPayloadSource = (node) => {
|
|
9122
|
+
var isRawPayloadSource = (node, isKnownLocalText) => {
|
|
8964
9123
|
let current = unwrap4(node);
|
|
8965
9124
|
if (current === null) return false;
|
|
8966
9125
|
if (current.type === import_utils59.AST_NODE_TYPES.AwaitExpression) {
|
|
@@ -8984,20 +9143,26 @@ var isRawPayloadSource = (node) => {
|
|
|
8984
9143
|
return !current.arguments.some(isSchemaParseReference) && isRawPayloadSource(callee.object);
|
|
8985
9144
|
}
|
|
8986
9145
|
const object = unwrap4(callee.object);
|
|
8987
|
-
return property.name === "parse" && object !== null && object.type === import_utils59.AST_NODE_TYPES.Identifier && object.name === "JSON" && !isLocalFileRead(current.arguments[0]);
|
|
9146
|
+
return property.name === "parse" && object !== null && object.type === import_utils59.AST_NODE_TYPES.Identifier && object.name === "JSON" && !isLocalFileRead(current.arguments[0]) && isKnownLocalText?.(current.arguments[0]) !== true;
|
|
8988
9147
|
};
|
|
8989
9148
|
var FILE_READ_RE = /^(readFile|readFileSync|readJson|readJsonSync|readJSON)$/;
|
|
9149
|
+
var isDirectLocalFileRead = (node) => {
|
|
9150
|
+
let current = unwrap4(node);
|
|
9151
|
+
if (current?.type === import_utils59.AST_NODE_TYPES.AwaitExpression) {
|
|
9152
|
+
current = unwrap4(current.argument);
|
|
9153
|
+
}
|
|
9154
|
+
if (current?.type !== import_utils59.AST_NODE_TYPES.CallExpression) return false;
|
|
9155
|
+
const callee = unwrap4(current.callee);
|
|
9156
|
+
const name = callee?.type === import_utils59.AST_NODE_TYPES.Identifier ? callee.name : callee?.type === import_utils59.AST_NODE_TYPES.MemberExpression && !callee.computed && callee.property.type === import_utils59.AST_NODE_TYPES.Identifier ? callee.property.name : null;
|
|
9157
|
+
return name !== null && FILE_READ_RE.test(name);
|
|
9158
|
+
};
|
|
8990
9159
|
var isLocalFileRead = (node) => {
|
|
8991
9160
|
let found = false;
|
|
8992
9161
|
const visit = (current) => {
|
|
8993
9162
|
if (found || current === null || current === void 0) return;
|
|
8994
|
-
if (current
|
|
8995
|
-
|
|
8996
|
-
|
|
8997
|
-
if (name !== null && FILE_READ_RE.test(name)) {
|
|
8998
|
-
found = true;
|
|
8999
|
-
return;
|
|
9000
|
-
}
|
|
9163
|
+
if (isDirectLocalFileRead(current)) {
|
|
9164
|
+
found = true;
|
|
9165
|
+
return;
|
|
9001
9166
|
}
|
|
9002
9167
|
for (const key of Object.keys(current)) {
|
|
9003
9168
|
if (key === "parent") continue;
|
|
@@ -9059,6 +9224,87 @@ var isValidationRead = (node) => {
|
|
|
9059
9224
|
}
|
|
9060
9225
|
return callee.type === import_utils59.AST_NODE_TYPES.Identifier && GUARD_NAME_RE.test(callee.name);
|
|
9061
9226
|
};
|
|
9227
|
+
var PRIMITIVE_TYPEOF_RESULTS = /* @__PURE__ */ new Set([
|
|
9228
|
+
"bigint",
|
|
9229
|
+
"boolean",
|
|
9230
|
+
"number",
|
|
9231
|
+
"string",
|
|
9232
|
+
"symbol",
|
|
9233
|
+
"undefined"
|
|
9234
|
+
]);
|
|
9235
|
+
var bindingValidationPolarity = (test, bindingName) => {
|
|
9236
|
+
if (test.type === import_utils59.AST_NODE_TYPES.UnaryExpression && test.operator === "!") {
|
|
9237
|
+
const inner = bindingValidationPolarity(test.argument, bindingName);
|
|
9238
|
+
return inner === "valid-when-true" ? "valid-when-false" : inner === "valid-when-false" ? "valid-when-true" : null;
|
|
9239
|
+
}
|
|
9240
|
+
if (test.type === import_utils59.AST_NODE_TYPES.BinaryExpression) {
|
|
9241
|
+
const typeofName = (node) => node.type === import_utils59.AST_NODE_TYPES.UnaryExpression && node.operator === "typeof" && node.argument.type === import_utils59.AST_NODE_TYPES.Identifier ? node.argument.name : null;
|
|
9242
|
+
const literalType = (node) => node.type === import_utils59.AST_NODE_TYPES.Literal && typeof node.value === "string" && PRIMITIVE_TYPEOF_RESULTS.has(node.value) ? node.value : null;
|
|
9243
|
+
const matches = typeofName(test.left) === bindingName && literalType(test.right) !== null || typeofName(test.right) === bindingName && literalType(test.left) !== null;
|
|
9244
|
+
if (!matches) return null;
|
|
9245
|
+
if (test.operator === "===" || test.operator === "==") {
|
|
9246
|
+
return "valid-when-true";
|
|
9247
|
+
}
|
|
9248
|
+
return test.operator === "!==" || test.operator === "!=" ? "valid-when-false" : null;
|
|
9249
|
+
}
|
|
9250
|
+
return test.type === import_utils59.AST_NODE_TYPES.CallExpression && test.arguments.length === 1 && test.arguments[0]?.type === import_utils59.AST_NODE_TYPES.Identifier && test.arguments[0].name === bindingName && test.callee.type === import_utils59.AST_NODE_TYPES.MemberExpression && !test.callee.computed && test.callee.object.type === import_utils59.AST_NODE_TYPES.Identifier && test.callee.object.name === "Array" && test.callee.property.type === import_utils59.AST_NODE_TYPES.Identifier && test.callee.property.name === "isArray" ? "valid-when-true" : null;
|
|
9251
|
+
};
|
|
9252
|
+
var nodeWithin2 = (node, container) => node.range[0] >= container.range[0] && node.range[1] <= container.range[1];
|
|
9253
|
+
var isFullyValidatedExtractedBinding = (member, source, context) => {
|
|
9254
|
+
const isValidationReference = (identifier) => {
|
|
9255
|
+
for (let current = identifier.parent; current !== void 0 && current !== null; current = current.parent) {
|
|
9256
|
+
if ((current.type === import_utils59.AST_NODE_TYPES.BinaryExpression || current.type === import_utils59.AST_NODE_TYPES.CallExpression || current.type === import_utils59.AST_NODE_TYPES.UnaryExpression) && bindingValidationPolarity(current, identifier.name) !== null) {
|
|
9257
|
+
return true;
|
|
9258
|
+
}
|
|
9259
|
+
if (current.type !== import_utils59.AST_NODE_TYPES.UnaryExpression && current.type !== import_utils59.AST_NODE_TYPES.MemberExpression && current.type !== import_utils59.AST_NODE_TYPES.CallExpression) {
|
|
9260
|
+
return false;
|
|
9261
|
+
}
|
|
9262
|
+
}
|
|
9263
|
+
return false;
|
|
9264
|
+
};
|
|
9265
|
+
const isGuardedUse = (identifier) => {
|
|
9266
|
+
for (let current = identifier.parent; current !== void 0 && current !== null; current = current.parent) {
|
|
9267
|
+
if (current.type === import_utils59.AST_NODE_TYPES.ConditionalExpression) {
|
|
9268
|
+
const polarity = bindingValidationPolarity(current.test, identifier.name);
|
|
9269
|
+
if (polarity === "valid-when-true" && nodeWithin2(identifier, current.consequent)) {
|
|
9270
|
+
return true;
|
|
9271
|
+
}
|
|
9272
|
+
if (polarity === "valid-when-false" && nodeWithin2(identifier, current.alternate)) {
|
|
9273
|
+
return true;
|
|
9274
|
+
}
|
|
9275
|
+
}
|
|
9276
|
+
if (current.type === import_utils59.AST_NODE_TYPES.IfStatement) {
|
|
9277
|
+
const polarity = bindingValidationPolarity(current.test, identifier.name);
|
|
9278
|
+
if (polarity === "valid-when-true" && nodeWithin2(identifier, current.consequent)) {
|
|
9279
|
+
return true;
|
|
9280
|
+
}
|
|
9281
|
+
if (polarity === "valid-when-false" && current.alternate !== null && nodeWithin2(identifier, current.alternate)) {
|
|
9282
|
+
return true;
|
|
9283
|
+
}
|
|
9284
|
+
}
|
|
9285
|
+
if (current.type === import_utils59.AST_NODE_TYPES.FunctionDeclaration || current.type === import_utils59.AST_NODE_TYPES.FunctionExpression || current.type === import_utils59.AST_NODE_TYPES.ArrowFunctionExpression) {
|
|
9286
|
+
return false;
|
|
9287
|
+
}
|
|
9288
|
+
}
|
|
9289
|
+
return false;
|
|
9290
|
+
};
|
|
9291
|
+
const declarator = member.parent;
|
|
9292
|
+
if (declarator.type !== import_utils59.AST_NODE_TYPES.VariableDeclarator || declarator.init !== member || declarator.id.type !== import_utils59.AST_NODE_TYPES.Identifier || declarator.parent.type !== import_utils59.AST_NODE_TYPES.VariableDeclaration || declarator.parent.kind !== "const") {
|
|
9293
|
+
return false;
|
|
9294
|
+
}
|
|
9295
|
+
const extracted = context.sourceCode.getDeclaredVariables(declarator)[0];
|
|
9296
|
+
if (extracted === void 0 || extracted.scope !== source.scope) return false;
|
|
9297
|
+
let hasValueUse = false;
|
|
9298
|
+
for (const reference of extracted.references) {
|
|
9299
|
+
const identifier = reference.identifier;
|
|
9300
|
+
if (identifier.type !== import_utils59.AST_NODE_TYPES.Identifier) return false;
|
|
9301
|
+
if (nodeWithin2(identifier, declarator)) continue;
|
|
9302
|
+
if (isValidationReference(identifier)) continue;
|
|
9303
|
+
hasValueUse = true;
|
|
9304
|
+
if (!isGuardedUse(identifier)) return false;
|
|
9305
|
+
}
|
|
9306
|
+
return hasValueUse;
|
|
9307
|
+
};
|
|
9062
9308
|
var isGuardTestPosition = (node) => {
|
|
9063
9309
|
let current = node;
|
|
9064
9310
|
let parent = current.parent;
|
|
@@ -9082,13 +9328,13 @@ var isGuardTestPosition = (node) => {
|
|
|
9082
9328
|
}
|
|
9083
9329
|
return false;
|
|
9084
9330
|
};
|
|
9085
|
-
var
|
|
9331
|
+
var unvalidatedVariableRef = (node, scope, tracked) => {
|
|
9086
9332
|
const unwrapped = unwrap4(node);
|
|
9087
9333
|
if (unwrapped === null || unwrapped.type !== import_utils59.AST_NODE_TYPES.Identifier) {
|
|
9088
|
-
return
|
|
9334
|
+
return null;
|
|
9089
9335
|
}
|
|
9090
9336
|
const variable = findVariable2(scope, unwrapped.name);
|
|
9091
|
-
return variable !== null && tracked.has(variable);
|
|
9337
|
+
return variable !== null && tracked.has(variable) ? variable : null;
|
|
9092
9338
|
};
|
|
9093
9339
|
var prefer_schema_for_api_payload_default = createRule({
|
|
9094
9340
|
name: "prefer-schema-for-api-payload",
|
|
@@ -9108,6 +9354,56 @@ var prefer_schema_for_api_payload_default = createRule({
|
|
|
9108
9354
|
return {};
|
|
9109
9355
|
}
|
|
9110
9356
|
const unvalidatedVariables = /* @__PURE__ */ new Set();
|
|
9357
|
+
const aliasGroups = /* @__PURE__ */ new Map();
|
|
9358
|
+
const localFileTextVariables = /* @__PURE__ */ new Set();
|
|
9359
|
+
const localFileTextRef = (node, scope) => {
|
|
9360
|
+
const unwrapped = unwrap4(node);
|
|
9361
|
+
if (unwrapped?.type !== import_utils59.AST_NODE_TYPES.Identifier) return null;
|
|
9362
|
+
const variable = findVariable2(scope, unwrapped.name);
|
|
9363
|
+
return variable !== null && localFileTextVariables.has(variable) ? variable : null;
|
|
9364
|
+
};
|
|
9365
|
+
const updateLocalFileText = (target, value, scope) => {
|
|
9366
|
+
const source = localFileTextRef(value, scope);
|
|
9367
|
+
if (isDirectLocalFileRead(value) || source !== null && source.scope === target.scope) {
|
|
9368
|
+
localFileTextVariables.add(target);
|
|
9369
|
+
} else {
|
|
9370
|
+
localFileTextVariables.delete(target);
|
|
9371
|
+
}
|
|
9372
|
+
};
|
|
9373
|
+
const clearBinding = (variable) => {
|
|
9374
|
+
unvalidatedVariables.delete(variable);
|
|
9375
|
+
const group = aliasGroups.get(variable);
|
|
9376
|
+
aliasGroups.delete(variable);
|
|
9377
|
+
group?.delete(variable);
|
|
9378
|
+
};
|
|
9379
|
+
const clearAliasGroup = (variable) => {
|
|
9380
|
+
const group = aliasGroups.get(variable);
|
|
9381
|
+
if (group === void 0) {
|
|
9382
|
+
unvalidatedVariables.delete(variable);
|
|
9383
|
+
return;
|
|
9384
|
+
}
|
|
9385
|
+
for (const alias of group) {
|
|
9386
|
+
unvalidatedVariables.delete(alias);
|
|
9387
|
+
aliasGroups.delete(alias);
|
|
9388
|
+
}
|
|
9389
|
+
group.clear();
|
|
9390
|
+
};
|
|
9391
|
+
const trackRawBinding = (variable) => {
|
|
9392
|
+
clearBinding(variable);
|
|
9393
|
+
const group = /* @__PURE__ */ new Set([variable]);
|
|
9394
|
+
unvalidatedVariables.add(variable);
|
|
9395
|
+
aliasGroups.set(variable, group);
|
|
9396
|
+
};
|
|
9397
|
+
const trackAlias = (target, source) => {
|
|
9398
|
+
if (target === source) return;
|
|
9399
|
+
const group = aliasGroups.get(source) ?? /* @__PURE__ */ new Set([source]);
|
|
9400
|
+
if (aliasGroups.get(target) === group) return;
|
|
9401
|
+
clearBinding(target);
|
|
9402
|
+
unvalidatedVariables.add(target);
|
|
9403
|
+
group.add(target);
|
|
9404
|
+
aliasGroups.set(source, group);
|
|
9405
|
+
aliasGroups.set(target, group);
|
|
9406
|
+
};
|
|
9111
9407
|
const isFullyNarrowedPattern = (declarator) => {
|
|
9112
9408
|
const declared = context.sourceCode.getDeclaredVariables(declarator);
|
|
9113
9409
|
return declared.length > 0 && declared.every(
|
|
@@ -9116,29 +9412,40 @@ var prefer_schema_for_api_payload_default = createRule({
|
|
|
9116
9412
|
)
|
|
9117
9413
|
);
|
|
9118
9414
|
};
|
|
9119
|
-
const trackInitializer = (declarator) => {
|
|
9120
|
-
if (!isRawPayloadSource(declarator.init)) return;
|
|
9415
|
+
const trackInitializer = (declarator, scope) => {
|
|
9121
9416
|
const declaredVars = context.sourceCode.getDeclaredVariables(declarator);
|
|
9122
9417
|
const variable = declaredVars[0];
|
|
9123
|
-
if (variable
|
|
9124
|
-
|
|
9418
|
+
if (variable === void 0) return;
|
|
9419
|
+
const localText = (candidate) => localFileTextRef(candidate, scope) !== null;
|
|
9420
|
+
if (isRawPayloadSource(declarator.init, localText)) {
|
|
9421
|
+
trackRawBinding(variable);
|
|
9422
|
+
return;
|
|
9125
9423
|
}
|
|
9424
|
+
const source = unvalidatedVariableRef(declarator.init, scope, unvalidatedVariables);
|
|
9425
|
+
if (source !== null) trackAlias(variable, source);
|
|
9126
9426
|
};
|
|
9127
9427
|
return {
|
|
9128
9428
|
VariableDeclarator(node) {
|
|
9129
9429
|
const scope = context.sourceCode.getScope(node);
|
|
9130
9430
|
if (node.id.type === import_utils59.AST_NODE_TYPES.Identifier) {
|
|
9131
|
-
|
|
9431
|
+
const variable = context.sourceCode.getDeclaredVariables(node)[0];
|
|
9432
|
+
if (variable !== void 0) {
|
|
9433
|
+
updateLocalFileText(variable, node.init, scope);
|
|
9434
|
+
}
|
|
9435
|
+
trackInitializer(node, scope);
|
|
9132
9436
|
return;
|
|
9133
9437
|
}
|
|
9134
9438
|
if (node.id.type === import_utils59.AST_NODE_TYPES.ObjectPattern || node.id.type === import_utils59.AST_NODE_TYPES.ArrayPattern) {
|
|
9135
|
-
if (isRawPayloadSource(
|
|
9439
|
+
if (isRawPayloadSource(
|
|
9440
|
+
node.init,
|
|
9441
|
+
(candidate) => localFileTextRef(candidate, scope) !== null
|
|
9442
|
+
)) {
|
|
9136
9443
|
if (!isFullyNarrowedPattern(node)) {
|
|
9137
9444
|
context.report({ node: node.id, messageId: "unparsedJsonAccess" });
|
|
9138
9445
|
}
|
|
9139
9446
|
return;
|
|
9140
9447
|
}
|
|
9141
|
-
if (
|
|
9448
|
+
if (unvalidatedVariableRef(node.init, scope, unvalidatedVariables) !== null) {
|
|
9142
9449
|
context.report({ node: node.id, messageId: "unparsedJsonAccess" });
|
|
9143
9450
|
}
|
|
9144
9451
|
}
|
|
@@ -9148,22 +9455,29 @@ var prefer_schema_for_api_payload_default = createRule({
|
|
|
9148
9455
|
if (node.left.type === import_utils59.AST_NODE_TYPES.Identifier) {
|
|
9149
9456
|
const variable = findVariable2(scope, node.left.name);
|
|
9150
9457
|
if (variable === null) return;
|
|
9151
|
-
|
|
9152
|
-
|
|
9458
|
+
const isLocalText = (candidate) => localFileTextRef(candidate, scope) !== null;
|
|
9459
|
+
updateLocalFileText(variable, node.right, scope);
|
|
9460
|
+
if (isRawPayloadSource(node.right, isLocalText)) {
|
|
9461
|
+
trackRawBinding(variable);
|
|
9153
9462
|
} else {
|
|
9154
|
-
unvalidatedVariables
|
|
9463
|
+
const source = unvalidatedVariableRef(node.right, scope, unvalidatedVariables);
|
|
9464
|
+
if (source === null) clearBinding(variable);
|
|
9465
|
+
else trackAlias(variable, source);
|
|
9155
9466
|
}
|
|
9156
9467
|
return;
|
|
9157
9468
|
}
|
|
9158
9469
|
if (node.left.type === import_utils59.AST_NODE_TYPES.ObjectPattern || node.left.type === import_utils59.AST_NODE_TYPES.ArrayPattern) {
|
|
9159
|
-
if (isRawPayloadSource(
|
|
9470
|
+
if (isRawPayloadSource(
|
|
9471
|
+
node.right,
|
|
9472
|
+
(candidate) => localFileTextRef(candidate, scope) !== null
|
|
9473
|
+
)) {
|
|
9160
9474
|
context.report({
|
|
9161
9475
|
node: node.left,
|
|
9162
9476
|
messageId: "unparsedJsonAccess"
|
|
9163
9477
|
});
|
|
9164
9478
|
return;
|
|
9165
9479
|
}
|
|
9166
|
-
if (
|
|
9480
|
+
if (unvalidatedVariableRef(node.right, scope, unvalidatedVariables) !== null) {
|
|
9167
9481
|
context.report({
|
|
9168
9482
|
node: node.left,
|
|
9169
9483
|
messageId: "unparsedJsonAccess"
|
|
@@ -9184,7 +9498,7 @@ var prefer_schema_for_api_payload_default = createRule({
|
|
|
9184
9498
|
continue;
|
|
9185
9499
|
}
|
|
9186
9500
|
const variable = findVariable2(scope, unwrapped.name);
|
|
9187
|
-
if (variable !== null)
|
|
9501
|
+
if (variable !== null) clearAliasGroup(variable);
|
|
9188
9502
|
}
|
|
9189
9503
|
},
|
|
9190
9504
|
MemberExpression(node) {
|
|
@@ -9192,7 +9506,10 @@ var prefer_schema_for_api_payload_default = createRule({
|
|
|
9192
9506
|
if (isValidationRead(node)) return;
|
|
9193
9507
|
const scope = context.sourceCode.getScope(node);
|
|
9194
9508
|
const obj = unwrap4(node.object);
|
|
9195
|
-
if (isRawPayloadSource(
|
|
9509
|
+
if (isRawPayloadSource(
|
|
9510
|
+
obj,
|
|
9511
|
+
(candidate) => localFileTextRef(candidate, scope) !== null
|
|
9512
|
+
)) {
|
|
9196
9513
|
const parent = node.parent;
|
|
9197
9514
|
if (parent.type === import_utils59.AST_NODE_TYPES.CallExpression && parent.callee === node && node.property.type === import_utils59.AST_NODE_TYPES.Identifier && (node.property.name === "parse" || node.property.name === "safeParse" || PROMISE_CHAIN_METHODS.has(node.property.name))) {
|
|
9198
9515
|
return;
|
|
@@ -9200,12 +9517,13 @@ var prefer_schema_for_api_payload_default = createRule({
|
|
|
9200
9517
|
context.report({ node, messageId: "unparsedJsonAccess" });
|
|
9201
9518
|
return;
|
|
9202
9519
|
}
|
|
9203
|
-
|
|
9204
|
-
|
|
9205
|
-
|
|
9206
|
-
|
|
9207
|
-
unvalidatedVariables.delete(variable);
|
|
9520
|
+
const variable = obj?.type === import_utils59.AST_NODE_TYPES.Identifier ? unvalidatedVariableRef(obj, scope, unvalidatedVariables) : null;
|
|
9521
|
+
if (variable !== null) {
|
|
9522
|
+
if (isFullyValidatedExtractedBinding(node, variable, context)) {
|
|
9523
|
+
return;
|
|
9208
9524
|
}
|
|
9525
|
+
context.report({ node, messageId: "unparsedJsonAccess" });
|
|
9526
|
+
clearAliasGroup(variable);
|
|
9209
9527
|
}
|
|
9210
9528
|
}
|
|
9211
9529
|
};
|
|
@@ -10969,8 +11287,8 @@ function initProvablyLacksSignal(init) {
|
|
|
10969
11287
|
}
|
|
10970
11288
|
return true;
|
|
10971
11289
|
}
|
|
10972
|
-
function
|
|
10973
|
-
return node.type === import_utils67.AST_NODE_TYPES.Literal && typeof node.value === "string" || node.type === import_utils67.AST_NODE_TYPES.TemplateLiteral;
|
|
11290
|
+
function isInlineUrl(node, resolvesToGlobal) {
|
|
11291
|
+
return node.type === import_utils67.AST_NODE_TYPES.Literal && typeof node.value === "string" || node.type === import_utils67.AST_NODE_TYPES.TemplateLiteral || node.type === import_utils67.AST_NODE_TYPES.NewExpression && node.callee.type === import_utils67.AST_NODE_TYPES.Identifier && node.callee.name === "URL" && resolvesToGlobal(node.callee);
|
|
10974
11292
|
}
|
|
10975
11293
|
var require_fetch_timeout_default = createRule({
|
|
10976
11294
|
name: "require-fetch-timeout",
|
|
@@ -11022,7 +11340,7 @@ var require_fetch_timeout_default = createRule({
|
|
|
11022
11340
|
return;
|
|
11023
11341
|
}
|
|
11024
11342
|
const [first, init] = node.arguments;
|
|
11025
|
-
if (node.arguments.length === 1 && first !== void 0 && !
|
|
11343
|
+
if (node.arguments.length === 1 && first !== void 0 && !isInlineUrl(first, resolvesToGlobal)) {
|
|
11026
11344
|
return;
|
|
11027
11345
|
}
|
|
11028
11346
|
if (init === void 0 || initProvablyLacksSignal(init)) {
|
|
@@ -11039,7 +11357,7 @@ var CONFIGISH_TYPE_RE = /(?:Options|Opts|Config|Configuration|Settings|Params|Pr
|
|
|
11039
11357
|
var CONFIGISH_NAME_RE = /^(?:options|opts|config|configuration|settings|params|props|args|env|environment|callbacks|flags|logger|log|clock)$/i;
|
|
11040
11358
|
var HTTP_TRANSPORT_TYPE_RE = /^(?:KyInstance|AxiosInstance|Session)$/;
|
|
11041
11359
|
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)$/;
|
|
11042
|
-
var VALUE_TYPE_RE = /^(?:ArrayBuffer|Blob|Buffer|Date|RegExp|URL|URLSearchParams)$/;
|
|
11360
|
+
var VALUE_TYPE_RE = /^(?:ArrayBuffer|Blob|Buffer|Date|NodePath|RegExp|URL|URLSearchParams)$/;
|
|
11043
11361
|
var TRANSPORT_WRAPPER_NAME_RE = /(?:Client$|^Http[A-Z])/;
|
|
11044
11362
|
var ERROR_VALUE_NAME_RE = /Error$/;
|
|
11045
11363
|
var FLUENT_BUILDER_NAME_RE = /Builder$/;
|
|
@@ -11503,7 +11821,7 @@ var require_interface_for_injected_service_default = createRule({
|
|
|
11503
11821
|
if (node.abstract === true) return;
|
|
11504
11822
|
if (node.decorators.length > 0) return;
|
|
11505
11823
|
const ctor = node.body.body.find(
|
|
11506
|
-
(member) => member.type === import_utils68.AST_NODE_TYPES.MethodDefinition && member.kind === "constructor"
|
|
11824
|
+
(member) => member.type === import_utils68.AST_NODE_TYPES.MethodDefinition && member.kind === "constructor" && member.value.body !== null && member.value.body !== void 0
|
|
11507
11825
|
);
|
|
11508
11826
|
if (ctor === void 0) return;
|
|
11509
11827
|
const constructorFacts = readConstructor(
|
|
@@ -12382,7 +12700,7 @@ var rules = {
|
|
|
12382
12700
|
};
|
|
12383
12701
|
var meta = {
|
|
12384
12702
|
name: "@sarj/eslint-plugin",
|
|
12385
|
-
version: "11.0
|
|
12703
|
+
version: "11.2.0"
|
|
12386
12704
|
};
|
|
12387
12705
|
var applicationOnlyRules = [
|
|
12388
12706
|
"no-restricted-library-load",
|