@sarj/eslint-plugin 15.4.0 → 15.5.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 +169 -24
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +171 -26
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -607,6 +607,9 @@ function isAssertionStatement(statement) {
|
|
|
607
607
|
const expression = statement.expression;
|
|
608
608
|
return expression.type === import_utils3.AST_NODE_TYPES.CallExpression && isAssertionCall(expression);
|
|
609
609
|
}
|
|
610
|
+
function isTypeOnlyContractStatement(statement) {
|
|
611
|
+
return statement.type === import_utils3.AST_NODE_TYPES.TSTypeAliasDeclaration || statement.type === import_utils3.AST_NODE_TYPES.TSInterfaceDeclaration;
|
|
612
|
+
}
|
|
610
613
|
function normalizedLiteral(node) {
|
|
611
614
|
if ("regex" in node) {
|
|
612
615
|
return ["Literal", "regex", node.regex.pattern, node.regex.flags];
|
|
@@ -664,7 +667,7 @@ var duplicate_test_body_default = createRule({
|
|
|
664
667
|
return;
|
|
665
668
|
}
|
|
666
669
|
const body2 = candidate.body;
|
|
667
|
-
if (body2.body.type !== import_utils3.AST_NODE_TYPES.BlockStatement || body2.body.body.length < MIN_STATEMENTS || body2.body.body.every(isAssertionStatement)) {
|
|
670
|
+
if (body2.body.type !== import_utils3.AST_NODE_TYPES.BlockStatement || body2.body.body.length < MIN_STATEMENTS || body2.body.body.every(isAssertionStatement) || body2.body.body.some(isTypeOnlyContractStatement)) {
|
|
668
671
|
return;
|
|
669
672
|
}
|
|
670
673
|
const comments = context.sourceCode.getCommentsInside(body2.body).map((comment) => [comment.type, comment.value]);
|
|
@@ -3559,7 +3562,11 @@ var NUMBER_METHODS = /* @__PURE__ */ new Set([
|
|
|
3559
3562
|
"lt",
|
|
3560
3563
|
"lte",
|
|
3561
3564
|
"max",
|
|
3562
|
-
"min"
|
|
3565
|
+
"min",
|
|
3566
|
+
"negative",
|
|
3567
|
+
"nonnegative",
|
|
3568
|
+
"nonpositive",
|
|
3569
|
+
"positive"
|
|
3563
3570
|
]);
|
|
3564
3571
|
var LENGTH_METHODS = /* @__PURE__ */ new Set(["length", "max", "min"]);
|
|
3565
3572
|
var RESHAPING_METHODS = /* @__PURE__ */ new Set([
|
|
@@ -3696,13 +3703,29 @@ var no_impossible_zod_literal_bounds_default = createRule({
|
|
|
3696
3703
|
let upper = null;
|
|
3697
3704
|
for (const { method, node } of chain.calls) {
|
|
3698
3705
|
if (!allowed.has(method)) return null;
|
|
3699
|
-
const
|
|
3706
|
+
const semantic = method === "positive" ? { exclusive: true, lower: true, value: 0 } : method === "nonnegative" ? { exclusive: false, lower: true, value: 0 } : method === "negative" ? { exclusive: true, lower: false, value: 0 } : method === "nonpositive" ? { exclusive: false, lower: false, value: 0 } : null;
|
|
3707
|
+
const value = semantic?.value ?? finiteNumber(node.arguments[0]);
|
|
3700
3708
|
if (value === null) return null;
|
|
3701
3709
|
if (chain.kind !== "number" && (!Number.isInteger(value) || value < 0)) {
|
|
3702
3710
|
return null;
|
|
3703
3711
|
}
|
|
3704
3712
|
const label = `${method}(${String(value)})`;
|
|
3705
|
-
if (
|
|
3713
|
+
if (semantic !== null) {
|
|
3714
|
+
if (node.arguments.length !== 0) return null;
|
|
3715
|
+
if (semantic.lower) {
|
|
3716
|
+
lower = strongerLower(lower, {
|
|
3717
|
+
exclusive: semantic.exclusive,
|
|
3718
|
+
label: `${method}()`,
|
|
3719
|
+
value
|
|
3720
|
+
});
|
|
3721
|
+
} else {
|
|
3722
|
+
upper = strongerUpper(upper, {
|
|
3723
|
+
exclusive: semantic.exclusive,
|
|
3724
|
+
label: `${method}()`,
|
|
3725
|
+
value
|
|
3726
|
+
});
|
|
3727
|
+
}
|
|
3728
|
+
} else if (method === "length") {
|
|
3706
3729
|
lower = strongerLower(lower, { exclusive: false, label, value });
|
|
3707
3730
|
upper = strongerUpper(upper, { exclusive: false, label, value });
|
|
3708
3731
|
} else if (method === "gt" || method === "gte" || method === "min") {
|
|
@@ -6815,6 +6838,13 @@ function nearestEnclosingFunction(node) {
|
|
|
6815
6838
|
}
|
|
6816
6839
|
return null;
|
|
6817
6840
|
}
|
|
6841
|
+
function isImmediatelyConsumedSleep(node) {
|
|
6842
|
+
const parent = node.parent;
|
|
6843
|
+
if (parent?.type === import_utils34.AST_NODE_TYPES.AwaitExpression || parent?.type === import_utils34.AST_NODE_TYPES.ReturnStatement || parent?.type === import_utils34.AST_NODE_TYPES.ExpressionStatement) {
|
|
6844
|
+
return true;
|
|
6845
|
+
}
|
|
6846
|
+
return parent?.type === import_utils34.AST_NODE_TYPES.ArrowFunctionExpression && parent.body === node;
|
|
6847
|
+
}
|
|
6818
6848
|
function isTestBody(fn) {
|
|
6819
6849
|
const call = fn.parent;
|
|
6820
6850
|
if (call?.type !== import_utils34.AST_NODE_TYPES.CallExpression || !call.arguments.some((argument) => argument === fn)) {
|
|
@@ -6857,6 +6887,9 @@ var no_sleep_in_test_body_default = createRule({
|
|
|
6857
6887
|
return {};
|
|
6858
6888
|
}
|
|
6859
6889
|
const report = (node) => {
|
|
6890
|
+
if (!isImmediatelyConsumedSleep(node)) {
|
|
6891
|
+
return;
|
|
6892
|
+
}
|
|
6860
6893
|
const enclosing = nearestEnclosingFunction(node);
|
|
6861
6894
|
if (enclosing === null || !isTestBody(enclosing)) {
|
|
6862
6895
|
return;
|
|
@@ -7154,6 +7187,27 @@ function isSmallStaticForLoop(node) {
|
|
|
7154
7187
|
const iterations = node.test.right.value - declaration.init.value + (node.test.operator === "<=" ? 1 : 0);
|
|
7155
7188
|
return iterations >= 0 && iterations <= 8;
|
|
7156
7189
|
}
|
|
7190
|
+
function isStringSeededReduce(node) {
|
|
7191
|
+
if (node.callee.type !== "MemberExpression" || node.callee.computed || node.callee.property.type !== "Identifier" || node.callee.property.name !== "reduce" || node.arguments.length !== 2) {
|
|
7192
|
+
return false;
|
|
7193
|
+
}
|
|
7194
|
+
const [callback, initial] = node.arguments;
|
|
7195
|
+
if (node.callee.object.type === "ArrayExpression" && node.callee.object.elements.length <= 8) {
|
|
7196
|
+
return false;
|
|
7197
|
+
}
|
|
7198
|
+
if (callback === void 0 || initial === void 0 || callback.type === "SpreadElement" || initial.type === "SpreadElement" || callback.type !== "ArrowFunctionExpression" && callback.type !== "FunctionExpression" || callback.params[0]?.type !== "Identifier" || !isStringLiteralInit(initial)) {
|
|
7199
|
+
return false;
|
|
7200
|
+
}
|
|
7201
|
+
const accumulator = callback.params[0].name;
|
|
7202
|
+
if (callback.body.type !== "BlockStatement") {
|
|
7203
|
+
return isConcatOntoTarget(callback.body, accumulator);
|
|
7204
|
+
}
|
|
7205
|
+
if (callback.body.body.length !== 1 || callback.body.body[0]?.type !== "ReturnStatement") {
|
|
7206
|
+
return false;
|
|
7207
|
+
}
|
|
7208
|
+
const returned = callback.body.body[0].argument;
|
|
7209
|
+
return returned !== null && isConcatOntoTarget(returned, accumulator);
|
|
7210
|
+
}
|
|
7157
7211
|
var no_string_concat_in_loop_default = createRule({
|
|
7158
7212
|
name: "no-string-concat-in-loop",
|
|
7159
7213
|
documentation: noStringConcatInLoopDocumentation,
|
|
@@ -7164,7 +7218,8 @@ var no_string_concat_in_loop_default = createRule({
|
|
|
7164
7218
|
},
|
|
7165
7219
|
schema: [],
|
|
7166
7220
|
messages: {
|
|
7167
|
-
noStringConcatInLoop: 'Avoid building a string with `+=` inside a loop \u2014 this is O(n^2). Push the parts onto an array and use `arr.join("")` after the loop.'
|
|
7221
|
+
noStringConcatInLoop: 'Avoid building a string with `+=` inside a loop \u2014 this is O(n^2). Push the parts onto an array and use `arr.join("")` after the loop.',
|
|
7222
|
+
noStringReduce: "Avoid concatenating a growing string in `reduce` \u2014 this is O(n^2). Map the fragments and join them once instead."
|
|
7168
7223
|
}
|
|
7169
7224
|
},
|
|
7170
7225
|
defaultOptions: [],
|
|
@@ -7174,6 +7229,11 @@ var no_string_concat_in_loop_default = createRule({
|
|
|
7174
7229
|
}
|
|
7175
7230
|
const reported = /* @__PURE__ */ new WeakMap();
|
|
7176
7231
|
return {
|
|
7232
|
+
CallExpression(node) {
|
|
7233
|
+
if (isStringSeededReduce(node)) {
|
|
7234
|
+
context.report({ node, messageId: "noStringReduce" });
|
|
7235
|
+
}
|
|
7236
|
+
},
|
|
7177
7237
|
AssignmentExpression(node) {
|
|
7178
7238
|
if (node.left.type !== "Identifier") {
|
|
7179
7239
|
return;
|
|
@@ -7278,6 +7338,9 @@ function isLiteral(node) {
|
|
|
7278
7338
|
return false;
|
|
7279
7339
|
}
|
|
7280
7340
|
}
|
|
7341
|
+
function isStructuralLiteral(node) {
|
|
7342
|
+
return node.type === import_utils37.AST_NODE_TYPES.ArrayExpression || node.type === import_utils37.AST_NODE_TYPES.ObjectExpression;
|
|
7343
|
+
}
|
|
7281
7344
|
function expectOperand(callee) {
|
|
7282
7345
|
const receiver = callee.object;
|
|
7283
7346
|
if (receiver.type !== import_utils37.AST_NODE_TYPES.CallExpression || receiver.callee.type !== import_utils37.AST_NODE_TYPES.Identifier || receiver.callee.name !== "expect" || receiver.arguments.length !== 1) {
|
|
@@ -7334,6 +7397,9 @@ var no_tautological_expect_default = createRule({
|
|
|
7334
7397
|
if (!EQUALITY_MATCHERS.has(matcher) || node.arguments.length !== 1 || expected === void 0 || !isLiteral(expected)) {
|
|
7335
7398
|
return;
|
|
7336
7399
|
}
|
|
7400
|
+
if (matcher === "toBe" && (isStructuralLiteral(operand) || isStructuralLiteral(expected))) {
|
|
7401
|
+
return;
|
|
7402
|
+
}
|
|
7337
7403
|
if (context.sourceCode.getText(operand) !== context.sourceCode.getText(expected)) {
|
|
7338
7404
|
return;
|
|
7339
7405
|
}
|
|
@@ -7847,7 +7913,13 @@ var no_declaration_comment_wall_default = createRule({
|
|
|
7847
7913
|
const lead = ownsItsLine ? endingOn.get(member.loc.start.line - 1) : void 0;
|
|
7848
7914
|
if (lead !== void 0) {
|
|
7849
7915
|
const before = sourceCode.getTokenBefore(lead, { includeComments: false });
|
|
7850
|
-
if (before === null || before.loc.end.line < lead.loc.start.line)
|
|
7916
|
+
if (before === null || before.loc.end.line < lead.loc.start.line) {
|
|
7917
|
+
const previousLine = endingOn.get(lead.loc.start.line - 1);
|
|
7918
|
+
if (lead.type === import_utils40.AST_TOKEN_TYPES.Line && previousLine?.type === import_utils40.AST_TOKEN_TYPES.Line && previousLine.loc.start.column === lead.loc.start.column) {
|
|
7919
|
+
return void 0;
|
|
7920
|
+
}
|
|
7921
|
+
return lead;
|
|
7922
|
+
}
|
|
7851
7923
|
}
|
|
7852
7924
|
const trail = startingOn.get(member.loc.end.line);
|
|
7853
7925
|
return trail !== void 0 && trail.range[0] > member.range[0] ? trail : void 0;
|
|
@@ -8149,7 +8221,13 @@ var no_type_member_comment_wall_default = createRule({
|
|
|
8149
8221
|
const lead = ownsItsLine ? endingOn.get(member.loc.start.line - 1) : void 0;
|
|
8150
8222
|
if (lead !== void 0) {
|
|
8151
8223
|
const before = sourceCode.getTokenBefore(lead, { includeComments: false });
|
|
8152
|
-
if (before === null || before.loc.end.line < lead.loc.start.line)
|
|
8224
|
+
if (before === null || before.loc.end.line < lead.loc.start.line) {
|
|
8225
|
+
const previousLine = endingOn.get(lead.loc.start.line - 1);
|
|
8226
|
+
if (lead.type === import_utils42.AST_TOKEN_TYPES.Line && previousLine?.type === import_utils42.AST_TOKEN_TYPES.Line && previousLine.loc.start.column === lead.loc.start.column) {
|
|
8227
|
+
return void 0;
|
|
8228
|
+
}
|
|
8229
|
+
return lead;
|
|
8230
|
+
}
|
|
8153
8231
|
}
|
|
8154
8232
|
const trail = startingOn.get(member.loc.end.line);
|
|
8155
8233
|
return trail !== void 0 && trail.range[0] > member.range[0] ? trail : void 0;
|
|
@@ -8446,6 +8524,10 @@ var no_unnecessary_use_client_default = createRule({
|
|
|
8446
8524
|
var import_utils44 = require("@typescript-eslint/utils");
|
|
8447
8525
|
var MOCK_TYPE_NAMES = /* @__PURE__ */ new Set([
|
|
8448
8526
|
"Mock",
|
|
8527
|
+
"Mocked",
|
|
8528
|
+
"MockedClass",
|
|
8529
|
+
"MockedFunction",
|
|
8530
|
+
"MockedObject",
|
|
8449
8531
|
"MockInstance",
|
|
8450
8532
|
"SpyInstance"
|
|
8451
8533
|
]);
|
|
@@ -8689,9 +8771,9 @@ var no_zod_native_enum_default = createRule({
|
|
|
8689
8771
|
}
|
|
8690
8772
|
function isZodMemberCall(node, api) {
|
|
8691
8773
|
const callee = node.callee;
|
|
8692
|
-
if (callee.type === import_utils45.AST_NODE_TYPES.MemberExpression &&
|
|
8774
|
+
if (callee.type === import_utils45.AST_NODE_TYPES.MemberExpression && callee.object.type === import_utils45.AST_NODE_TYPES.Identifier && (callee.property.type === import_utils45.AST_NODE_TYPES.Identifier && !callee.computed && callee.property.name === api || callee.computed && callee.property.type === import_utils45.AST_NODE_TYPES.Literal && callee.property.value === api)) {
|
|
8693
8775
|
const binding = resolvedBinding(callee.object);
|
|
8694
|
-
return binding !== null && zodNamespaceBindings.has(binding)
|
|
8776
|
+
return binding !== null && zodNamespaceBindings.has(binding);
|
|
8695
8777
|
}
|
|
8696
8778
|
if (callee.type === import_utils45.AST_NODE_TYPES.Identifier) {
|
|
8697
8779
|
const binding = resolvedBinding(callee);
|
|
@@ -9535,6 +9617,27 @@ var prefer_immutable_module_constant_default = createRule({
|
|
|
9535
9617
|
}
|
|
9536
9618
|
const exportedNames2 = /* @__PURE__ */ new Set();
|
|
9537
9619
|
const typeAliases2 = /* @__PURE__ */ new Map();
|
|
9620
|
+
const mutatesThroughConstAlias = (root) => {
|
|
9621
|
+
const pending = [root];
|
|
9622
|
+
const seen = /* @__PURE__ */ new Set();
|
|
9623
|
+
while (pending.length > 0) {
|
|
9624
|
+
const variable = pending.pop();
|
|
9625
|
+
if (variable === void 0 || seen.has(variable)) continue;
|
|
9626
|
+
seen.add(variable);
|
|
9627
|
+
for (const reference of variable.references) {
|
|
9628
|
+
const identifier = reference.identifier;
|
|
9629
|
+
if (identifier.type !== import_utils51.AST_NODE_TYPES.Identifier) continue;
|
|
9630
|
+
if (referenceMutates(identifier, isUnshadowedGlobal)) return true;
|
|
9631
|
+
const declarator = identifier.parent;
|
|
9632
|
+
if (declarator.type !== import_utils51.AST_NODE_TYPES.VariableDeclarator || declarator.init !== identifier || declarator.id.type !== import_utils51.AST_NODE_TYPES.Identifier || declarator.parent.type !== import_utils51.AST_NODE_TYPES.VariableDeclaration || declarator.parent.kind !== "const") {
|
|
9633
|
+
continue;
|
|
9634
|
+
}
|
|
9635
|
+
const alias = sourceCode.getDeclaredVariables(declarator)[0];
|
|
9636
|
+
if (alias !== void 0) pending.push(alias);
|
|
9637
|
+
}
|
|
9638
|
+
}
|
|
9639
|
+
return false;
|
|
9640
|
+
};
|
|
9538
9641
|
return {
|
|
9539
9642
|
Program(node) {
|
|
9540
9643
|
for (const statement of node.body) {
|
|
@@ -9575,9 +9678,7 @@ var prefer_immutable_module_constant_default = createRule({
|
|
|
9575
9678
|
return;
|
|
9576
9679
|
}
|
|
9577
9680
|
const variable = sourceCode.getDeclaredVariables(node)[0];
|
|
9578
|
-
if (!directlyExported && !exportedNames2.has(node.id.name) && variable
|
|
9579
|
-
(reference) => reference.identifier.type === import_utils51.AST_NODE_TYPES.Identifier && referenceMutates(reference.identifier, isUnshadowedGlobal)
|
|
9580
|
-
) === true) {
|
|
9681
|
+
if (!directlyExported && !exportedNames2.has(node.id.name) && variable !== void 0 && mutatesThroughConstAlias(variable)) {
|
|
9581
9682
|
return;
|
|
9582
9683
|
}
|
|
9583
9684
|
context.report({
|
|
@@ -10356,6 +10457,10 @@ var prefer_module_level_schema_default = createRule({
|
|
|
10356
10457
|
}
|
|
10357
10458
|
for (const definition of resolved.defs) {
|
|
10358
10459
|
if (definition.type === "ImportBinding") {
|
|
10460
|
+
const parent = reference.identifier.parent;
|
|
10461
|
+
if (parent?.type === import_utils54.AST_NODE_TYPES.CallExpression && parent.callee === reference.identifier && !zodNamespaces.has(reference.identifier.name)) {
|
|
10462
|
+
return false;
|
|
10463
|
+
}
|
|
10359
10464
|
continue;
|
|
10360
10465
|
}
|
|
10361
10466
|
if (definition.node.type === import_utils54.AST_NODE_TYPES.VariableDeclarator && definition.node.parent.type === import_utils54.AST_NODE_TYPES.VariableDeclaration && definition.node.parent.kind !== "const") {
|
|
@@ -12187,10 +12292,7 @@ var SHAPE_PRESERVING_METHODS = /* @__PURE__ */ new Set([
|
|
|
12187
12292
|
]);
|
|
12188
12293
|
var OPTIONAL_MODIFIERS = /* @__PURE__ */ new Set([
|
|
12189
12294
|
"optional",
|
|
12190
|
-
"nullish"
|
|
12191
|
-
"default",
|
|
12192
|
-
"prefault",
|
|
12193
|
-
"catch"
|
|
12295
|
+
"nullish"
|
|
12194
12296
|
]);
|
|
12195
12297
|
var NULLABLE_MODIFIERS = /* @__PURE__ */ new Set(["nullable", "nullish"]);
|
|
12196
12298
|
var RESHAPING_MODIFIERS = /* @__PURE__ */ new Set([
|
|
@@ -13459,6 +13561,7 @@ var ZOD_PARSE_METHODS = /* @__PURE__ */ new Set([
|
|
|
13459
13561
|
"parseAsync",
|
|
13460
13562
|
"safeParseAsync"
|
|
13461
13563
|
]);
|
|
13564
|
+
var FORM_VALUE_METHODS = /* @__PURE__ */ new Set(["get", "getAll"]);
|
|
13462
13565
|
var zodReceiverRoot = (node) => {
|
|
13463
13566
|
let current = node;
|
|
13464
13567
|
while (true) {
|
|
@@ -13533,7 +13636,7 @@ var require_zod_form_validation_default = createRule({
|
|
|
13533
13636
|
};
|
|
13534
13637
|
const isFormSourceIdentifier = (node) => {
|
|
13535
13638
|
if (node.type !== import_utils66.AST_NODE_TYPES.Identifier) return false;
|
|
13536
|
-
|
|
13639
|
+
const conventionalName = /formdata/i.test(node.name);
|
|
13537
13640
|
let scope = context.sourceCode.getScope(node);
|
|
13538
13641
|
while (scope !== null) {
|
|
13539
13642
|
const variable = scope.set.get(node.name);
|
|
@@ -13542,16 +13645,16 @@ var require_zod_form_validation_default = createRule({
|
|
|
13542
13645
|
if (def !== void 0 && def.type === "Variable" && def.node.type === import_utils66.AST_NODE_TYPES.VariableDeclarator && def.node.init !== null) {
|
|
13543
13646
|
return isFormDataMethodCall(def.node.init);
|
|
13544
13647
|
}
|
|
13545
|
-
return
|
|
13648
|
+
return def?.type === "Parameter" && conventionalName;
|
|
13546
13649
|
}
|
|
13547
13650
|
scope = scope.upper;
|
|
13548
13651
|
}
|
|
13549
|
-
return
|
|
13652
|
+
return conventionalName;
|
|
13550
13653
|
};
|
|
13551
13654
|
const isFormDataGetCall = (node) => {
|
|
13552
13655
|
const callee = node.callee;
|
|
13553
13656
|
if (callee.type !== import_utils66.AST_NODE_TYPES.MemberExpression) return false;
|
|
13554
|
-
if (callee.property.type !== import_utils66.AST_NODE_TYPES.Identifier || callee.property.name
|
|
13657
|
+
if (callee.property.type !== import_utils66.AST_NODE_TYPES.Identifier || !FORM_VALUE_METHODS.has(callee.property.name)) {
|
|
13555
13658
|
return false;
|
|
13556
13659
|
}
|
|
13557
13660
|
return isFormSourceIdentifier(callee.object);
|
|
@@ -13645,6 +13748,40 @@ var require_zod_form_validation_default = createRule({
|
|
|
13645
13748
|
}
|
|
13646
13749
|
return ["===", "!==", "==", "!="].includes(parent.operator) && (parent.right.type === import_utils66.AST_NODE_TYPES.Literal && parent.right.value === null || parent.right.type === import_utils66.AST_NODE_TYPES.Identifier && parent.right.name === "undefined");
|
|
13647
13750
|
};
|
|
13751
|
+
const isDescendantOf = (node, ancestor) => {
|
|
13752
|
+
let current = node;
|
|
13753
|
+
while (current !== void 0 && current !== null) {
|
|
13754
|
+
if (current === ancestor) return true;
|
|
13755
|
+
current = current.parent;
|
|
13756
|
+
}
|
|
13757
|
+
return false;
|
|
13758
|
+
};
|
|
13759
|
+
const blockTerminates = (node) => {
|
|
13760
|
+
if (node.type === import_utils66.AST_NODE_TYPES.ReturnStatement || node.type === import_utils66.AST_NODE_TYPES.ThrowStatement) {
|
|
13761
|
+
return true;
|
|
13762
|
+
}
|
|
13763
|
+
if (node.type !== import_utils66.AST_NODE_TYPES.BlockStatement || node.body.length === 0) return false;
|
|
13764
|
+
const last = node.body.at(-1);
|
|
13765
|
+
return last !== void 0 && blockTerminates(last);
|
|
13766
|
+
};
|
|
13767
|
+
const narrowingIf = (identifier) => {
|
|
13768
|
+
const comparison = identifier.parent;
|
|
13769
|
+
if (comparison?.type !== import_utils66.AST_NODE_TYPES.BinaryExpression || comparison.operator !== "instanceof" || comparison.left !== identifier || comparison.right.type !== import_utils66.AST_NODE_TYPES.Identifier || comparison.right.name !== "File" && comparison.right.name !== "Blob") {
|
|
13770
|
+
return null;
|
|
13771
|
+
}
|
|
13772
|
+
const maybeNegation = comparison.parent;
|
|
13773
|
+
const negated = maybeNegation?.type === import_utils66.AST_NODE_TYPES.UnaryExpression && maybeNegation.operator === "!";
|
|
13774
|
+
const test = negated ? maybeNegation : comparison;
|
|
13775
|
+
const branch = test.parent;
|
|
13776
|
+
return branch?.type === import_utils66.AST_NODE_TYPES.IfStatement && branch.test === test ? { branch, positive: !negated } : null;
|
|
13777
|
+
};
|
|
13778
|
+
const useDominatedByNarrowing = (use, narrowings) => narrowings.some(({ branch, positive }) => {
|
|
13779
|
+
if (positive) return isDescendantOf(use, branch.consequent);
|
|
13780
|
+
if (!blockTerminates(branch.consequent)) return false;
|
|
13781
|
+
const branchStatement = containingStatement(branch);
|
|
13782
|
+
const useStatement = containingStatement(use);
|
|
13783
|
+
return branchStatement !== null && useStatement !== null && branchStatement.parent === useStatement.parent && branchStatement.range[1] < useStatement.range[0];
|
|
13784
|
+
});
|
|
13648
13785
|
const statementWithinBlock = (node, block) => {
|
|
13649
13786
|
let current = node;
|
|
13650
13787
|
while (current.parent !== void 0 && current.parent !== block) {
|
|
@@ -13659,14 +13796,16 @@ var require_zod_form_validation_default = createRule({
|
|
|
13659
13796
|
(identifier) => identifier.type === import_utils66.AST_NODE_TYPES.Identifier
|
|
13660
13797
|
);
|
|
13661
13798
|
if (references.length === 0) return false;
|
|
13662
|
-
|
|
13799
|
+
const narrowings = references.map(narrowingIf).filter(
|
|
13800
|
+
(value) => value !== null
|
|
13801
|
+
);
|
|
13663
13802
|
const validationStatements = references.map((reference) => guaranteedValidationStatement(declarator, reference)).filter(
|
|
13664
13803
|
(statement) => statement !== null
|
|
13665
13804
|
);
|
|
13666
13805
|
const declarationStatement = containingStatement(declarator);
|
|
13667
13806
|
const declarationBlock = declarationStatement?.parent;
|
|
13668
13807
|
return references.every((reference) => {
|
|
13669
|
-
if (zodParseAncestor(reference) !== null || isSafePrevalidationInspection(reference)) {
|
|
13808
|
+
if (zodParseAncestor(reference) !== null || isSafePrevalidationInspection(reference) || useDominatedByNarrowing(reference, narrowings)) {
|
|
13670
13809
|
return true;
|
|
13671
13810
|
}
|
|
13672
13811
|
if (declarationBlock === void 0) return false;
|
|
@@ -14196,7 +14335,13 @@ var NON_SCHEMA_TERMINALS = /* @__PURE__ */ new Set([
|
|
|
14196
14335
|
"safeDecodeAsync",
|
|
14197
14336
|
"toJSONSchema",
|
|
14198
14337
|
"registry",
|
|
14199
|
-
"implement"
|
|
14338
|
+
"implement",
|
|
14339
|
+
"flattenError",
|
|
14340
|
+
"formatError",
|
|
14341
|
+
"isNullable",
|
|
14342
|
+
"isOptional",
|
|
14343
|
+
"prettifyError",
|
|
14344
|
+
"treeifyError"
|
|
14200
14345
|
]);
|
|
14201
14346
|
var terminalMethodName = (callee) => !callee.computed && callee.property.type === import_utils69.AST_NODE_TYPES.Identifier ? callee.property.name : null;
|
|
14202
14347
|
var calleeChainRoot = (node) => {
|
|
@@ -14445,7 +14590,7 @@ var rules = {
|
|
|
14445
14590
|
};
|
|
14446
14591
|
var meta = {
|
|
14447
14592
|
name: "@sarj/eslint-plugin",
|
|
14448
|
-
version: "15.
|
|
14593
|
+
version: "15.5.0"
|
|
14449
14594
|
};
|
|
14450
14595
|
var applicationOnlyRules = [
|
|
14451
14596
|
"no-restricted-library-load",
|
package/dist/index.d.cts
CHANGED
|
@@ -225,7 +225,7 @@ declare const rules: {
|
|
|
225
225
|
readonly "no-silent-promise-catch": DocumentedRule<readonly [], "silentCatch">;
|
|
226
226
|
readonly "no-sleep-in-test-body": DocumentedRule<readonly [], "noSleepInTestBody">;
|
|
227
227
|
readonly "no-storage-in-stateless-modules": DocumentedRule<readonly [RuleOptions$3?], "storageInStatelessModule">;
|
|
228
|
-
readonly "no-string-concat-in-loop": DocumentedRule<readonly [], "noStringConcatInLoop">;
|
|
228
|
+
readonly "no-string-concat-in-loop": DocumentedRule<readonly [], "noStringConcatInLoop" | "noStringReduce">;
|
|
229
229
|
readonly "no-tautological-expect": DocumentedRule<readonly [], "tautologicalComparison" | "tautologicalMatcher">;
|
|
230
230
|
readonly "no-typed-doc-sections": DocumentedRule<readonly [], "typedSection">;
|
|
231
231
|
readonly "no-trailing-value-narration": DocumentedRule<readonly [], "deleteNarration" | "narratesValue">;
|
|
@@ -415,7 +415,7 @@ type FlatPreset = {
|
|
|
415
415
|
declare const plugin: {
|
|
416
416
|
readonly meta: {
|
|
417
417
|
readonly name: "@sarj/eslint-plugin";
|
|
418
|
-
readonly version: "15.
|
|
418
|
+
readonly version: "15.5.0";
|
|
419
419
|
};
|
|
420
420
|
readonly rules: {
|
|
421
421
|
readonly "duplicate-test-body": DocumentedRule<readonly [], "duplicateTestBody">;
|
|
@@ -455,7 +455,7 @@ declare const plugin: {
|
|
|
455
455
|
readonly "no-silent-promise-catch": DocumentedRule<readonly [], "silentCatch">;
|
|
456
456
|
readonly "no-sleep-in-test-body": DocumentedRule<readonly [], "noSleepInTestBody">;
|
|
457
457
|
readonly "no-storage-in-stateless-modules": DocumentedRule<readonly [RuleOptions$3?], "storageInStatelessModule">;
|
|
458
|
-
readonly "no-string-concat-in-loop": DocumentedRule<readonly [], "noStringConcatInLoop">;
|
|
458
|
+
readonly "no-string-concat-in-loop": DocumentedRule<readonly [], "noStringConcatInLoop" | "noStringReduce">;
|
|
459
459
|
readonly "no-tautological-expect": DocumentedRule<readonly [], "tautologicalComparison" | "tautologicalMatcher">;
|
|
460
460
|
readonly "no-typed-doc-sections": DocumentedRule<readonly [], "typedSection">;
|
|
461
461
|
readonly "no-trailing-value-narration": DocumentedRule<readonly [], "deleteNarration" | "narratesValue">;
|
package/dist/index.d.ts
CHANGED
|
@@ -225,7 +225,7 @@ declare const rules: {
|
|
|
225
225
|
readonly "no-silent-promise-catch": DocumentedRule<readonly [], "silentCatch">;
|
|
226
226
|
readonly "no-sleep-in-test-body": DocumentedRule<readonly [], "noSleepInTestBody">;
|
|
227
227
|
readonly "no-storage-in-stateless-modules": DocumentedRule<readonly [RuleOptions$3?], "storageInStatelessModule">;
|
|
228
|
-
readonly "no-string-concat-in-loop": DocumentedRule<readonly [], "noStringConcatInLoop">;
|
|
228
|
+
readonly "no-string-concat-in-loop": DocumentedRule<readonly [], "noStringConcatInLoop" | "noStringReduce">;
|
|
229
229
|
readonly "no-tautological-expect": DocumentedRule<readonly [], "tautologicalComparison" | "tautologicalMatcher">;
|
|
230
230
|
readonly "no-typed-doc-sections": DocumentedRule<readonly [], "typedSection">;
|
|
231
231
|
readonly "no-trailing-value-narration": DocumentedRule<readonly [], "deleteNarration" | "narratesValue">;
|
|
@@ -415,7 +415,7 @@ type FlatPreset = {
|
|
|
415
415
|
declare const plugin: {
|
|
416
416
|
readonly meta: {
|
|
417
417
|
readonly name: "@sarj/eslint-plugin";
|
|
418
|
-
readonly version: "15.
|
|
418
|
+
readonly version: "15.5.0";
|
|
419
419
|
};
|
|
420
420
|
readonly rules: {
|
|
421
421
|
readonly "duplicate-test-body": DocumentedRule<readonly [], "duplicateTestBody">;
|
|
@@ -455,7 +455,7 @@ declare const plugin: {
|
|
|
455
455
|
readonly "no-silent-promise-catch": DocumentedRule<readonly [], "silentCatch">;
|
|
456
456
|
readonly "no-sleep-in-test-body": DocumentedRule<readonly [], "noSleepInTestBody">;
|
|
457
457
|
readonly "no-storage-in-stateless-modules": DocumentedRule<readonly [RuleOptions$3?], "storageInStatelessModule">;
|
|
458
|
-
readonly "no-string-concat-in-loop": DocumentedRule<readonly [], "noStringConcatInLoop">;
|
|
458
|
+
readonly "no-string-concat-in-loop": DocumentedRule<readonly [], "noStringConcatInLoop" | "noStringReduce">;
|
|
459
459
|
readonly "no-tautological-expect": DocumentedRule<readonly [], "tautologicalComparison" | "tautologicalMatcher">;
|
|
460
460
|
readonly "no-typed-doc-sections": DocumentedRule<readonly [], "typedSection">;
|
|
461
461
|
readonly "no-trailing-value-narration": DocumentedRule<readonly [], "deleteNarration" | "narratesValue">;
|
package/dist/index.js
CHANGED
|
@@ -564,6 +564,9 @@ function isAssertionStatement(statement) {
|
|
|
564
564
|
const expression = statement.expression;
|
|
565
565
|
return expression.type === AST_NODE_TYPES2.CallExpression && isAssertionCall(expression);
|
|
566
566
|
}
|
|
567
|
+
function isTypeOnlyContractStatement(statement) {
|
|
568
|
+
return statement.type === AST_NODE_TYPES2.TSTypeAliasDeclaration || statement.type === AST_NODE_TYPES2.TSInterfaceDeclaration;
|
|
569
|
+
}
|
|
567
570
|
function normalizedLiteral(node) {
|
|
568
571
|
if ("regex" in node) {
|
|
569
572
|
return ["Literal", "regex", node.regex.pattern, node.regex.flags];
|
|
@@ -621,7 +624,7 @@ var duplicate_test_body_default = createRule({
|
|
|
621
624
|
return;
|
|
622
625
|
}
|
|
623
626
|
const body2 = candidate.body;
|
|
624
|
-
if (body2.body.type !== AST_NODE_TYPES2.BlockStatement || body2.body.body.length < MIN_STATEMENTS || body2.body.body.every(isAssertionStatement)) {
|
|
627
|
+
if (body2.body.type !== AST_NODE_TYPES2.BlockStatement || body2.body.body.length < MIN_STATEMENTS || body2.body.body.every(isAssertionStatement) || body2.body.body.some(isTypeOnlyContractStatement)) {
|
|
625
628
|
return;
|
|
626
629
|
}
|
|
627
630
|
const comments = context.sourceCode.getCommentsInside(body2.body).map((comment) => [comment.type, comment.value]);
|
|
@@ -3521,7 +3524,11 @@ var NUMBER_METHODS = /* @__PURE__ */ new Set([
|
|
|
3521
3524
|
"lt",
|
|
3522
3525
|
"lte",
|
|
3523
3526
|
"max",
|
|
3524
|
-
"min"
|
|
3527
|
+
"min",
|
|
3528
|
+
"negative",
|
|
3529
|
+
"nonnegative",
|
|
3530
|
+
"nonpositive",
|
|
3531
|
+
"positive"
|
|
3525
3532
|
]);
|
|
3526
3533
|
var LENGTH_METHODS = /* @__PURE__ */ new Set(["length", "max", "min"]);
|
|
3527
3534
|
var RESHAPING_METHODS = /* @__PURE__ */ new Set([
|
|
@@ -3658,13 +3665,29 @@ var no_impossible_zod_literal_bounds_default = createRule({
|
|
|
3658
3665
|
let upper = null;
|
|
3659
3666
|
for (const { method, node } of chain.calls) {
|
|
3660
3667
|
if (!allowed.has(method)) return null;
|
|
3661
|
-
const
|
|
3668
|
+
const semantic = method === "positive" ? { exclusive: true, lower: true, value: 0 } : method === "nonnegative" ? { exclusive: false, lower: true, value: 0 } : method === "negative" ? { exclusive: true, lower: false, value: 0 } : method === "nonpositive" ? { exclusive: false, lower: false, value: 0 } : null;
|
|
3669
|
+
const value = semantic?.value ?? finiteNumber(node.arguments[0]);
|
|
3662
3670
|
if (value === null) return null;
|
|
3663
3671
|
if (chain.kind !== "number" && (!Number.isInteger(value) || value < 0)) {
|
|
3664
3672
|
return null;
|
|
3665
3673
|
}
|
|
3666
3674
|
const label = `${method}(${String(value)})`;
|
|
3667
|
-
if (
|
|
3675
|
+
if (semantic !== null) {
|
|
3676
|
+
if (node.arguments.length !== 0) return null;
|
|
3677
|
+
if (semantic.lower) {
|
|
3678
|
+
lower = strongerLower(lower, {
|
|
3679
|
+
exclusive: semantic.exclusive,
|
|
3680
|
+
label: `${method}()`,
|
|
3681
|
+
value
|
|
3682
|
+
});
|
|
3683
|
+
} else {
|
|
3684
|
+
upper = strongerUpper(upper, {
|
|
3685
|
+
exclusive: semantic.exclusive,
|
|
3686
|
+
label: `${method}()`,
|
|
3687
|
+
value
|
|
3688
|
+
});
|
|
3689
|
+
}
|
|
3690
|
+
} else if (method === "length") {
|
|
3668
3691
|
lower = strongerLower(lower, { exclusive: false, label, value });
|
|
3669
3692
|
upper = strongerUpper(upper, { exclusive: false, label, value });
|
|
3670
3693
|
} else if (method === "gt" || method === "gte" || method === "min") {
|
|
@@ -6777,6 +6800,13 @@ function nearestEnclosingFunction(node) {
|
|
|
6777
6800
|
}
|
|
6778
6801
|
return null;
|
|
6779
6802
|
}
|
|
6803
|
+
function isImmediatelyConsumedSleep(node) {
|
|
6804
|
+
const parent = node.parent;
|
|
6805
|
+
if (parent?.type === AST_NODE_TYPES25.AwaitExpression || parent?.type === AST_NODE_TYPES25.ReturnStatement || parent?.type === AST_NODE_TYPES25.ExpressionStatement) {
|
|
6806
|
+
return true;
|
|
6807
|
+
}
|
|
6808
|
+
return parent?.type === AST_NODE_TYPES25.ArrowFunctionExpression && parent.body === node;
|
|
6809
|
+
}
|
|
6780
6810
|
function isTestBody(fn) {
|
|
6781
6811
|
const call = fn.parent;
|
|
6782
6812
|
if (call?.type !== AST_NODE_TYPES25.CallExpression || !call.arguments.some((argument) => argument === fn)) {
|
|
@@ -6819,6 +6849,9 @@ var no_sleep_in_test_body_default = createRule({
|
|
|
6819
6849
|
return {};
|
|
6820
6850
|
}
|
|
6821
6851
|
const report = (node) => {
|
|
6852
|
+
if (!isImmediatelyConsumedSleep(node)) {
|
|
6853
|
+
return;
|
|
6854
|
+
}
|
|
6822
6855
|
const enclosing = nearestEnclosingFunction(node);
|
|
6823
6856
|
if (enclosing === null || !isTestBody(enclosing)) {
|
|
6824
6857
|
return;
|
|
@@ -7116,6 +7149,27 @@ function isSmallStaticForLoop(node) {
|
|
|
7116
7149
|
const iterations = node.test.right.value - declaration.init.value + (node.test.operator === "<=" ? 1 : 0);
|
|
7117
7150
|
return iterations >= 0 && iterations <= 8;
|
|
7118
7151
|
}
|
|
7152
|
+
function isStringSeededReduce(node) {
|
|
7153
|
+
if (node.callee.type !== "MemberExpression" || node.callee.computed || node.callee.property.type !== "Identifier" || node.callee.property.name !== "reduce" || node.arguments.length !== 2) {
|
|
7154
|
+
return false;
|
|
7155
|
+
}
|
|
7156
|
+
const [callback, initial] = node.arguments;
|
|
7157
|
+
if (node.callee.object.type === "ArrayExpression" && node.callee.object.elements.length <= 8) {
|
|
7158
|
+
return false;
|
|
7159
|
+
}
|
|
7160
|
+
if (callback === void 0 || initial === void 0 || callback.type === "SpreadElement" || initial.type === "SpreadElement" || callback.type !== "ArrowFunctionExpression" && callback.type !== "FunctionExpression" || callback.params[0]?.type !== "Identifier" || !isStringLiteralInit(initial)) {
|
|
7161
|
+
return false;
|
|
7162
|
+
}
|
|
7163
|
+
const accumulator = callback.params[0].name;
|
|
7164
|
+
if (callback.body.type !== "BlockStatement") {
|
|
7165
|
+
return isConcatOntoTarget(callback.body, accumulator);
|
|
7166
|
+
}
|
|
7167
|
+
if (callback.body.body.length !== 1 || callback.body.body[0]?.type !== "ReturnStatement") {
|
|
7168
|
+
return false;
|
|
7169
|
+
}
|
|
7170
|
+
const returned = callback.body.body[0].argument;
|
|
7171
|
+
return returned !== null && isConcatOntoTarget(returned, accumulator);
|
|
7172
|
+
}
|
|
7119
7173
|
var no_string_concat_in_loop_default = createRule({
|
|
7120
7174
|
name: "no-string-concat-in-loop",
|
|
7121
7175
|
documentation: noStringConcatInLoopDocumentation,
|
|
@@ -7126,7 +7180,8 @@ var no_string_concat_in_loop_default = createRule({
|
|
|
7126
7180
|
},
|
|
7127
7181
|
schema: [],
|
|
7128
7182
|
messages: {
|
|
7129
|
-
noStringConcatInLoop: 'Avoid building a string with `+=` inside a loop \u2014 this is O(n^2). Push the parts onto an array and use `arr.join("")` after the loop.'
|
|
7183
|
+
noStringConcatInLoop: 'Avoid building a string with `+=` inside a loop \u2014 this is O(n^2). Push the parts onto an array and use `arr.join("")` after the loop.',
|
|
7184
|
+
noStringReduce: "Avoid concatenating a growing string in `reduce` \u2014 this is O(n^2). Map the fragments and join them once instead."
|
|
7130
7185
|
}
|
|
7131
7186
|
},
|
|
7132
7187
|
defaultOptions: [],
|
|
@@ -7136,6 +7191,11 @@ var no_string_concat_in_loop_default = createRule({
|
|
|
7136
7191
|
}
|
|
7137
7192
|
const reported = /* @__PURE__ */ new WeakMap();
|
|
7138
7193
|
return {
|
|
7194
|
+
CallExpression(node) {
|
|
7195
|
+
if (isStringSeededReduce(node)) {
|
|
7196
|
+
context.report({ node, messageId: "noStringReduce" });
|
|
7197
|
+
}
|
|
7198
|
+
},
|
|
7139
7199
|
AssignmentExpression(node) {
|
|
7140
7200
|
if (node.left.type !== "Identifier") {
|
|
7141
7201
|
return;
|
|
@@ -7240,6 +7300,9 @@ function isLiteral(node) {
|
|
|
7240
7300
|
return false;
|
|
7241
7301
|
}
|
|
7242
7302
|
}
|
|
7303
|
+
function isStructuralLiteral(node) {
|
|
7304
|
+
return node.type === AST_NODE_TYPES27.ArrayExpression || node.type === AST_NODE_TYPES27.ObjectExpression;
|
|
7305
|
+
}
|
|
7243
7306
|
function expectOperand(callee) {
|
|
7244
7307
|
const receiver = callee.object;
|
|
7245
7308
|
if (receiver.type !== AST_NODE_TYPES27.CallExpression || receiver.callee.type !== AST_NODE_TYPES27.Identifier || receiver.callee.name !== "expect" || receiver.arguments.length !== 1) {
|
|
@@ -7296,6 +7359,9 @@ var no_tautological_expect_default = createRule({
|
|
|
7296
7359
|
if (!EQUALITY_MATCHERS.has(matcher) || node.arguments.length !== 1 || expected === void 0 || !isLiteral(expected)) {
|
|
7297
7360
|
return;
|
|
7298
7361
|
}
|
|
7362
|
+
if (matcher === "toBe" && (isStructuralLiteral(operand) || isStructuralLiteral(expected))) {
|
|
7363
|
+
return;
|
|
7364
|
+
}
|
|
7299
7365
|
if (context.sourceCode.getText(operand) !== context.sourceCode.getText(expected)) {
|
|
7300
7366
|
return;
|
|
7301
7367
|
}
|
|
@@ -7609,7 +7675,7 @@ var no_trailing_value_narration_default = createRule({
|
|
|
7609
7675
|
});
|
|
7610
7676
|
|
|
7611
7677
|
// src/rules/no-declaration-comment-wall.ts
|
|
7612
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES29 } from "@typescript-eslint/utils";
|
|
7678
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES29, AST_TOKEN_TYPES } from "@typescript-eslint/utils";
|
|
7613
7679
|
|
|
7614
7680
|
// src/rules/_comment-wall.ts
|
|
7615
7681
|
import { AST_NODE_TYPES as AST_NODE_TYPES28 } from "@typescript-eslint/utils";
|
|
@@ -7809,7 +7875,13 @@ var no_declaration_comment_wall_default = createRule({
|
|
|
7809
7875
|
const lead = ownsItsLine ? endingOn.get(member.loc.start.line - 1) : void 0;
|
|
7810
7876
|
if (lead !== void 0) {
|
|
7811
7877
|
const before = sourceCode.getTokenBefore(lead, { includeComments: false });
|
|
7812
|
-
if (before === null || before.loc.end.line < lead.loc.start.line)
|
|
7878
|
+
if (before === null || before.loc.end.line < lead.loc.start.line) {
|
|
7879
|
+
const previousLine = endingOn.get(lead.loc.start.line - 1);
|
|
7880
|
+
if (lead.type === AST_TOKEN_TYPES.Line && previousLine?.type === AST_TOKEN_TYPES.Line && previousLine.loc.start.column === lead.loc.start.column) {
|
|
7881
|
+
return void 0;
|
|
7882
|
+
}
|
|
7883
|
+
return lead;
|
|
7884
|
+
}
|
|
7813
7885
|
}
|
|
7814
7886
|
const trail = startingOn.get(member.loc.end.line);
|
|
7815
7887
|
return trail !== void 0 && trail.range[0] > member.range[0] ? trail : void 0;
|
|
@@ -8048,7 +8120,7 @@ var no_union_in_comment_default = createRule({
|
|
|
8048
8120
|
});
|
|
8049
8121
|
|
|
8050
8122
|
// src/rules/no-type-member-comment-wall.ts
|
|
8051
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES31 } from "@typescript-eslint/utils";
|
|
8123
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES31, AST_TOKEN_TYPES as AST_TOKEN_TYPES2 } from "@typescript-eslint/utils";
|
|
8052
8124
|
var noTypeMemberCommentWallDocumentation = {
|
|
8053
8125
|
summary: "Flag an object type whose member comments mostly re-spell the members' own names and types.",
|
|
8054
8126
|
rationale: "Repetitive member comments add scanning cost while hiding the comments that describe facts absent from the type.",
|
|
@@ -8111,7 +8183,13 @@ var no_type_member_comment_wall_default = createRule({
|
|
|
8111
8183
|
const lead = ownsItsLine ? endingOn.get(member.loc.start.line - 1) : void 0;
|
|
8112
8184
|
if (lead !== void 0) {
|
|
8113
8185
|
const before = sourceCode.getTokenBefore(lead, { includeComments: false });
|
|
8114
|
-
if (before === null || before.loc.end.line < lead.loc.start.line)
|
|
8186
|
+
if (before === null || before.loc.end.line < lead.loc.start.line) {
|
|
8187
|
+
const previousLine = endingOn.get(lead.loc.start.line - 1);
|
|
8188
|
+
if (lead.type === AST_TOKEN_TYPES2.Line && previousLine?.type === AST_TOKEN_TYPES2.Line && previousLine.loc.start.column === lead.loc.start.column) {
|
|
8189
|
+
return void 0;
|
|
8190
|
+
}
|
|
8191
|
+
return lead;
|
|
8192
|
+
}
|
|
8115
8193
|
}
|
|
8116
8194
|
const trail = startingOn.get(member.loc.end.line);
|
|
8117
8195
|
return trail !== void 0 && trail.range[0] > member.range[0] ? trail : void 0;
|
|
@@ -8411,6 +8489,10 @@ import {
|
|
|
8411
8489
|
} from "@typescript-eslint/utils";
|
|
8412
8490
|
var MOCK_TYPE_NAMES = /* @__PURE__ */ new Set([
|
|
8413
8491
|
"Mock",
|
|
8492
|
+
"Mocked",
|
|
8493
|
+
"MockedClass",
|
|
8494
|
+
"MockedFunction",
|
|
8495
|
+
"MockedObject",
|
|
8414
8496
|
"MockInstance",
|
|
8415
8497
|
"SpyInstance"
|
|
8416
8498
|
]);
|
|
@@ -8658,9 +8740,9 @@ var no_zod_native_enum_default = createRule({
|
|
|
8658
8740
|
}
|
|
8659
8741
|
function isZodMemberCall(node, api) {
|
|
8660
8742
|
const callee = node.callee;
|
|
8661
|
-
if (callee.type === AST_NODE_TYPES34.MemberExpression &&
|
|
8743
|
+
if (callee.type === AST_NODE_TYPES34.MemberExpression && callee.object.type === AST_NODE_TYPES34.Identifier && (callee.property.type === AST_NODE_TYPES34.Identifier && !callee.computed && callee.property.name === api || callee.computed && callee.property.type === AST_NODE_TYPES34.Literal && callee.property.value === api)) {
|
|
8662
8744
|
const binding = resolvedBinding(callee.object);
|
|
8663
|
-
return binding !== null && zodNamespaceBindings.has(binding)
|
|
8745
|
+
return binding !== null && zodNamespaceBindings.has(binding);
|
|
8664
8746
|
}
|
|
8665
8747
|
if (callee.type === AST_NODE_TYPES34.Identifier) {
|
|
8666
8748
|
const binding = resolvedBinding(callee);
|
|
@@ -9504,6 +9586,27 @@ var prefer_immutable_module_constant_default = createRule({
|
|
|
9504
9586
|
}
|
|
9505
9587
|
const exportedNames2 = /* @__PURE__ */ new Set();
|
|
9506
9588
|
const typeAliases2 = /* @__PURE__ */ new Map();
|
|
9589
|
+
const mutatesThroughConstAlias = (root) => {
|
|
9590
|
+
const pending = [root];
|
|
9591
|
+
const seen = /* @__PURE__ */ new Set();
|
|
9592
|
+
while (pending.length > 0) {
|
|
9593
|
+
const variable = pending.pop();
|
|
9594
|
+
if (variable === void 0 || seen.has(variable)) continue;
|
|
9595
|
+
seen.add(variable);
|
|
9596
|
+
for (const reference of variable.references) {
|
|
9597
|
+
const identifier = reference.identifier;
|
|
9598
|
+
if (identifier.type !== AST_NODE_TYPES39.Identifier) continue;
|
|
9599
|
+
if (referenceMutates(identifier, isUnshadowedGlobal)) return true;
|
|
9600
|
+
const declarator = identifier.parent;
|
|
9601
|
+
if (declarator.type !== AST_NODE_TYPES39.VariableDeclarator || declarator.init !== identifier || declarator.id.type !== AST_NODE_TYPES39.Identifier || declarator.parent.type !== AST_NODE_TYPES39.VariableDeclaration || declarator.parent.kind !== "const") {
|
|
9602
|
+
continue;
|
|
9603
|
+
}
|
|
9604
|
+
const alias = sourceCode.getDeclaredVariables(declarator)[0];
|
|
9605
|
+
if (alias !== void 0) pending.push(alias);
|
|
9606
|
+
}
|
|
9607
|
+
}
|
|
9608
|
+
return false;
|
|
9609
|
+
};
|
|
9507
9610
|
return {
|
|
9508
9611
|
Program(node) {
|
|
9509
9612
|
for (const statement of node.body) {
|
|
@@ -9544,9 +9647,7 @@ var prefer_immutable_module_constant_default = createRule({
|
|
|
9544
9647
|
return;
|
|
9545
9648
|
}
|
|
9546
9649
|
const variable = sourceCode.getDeclaredVariables(node)[0];
|
|
9547
|
-
if (!directlyExported && !exportedNames2.has(node.id.name) && variable
|
|
9548
|
-
(reference) => reference.identifier.type === AST_NODE_TYPES39.Identifier && referenceMutates(reference.identifier, isUnshadowedGlobal)
|
|
9549
|
-
) === true) {
|
|
9650
|
+
if (!directlyExported && !exportedNames2.has(node.id.name) && variable !== void 0 && mutatesThroughConstAlias(variable)) {
|
|
9550
9651
|
return;
|
|
9551
9652
|
}
|
|
9552
9653
|
context.report({
|
|
@@ -10325,6 +10426,10 @@ var prefer_module_level_schema_default = createRule({
|
|
|
10325
10426
|
}
|
|
10326
10427
|
for (const definition of resolved.defs) {
|
|
10327
10428
|
if (definition.type === "ImportBinding") {
|
|
10429
|
+
const parent = reference.identifier.parent;
|
|
10430
|
+
if (parent?.type === AST_NODE_TYPES42.CallExpression && parent.callee === reference.identifier && !zodNamespaces.has(reference.identifier.name)) {
|
|
10431
|
+
return false;
|
|
10432
|
+
}
|
|
10328
10433
|
continue;
|
|
10329
10434
|
}
|
|
10330
10435
|
if (definition.node.type === AST_NODE_TYPES42.VariableDeclarator && definition.node.parent.type === AST_NODE_TYPES42.VariableDeclaration && definition.node.parent.kind !== "const") {
|
|
@@ -12156,10 +12261,7 @@ var SHAPE_PRESERVING_METHODS = /* @__PURE__ */ new Set([
|
|
|
12156
12261
|
]);
|
|
12157
12262
|
var OPTIONAL_MODIFIERS = /* @__PURE__ */ new Set([
|
|
12158
12263
|
"optional",
|
|
12159
|
-
"nullish"
|
|
12160
|
-
"default",
|
|
12161
|
-
"prefault",
|
|
12162
|
-
"catch"
|
|
12264
|
+
"nullish"
|
|
12163
12265
|
]);
|
|
12164
12266
|
var NULLABLE_MODIFIERS = /* @__PURE__ */ new Set(["nullable", "nullish"]);
|
|
12165
12267
|
var RESHAPING_MODIFIERS = /* @__PURE__ */ new Set([
|
|
@@ -13434,6 +13536,7 @@ var ZOD_PARSE_METHODS = /* @__PURE__ */ new Set([
|
|
|
13434
13536
|
"parseAsync",
|
|
13435
13537
|
"safeParseAsync"
|
|
13436
13538
|
]);
|
|
13539
|
+
var FORM_VALUE_METHODS = /* @__PURE__ */ new Set(["get", "getAll"]);
|
|
13437
13540
|
var zodReceiverRoot = (node) => {
|
|
13438
13541
|
let current = node;
|
|
13439
13542
|
while (true) {
|
|
@@ -13508,7 +13611,7 @@ var require_zod_form_validation_default = createRule({
|
|
|
13508
13611
|
};
|
|
13509
13612
|
const isFormSourceIdentifier = (node) => {
|
|
13510
13613
|
if (node.type !== AST_NODE_TYPES53.Identifier) return false;
|
|
13511
|
-
|
|
13614
|
+
const conventionalName = /formdata/i.test(node.name);
|
|
13512
13615
|
let scope = context.sourceCode.getScope(node);
|
|
13513
13616
|
while (scope !== null) {
|
|
13514
13617
|
const variable = scope.set.get(node.name);
|
|
@@ -13517,16 +13620,16 @@ var require_zod_form_validation_default = createRule({
|
|
|
13517
13620
|
if (def !== void 0 && def.type === "Variable" && def.node.type === AST_NODE_TYPES53.VariableDeclarator && def.node.init !== null) {
|
|
13518
13621
|
return isFormDataMethodCall(def.node.init);
|
|
13519
13622
|
}
|
|
13520
|
-
return
|
|
13623
|
+
return def?.type === "Parameter" && conventionalName;
|
|
13521
13624
|
}
|
|
13522
13625
|
scope = scope.upper;
|
|
13523
13626
|
}
|
|
13524
|
-
return
|
|
13627
|
+
return conventionalName;
|
|
13525
13628
|
};
|
|
13526
13629
|
const isFormDataGetCall = (node) => {
|
|
13527
13630
|
const callee = node.callee;
|
|
13528
13631
|
if (callee.type !== AST_NODE_TYPES53.MemberExpression) return false;
|
|
13529
|
-
if (callee.property.type !== AST_NODE_TYPES53.Identifier || callee.property.name
|
|
13632
|
+
if (callee.property.type !== AST_NODE_TYPES53.Identifier || !FORM_VALUE_METHODS.has(callee.property.name)) {
|
|
13530
13633
|
return false;
|
|
13531
13634
|
}
|
|
13532
13635
|
return isFormSourceIdentifier(callee.object);
|
|
@@ -13620,6 +13723,40 @@ var require_zod_form_validation_default = createRule({
|
|
|
13620
13723
|
}
|
|
13621
13724
|
return ["===", "!==", "==", "!="].includes(parent.operator) && (parent.right.type === AST_NODE_TYPES53.Literal && parent.right.value === null || parent.right.type === AST_NODE_TYPES53.Identifier && parent.right.name === "undefined");
|
|
13622
13725
|
};
|
|
13726
|
+
const isDescendantOf = (node, ancestor) => {
|
|
13727
|
+
let current = node;
|
|
13728
|
+
while (current !== void 0 && current !== null) {
|
|
13729
|
+
if (current === ancestor) return true;
|
|
13730
|
+
current = current.parent;
|
|
13731
|
+
}
|
|
13732
|
+
return false;
|
|
13733
|
+
};
|
|
13734
|
+
const blockTerminates = (node) => {
|
|
13735
|
+
if (node.type === AST_NODE_TYPES53.ReturnStatement || node.type === AST_NODE_TYPES53.ThrowStatement) {
|
|
13736
|
+
return true;
|
|
13737
|
+
}
|
|
13738
|
+
if (node.type !== AST_NODE_TYPES53.BlockStatement || node.body.length === 0) return false;
|
|
13739
|
+
const last = node.body.at(-1);
|
|
13740
|
+
return last !== void 0 && blockTerminates(last);
|
|
13741
|
+
};
|
|
13742
|
+
const narrowingIf = (identifier) => {
|
|
13743
|
+
const comparison = identifier.parent;
|
|
13744
|
+
if (comparison?.type !== AST_NODE_TYPES53.BinaryExpression || comparison.operator !== "instanceof" || comparison.left !== identifier || comparison.right.type !== AST_NODE_TYPES53.Identifier || comparison.right.name !== "File" && comparison.right.name !== "Blob") {
|
|
13745
|
+
return null;
|
|
13746
|
+
}
|
|
13747
|
+
const maybeNegation = comparison.parent;
|
|
13748
|
+
const negated = maybeNegation?.type === AST_NODE_TYPES53.UnaryExpression && maybeNegation.operator === "!";
|
|
13749
|
+
const test = negated ? maybeNegation : comparison;
|
|
13750
|
+
const branch = test.parent;
|
|
13751
|
+
return branch?.type === AST_NODE_TYPES53.IfStatement && branch.test === test ? { branch, positive: !negated } : null;
|
|
13752
|
+
};
|
|
13753
|
+
const useDominatedByNarrowing = (use, narrowings) => narrowings.some(({ branch, positive }) => {
|
|
13754
|
+
if (positive) return isDescendantOf(use, branch.consequent);
|
|
13755
|
+
if (!blockTerminates(branch.consequent)) return false;
|
|
13756
|
+
const branchStatement = containingStatement(branch);
|
|
13757
|
+
const useStatement = containingStatement(use);
|
|
13758
|
+
return branchStatement !== null && useStatement !== null && branchStatement.parent === useStatement.parent && branchStatement.range[1] < useStatement.range[0];
|
|
13759
|
+
});
|
|
13623
13760
|
const statementWithinBlock = (node, block) => {
|
|
13624
13761
|
let current = node;
|
|
13625
13762
|
while (current.parent !== void 0 && current.parent !== block) {
|
|
@@ -13634,14 +13771,16 @@ var require_zod_form_validation_default = createRule({
|
|
|
13634
13771
|
(identifier) => identifier.type === AST_NODE_TYPES53.Identifier
|
|
13635
13772
|
);
|
|
13636
13773
|
if (references.length === 0) return false;
|
|
13637
|
-
|
|
13774
|
+
const narrowings = references.map(narrowingIf).filter(
|
|
13775
|
+
(value) => value !== null
|
|
13776
|
+
);
|
|
13638
13777
|
const validationStatements = references.map((reference) => guaranteedValidationStatement(declarator, reference)).filter(
|
|
13639
13778
|
(statement) => statement !== null
|
|
13640
13779
|
);
|
|
13641
13780
|
const declarationStatement = containingStatement(declarator);
|
|
13642
13781
|
const declarationBlock = declarationStatement?.parent;
|
|
13643
13782
|
return references.every((reference) => {
|
|
13644
|
-
if (zodParseAncestor(reference) !== null || isSafePrevalidationInspection(reference)) {
|
|
13783
|
+
if (zodParseAncestor(reference) !== null || isSafePrevalidationInspection(reference) || useDominatedByNarrowing(reference, narrowings)) {
|
|
13645
13784
|
return true;
|
|
13646
13785
|
}
|
|
13647
13786
|
if (declarationBlock === void 0) return false;
|
|
@@ -14174,7 +14313,13 @@ var NON_SCHEMA_TERMINALS = /* @__PURE__ */ new Set([
|
|
|
14174
14313
|
"safeDecodeAsync",
|
|
14175
14314
|
"toJSONSchema",
|
|
14176
14315
|
"registry",
|
|
14177
|
-
"implement"
|
|
14316
|
+
"implement",
|
|
14317
|
+
"flattenError",
|
|
14318
|
+
"formatError",
|
|
14319
|
+
"isNullable",
|
|
14320
|
+
"isOptional",
|
|
14321
|
+
"prettifyError",
|
|
14322
|
+
"treeifyError"
|
|
14178
14323
|
]);
|
|
14179
14324
|
var terminalMethodName = (callee) => !callee.computed && callee.property.type === AST_NODE_TYPES55.Identifier ? callee.property.name : null;
|
|
14180
14325
|
var calleeChainRoot = (node) => {
|
|
@@ -14423,7 +14568,7 @@ var rules = {
|
|
|
14423
14568
|
};
|
|
14424
14569
|
var meta = {
|
|
14425
14570
|
name: "@sarj/eslint-plugin",
|
|
14426
|
-
version: "15.
|
|
14571
|
+
version: "15.5.0"
|
|
14427
14572
|
};
|
|
14428
14573
|
var applicationOnlyRules = [
|
|
14429
14574
|
"no-restricted-library-load",
|