@sarj/eslint-plugin 18.0.0 → 18.0.3
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 +108 -95
- package/dist/index.js +93 -80
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -50,7 +50,7 @@ __export(src_exports, {
|
|
|
50
50
|
module.exports = __toCommonJS(src_exports);
|
|
51
51
|
|
|
52
52
|
// src/rules/no-logical-or-fallback.ts
|
|
53
|
-
var
|
|
53
|
+
var import_utils4 = require("@typescript-eslint/utils");
|
|
54
54
|
var import_ts_api_utils = require("ts-api-utils");
|
|
55
55
|
var import_typescript = __toESM(require("typescript"), 1);
|
|
56
56
|
|
|
@@ -590,7 +590,30 @@ function commentLineEnd(sourceText, start) {
|
|
|
590
590
|
return end === -1 ? sourceText.length : start + end;
|
|
591
591
|
}
|
|
592
592
|
|
|
593
|
+
// src/rules/_unwrap-expression.ts
|
|
594
|
+
var import_utils3 = require("@typescript-eslint/utils");
|
|
595
|
+
function unwrapExpression(node) {
|
|
596
|
+
while (isErasedExpression(node)) {
|
|
597
|
+
node = node.expression;
|
|
598
|
+
}
|
|
599
|
+
return node;
|
|
600
|
+
}
|
|
601
|
+
function outerExpression(node) {
|
|
602
|
+
while (node.parent !== void 0 && node.parent !== null && isErasedExpression(node.parent) && node.parent.expression === node) node = node.parent;
|
|
603
|
+
return node;
|
|
604
|
+
}
|
|
605
|
+
function directArgumentCall(node) {
|
|
606
|
+
const argument = outerExpression(node);
|
|
607
|
+
const call = argument.parent;
|
|
608
|
+
return call?.type === import_utils3.AST_NODE_TYPES.CallExpression && call.arguments.some((item) => item === argument) ? call : null;
|
|
609
|
+
}
|
|
610
|
+
function isErasedExpression(node) {
|
|
611
|
+
return node.type === import_utils3.AST_NODE_TYPES.TSAsExpression || node.type === import_utils3.AST_NODE_TYPES.TSSatisfiesExpression || node.type === import_utils3.AST_NODE_TYPES.TSNonNullExpression || node.type === import_utils3.AST_NODE_TYPES.TSTypeAssertion;
|
|
612
|
+
}
|
|
613
|
+
|
|
593
614
|
// src/rules/no-logical-or-fallback.ts
|
|
615
|
+
var PRIMITIVE_FLAGS = import_typescript.default.TypeFlags.StringLike | import_typescript.default.TypeFlags.NumberLike | import_typescript.default.TypeFlags.BigIntLike | import_typescript.default.TypeFlags.BooleanLike;
|
|
616
|
+
var GLOBAL_RECEIVERS = /* @__PURE__ */ new Set(["globalThis", "window", "self"]);
|
|
594
617
|
var NO_LOGICAL_OR_FALLBACK_DOCUMENTATION = {
|
|
595
618
|
defaultLevel: "warning",
|
|
596
619
|
summary: "Use nullish defaults or explicit falsy-value checks instead of logical OR fallbacks.",
|
|
@@ -599,8 +622,8 @@ var NO_LOGICAL_OR_FALLBACK_DOCUMENTATION = {
|
|
|
599
622
|
category: "correctness",
|
|
600
623
|
autofix: "none",
|
|
601
624
|
limitations: [
|
|
602
|
-
"Requires TypeScript type information and strict null checks. Reports non-nullable string, number or bigint value fallbacks, including mixed primitive unions. Nullable inputs remain owned by @typescript-eslint/prefer-nullish-coalescing; both rules are enabled in the managed strict config.",
|
|
603
|
-
"Preserves boolean aggregation, conditions, negations, left-hand && guards, and calls to the unshadowed Boolean constructor. Constant truthiness stays with no-unnecessary-condition. Unknown, any, generic, object-only and generated inputs are excluded. Strings and comments are never scanned as code.",
|
|
625
|
+
"Requires TypeScript type information and strict null checks. Reports non-nullable string, number or bigint value fallbacks, including branded primitives and mixed primitive unions. Nullable inputs, including nullable booleans, remain owned by @typescript-eslint/prefer-nullish-coalescing; both rules are enabled in the managed strict config.",
|
|
626
|
+
"Preserves non-nullable boolean aggregation, conditions, negations, left-hand && guards, and calls to the native unshadowed Boolean constructor, including erased TypeScript wrappers and globalThis/window/self access. Constant truthiness stays with no-unnecessary-condition. Unknown, any, unresolved generic, object-only and generated inputs are excluded. Strings and comments are never scanned as code.",
|
|
604
627
|
"No automatic replacement is offered: replacing || with ?? would change empty-string or zero behavior. Non-nullable ||= expressions remain outside this companion rule."
|
|
605
628
|
],
|
|
606
629
|
references: ["https://typescript-eslint.io/rules/prefer-nullish-coalescing/"],
|
|
@@ -628,83 +651,72 @@ var no_logical_or_fallback_default = createRule({
|
|
|
628
651
|
if (!(options.strictNullChecks ?? options.strict ?? false)) return {};
|
|
629
652
|
return {
|
|
630
653
|
LogicalExpression(node) {
|
|
631
|
-
if (node.operator !== "||" || booleanContext(node, context.sourceCode)) return;
|
|
654
|
+
if (node.operator !== "||" || booleanContext(node, context.sourceCode, services)) return;
|
|
632
655
|
const type = checker.getTypeAtLocation(services.esTreeNodeToTSNodeMap.get(node.left));
|
|
633
|
-
const members = type.isUnion() ? type.types : [type];
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
const truthiness = members.map(literalTruthiness);
|
|
656
|
+
const members = (type.isUnion() ? type.types : [type]).map(primitivePart);
|
|
657
|
+
if (members.some((member3) => member3 === void 0) || !members.some((member3) => member3 !== void 0 && (member3.flags & (import_typescript.default.TypeFlags.StringLike | import_typescript.default.TypeFlags.NumberLike | import_typescript.default.TypeFlags.BigIntLike)) !== 0)) return;
|
|
658
|
+
const truthiness = members.map((member3) => member3 === void 0 ? void 0 : literalTruthiness(member3));
|
|
637
659
|
if (truthiness.every((value) => value === true) || truthiness.every((value) => value === false)) return;
|
|
638
660
|
context.report({ node, messageId: "logicalOrFallback" });
|
|
639
661
|
}
|
|
640
662
|
};
|
|
641
663
|
}
|
|
642
664
|
});
|
|
665
|
+
function primitivePart(type) {
|
|
666
|
+
if ((type.flags & PRIMITIVE_FLAGS) !== 0) return type;
|
|
667
|
+
if (!type.isIntersection() || type.types.some((member3) => (member3.flags & import_typescript.default.TypeFlags.TypeParameter) !== 0)) return void 0;
|
|
668
|
+
return type.types.find((member3) => (member3.flags & PRIMITIVE_FLAGS) !== 0);
|
|
669
|
+
}
|
|
643
670
|
function literalTruthiness(type) {
|
|
644
671
|
if (type.isStringLiteral() || type.isNumberLiteral()) return Boolean(type.value);
|
|
645
672
|
if ((0, import_ts_api_utils.isBooleanLiteralType)(type)) return type.intrinsicName === "true";
|
|
646
673
|
if ((0, import_ts_api_utils.isBigIntLiteralType)(type)) return type.value.base10Value !== "0";
|
|
647
674
|
return void 0;
|
|
648
675
|
}
|
|
649
|
-
function booleanContext(node, source) {
|
|
650
|
-
let current = node;
|
|
676
|
+
function booleanContext(node, source, services) {
|
|
677
|
+
let current = outerExpression(node);
|
|
651
678
|
while (current.parent !== void 0) {
|
|
652
679
|
const parent = current.parent;
|
|
653
680
|
switch (parent.type) {
|
|
654
|
-
case
|
|
655
|
-
case import_utils3.AST_NODE_TYPES.TSSatisfiesExpression:
|
|
656
|
-
case import_utils3.AST_NODE_TYPES.TSNonNullExpression:
|
|
657
|
-
current = parent;
|
|
658
|
-
continue;
|
|
659
|
-
case import_utils3.AST_NODE_TYPES.LogicalExpression:
|
|
681
|
+
case import_utils4.AST_NODE_TYPES.LogicalExpression:
|
|
660
682
|
if (parent.operator === "&&" && parent.left === current) return true;
|
|
661
|
-
current = parent;
|
|
683
|
+
current = outerExpression(parent);
|
|
662
684
|
continue;
|
|
663
|
-
case
|
|
664
|
-
case
|
|
665
|
-
case
|
|
666
|
-
case
|
|
667
|
-
case
|
|
685
|
+
case import_utils4.AST_NODE_TYPES.IfStatement:
|
|
686
|
+
case import_utils4.AST_NODE_TYPES.WhileStatement:
|
|
687
|
+
case import_utils4.AST_NODE_TYPES.DoWhileStatement:
|
|
688
|
+
case import_utils4.AST_NODE_TYPES.ForStatement:
|
|
689
|
+
case import_utils4.AST_NODE_TYPES.ConditionalExpression:
|
|
668
690
|
return parent.test === current;
|
|
669
|
-
case
|
|
691
|
+
case import_utils4.AST_NODE_TYPES.UnaryExpression:
|
|
670
692
|
return parent.operator === "!";
|
|
671
|
-
case
|
|
672
|
-
return parent.
|
|
693
|
+
case import_utils4.AST_NODE_TYPES.CallExpression:
|
|
694
|
+
return parent.arguments[0] === current && nativeBoolean(parent.callee, source, services);
|
|
673
695
|
default:
|
|
674
696
|
return false;
|
|
675
697
|
}
|
|
676
698
|
}
|
|
677
699
|
return false;
|
|
678
700
|
}
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
701
|
+
function nativeBoolean(node, source, services) {
|
|
702
|
+
const callee = unwrapExpression(node);
|
|
703
|
+
const checker = services.program.getTypeChecker();
|
|
704
|
+
let symbol;
|
|
705
|
+
if (callee.type === import_utils4.AST_NODE_TYPES.Identifier && callee.name === "Boolean" && !import_utils4.ASTUtils.findVariable(source.getScope(callee), callee.name)?.defs.length) {
|
|
706
|
+
symbol = checker.getSymbolAtLocation(services.esTreeNodeToTSNodeMap.get(callee));
|
|
707
|
+
} else if (callee.type === import_utils4.AST_NODE_TYPES.MemberExpression && import_utils4.ASTUtils.getPropertyName(callee) === "Boolean") {
|
|
708
|
+
const receiver = unwrapExpression(callee.object);
|
|
709
|
+
if (receiver.type !== import_utils4.AST_NODE_TYPES.Identifier || !GLOBAL_RECEIVERS.has(receiver.name) || import_utils4.ASTUtils.findVariable(source.getScope(receiver), receiver.name)?.defs.length) return false;
|
|
710
|
+
symbol = checker.getTypeAtLocation(services.esTreeNodeToTSNodeMap.get(receiver)).getProperty("Boolean");
|
|
689
711
|
}
|
|
690
|
-
return
|
|
691
|
-
}
|
|
692
|
-
function outerExpression(node) {
|
|
693
|
-
while (node.parent !== void 0 && node.parent !== null && isErasedExpression(node.parent) && node.parent.expression === node) node = node.parent;
|
|
694
|
-
return node;
|
|
695
|
-
}
|
|
696
|
-
function directArgumentCall(node) {
|
|
697
|
-
const argument = outerExpression(node);
|
|
698
|
-
const call = argument.parent;
|
|
699
|
-
return call?.type === import_utils4.AST_NODE_TYPES.CallExpression && call.arguments.some((item) => item === argument) ? call : null;
|
|
700
|
-
}
|
|
701
|
-
function isErasedExpression(node) {
|
|
702
|
-
return node.type === import_utils4.AST_NODE_TYPES.TSAsExpression || node.type === import_utils4.AST_NODE_TYPES.TSSatisfiesExpression || node.type === import_utils4.AST_NODE_TYPES.TSNonNullExpression || node.type === import_utils4.AST_NODE_TYPES.TSTypeAssertion;
|
|
712
|
+
return symbol?.declarations !== void 0 && symbol.declarations.length > 0 && symbol.declarations.every((declaration) => services.program.isSourceFileDefaultLibrary(declaration.getSourceFile()));
|
|
703
713
|
}
|
|
704
714
|
|
|
705
715
|
// src/rules/no-zod-parse-typed-object.ts
|
|
716
|
+
var import_utils5 = require("@typescript-eslint/utils");
|
|
717
|
+
var import_ts_api_utils2 = require("ts-api-utils");
|
|
718
|
+
var import_typescript2 = __toESM(require("typescript"), 1);
|
|
706
719
|
var PARSE_METHODS = /* @__PURE__ */ new Set(["parse", "parseAsync", "safeParse", "safeParseAsync"]);
|
|
707
|
-
var TUPLE_INDEX_RE = /^(?:0|[1-9]\d*)$/u;
|
|
708
720
|
var OPAQUE_FLAGS = import_typescript2.default.TypeFlags.Any | import_typescript2.default.TypeFlags.Unknown | import_typescript2.default.TypeFlags.Never | import_typescript2.default.TypeFlags.TypeParameter | import_typescript2.default.TypeFlags.Conditional | import_typescript2.default.TypeFlags.IndexedAccess | import_typescript2.default.TypeFlags.Intersection | import_typescript2.default.TypeFlags.NonPrimitive;
|
|
709
721
|
var NO_ZOD_PARSE_TYPED_OBJECT_DOCUMENTATION = {
|
|
710
722
|
defaultLevel: "warning",
|
|
@@ -717,7 +729,7 @@ var NO_ZOD_PARSE_TYPED_OBJECT_DOCUMENTATION = {
|
|
|
717
729
|
"Requires type information, strict null checks, and a native installed Zod parse, parseAsync, safeParse or safeParseAsync signature. Recognizes imported schemas, aliases, member access and awaited service results without guessing from names.",
|
|
718
730
|
"Reports fully known object or array inputs assignable to the schema input, when schema input and output have the same value shape. Optional-to-required defaults are included; type-changing transforms, coercions, brands, incompatible contracts, primitive roots and nested any/unknown/generic contracts are excluded.",
|
|
719
731
|
"Static types do not establish runtime trust or prove refinements and normalization redundant. This is an architectural warning with no automatic removal. Keep intentional validation at an unknown-data boundary or document an exact local suppression. Tests, stories and generated code are excluded.",
|
|
720
|
-
"Shape comparison ignores undefined introduced by optional properties and is bounded to 128 object pairs
|
|
732
|
+
"Shape comparison ignores undefined introduced by optional properties and checks tuple element types and rest positions. It is bounded to 128 object pairs, visited input objects, properties, tuple elements or primitive union alternatives; object unions have at most 16 alternatives. Opaque or larger graphs are conservatively excluded."
|
|
721
733
|
],
|
|
722
734
|
references: ["https://zod.dev/basics"],
|
|
723
735
|
examples: [
|
|
@@ -777,7 +789,11 @@ function knownValue(checker, type, location, seen) {
|
|
|
777
789
|
if (seen.has(type)) return true;
|
|
778
790
|
if (seen.size >= 128 || type.getCallSignatures().length > 0 || type.getConstructSignatures().length > 0) return false;
|
|
779
791
|
seen.add(type);
|
|
780
|
-
if (
|
|
792
|
+
if ((0, import_ts_api_utils2.isTupleTypeReference)(type)) {
|
|
793
|
+
const elements = checker.getTypeArguments(type);
|
|
794
|
+
return elements.length <= 128 && elements.every((element) => knownValue(checker, element, location, seen));
|
|
795
|
+
}
|
|
796
|
+
if (checker.isArrayType(type)) {
|
|
781
797
|
const element = type.getNumberIndexType();
|
|
782
798
|
return element !== void 0 && knownValue(checker, element, location, seen);
|
|
783
799
|
}
|
|
@@ -793,7 +809,8 @@ function sameShape(checker, input, output, location) {
|
|
|
793
809
|
if (left.isUnion() || right.isUnion()) {
|
|
794
810
|
const a = (left.isUnion() ? left.types : [left]).filter((member3) => (member3.flags & import_typescript2.default.TypeFlags.Undefined) === 0);
|
|
795
811
|
const b = (right.isUnion() ? right.types : [right]).filter((member3) => (member3.flags & import_typescript2.default.TypeFlags.Undefined) === 0);
|
|
796
|
-
|
|
812
|
+
const limit = [...a, ...b].every((member3) => (member3.flags & (import_typescript2.default.TypeFlags.Object | OPAQUE_FLAGS)) === 0) ? 128 : 16;
|
|
813
|
+
return a.length > 0 && a.length === b.length && a.length <= limit && a.every((member3) => b.some((other) => compare(member3, other))) && b.every((member3) => a.some((other) => compare(other, member3)));
|
|
797
814
|
}
|
|
798
815
|
if ((left.flags & import_typescript2.default.TypeFlags.Object) === 0 || (right.flags & import_typescript2.default.TypeFlags.Object) === 0) {
|
|
799
816
|
return checker.isTypeAssignableTo(left, right) && checker.isTypeAssignableTo(right, left);
|
|
@@ -811,9 +828,9 @@ function sameShape(checker, input, output, location) {
|
|
|
811
828
|
function sameObjectShape(left, right) {
|
|
812
829
|
const leftTuple = checker.isTupleType(left);
|
|
813
830
|
const rightTuple = checker.isTupleType(right);
|
|
814
|
-
if (leftTuple
|
|
815
|
-
if (checker.isArrayType(left)
|
|
816
|
-
if (!checker.isArrayType(right)
|
|
831
|
+
if (leftTuple || rightTuple) return leftTuple && rightTuple && sameTuplePositions(left, right);
|
|
832
|
+
if (checker.isArrayType(left)) {
|
|
833
|
+
if (!checker.isArrayType(right)) return false;
|
|
817
834
|
const a2 = left.getNumberIndexType();
|
|
818
835
|
const b2 = right.getNumberIndexType();
|
|
819
836
|
return a2 !== void 0 && b2 !== void 0 && compare(a2, b2);
|
|
@@ -829,17 +846,13 @@ function sameShape(checker, input, output, location) {
|
|
|
829
846
|
return a.length === b.length && a.every((index) => b.some((other) => checker.isTypeAssignableTo(index.keyType, other.keyType) && checker.isTypeAssignableTo(other.keyType, index.keyType) && compare(index.type, other.type)));
|
|
830
847
|
}
|
|
831
848
|
function sameTuplePositions(left, right) {
|
|
832
|
-
|
|
833
|
-
const
|
|
834
|
-
|
|
835
|
-
const
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
const otherProperties = right.getProperties().filter((property) => TUPLE_INDEX_RE.test(property.name));
|
|
840
|
-
return properties.length <= 128 && properties.length === otherProperties.length && properties.every((property) => {
|
|
841
|
-
const other = right.getProperty(property.name);
|
|
842
|
-
return other !== void 0 && compare(checker.getTypeOfSymbolAtLocation(property, location), checker.getTypeOfSymbolAtLocation(other, location));
|
|
849
|
+
if (!(0, import_ts_api_utils2.isTupleTypeReference)(left) || !(0, import_ts_api_utils2.isTupleTypeReference)(right)) return false;
|
|
850
|
+
const a = checker.getTypeArguments(left);
|
|
851
|
+
const b = checker.getTypeArguments(right);
|
|
852
|
+
const flags = right.target.elementFlags;
|
|
853
|
+
return a.length <= 128 && a.length === b.length && left.target.elementFlags.every((flag, index) => flag === flags[index]) && a.every((element, index) => {
|
|
854
|
+
const other = b[index];
|
|
855
|
+
return other !== void 0 && compare(element, other);
|
|
843
856
|
});
|
|
844
857
|
}
|
|
845
858
|
return compare(input, output);
|
|
@@ -882,7 +895,7 @@ function stableValueBinding(variable, acceptRead) {
|
|
|
882
895
|
var VIEWS = /* @__PURE__ */ new WeakMap();
|
|
883
896
|
function renderFunction(node) {
|
|
884
897
|
let parent = node.parent;
|
|
885
|
-
while (parent !== void 0) {
|
|
898
|
+
while (parent !== void 0 && parent !== null) {
|
|
886
899
|
if (isFunction(parent)) {
|
|
887
900
|
let view = VIEWS.get(parent);
|
|
888
901
|
if (view === void 0) {
|
|
@@ -2510,7 +2523,7 @@ function nativeRead(node, name) {
|
|
|
2510
2523
|
}
|
|
2511
2524
|
|
|
2512
2525
|
// src/rules/_native-fetch-reference.ts
|
|
2513
|
-
var
|
|
2526
|
+
var GLOBAL_RECEIVERS2 = /* @__PURE__ */ new Set(["globalThis", "self", "window"]);
|
|
2514
2527
|
function nativeFetchReference(node, sourceCode) {
|
|
2515
2528
|
return lexicalFetchReference(node, sourceCode) && nativeRuntimeUnchanged(sourceCode, "fetch");
|
|
2516
2529
|
}
|
|
@@ -2533,7 +2546,7 @@ function lexicalFetchReference(node, sourceCode, seen = /* @__PURE__ */ new Set(
|
|
|
2533
2546
|
}
|
|
2534
2547
|
function globalReceiver(node, sourceCode) {
|
|
2535
2548
|
const receiver = unwrapExpression(node);
|
|
2536
|
-
return receiver.type === import_utils22.AST_NODE_TYPES.Identifier &&
|
|
2549
|
+
return receiver.type === import_utils22.AST_NODE_TYPES.Identifier && GLOBAL_RECEIVERS2.has(receiver.name) && !import_utils22.ASTUtils.findVariable(sourceCode.getScope(receiver), receiver.name)?.defs.length;
|
|
2537
2550
|
}
|
|
2538
2551
|
|
|
2539
2552
|
// src/rules/_test-mock-provenance.ts
|
|
@@ -5526,7 +5539,7 @@ function isSearchParamReceiver(call, services) {
|
|
|
5526
5539
|
// package.json
|
|
5527
5540
|
var package_default = {
|
|
5528
5541
|
name: "@sarj/eslint-plugin",
|
|
5529
|
-
version: "18.0.
|
|
5542
|
+
version: "18.0.3",
|
|
5530
5543
|
packageManager: "npm@12.2.1",
|
|
5531
5544
|
description: "Custom ESLint rules for hypermodern TypeScript / React / Next.js projects",
|
|
5532
5545
|
type: "module",
|
|
@@ -7958,7 +7971,7 @@ var no_known_value_widening_default = createRule({
|
|
|
7958
7971
|
|
|
7959
7972
|
// src/rules/no-invalid-typed-mutation.ts
|
|
7960
7973
|
var import_utils53 = require("@typescript-eslint/utils");
|
|
7961
|
-
var
|
|
7974
|
+
var import_ts_api_utils3 = require("ts-api-utils");
|
|
7962
7975
|
var import_typescript20 = __toESM(require("typescript"), 1);
|
|
7963
7976
|
var NO_INVALID_TYPED_MUTATION_DOCUMENTATION = {
|
|
7964
7977
|
summary: "Keep native object mutation APIs from writing incompatible values into declared property types.",
|
|
@@ -8129,7 +8142,7 @@ function typedDataProperty(property) {
|
|
|
8129
8142
|
function propertyWriteType(target, property, node, checker, exact) {
|
|
8130
8143
|
const exposed = checker.getTypeOfSymbolAtLocation(property, node);
|
|
8131
8144
|
if (!exact || (property.flags & import_typescript20.default.SymbolFlags.Optional) === 0 || (property.flags & import_typescript20.default.SymbolFlags.Transient) !== 0) return exposed;
|
|
8132
|
-
if ((target.aliasTypeArguments?.length ?? 0) > 0 || (0,
|
|
8145
|
+
if ((target.aliasTypeArguments?.length ?? 0) > 0 || (0, import_ts_api_utils3.isTypeReference)(target) && checker.getTypeArguments(target).length > 0 || (0, import_ts_api_utils3.isObjectType)(target) && (target.objectFlags & (import_typescript20.default.ObjectFlags.Mapped | import_typescript20.default.ObjectFlags.Instantiated)) !== 0) return exposed;
|
|
8133
8146
|
const declaration = property.getDeclarations()?.[0];
|
|
8134
8147
|
if (declaration === void 0 || !(import_typescript20.default.isPropertySignature(declaration) || import_typescript20.default.isPropertyDeclaration(declaration)) || declaration.questionToken === void 0 || declaration.type === void 0) return exposed;
|
|
8135
8148
|
const authored = checker.getTypeFromTypeNode(declaration.type);
|
|
@@ -8142,10 +8155,10 @@ function definiteType(type, checker, seen = /* @__PURE__ */ new Set()) {
|
|
|
8142
8155
|
const unsafe = import_typescript20.default.TypeFlags.Any | import_typescript20.default.TypeFlags.Unknown | import_typescript20.default.TypeFlags.Never | import_typescript20.default.TypeFlags.TypeParameter | import_typescript20.default.TypeFlags.Conditional | import_typescript20.default.TypeFlags.IndexedAccess | import_typescript20.default.TypeFlags.Substitution;
|
|
8143
8156
|
if ((type.flags & unsafe) !== 0) return false;
|
|
8144
8157
|
if (type.isUnionOrIntersection()) return type.types.every((part) => definiteType(part, checker, seen));
|
|
8145
|
-
const arguments_ = (0,
|
|
8158
|
+
const arguments_ = (0, import_ts_api_utils3.isTypeReference)(type) ? checker.getTypeArguments(type) : type.aliasTypeArguments ?? [];
|
|
8146
8159
|
if (!arguments_.every((argument) => definiteType(argument, checker, seen))) return false;
|
|
8147
8160
|
if (!definiteSignatures(type, checker, seen)) return false;
|
|
8148
|
-
if ((0,
|
|
8161
|
+
if ((0, import_ts_api_utils3.isTypeReference)(type) || (type.flags & import_typescript20.default.TypeFlags.Object) === 0) return true;
|
|
8149
8162
|
return type.getProperties().every((property) => {
|
|
8150
8163
|
const declaration = property.valueDeclaration ?? property.getDeclarations()?.[0];
|
|
8151
8164
|
return declaration !== void 0 && definiteType(checker.getTypeOfSymbolAtLocation(property, declaration), checker, seen);
|
|
@@ -8246,7 +8259,7 @@ function hasSeparatePredicateContract(node, checker) {
|
|
|
8246
8259
|
// src/rules/_contradictory-array-predicate.ts
|
|
8247
8260
|
var import_utils54 = require("@typescript-eslint/utils");
|
|
8248
8261
|
var import_typescript22 = __toESM(require("typescript"), 1);
|
|
8249
|
-
var
|
|
8262
|
+
var import_ts_api_utils4 = require("ts-api-utils");
|
|
8250
8263
|
var HOST_GLOBALS = ["globalThis", "window", "self", "global"];
|
|
8251
8264
|
var PRIMITIVE_ELEMENTS = import_typescript22.default.TypeFlags.String | import_typescript22.default.TypeFlags.Number | import_typescript22.default.TypeFlags.Boolean | import_typescript22.default.TypeFlags.BigInt | import_typescript22.default.TypeFlags.ESSymbol;
|
|
8252
8265
|
var OBJECT_REFLECTION2 = /* @__PURE__ */ new Set(["getPrototypeOf", "getOwnPropertyDescriptor", "getOwnPropertyDescriptors", "prototype", "constructor", "__proto__"]);
|
|
@@ -8281,7 +8294,7 @@ function contradictoryArrayPredicate(sourceCode, services) {
|
|
|
8281
8294
|
};
|
|
8282
8295
|
}
|
|
8283
8296
|
function plainPrimitiveArray(target, checker) {
|
|
8284
|
-
if (!checker.isArrayType(target) || !(0,
|
|
8297
|
+
if (!checker.isArrayType(target) || !(0, import_ts_api_utils4.isTypeReference)(target)) return false;
|
|
8285
8298
|
const [element] = checker.getTypeArguments(target);
|
|
8286
8299
|
return element !== void 0 && (element.flags & PRIMITIVE_ELEMENTS) !== 0 && (element.flags & (import_typescript22.default.TypeFlags.Enum | import_typescript22.default.TypeFlags.EnumLiteral | import_typescript22.default.TypeFlags.Intersection)) === 0;
|
|
8287
8300
|
}
|
|
@@ -8565,7 +8578,7 @@ function primitiveKind(type, allowLiterals) {
|
|
|
8565
8578
|
|
|
8566
8579
|
// src/rules/no-partial-type-predicate.ts
|
|
8567
8580
|
var import_utils57 = require("@typescript-eslint/utils");
|
|
8568
|
-
var
|
|
8581
|
+
var import_ts_api_utils5 = require("ts-api-utils");
|
|
8569
8582
|
var import_typescript25 = __toESM(require("typescript"), 1);
|
|
8570
8583
|
|
|
8571
8584
|
// src/rules/_uuid-predicate-witness.ts
|
|
@@ -8737,7 +8750,7 @@ function primitiveKind2(type) {
|
|
|
8737
8750
|
return void 0;
|
|
8738
8751
|
}
|
|
8739
8752
|
function numericWitnessInInput(value, input) {
|
|
8740
|
-
return (input.isUnion() ? input.types : [input]).some((member3) => (member3.flags & (import_typescript25.default.TypeFlags.Unknown | import_typescript25.default.TypeFlags.Number)) !== 0 || Number.isFinite(value) && (0,
|
|
8753
|
+
return (input.isUnion() ? input.types : [input]).some((member3) => (member3.flags & (import_typescript25.default.TypeFlags.Unknown | import_typescript25.default.TypeFlags.Number)) !== 0 || Number.isFinite(value) && (0, import_ts_api_utils5.isNumberLiteralType)(member3) && member3.value === value);
|
|
8741
8754
|
}
|
|
8742
8755
|
function returnedExpression2(node) {
|
|
8743
8756
|
if (node.body === void 0) return void 0;
|
|
@@ -9323,7 +9336,7 @@ function isDirectTest(identifier) {
|
|
|
9323
9336
|
|
|
9324
9337
|
// src/rules/no-invalid-zod-custom-parse.ts
|
|
9325
9338
|
var import_utils61 = require("@typescript-eslint/utils");
|
|
9326
|
-
var
|
|
9339
|
+
var import_ts_api_utils6 = require("ts-api-utils");
|
|
9327
9340
|
var import_typescript27 = __toESM(require("typescript"), 1);
|
|
9328
9341
|
var NO_INVALID_ZOD_CUSTOM_PARSE_DOCUMENTATION = {
|
|
9329
9342
|
summary: "Do not parse an incompatible primitive literal through an unvalidated Zod custom schema.",
|
|
@@ -9419,10 +9432,10 @@ function primitiveDomain(type) {
|
|
|
9419
9432
|
function acceptsPrimitive(type, value) {
|
|
9420
9433
|
if (type.isUnion()) return type.types.some((member3) => acceptsPrimitive(member3, value));
|
|
9421
9434
|
if (value === null) return (type.flags & import_typescript27.default.TypeFlags.Null) !== 0;
|
|
9422
|
-
if (typeof value === "string") return (type.flags & import_typescript27.default.TypeFlags.String) !== 0 || (0,
|
|
9423
|
-
if (typeof value === "number") return (type.flags & import_typescript27.default.TypeFlags.Number) !== 0 || (0,
|
|
9424
|
-
if (typeof value === "boolean") return (0,
|
|
9425
|
-
return (type.flags & import_typescript27.default.TypeFlags.BigInt) !== 0 || (0,
|
|
9435
|
+
if (typeof value === "string") return (type.flags & import_typescript27.default.TypeFlags.String) !== 0 || (0, import_ts_api_utils6.isStringLiteralType)(type) && type.value === value;
|
|
9436
|
+
if (typeof value === "number") return (type.flags & import_typescript27.default.TypeFlags.Number) !== 0 || (0, import_ts_api_utils6.isNumberLiteralType)(type) && type.value === value;
|
|
9437
|
+
if (typeof value === "boolean") return (0, import_ts_api_utils6.isBooleanLiteralType)(type) && type.intrinsicName === String(value);
|
|
9438
|
+
return (type.flags & import_typescript27.default.TypeFlags.BigInt) !== 0 || (0, import_ts_api_utils6.isBigIntLiteralType)(type) && bigintValue(type) === value;
|
|
9426
9439
|
}
|
|
9427
9440
|
function bigintValue(type) {
|
|
9428
9441
|
return BigInt(`${type.value.negative ? "-" : ""}${type.value.base10Value}`);
|
|
@@ -14808,7 +14821,7 @@ var NO_DETACHED_GLOBAL_FETCH_DOCUMENTATION = {
|
|
|
14808
14821
|
}
|
|
14809
14822
|
]
|
|
14810
14823
|
};
|
|
14811
|
-
var
|
|
14824
|
+
var GLOBAL_RECEIVERS3 = /* @__PURE__ */ new Set([
|
|
14812
14825
|
"globalThis",
|
|
14813
14826
|
"self",
|
|
14814
14827
|
"window"
|
|
@@ -14855,7 +14868,7 @@ var no_detached_global_fetch_default = createRule({
|
|
|
14855
14868
|
return variable === null || variable.defs.length === 0;
|
|
14856
14869
|
}
|
|
14857
14870
|
function isGlobalReceiver(node) {
|
|
14858
|
-
return node.type === import_utils92.AST_NODE_TYPES.Identifier &&
|
|
14871
|
+
return node.type === import_utils92.AST_NODE_TYPES.Identifier && GLOBAL_RECEIVERS3.has(node.name) && resolvesToGlobal(node);
|
|
14859
14872
|
}
|
|
14860
14873
|
function recordAlias(identifier) {
|
|
14861
14874
|
const variable = bindingOf(identifier);
|
|
@@ -14914,7 +14927,7 @@ var no_detached_global_fetch_default = createRule({
|
|
|
14914
14927
|
return false;
|
|
14915
14928
|
if (node.type !== import_utils92.AST_NODE_TYPES.Identifier || !resolvesToGlobal(node))
|
|
14916
14929
|
return false;
|
|
14917
|
-
return
|
|
14930
|
+
return GLOBAL_RECEIVERS3.has(node.name) || node.name === "undefined";
|
|
14918
14931
|
}
|
|
14919
14932
|
return {
|
|
14920
14933
|
AssignmentExpression(node) {
|
|
@@ -16202,7 +16215,7 @@ var EQUALITY_OPERATORS = /* @__PURE__ */ new Set([
|
|
|
16202
16215
|
"==",
|
|
16203
16216
|
"==="
|
|
16204
16217
|
]);
|
|
16205
|
-
var
|
|
16218
|
+
var PRIMITIVE_FLAGS2 = import_typescript29.default.TypeFlags.BigIntLike | import_typescript29.default.TypeFlags.BooleanLike | import_typescript29.default.TypeFlags.ESSymbolLike | import_typescript29.default.TypeFlags.Never | import_typescript29.default.TypeFlags.Null | import_typescript29.default.TypeFlags.NumberLike | import_typescript29.default.TypeFlags.StringLike | import_typescript29.default.TypeFlags.Undefined | import_typescript29.default.TypeFlags.Void;
|
|
16206
16219
|
function unwrapComparisonExpression(node) {
|
|
16207
16220
|
let current = unwrapExpression(node);
|
|
16208
16221
|
while (current.type === import_utils98.AST_NODE_TYPES.ChainExpression) {
|
|
@@ -16256,7 +16269,7 @@ function typeMayContainObject(type, checker) {
|
|
|
16256
16269
|
if (type.isUnionOrIntersection()) {
|
|
16257
16270
|
return type.types.some((member3) => typeMayContainObject(member3, checker));
|
|
16258
16271
|
}
|
|
16259
|
-
if ((type.flags &
|
|
16272
|
+
if ((type.flags & PRIMITIVE_FLAGS2) !== 0) return false;
|
|
16260
16273
|
if ((type.flags & (import_typescript29.default.TypeFlags.Any | import_typescript29.default.TypeFlags.Unknown | import_typescript29.default.TypeFlags.TypeParameter)) !== 0) {
|
|
16261
16274
|
return true;
|
|
16262
16275
|
}
|
|
@@ -33451,7 +33464,7 @@ var import_utils182 = require("@typescript-eslint/utils");
|
|
|
33451
33464
|
var import_typescript34 = __toESM(require("typescript"), 1);
|
|
33452
33465
|
|
|
33453
33466
|
// src/rules/_equivalent-zod-output-contracts.ts
|
|
33454
|
-
var
|
|
33467
|
+
var import_ts_api_utils7 = require("ts-api-utils");
|
|
33455
33468
|
var import_typescript32 = __toESM(require("typescript"), 1);
|
|
33456
33469
|
var MAX_CONTRACT_PAIRS = 128;
|
|
33457
33470
|
var MAX_UNION_MEMBERS = 16;
|
|
@@ -33480,8 +33493,8 @@ function seenPair(comparison2, left, right) {
|
|
|
33480
33493
|
function equivalentPair(comparison2, left, right) {
|
|
33481
33494
|
if (!mutuallyAssignable(comparison2.checker, left, right)) return false;
|
|
33482
33495
|
if (left.isUnion() || right.isUnion()) return equivalentUnions(comparison2, left, right);
|
|
33483
|
-
const leftContainer = comparison2.checker.isArrayType(left) || (0,
|
|
33484
|
-
const rightContainer = comparison2.checker.isArrayType(right) || (0,
|
|
33496
|
+
const leftContainer = comparison2.checker.isArrayType(left) || (0, import_ts_api_utils7.isTupleTypeReference)(left);
|
|
33497
|
+
const rightContainer = comparison2.checker.isArrayType(right) || (0, import_ts_api_utils7.isTupleTypeReference)(right);
|
|
33485
33498
|
if (leftContainer || rightContainer) return equivalentContainers(comparison2, left, right);
|
|
33486
33499
|
if (hasClassDeclaration(left) || hasClassDeclaration(right)) return false;
|
|
33487
33500
|
if (!objectLike(left) || !objectLike(right)) return false;
|
|
@@ -33510,9 +33523,9 @@ function queuePair(comparison2, left, right) {
|
|
|
33510
33523
|
return true;
|
|
33511
33524
|
}
|
|
33512
33525
|
function equivalentContainers(comparison2, left, right) {
|
|
33513
|
-
if (!(0,
|
|
33514
|
-
const leftTuple = (0,
|
|
33515
|
-
const rightTuple = (0,
|
|
33526
|
+
if (!(0, import_ts_api_utils7.isTypeReference)(left) || !(0, import_ts_api_utils7.isTypeReference)(right)) return false;
|
|
33527
|
+
const leftTuple = (0, import_ts_api_utils7.isTupleTypeReference)(left);
|
|
33528
|
+
const rightTuple = (0, import_ts_api_utils7.isTupleTypeReference)(right);
|
|
33516
33529
|
if (leftTuple !== rightTuple) return false;
|
|
33517
33530
|
if (leftTuple && rightTuple && (left.target.readonly !== right.target.readonly || left.target.elementFlags.length !== right.target.elementFlags.length || left.target.elementFlags.some((flag, index) => flag !== right.target.elementFlags[index]))) return false;
|
|
33518
33531
|
const leftIndex = comparison2.checker.getIndexInfoOfType(left, import_typescript32.default.IndexKind.Number);
|
|
@@ -33550,7 +33563,7 @@ function equivalentProperty(comparison2, left, right, property, other) {
|
|
|
33550
33563
|
const { checker } = comparison2;
|
|
33551
33564
|
if (opaqueProperty(property) || opaqueProperty(other)) return false;
|
|
33552
33565
|
if ((property.flags & import_typescript32.default.SymbolFlags.Optional) !== (other.flags & import_typescript32.default.SymbolFlags.Optional)) return false;
|
|
33553
|
-
if ((0,
|
|
33566
|
+
if ((0, import_ts_api_utils7.isPropertyReadonlyInType)(left, property.getEscapedName(), checker) !== (0, import_ts_api_utils7.isPropertyReadonlyInType)(right, other.getEscapedName(), checker)) return false;
|
|
33554
33567
|
const declaration = property.valueDeclaration ?? property.getDeclarations()?.[0];
|
|
33555
33568
|
const otherDeclaration = other.valueDeclaration ?? other.getDeclarations()?.[0];
|
|
33556
33569
|
return declaration !== void 0 && otherDeclaration !== void 0 && queuePair(
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/rules/no-logical-or-fallback.ts
|
|
2
|
-
import { ASTUtils, AST_NODE_TYPES as
|
|
2
|
+
import { ASTUtils, AST_NODE_TYPES as AST_NODE_TYPES3 } from "@typescript-eslint/utils";
|
|
3
3
|
import { isBigIntLiteralType, isBooleanLiteralType } from "ts-api-utils";
|
|
4
4
|
import ts from "typescript";
|
|
5
5
|
|
|
@@ -539,7 +539,30 @@ function commentLineEnd(sourceText, start) {
|
|
|
539
539
|
return end === -1 ? sourceText.length : start + end;
|
|
540
540
|
}
|
|
541
541
|
|
|
542
|
+
// src/rules/_unwrap-expression.ts
|
|
543
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES2 } from "@typescript-eslint/utils";
|
|
544
|
+
function unwrapExpression(node) {
|
|
545
|
+
while (isErasedExpression(node)) {
|
|
546
|
+
node = node.expression;
|
|
547
|
+
}
|
|
548
|
+
return node;
|
|
549
|
+
}
|
|
550
|
+
function outerExpression(node) {
|
|
551
|
+
while (node.parent !== void 0 && node.parent !== null && isErasedExpression(node.parent) && node.parent.expression === node) node = node.parent;
|
|
552
|
+
return node;
|
|
553
|
+
}
|
|
554
|
+
function directArgumentCall(node) {
|
|
555
|
+
const argument = outerExpression(node);
|
|
556
|
+
const call = argument.parent;
|
|
557
|
+
return call?.type === AST_NODE_TYPES2.CallExpression && call.arguments.some((item) => item === argument) ? call : null;
|
|
558
|
+
}
|
|
559
|
+
function isErasedExpression(node) {
|
|
560
|
+
return node.type === AST_NODE_TYPES2.TSAsExpression || node.type === AST_NODE_TYPES2.TSSatisfiesExpression || node.type === AST_NODE_TYPES2.TSNonNullExpression || node.type === AST_NODE_TYPES2.TSTypeAssertion;
|
|
561
|
+
}
|
|
562
|
+
|
|
542
563
|
// src/rules/no-logical-or-fallback.ts
|
|
564
|
+
var PRIMITIVE_FLAGS = ts.TypeFlags.StringLike | ts.TypeFlags.NumberLike | ts.TypeFlags.BigIntLike | ts.TypeFlags.BooleanLike;
|
|
565
|
+
var GLOBAL_RECEIVERS = /* @__PURE__ */ new Set(["globalThis", "window", "self"]);
|
|
543
566
|
var NO_LOGICAL_OR_FALLBACK_DOCUMENTATION = {
|
|
544
567
|
defaultLevel: "warning",
|
|
545
568
|
summary: "Use nullish defaults or explicit falsy-value checks instead of logical OR fallbacks.",
|
|
@@ -548,8 +571,8 @@ var NO_LOGICAL_OR_FALLBACK_DOCUMENTATION = {
|
|
|
548
571
|
category: "correctness",
|
|
549
572
|
autofix: "none",
|
|
550
573
|
limitations: [
|
|
551
|
-
"Requires TypeScript type information and strict null checks. Reports non-nullable string, number or bigint value fallbacks, including mixed primitive unions. Nullable inputs remain owned by @typescript-eslint/prefer-nullish-coalescing; both rules are enabled in the managed strict config.",
|
|
552
|
-
"Preserves boolean aggregation, conditions, negations, left-hand && guards, and calls to the unshadowed Boolean constructor. Constant truthiness stays with no-unnecessary-condition. Unknown, any, generic, object-only and generated inputs are excluded. Strings and comments are never scanned as code.",
|
|
574
|
+
"Requires TypeScript type information and strict null checks. Reports non-nullable string, number or bigint value fallbacks, including branded primitives and mixed primitive unions. Nullable inputs, including nullable booleans, remain owned by @typescript-eslint/prefer-nullish-coalescing; both rules are enabled in the managed strict config.",
|
|
575
|
+
"Preserves non-nullable boolean aggregation, conditions, negations, left-hand && guards, and calls to the native unshadowed Boolean constructor, including erased TypeScript wrappers and globalThis/window/self access. Constant truthiness stays with no-unnecessary-condition. Unknown, any, unresolved generic, object-only and generated inputs are excluded. Strings and comments are never scanned as code.",
|
|
553
576
|
"No automatic replacement is offered: replacing || with ?? would change empty-string or zero behavior. Non-nullable ||= expressions remain outside this companion rule."
|
|
554
577
|
],
|
|
555
578
|
references: ["https://typescript-eslint.io/rules/prefer-nullish-coalescing/"],
|
|
@@ -577,83 +600,72 @@ var no_logical_or_fallback_default = createRule({
|
|
|
577
600
|
if (!(options.strictNullChecks ?? options.strict ?? false)) return {};
|
|
578
601
|
return {
|
|
579
602
|
LogicalExpression(node) {
|
|
580
|
-
if (node.operator !== "||" || booleanContext(node, context.sourceCode)) return;
|
|
603
|
+
if (node.operator !== "||" || booleanContext(node, context.sourceCode, services)) return;
|
|
581
604
|
const type = checker.getTypeAtLocation(services.esTreeNodeToTSNodeMap.get(node.left));
|
|
582
|
-
const members = type.isUnion() ? type.types : [type];
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
const truthiness = members.map(literalTruthiness);
|
|
605
|
+
const members = (type.isUnion() ? type.types : [type]).map(primitivePart);
|
|
606
|
+
if (members.some((member3) => member3 === void 0) || !members.some((member3) => member3 !== void 0 && (member3.flags & (ts.TypeFlags.StringLike | ts.TypeFlags.NumberLike | ts.TypeFlags.BigIntLike)) !== 0)) return;
|
|
607
|
+
const truthiness = members.map((member3) => member3 === void 0 ? void 0 : literalTruthiness(member3));
|
|
586
608
|
if (truthiness.every((value) => value === true) || truthiness.every((value) => value === false)) return;
|
|
587
609
|
context.report({ node, messageId: "logicalOrFallback" });
|
|
588
610
|
}
|
|
589
611
|
};
|
|
590
612
|
}
|
|
591
613
|
});
|
|
614
|
+
function primitivePart(type) {
|
|
615
|
+
if ((type.flags & PRIMITIVE_FLAGS) !== 0) return type;
|
|
616
|
+
if (!type.isIntersection() || type.types.some((member3) => (member3.flags & ts.TypeFlags.TypeParameter) !== 0)) return void 0;
|
|
617
|
+
return type.types.find((member3) => (member3.flags & PRIMITIVE_FLAGS) !== 0);
|
|
618
|
+
}
|
|
592
619
|
function literalTruthiness(type) {
|
|
593
620
|
if (type.isStringLiteral() || type.isNumberLiteral()) return Boolean(type.value);
|
|
594
621
|
if (isBooleanLiteralType(type)) return type.intrinsicName === "true";
|
|
595
622
|
if (isBigIntLiteralType(type)) return type.value.base10Value !== "0";
|
|
596
623
|
return void 0;
|
|
597
624
|
}
|
|
598
|
-
function booleanContext(node, source) {
|
|
599
|
-
let current = node;
|
|
625
|
+
function booleanContext(node, source, services) {
|
|
626
|
+
let current = outerExpression(node);
|
|
600
627
|
while (current.parent !== void 0) {
|
|
601
628
|
const parent = current.parent;
|
|
602
629
|
switch (parent.type) {
|
|
603
|
-
case
|
|
604
|
-
case AST_NODE_TYPES2.TSSatisfiesExpression:
|
|
605
|
-
case AST_NODE_TYPES2.TSNonNullExpression:
|
|
606
|
-
current = parent;
|
|
607
|
-
continue;
|
|
608
|
-
case AST_NODE_TYPES2.LogicalExpression:
|
|
630
|
+
case AST_NODE_TYPES3.LogicalExpression:
|
|
609
631
|
if (parent.operator === "&&" && parent.left === current) return true;
|
|
610
|
-
current = parent;
|
|
632
|
+
current = outerExpression(parent);
|
|
611
633
|
continue;
|
|
612
|
-
case
|
|
613
|
-
case
|
|
614
|
-
case
|
|
615
|
-
case
|
|
616
|
-
case
|
|
634
|
+
case AST_NODE_TYPES3.IfStatement:
|
|
635
|
+
case AST_NODE_TYPES3.WhileStatement:
|
|
636
|
+
case AST_NODE_TYPES3.DoWhileStatement:
|
|
637
|
+
case AST_NODE_TYPES3.ForStatement:
|
|
638
|
+
case AST_NODE_TYPES3.ConditionalExpression:
|
|
617
639
|
return parent.test === current;
|
|
618
|
-
case
|
|
640
|
+
case AST_NODE_TYPES3.UnaryExpression:
|
|
619
641
|
return parent.operator === "!";
|
|
620
|
-
case
|
|
621
|
-
return parent.
|
|
642
|
+
case AST_NODE_TYPES3.CallExpression:
|
|
643
|
+
return parent.arguments[0] === current && nativeBoolean(parent.callee, source, services);
|
|
622
644
|
default:
|
|
623
645
|
return false;
|
|
624
646
|
}
|
|
625
647
|
}
|
|
626
648
|
return false;
|
|
627
649
|
}
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
650
|
+
function nativeBoolean(node, source, services) {
|
|
651
|
+
const callee = unwrapExpression(node);
|
|
652
|
+
const checker = services.program.getTypeChecker();
|
|
653
|
+
let symbol;
|
|
654
|
+
if (callee.type === AST_NODE_TYPES3.Identifier && callee.name === "Boolean" && !ASTUtils.findVariable(source.getScope(callee), callee.name)?.defs.length) {
|
|
655
|
+
symbol = checker.getSymbolAtLocation(services.esTreeNodeToTSNodeMap.get(callee));
|
|
656
|
+
} else if (callee.type === AST_NODE_TYPES3.MemberExpression && ASTUtils.getPropertyName(callee) === "Boolean") {
|
|
657
|
+
const receiver = unwrapExpression(callee.object);
|
|
658
|
+
if (receiver.type !== AST_NODE_TYPES3.Identifier || !GLOBAL_RECEIVERS.has(receiver.name) || ASTUtils.findVariable(source.getScope(receiver), receiver.name)?.defs.length) return false;
|
|
659
|
+
symbol = checker.getTypeAtLocation(services.esTreeNodeToTSNodeMap.get(receiver)).getProperty("Boolean");
|
|
638
660
|
}
|
|
639
|
-
return
|
|
640
|
-
}
|
|
641
|
-
function outerExpression(node) {
|
|
642
|
-
while (node.parent !== void 0 && node.parent !== null && isErasedExpression(node.parent) && node.parent.expression === node) node = node.parent;
|
|
643
|
-
return node;
|
|
644
|
-
}
|
|
645
|
-
function directArgumentCall(node) {
|
|
646
|
-
const argument = outerExpression(node);
|
|
647
|
-
const call = argument.parent;
|
|
648
|
-
return call?.type === AST_NODE_TYPES3.CallExpression && call.arguments.some((item) => item === argument) ? call : null;
|
|
649
|
-
}
|
|
650
|
-
function isErasedExpression(node) {
|
|
651
|
-
return node.type === AST_NODE_TYPES3.TSAsExpression || node.type === AST_NODE_TYPES3.TSSatisfiesExpression || node.type === AST_NODE_TYPES3.TSNonNullExpression || node.type === AST_NODE_TYPES3.TSTypeAssertion;
|
|
661
|
+
return symbol?.declarations !== void 0 && symbol.declarations.length > 0 && symbol.declarations.every((declaration) => services.program.isSourceFileDefaultLibrary(declaration.getSourceFile()));
|
|
652
662
|
}
|
|
653
663
|
|
|
654
664
|
// src/rules/no-zod-parse-typed-object.ts
|
|
665
|
+
import { ASTUtils as ASTUtils2, AST_NODE_TYPES as AST_NODE_TYPES4 } from "@typescript-eslint/utils";
|
|
666
|
+
import { isTupleTypeReference } from "ts-api-utils";
|
|
667
|
+
import ts2 from "typescript";
|
|
655
668
|
var PARSE_METHODS = /* @__PURE__ */ new Set(["parse", "parseAsync", "safeParse", "safeParseAsync"]);
|
|
656
|
-
var TUPLE_INDEX_RE = /^(?:0|[1-9]\d*)$/u;
|
|
657
669
|
var OPAQUE_FLAGS = ts2.TypeFlags.Any | ts2.TypeFlags.Unknown | ts2.TypeFlags.Never | ts2.TypeFlags.TypeParameter | ts2.TypeFlags.Conditional | ts2.TypeFlags.IndexedAccess | ts2.TypeFlags.Intersection | ts2.TypeFlags.NonPrimitive;
|
|
658
670
|
var NO_ZOD_PARSE_TYPED_OBJECT_DOCUMENTATION = {
|
|
659
671
|
defaultLevel: "warning",
|
|
@@ -666,7 +678,7 @@ var NO_ZOD_PARSE_TYPED_OBJECT_DOCUMENTATION = {
|
|
|
666
678
|
"Requires type information, strict null checks, and a native installed Zod parse, parseAsync, safeParse or safeParseAsync signature. Recognizes imported schemas, aliases, member access and awaited service results without guessing from names.",
|
|
667
679
|
"Reports fully known object or array inputs assignable to the schema input, when schema input and output have the same value shape. Optional-to-required defaults are included; type-changing transforms, coercions, brands, incompatible contracts, primitive roots and nested any/unknown/generic contracts are excluded.",
|
|
668
680
|
"Static types do not establish runtime trust or prove refinements and normalization redundant. This is an architectural warning with no automatic removal. Keep intentional validation at an unknown-data boundary or document an exact local suppression. Tests, stories and generated code are excluded.",
|
|
669
|
-
"Shape comparison ignores undefined introduced by optional properties and is bounded to 128 object pairs
|
|
681
|
+
"Shape comparison ignores undefined introduced by optional properties and checks tuple element types and rest positions. It is bounded to 128 object pairs, visited input objects, properties, tuple elements or primitive union alternatives; object unions have at most 16 alternatives. Opaque or larger graphs are conservatively excluded."
|
|
670
682
|
],
|
|
671
683
|
references: ["https://zod.dev/basics"],
|
|
672
684
|
examples: [
|
|
@@ -726,7 +738,11 @@ function knownValue(checker, type, location, seen) {
|
|
|
726
738
|
if (seen.has(type)) return true;
|
|
727
739
|
if (seen.size >= 128 || type.getCallSignatures().length > 0 || type.getConstructSignatures().length > 0) return false;
|
|
728
740
|
seen.add(type);
|
|
729
|
-
if (
|
|
741
|
+
if (isTupleTypeReference(type)) {
|
|
742
|
+
const elements = checker.getTypeArguments(type);
|
|
743
|
+
return elements.length <= 128 && elements.every((element) => knownValue(checker, element, location, seen));
|
|
744
|
+
}
|
|
745
|
+
if (checker.isArrayType(type)) {
|
|
730
746
|
const element = type.getNumberIndexType();
|
|
731
747
|
return element !== void 0 && knownValue(checker, element, location, seen);
|
|
732
748
|
}
|
|
@@ -742,7 +758,8 @@ function sameShape(checker, input, output, location) {
|
|
|
742
758
|
if (left.isUnion() || right.isUnion()) {
|
|
743
759
|
const a = (left.isUnion() ? left.types : [left]).filter((member3) => (member3.flags & ts2.TypeFlags.Undefined) === 0);
|
|
744
760
|
const b = (right.isUnion() ? right.types : [right]).filter((member3) => (member3.flags & ts2.TypeFlags.Undefined) === 0);
|
|
745
|
-
|
|
761
|
+
const limit = [...a, ...b].every((member3) => (member3.flags & (ts2.TypeFlags.Object | OPAQUE_FLAGS)) === 0) ? 128 : 16;
|
|
762
|
+
return a.length > 0 && a.length === b.length && a.length <= limit && a.every((member3) => b.some((other) => compare(member3, other))) && b.every((member3) => a.some((other) => compare(other, member3)));
|
|
746
763
|
}
|
|
747
764
|
if ((left.flags & ts2.TypeFlags.Object) === 0 || (right.flags & ts2.TypeFlags.Object) === 0) {
|
|
748
765
|
return checker.isTypeAssignableTo(left, right) && checker.isTypeAssignableTo(right, left);
|
|
@@ -760,9 +777,9 @@ function sameShape(checker, input, output, location) {
|
|
|
760
777
|
function sameObjectShape(left, right) {
|
|
761
778
|
const leftTuple = checker.isTupleType(left);
|
|
762
779
|
const rightTuple = checker.isTupleType(right);
|
|
763
|
-
if (leftTuple
|
|
764
|
-
if (checker.isArrayType(left)
|
|
765
|
-
if (!checker.isArrayType(right)
|
|
780
|
+
if (leftTuple || rightTuple) return leftTuple && rightTuple && sameTuplePositions(left, right);
|
|
781
|
+
if (checker.isArrayType(left)) {
|
|
782
|
+
if (!checker.isArrayType(right)) return false;
|
|
766
783
|
const a2 = left.getNumberIndexType();
|
|
767
784
|
const b2 = right.getNumberIndexType();
|
|
768
785
|
return a2 !== void 0 && b2 !== void 0 && compare(a2, b2);
|
|
@@ -778,17 +795,13 @@ function sameShape(checker, input, output, location) {
|
|
|
778
795
|
return a.length === b.length && a.every((index) => b.some((other) => checker.isTypeAssignableTo(index.keyType, other.keyType) && checker.isTypeAssignableTo(other.keyType, index.keyType) && compare(index.type, other.type)));
|
|
779
796
|
}
|
|
780
797
|
function sameTuplePositions(left, right) {
|
|
781
|
-
|
|
782
|
-
const
|
|
783
|
-
|
|
784
|
-
const
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
const otherProperties = right.getProperties().filter((property) => TUPLE_INDEX_RE.test(property.name));
|
|
789
|
-
return properties.length <= 128 && properties.length === otherProperties.length && properties.every((property) => {
|
|
790
|
-
const other = right.getProperty(property.name);
|
|
791
|
-
return other !== void 0 && compare(checker.getTypeOfSymbolAtLocation(property, location), checker.getTypeOfSymbolAtLocation(other, location));
|
|
798
|
+
if (!isTupleTypeReference(left) || !isTupleTypeReference(right)) return false;
|
|
799
|
+
const a = checker.getTypeArguments(left);
|
|
800
|
+
const b = checker.getTypeArguments(right);
|
|
801
|
+
const flags = right.target.elementFlags;
|
|
802
|
+
return a.length <= 128 && a.length === b.length && left.target.elementFlags.every((flag, index) => flag === flags[index]) && a.every((element, index) => {
|
|
803
|
+
const other = b[index];
|
|
804
|
+
return other !== void 0 && compare(element, other);
|
|
792
805
|
});
|
|
793
806
|
}
|
|
794
807
|
return compare(input, output);
|
|
@@ -837,7 +850,7 @@ function stableValueBinding(variable, acceptRead) {
|
|
|
837
850
|
var VIEWS = /* @__PURE__ */ new WeakMap();
|
|
838
851
|
function renderFunction(node) {
|
|
839
852
|
let parent = node.parent;
|
|
840
|
-
while (parent !== void 0) {
|
|
853
|
+
while (parent !== void 0 && parent !== null) {
|
|
841
854
|
if (isFunction(parent)) {
|
|
842
855
|
let view = VIEWS.get(parent);
|
|
843
856
|
if (view === void 0) {
|
|
@@ -2465,7 +2478,7 @@ function nativeRead(node, name) {
|
|
|
2465
2478
|
}
|
|
2466
2479
|
|
|
2467
2480
|
// src/rules/_native-fetch-reference.ts
|
|
2468
|
-
var
|
|
2481
|
+
var GLOBAL_RECEIVERS2 = /* @__PURE__ */ new Set(["globalThis", "self", "window"]);
|
|
2469
2482
|
function nativeFetchReference(node, sourceCode) {
|
|
2470
2483
|
return lexicalFetchReference(node, sourceCode) && nativeRuntimeUnchanged(sourceCode, "fetch");
|
|
2471
2484
|
}
|
|
@@ -2488,7 +2501,7 @@ function lexicalFetchReference(node, sourceCode, seen = /* @__PURE__ */ new Set(
|
|
|
2488
2501
|
}
|
|
2489
2502
|
function globalReceiver(node, sourceCode) {
|
|
2490
2503
|
const receiver = unwrapExpression(node);
|
|
2491
|
-
return receiver.type === AST_NODE_TYPES20.Identifier &&
|
|
2504
|
+
return receiver.type === AST_NODE_TYPES20.Identifier && GLOBAL_RECEIVERS2.has(receiver.name) && !ASTUtils10.findVariable(sourceCode.getScope(receiver), receiver.name)?.defs.length;
|
|
2492
2505
|
}
|
|
2493
2506
|
|
|
2494
2507
|
// src/rules/_test-mock-provenance.ts
|
|
@@ -5481,7 +5494,7 @@ function isSearchParamReceiver(call, services) {
|
|
|
5481
5494
|
// package.json
|
|
5482
5495
|
var package_default = {
|
|
5483
5496
|
name: "@sarj/eslint-plugin",
|
|
5484
|
-
version: "18.0.
|
|
5497
|
+
version: "18.0.3",
|
|
5485
5498
|
packageManager: "npm@12.2.1",
|
|
5486
5499
|
description: "Custom ESLint rules for hypermodern TypeScript / React / Next.js projects",
|
|
5487
5500
|
type: "module",
|
|
@@ -14769,7 +14782,7 @@ var NO_DETACHED_GLOBAL_FETCH_DOCUMENTATION = {
|
|
|
14769
14782
|
}
|
|
14770
14783
|
]
|
|
14771
14784
|
};
|
|
14772
|
-
var
|
|
14785
|
+
var GLOBAL_RECEIVERS3 = /* @__PURE__ */ new Set([
|
|
14773
14786
|
"globalThis",
|
|
14774
14787
|
"self",
|
|
14775
14788
|
"window"
|
|
@@ -14816,7 +14829,7 @@ var no_detached_global_fetch_default = createRule({
|
|
|
14816
14829
|
return variable === null || variable.defs.length === 0;
|
|
14817
14830
|
}
|
|
14818
14831
|
function isGlobalReceiver(node) {
|
|
14819
|
-
return node.type === AST_NODE_TYPES85.Identifier &&
|
|
14832
|
+
return node.type === AST_NODE_TYPES85.Identifier && GLOBAL_RECEIVERS3.has(node.name) && resolvesToGlobal(node);
|
|
14820
14833
|
}
|
|
14821
14834
|
function recordAlias(identifier) {
|
|
14822
14835
|
const variable = bindingOf(identifier);
|
|
@@ -14875,7 +14888,7 @@ var no_detached_global_fetch_default = createRule({
|
|
|
14875
14888
|
return false;
|
|
14876
14889
|
if (node.type !== AST_NODE_TYPES85.Identifier || !resolvesToGlobal(node))
|
|
14877
14890
|
return false;
|
|
14878
|
-
return
|
|
14891
|
+
return GLOBAL_RECEIVERS3.has(node.name) || node.name === "undefined";
|
|
14879
14892
|
}
|
|
14880
14893
|
return {
|
|
14881
14894
|
AssignmentExpression(node) {
|
|
@@ -16163,7 +16176,7 @@ var EQUALITY_OPERATORS = /* @__PURE__ */ new Set([
|
|
|
16163
16176
|
"==",
|
|
16164
16177
|
"==="
|
|
16165
16178
|
]);
|
|
16166
|
-
var
|
|
16179
|
+
var PRIMITIVE_FLAGS2 = ts30.TypeFlags.BigIntLike | ts30.TypeFlags.BooleanLike | ts30.TypeFlags.ESSymbolLike | ts30.TypeFlags.Never | ts30.TypeFlags.Null | ts30.TypeFlags.NumberLike | ts30.TypeFlags.StringLike | ts30.TypeFlags.Undefined | ts30.TypeFlags.Void;
|
|
16167
16180
|
function unwrapComparisonExpression(node) {
|
|
16168
16181
|
let current = unwrapExpression(node);
|
|
16169
16182
|
while (current.type === AST_NODE_TYPES90.ChainExpression) {
|
|
@@ -16217,7 +16230,7 @@ function typeMayContainObject(type, checker) {
|
|
|
16217
16230
|
if (type.isUnionOrIntersection()) {
|
|
16218
16231
|
return type.types.some((member3) => typeMayContainObject(member3, checker));
|
|
16219
16232
|
}
|
|
16220
|
-
if ((type.flags &
|
|
16233
|
+
if ((type.flags & PRIMITIVE_FLAGS2) !== 0) return false;
|
|
16221
16234
|
if ((type.flags & (ts30.TypeFlags.Any | ts30.TypeFlags.Unknown | ts30.TypeFlags.TypeParameter)) !== 0) {
|
|
16222
16235
|
return true;
|
|
16223
16236
|
}
|
|
@@ -33440,7 +33453,7 @@ import { ASTUtils as ASTUtils111, AST_NODE_TYPES as AST_NODE_TYPES165 } from "@t
|
|
|
33440
33453
|
import ts39 from "typescript";
|
|
33441
33454
|
|
|
33442
33455
|
// src/rules/_equivalent-zod-output-contracts.ts
|
|
33443
|
-
import { isPropertyReadonlyInType, isTupleTypeReference, isTypeReference as isTypeReference3 } from "ts-api-utils";
|
|
33456
|
+
import { isPropertyReadonlyInType, isTupleTypeReference as isTupleTypeReference2, isTypeReference as isTypeReference3 } from "ts-api-utils";
|
|
33444
33457
|
import ts37 from "typescript";
|
|
33445
33458
|
var MAX_CONTRACT_PAIRS = 128;
|
|
33446
33459
|
var MAX_UNION_MEMBERS = 16;
|
|
@@ -33469,8 +33482,8 @@ function seenPair(comparison2, left, right) {
|
|
|
33469
33482
|
function equivalentPair(comparison2, left, right) {
|
|
33470
33483
|
if (!mutuallyAssignable(comparison2.checker, left, right)) return false;
|
|
33471
33484
|
if (left.isUnion() || right.isUnion()) return equivalentUnions(comparison2, left, right);
|
|
33472
|
-
const leftContainer = comparison2.checker.isArrayType(left) ||
|
|
33473
|
-
const rightContainer = comparison2.checker.isArrayType(right) ||
|
|
33485
|
+
const leftContainer = comparison2.checker.isArrayType(left) || isTupleTypeReference2(left);
|
|
33486
|
+
const rightContainer = comparison2.checker.isArrayType(right) || isTupleTypeReference2(right);
|
|
33474
33487
|
if (leftContainer || rightContainer) return equivalentContainers(comparison2, left, right);
|
|
33475
33488
|
if (hasClassDeclaration(left) || hasClassDeclaration(right)) return false;
|
|
33476
33489
|
if (!objectLike(left) || !objectLike(right)) return false;
|
|
@@ -33500,8 +33513,8 @@ function queuePair(comparison2, left, right) {
|
|
|
33500
33513
|
}
|
|
33501
33514
|
function equivalentContainers(comparison2, left, right) {
|
|
33502
33515
|
if (!isTypeReference3(left) || !isTypeReference3(right)) return false;
|
|
33503
|
-
const leftTuple =
|
|
33504
|
-
const rightTuple =
|
|
33516
|
+
const leftTuple = isTupleTypeReference2(left);
|
|
33517
|
+
const rightTuple = isTupleTypeReference2(right);
|
|
33505
33518
|
if (leftTuple !== rightTuple) return false;
|
|
33506
33519
|
if (leftTuple && rightTuple && (left.target.readonly !== right.target.readonly || left.target.elementFlags.length !== right.target.elementFlags.length || left.target.elementFlags.some((flag, index) => flag !== right.target.elementFlags[index]))) return false;
|
|
33507
33520
|
const leftIndex = comparison2.checker.getIndexInfoOfType(left, ts37.IndexKind.Number);
|