@sarj/eslint-plugin 16.6.0 → 16.8.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 +168 -85
- package/dist/index.d.cts +19 -19
- package/dist/index.d.ts +19 -19
- package/dist/index.js +243 -160
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// package.json
|
|
2
2
|
var package_default = {
|
|
3
3
|
name: "@sarj/eslint-plugin",
|
|
4
|
-
version: "16.
|
|
4
|
+
version: "16.8.0",
|
|
5
5
|
packageManager: "npm@12.1.0",
|
|
6
6
|
description: "Custom ESLint rules for hypermodern TypeScript / React / Next.js projects",
|
|
7
7
|
type: "module",
|
|
@@ -419,8 +419,9 @@ function commentLineEnd(sourceText, start) {
|
|
|
419
419
|
}
|
|
420
420
|
|
|
421
421
|
// src/rules/require-explicit-contract-implementation.ts
|
|
422
|
+
var ESCAPED_CLASSES = /* @__PURE__ */ new WeakMap();
|
|
422
423
|
var REQUIRE_EXPLICIT_CONTRACT_IMPLEMENTATION_DOCUMENTATION = {
|
|
423
|
-
defaultLevel: "
|
|
424
|
+
defaultLevel: "error",
|
|
424
425
|
summary: "Require nominal inheritance when an injected abstract class is rejected by an instanceof guard.",
|
|
425
426
|
rationale: "A structurally assignable fake can still fail a constructor's nominal runtime guard. Pure structural interfaces do not require an implements clause.",
|
|
426
427
|
remediation: "Use an implementation inheriting the existing abstract class, or remove the nominal guard if the boundary is intentionally structural.",
|
|
@@ -428,8 +429,8 @@ var REQUIRE_EXPLICIT_CONTRACT_IMPLEMENTATION_DOCUMENTATION = {
|
|
|
428
429
|
autofix: "none",
|
|
429
430
|
limitations: [
|
|
430
431
|
"Requires direct construction of both owned consumer and collaborator classes, with a first-statement consumer constructor guard rejecting the exact parameter with if (!(parameter instanceof Contract)) throw.",
|
|
431
|
-
"The contract must resolve to an abstract class without decorators, unresolved ancestors, or custom computed static members in its resolved hierarchy.",
|
|
432
|
-
"Structural interfaces, non-rejecting branches, reassignment before the guard, casts, unresolved heritage, dynamic factories, explicit implementation constructors or initializers, modules referencing prototype-mutator members or assigning prototypes, and third-party classes are excluded."
|
|
432
|
+
"The contract must resolve to an abstract class without decorators, static blocks, unresolved ancestors, or custom computed static members in its resolved hierarchy. Escaped class constructors are checked across every owned module in the typed program.",
|
|
433
|
+
"Structural interfaces, non-rejecting branches, reassignment before the guard, casts, unresolved heritage, dynamic factories, implementation static blocks, explicit implementation constructors or initializers, involved modules referencing prototype-mutator members or assigning prototypes, escaped class constructors, and third-party classes are excluded."
|
|
433
434
|
],
|
|
434
435
|
examples: [
|
|
435
436
|
{
|
|
@@ -452,6 +453,115 @@ var REQUIRE_EXPLICIT_CONTRACT_IMPLEMENTATION_DOCUMENTATION = {
|
|
|
452
453
|
}
|
|
453
454
|
]
|
|
454
455
|
};
|
|
456
|
+
function hasPrototypeMutation(source) {
|
|
457
|
+
function visit(node) {
|
|
458
|
+
const member = memberName(node);
|
|
459
|
+
if (member === "setPrototypeOf" || member === "__proto__" || member === "hasInstance") return true;
|
|
460
|
+
if (ts.isBinaryExpression(node) && node.operatorToken.kind >= ts.SyntaxKind.FirstAssignment && node.operatorToken.kind <= ts.SyntaxKind.LastAssignment && memberName(node.left) === "prototype") return true;
|
|
461
|
+
return ts.forEachChild(node, visit);
|
|
462
|
+
}
|
|
463
|
+
return visit(source) === true;
|
|
464
|
+
}
|
|
465
|
+
function memberName(node) {
|
|
466
|
+
if (ts.isPropertyAccessExpression(node)) return node.name.text;
|
|
467
|
+
if (ts.isElementAccessExpression(node) && ts.isStringLiteralLike(node.argumentExpression)) return node.argumentExpression.text;
|
|
468
|
+
return null;
|
|
469
|
+
}
|
|
470
|
+
function ownedSource(source) {
|
|
471
|
+
return !source.isDeclarationFile && !/(?:^|[/\\])(?:node_modules|vendor|vendored|generated|dist)(?:[/\\])/u.test(source.fileName) && !isGeneratedFile(source.fileName, source.text);
|
|
472
|
+
}
|
|
473
|
+
function escapedClasses(program, checker) {
|
|
474
|
+
const cached = ESCAPED_CLASSES.get(program);
|
|
475
|
+
if (cached !== void 0) return cached;
|
|
476
|
+
const escaped = /* @__PURE__ */ new Set();
|
|
477
|
+
const namespaceValues = /* @__PURE__ */ new Map();
|
|
478
|
+
function visit(node) {
|
|
479
|
+
if (ts.isTypeNode(node) || ts.isImportDeclaration(node)) return;
|
|
480
|
+
if (ts.isIdentifier(node) || ts.isPropertyAccessExpression(node) || ts.isElementAccessExpression(node)) {
|
|
481
|
+
recordEscapedReference(checker, node, escaped, namespaceValues);
|
|
482
|
+
}
|
|
483
|
+
ts.forEachChild(node, visit);
|
|
484
|
+
}
|
|
485
|
+
for (const source of program.getSourceFiles()) if (ownedSource(source)) visit(source);
|
|
486
|
+
ESCAPED_CLASSES.set(program, escaped);
|
|
487
|
+
return escaped;
|
|
488
|
+
}
|
|
489
|
+
function recordEscapedReference(checker, node, escaped, namespaceValues) {
|
|
490
|
+
const symbol = canonicalSymbol(checker, node);
|
|
491
|
+
if (symbol !== void 0) {
|
|
492
|
+
let values = namespaceValues.get(symbol);
|
|
493
|
+
if (values === void 0) {
|
|
494
|
+
values = ownedClassValues(checker, symbol);
|
|
495
|
+
namespaceValues.set(symbol, values);
|
|
496
|
+
}
|
|
497
|
+
if (!namespacePrefix(symbol, node) && !safeClassReference(node)) for (const value of values) escaped.add(value);
|
|
498
|
+
}
|
|
499
|
+
if (ts.isElementAccessExpression(node) && !safeClassReference(node)) {
|
|
500
|
+
const receiver = canonicalSymbol(checker, node.expression) ?? checker.getTypeAtLocation(node.expression).getSymbol();
|
|
501
|
+
if (receiver !== void 0) for (const value of ownedClassValues(checker, receiver)) escaped.add(value);
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
function ownedClassValues(checker, original, seen = /* @__PURE__ */ new Set()) {
|
|
505
|
+
const symbol = original.flags & ts.SymbolFlags.Alias ? checker.getAliasedSymbol(original) : original;
|
|
506
|
+
const values = /* @__PURE__ */ new Set();
|
|
507
|
+
if (seen.has(symbol)) return values;
|
|
508
|
+
seen.add(symbol);
|
|
509
|
+
if (symbol.declarations?.some((declaration) => ts.isClassDeclaration(declaration) && ownedSource(declaration.getSourceFile()))) values.add(symbol);
|
|
510
|
+
if (symbol.declarations?.some((declaration) => (ts.isSourceFile(declaration) || ts.isModuleDeclaration(declaration)) && ownedSource(declaration.getSourceFile()))) {
|
|
511
|
+
for (const exported of checker.getExportsOfModule(symbol)) {
|
|
512
|
+
for (const value of ownedClassValues(checker, exported, seen)) values.add(value);
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
return values;
|
|
516
|
+
}
|
|
517
|
+
function safeClassReference(node) {
|
|
518
|
+
let reference = ts.isPropertyAccessExpression(node.parent) && node.parent.name === node ? node.parent : node;
|
|
519
|
+
while (ts.isParenthesizedExpression(reference.parent)) reference = reference.parent;
|
|
520
|
+
const parent = reference.parent;
|
|
521
|
+
return ts.isClassDeclaration(parent) && parent.name === reference || ts.isNewExpression(parent) && parent.expression === reference || ts.isExpressionWithTypeArguments(parent) && parent.expression === reference || ts.isBinaryExpression(parent) && parent.operatorToken.kind === ts.SyntaxKind.InstanceOfKeyword && parent.right === reference;
|
|
522
|
+
}
|
|
523
|
+
function namespacePrefix(symbol, node) {
|
|
524
|
+
const parent = node.parent;
|
|
525
|
+
const memberCall = (ts.isPropertyAccessExpression(parent) || ts.isElementAccessExpression(parent)) && ts.isCallExpression(parent.parent) && parent.parent.expression === parent;
|
|
526
|
+
return !symbol.declarations?.some(ts.isClassDeclaration) && (ts.isPropertyAccessExpression(parent) || ts.isElementAccessExpression(parent)) && parent.expression === node && !memberCall;
|
|
527
|
+
}
|
|
528
|
+
function closedNominalBoundary(program, checker, call, consumer, missing) {
|
|
529
|
+
const { implementation, contractSymbol } = missing;
|
|
530
|
+
const implementationSymbol = implementation.name === void 0 ? void 0 : canonicalSymbol(checker, implementation.name);
|
|
531
|
+
const consumerSymbol = consumer.name === void 0 ? void 0 : canonicalSymbol(checker, consumer.name);
|
|
532
|
+
if (implementationSymbol === void 0 || consumerSymbol === void 0) return false;
|
|
533
|
+
const contract = contractSymbol.declarations?.find(ts.isClassDeclaration);
|
|
534
|
+
if (contract === void 0) return false;
|
|
535
|
+
const targets = /* @__PURE__ */ new Set([consumerSymbol, ...classHierarchySymbols(checker, contract), ...classHierarchySymbols(checker, implementation)]);
|
|
536
|
+
const sources = /* @__PURE__ */ new Set([call.getSourceFile(), consumer.getSourceFile(), implementation.getSourceFile(), ...contractSymbol.declarations?.map((item) => item.getSourceFile()) ?? []]);
|
|
537
|
+
return ![...sources].some(hasPrototypeMutation) && ![...targets].some((target) => escapedClasses(program, checker).has(target));
|
|
538
|
+
}
|
|
539
|
+
function classHierarchySymbols(checker, declaration, seen = /* @__PURE__ */ new Set()) {
|
|
540
|
+
const symbol = declaration.name === void 0 ? void 0 : canonicalSymbol(checker, declaration.name);
|
|
541
|
+
if (symbol === void 0 || seen.has(symbol)) return seen;
|
|
542
|
+
seen.add(symbol);
|
|
543
|
+
for (const clause of declaration.heritageClauses ?? []) {
|
|
544
|
+
if (clause.token !== ts.SyntaxKind.ExtendsKeyword) continue;
|
|
545
|
+
for (const parent of clause.types) {
|
|
546
|
+
const ancestor = canonicalSymbol(checker, parent.expression)?.declarations?.find(ts.isClassDeclaration);
|
|
547
|
+
if (ancestor !== void 0) classHierarchySymbols(checker, ancestor, seen);
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
return seen;
|
|
551
|
+
}
|
|
552
|
+
function missingImplementation(checker, signature, parameter, call, argument) {
|
|
553
|
+
const parameterType = checker.getTypeOfSymbolAtLocation(parameter, call);
|
|
554
|
+
const contractType = behavioralContract(checker, parameterType);
|
|
555
|
+
if (contractType === null) return null;
|
|
556
|
+
const contractSymbol = contractType.getSymbol();
|
|
557
|
+
if (contractSymbol === void 0 || !hasNominalRejectionGuard(checker, signature, parameter, contractSymbol)) return null;
|
|
558
|
+
const actualType = checker.getTypeAtLocation(argument);
|
|
559
|
+
if (!checker.isTypeAssignableTo(actualType, contractType)) return null;
|
|
560
|
+
const implementation = ownedClass(checker, argument);
|
|
561
|
+
if (implementation === null) return null;
|
|
562
|
+
if (nominallyInherits(checker, implementation, contractSymbol, /* @__PURE__ */ new Set()) !== false) return null;
|
|
563
|
+
return { implementation, contractSymbol };
|
|
564
|
+
}
|
|
455
565
|
function behavioralContract(checker, type) {
|
|
456
566
|
if (type.isUnion()) {
|
|
457
567
|
const substantive = type.types.filter((member) => (member.flags & (ts.TypeFlags.Null | ts.TypeFlags.Undefined)) === 0);
|
|
@@ -476,23 +586,9 @@ function ownedClass(checker, expression) {
|
|
|
476
586
|
if (declaration === void 0 || declaration !== constructed || declaration.getSourceFile().isDeclarationFile || /(?:^|[/\\])(?:node_modules|vendor|generated)(?:[/\\])/u.test(declaration.getSourceFile().fileName)) return null;
|
|
477
587
|
return declaration;
|
|
478
588
|
}
|
|
479
|
-
function memberName(node) {
|
|
480
|
-
if (ts.isPropertyAccessExpression(node)) return node.name.text;
|
|
481
|
-
if (ts.isElementAccessExpression(node) && ts.isStringLiteralLike(node.argumentExpression)) return node.argumentExpression.text;
|
|
482
|
-
return null;
|
|
483
|
-
}
|
|
484
|
-
function hasPrototypeMutation(source) {
|
|
485
|
-
function visit(node) {
|
|
486
|
-
const member = memberName(node);
|
|
487
|
-
if (member === "setPrototypeOf" || member === "__proto__" || member === "hasInstance") return true;
|
|
488
|
-
if (ts.isBinaryExpression(node) && node.operatorToken.kind >= ts.SyntaxKind.FirstAssignment && node.operatorToken.kind <= ts.SyntaxKind.LastAssignment && memberName(node.left) === "prototype") return true;
|
|
489
|
-
return ts.forEachChild(node, visit);
|
|
490
|
-
}
|
|
491
|
-
return visit(source) === true;
|
|
492
|
-
}
|
|
493
589
|
function nominallyInherits(checker, declaration, target, seen) {
|
|
494
590
|
if (ts.canHaveDecorators(declaration) && ts.getDecorators(declaration)?.length) return null;
|
|
495
|
-
if (hasPrototypeMutation(declaration.getSourceFile()) || declaration.members.some((member) => ts.isConstructorDeclaration(member) || ts.isPropertyDeclaration(member) && member.initializer !== void 0)) return null;
|
|
591
|
+
if (hasPrototypeMutation(declaration.getSourceFile()) || declaration.members.some((member) => ts.isConstructorDeclaration(member) || ts.isClassStaticBlockDeclaration(member) || ts.isPropertyDeclaration(member) && member.initializer !== void 0)) return null;
|
|
496
592
|
const symbol = declaration.name === void 0 ? void 0 : canonicalSymbol(checker, declaration.name);
|
|
497
593
|
if (symbol !== void 0) {
|
|
498
594
|
if (seen.has(symbol)) return null;
|
|
@@ -507,10 +603,6 @@ function nominallyInherits(checker, declaration, target, seen) {
|
|
|
507
603
|
const inherited = parentSymbol.declarations?.find(ts.isClassDeclaration);
|
|
508
604
|
return inherited === void 0 ? null : nominallyInherits(checker, inherited, target, new Set(seen));
|
|
509
605
|
}
|
|
510
|
-
function canonicalSymbol(checker, node) {
|
|
511
|
-
const symbol = checker.getSymbolAtLocation(node);
|
|
512
|
-
return symbol === void 0 ? void 0 : (symbol.flags & ts.SymbolFlags.Alias) !== 0 ? checker.getAliasedSymbol(symbol) : symbol;
|
|
513
|
-
}
|
|
514
606
|
function hasNominalRejectionGuard(checker, signature, parameter, contract) {
|
|
515
607
|
const declaration = signature.getDeclaration();
|
|
516
608
|
if (declaration === void 0 || !ts.isConstructorDeclaration(declaration)) return false;
|
|
@@ -535,7 +627,7 @@ function alwaysThrows(statement) {
|
|
|
535
627
|
return ts.isThrowStatement(statement) || ts.isBlock(statement) && statement.statements.length === 1 && ts.isThrowStatement(statement.statements[0]);
|
|
536
628
|
}
|
|
537
629
|
function hasOrdinaryInstanceCheck(checker, declaration, seen) {
|
|
538
|
-
if (seen.has(declaration) || ts.getDecorators(declaration)?.length || hasPrototypeMutation(declaration.getSourceFile())) return false;
|
|
630
|
+
if (seen.has(declaration) || ts.getDecorators(declaration)?.length || hasPrototypeMutation(declaration.getSourceFile()) || declaration.members.some(ts.isClassStaticBlockDeclaration)) return false;
|
|
539
631
|
seen.add(declaration);
|
|
540
632
|
if (declaration.members.some((member) => member.name !== void 0 && ts.isComputedPropertyName(member.name) && ts.canHaveModifiers(member) && ts.getModifiers(member)?.some((modifier) => modifier.kind === ts.SyntaxKind.StaticKeyword))) return false;
|
|
541
633
|
for (const clause of declaration.heritageClauses ?? []) {
|
|
@@ -547,6 +639,10 @@ function hasOrdinaryInstanceCheck(checker, declaration, seen) {
|
|
|
547
639
|
}
|
|
548
640
|
return true;
|
|
549
641
|
}
|
|
642
|
+
function canonicalSymbol(checker, node) {
|
|
643
|
+
const symbol = checker.getSymbolAtLocation(node);
|
|
644
|
+
return symbol === void 0 ? void 0 : (symbol.flags & ts.SymbolFlags.Alias) !== 0 ? checker.getAliasedSymbol(symbol) : symbol;
|
|
645
|
+
}
|
|
550
646
|
var require_explicit_contract_implementation_default = createRule({
|
|
551
647
|
name: "require-explicit-contract-implementation",
|
|
552
648
|
documentation: REQUIRE_EXPLICIT_CONTRACT_IMPLEMENTATION_DOCUMENTATION,
|
|
@@ -576,22 +672,13 @@ var require_explicit_contract_implementation_default = createRule({
|
|
|
576
672
|
if (argument.type !== AST_NODE_TYPES.NewExpression) continue;
|
|
577
673
|
const parameter = parameters[index];
|
|
578
674
|
if (parameter === void 0) continue;
|
|
579
|
-
const parameterType = checker.getTypeOfSymbolAtLocation(parameter, tsNode);
|
|
580
|
-
const contractType = behavioralContract(checker, parameterType);
|
|
581
|
-
if (contractType === null) continue;
|
|
582
|
-
const contractSymbol = contractType.getSymbol();
|
|
583
|
-
if (contractSymbol === void 0 || !hasNominalRejectionGuard(checker, signature, parameter, contractSymbol)) continue;
|
|
584
675
|
const tsArgument = services.esTreeNodeToTSNodeMap.get(argument);
|
|
585
|
-
const
|
|
586
|
-
if (!
|
|
587
|
-
const implementation = ownedClass(checker, tsArgument);
|
|
588
|
-
if (implementation === null) continue;
|
|
589
|
-
const relationship = nominallyInherits(checker, implementation, contractSymbol, /* @__PURE__ */ new Set());
|
|
590
|
-
if (relationship !== false) continue;
|
|
676
|
+
const missing = missingImplementation(checker, signature, parameter, tsNode, tsArgument);
|
|
677
|
+
if (missing === null || !closedNominalBoundary(services.program, checker, tsNode, consumer, missing)) continue;
|
|
591
678
|
context.report({
|
|
592
679
|
node: argument,
|
|
593
680
|
messageId: "declareActualContract",
|
|
594
|
-
data: { implementation: implementation.name?.text ?? "class", contract: contractSymbol.getName() }
|
|
681
|
+
data: { implementation: missing.implementation.name?.text ?? "class", contract: missing.contractSymbol.getName() }
|
|
595
682
|
});
|
|
596
683
|
}
|
|
597
684
|
}
|
|
@@ -1431,7 +1518,7 @@ function abstractContractOperations(node, functionAliases) {
|
|
|
1431
1518
|
|
|
1432
1519
|
// src/rules/require-explicit-service-contract.ts
|
|
1433
1520
|
var REQUIRE_EXPLICIT_SERVICE_CONTRACT_DOCUMENTATION = {
|
|
1434
|
-
defaultLevel: "
|
|
1521
|
+
defaultLevel: "error",
|
|
1435
1522
|
summary: "Require explicit contracts for classes that invoke retained collaborators.",
|
|
1436
1523
|
rationale: "A one-operation service can orchestrate a collaborator without declaring the contract that callers consume and implementations and fakes satisfy.",
|
|
1437
1524
|
remediation: "Explicitly implement a focused interface or extend an abstract class covering the service operations. Export the contract only when its consumers need it.",
|
|
@@ -7440,7 +7527,7 @@ import {
|
|
|
7440
7527
|
} from "@typescript-eslint/utils";
|
|
7441
7528
|
import ts6 from "typescript";
|
|
7442
7529
|
var NO_JSON_STRINGIFY_OBJECT_EQUALITY_DOCUMENTATION = {
|
|
7443
|
-
defaultLevel: "
|
|
7530
|
+
defaultLevel: "error",
|
|
7444
7531
|
summary: "Do not use JSON serialization as structural object equality.",
|
|
7445
7532
|
rationale: "JSON text equality depends on property insertion order and serialization behavior, so semantically equal objects can compare unequal and distinct values can collapse together.",
|
|
7446
7533
|
remediation: "Compare an explicit domain projection structurally, or use a reviewed canonical serializer when JSON semantics are required.",
|
|
@@ -12674,7 +12761,7 @@ var TEST_MODULES = /* @__PURE__ */ new Set(["vitest", "@jest/globals", "bun:test
|
|
|
12674
12761
|
var TEST_NAMES2 = /* @__PURE__ */ new Set(["it", "test"]);
|
|
12675
12762
|
var MODIFIERS = /* @__PURE__ */ new Set(["only", "skip", "concurrent", "fails", "failing", "todo"]);
|
|
12676
12763
|
var NO_DUPLICATE_TEST_CASE_DOCUMENTATION = {
|
|
12677
|
-
defaultLevel: "
|
|
12764
|
+
defaultLevel: "error",
|
|
12678
12765
|
summary: "Report repeated literal rows in framework test.each or it.each tables.",
|
|
12679
12766
|
rationale: "Identical rows repeat the same inputs and expected values without exposing a distinct case. Accidental duplicates consume test time and hide a missing boundary vector.",
|
|
12680
12767
|
remediation: "Remove the accidental duplicate or replace it with the intended distinct boundary. Preserve intentional repeated or stateful scenarios with a local explanation; do not delete their coverage automatically.",
|
|
@@ -17552,7 +17639,7 @@ var OPERATIONAL_ROLES = /* @__PURE__ */ new Set([
|
|
|
17552
17639
|
]);
|
|
17553
17640
|
var MAX_ALIAS_DEPTH = 16;
|
|
17554
17641
|
var PREFER_NOMINAL_ID_TYPES_DOCUMENTATION = {
|
|
17555
|
-
defaultLevel: "
|
|
17642
|
+
defaultLevel: "error",
|
|
17556
17643
|
summary: "Distinguish identifier roles sharing primitive types at callable boundaries.",
|
|
17557
17644
|
rationale: "Two identifier roles represented by the same primitive accept each other's values, so swapped arguments survive type checking. Transparent aliases do not prevent this.",
|
|
17558
17645
|
remediation: "Introduce distinct branded identifier types at a validated domain boundary and use them in the callable contract. Keep wire representations primitive until validation; suppress a required external signature locally with a reason.",
|
|
@@ -17717,14 +17804,14 @@ var prefer_named_callback_domain_default = createRule({
|
|
|
17717
17804
|
// src/rules/prefer-named-complex-return-type.ts
|
|
17718
17805
|
import { AST_NODE_TYPES as AST_NODE_TYPES86 } from "@typescript-eslint/utils";
|
|
17719
17806
|
var PREFER_NAMED_COMPLEX_RETURN_TYPE_DOCUMENTATION = {
|
|
17720
|
-
defaultLevel: "
|
|
17807
|
+
defaultLevel: "error",
|
|
17721
17808
|
summary: "Prefer a named contract for structurally complex function return types.",
|
|
17722
17809
|
rationale: "A large inline return annotation hides a reusable domain concept and makes signatures difficult to scan.",
|
|
17723
17810
|
remediation: "Name the complex nested shape while preserving its generic wrappers and type parameters; reference the named contract from the return annotation.",
|
|
17724
17811
|
category: "maintainability",
|
|
17725
17812
|
limitations: [
|
|
17726
17813
|
"Only explicit object types with at least three members and unions with at least three object variants are reported.",
|
|
17727
|
-
"Any single-argument generic wrapper is traversed to find nested shapes, not assumed semantically transparent. Inferred return types are outside this rule; extraction is manual and must preserve locally bound type parameters."
|
|
17814
|
+
"Any single-argument generic wrapper is traversed to find nested shapes, not assumed semantically transparent. Inferred return types are outside this rule; extraction is manual and must preserve locally bound type parameters with generic named contracts. Types depending on polymorphic this or a local value query are excluded."
|
|
17728
17815
|
],
|
|
17729
17816
|
examples: [
|
|
17730
17817
|
{ id: "named-result", title: "Name a multi-state result", outcome: "no-match", files: [{ path: "src/queue.ts", source: "type ClaimResult = { state: 'idle' } | { state: 'waiting'; retryAt: number } | { state: 'claimed'; id: string }; export function claim(): ClaimResult { return { state: 'idle' }; }" }], focusPath: "src/queue.ts", expectedCount: 0, public: true },
|
|
@@ -17740,10 +17827,13 @@ function unwrap4(node) {
|
|
|
17740
17827
|
}
|
|
17741
17828
|
function report(context, node) {
|
|
17742
17829
|
const annotation = node.returnType?.typeAnnotation;
|
|
17743
|
-
if (annotation !== void 0 && isComplex(annotation)) {
|
|
17830
|
+
if (annotation !== void 0 && isComplex(annotation) && !hasValueDependency(annotation)) {
|
|
17744
17831
|
context.report({ node: annotation, messageId: "nameComplexReturnType" });
|
|
17745
17832
|
}
|
|
17746
17833
|
}
|
|
17834
|
+
function hasValueDependency(node) {
|
|
17835
|
+
return node.type === AST_NODE_TYPES86.TSThisType || node.type === AST_NODE_TYPES86.TSTypeQuery || forEachOwnAstChild(node, hasValueDependency);
|
|
17836
|
+
}
|
|
17747
17837
|
function isComplex(node) {
|
|
17748
17838
|
const type = unwrap4(node);
|
|
17749
17839
|
if (type.type === AST_NODE_TYPES86.TSTypeLiteral) return type.members.length >= 3;
|
|
@@ -19397,22 +19487,22 @@ var prefer_shared_zod_enum_default = createRule({
|
|
|
19397
19487
|
});
|
|
19398
19488
|
|
|
19399
19489
|
// src/rules/prefer-switch-for-repeated-equality.ts
|
|
19400
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES95 } from "@typescript-eslint/utils";
|
|
19490
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES95, ASTUtils as ASTUtils57 } from "@typescript-eslint/utils";
|
|
19401
19491
|
var PREFER_SWITCH_FOR_REPEATED_EQUALITY_DOCUMENTATION = {
|
|
19402
|
-
defaultLevel: "
|
|
19492
|
+
defaultLevel: "error",
|
|
19403
19493
|
summary: "Prefer switch over long if/else-if chains that compare one value for strict equality.",
|
|
19404
19494
|
rationale: "A switch makes finite dispatch cases visually uniform and easier to extend without duplicating the discriminant.",
|
|
19405
19495
|
remediation: "Replace three or more strict-equality branches over the same discriminant with a switch; keep if statements for ranges, guards, and heterogeneous predicates.",
|
|
19406
19496
|
category: "maintainability",
|
|
19407
19497
|
limitations: [
|
|
19408
19498
|
"Only direct if/else-if chains with at least three strict-equality tests are reported.",
|
|
19409
|
-
"The discriminant must be a
|
|
19410
|
-
"Case values
|
|
19499
|
+
"The discriminant must be a resolved lexical variable or parameter; unresolved globals, calls, getters, and indexed reads are excluded. Preserve branch scopes and break/continue targets when converting manually; no autofix is offered.",
|
|
19500
|
+
"Case values must be primitive literals. Member references and named constants are excluded because evaluating them can observe getters or mutate the selector. Generated sources are excluded.",
|
|
19411
19501
|
"The rule deliberately ignores compound predicates, loose equality, ranges, and chains that compare different discriminants."
|
|
19412
19502
|
],
|
|
19413
19503
|
examples: [
|
|
19414
19504
|
{ id: "switch-dispatch", title: "Make finite dispatch explicit", outcome: "no-match", files: [{ path: "src/render.ts", source: "switch (kind) { case 'a': return a(); case 'b': return b(); case 'c': return c(); default: return fallback(); }" }], focusPath: "src/render.ts", expectedCount: 0, public: true },
|
|
19415
|
-
{ id: "repeated-equality", title: "Avoid repeating the discriminant", outcome: "match", files: [{ path: "src/render.ts", source: "if (kind === 'a') return a(); else if (kind === 'b') return b(); else if (kind === 'c') return c();" }], focusPath: "src/render.ts", expectedCount: 1, public: true },
|
|
19505
|
+
{ id: "repeated-equality", title: "Avoid repeating the discriminant", outcome: "match", files: [{ path: "src/render.ts", source: "function render(kind: string) { if (kind === 'a') return a(); else if (kind === 'b') return b(); else if (kind === 'c') return c(); }" }], focusPath: "src/render.ts", expectedCount: 1, public: true },
|
|
19416
19506
|
{ id: "escaped-middle", scenarioId: "native-discriminant", title: "Use native identifier identity", outcome: "match", files: [{ path: "src/dispatch.ts", source: `function probe(kind){if(kind==='a')return 1;else if(\\u006bind==='b')return 2;else if(kind==='c')return 3;return 0;}
|
|
19417
19507
|
console.log(JSON.stringify(["a","b","c","d"].map(probe)));` }], focusPath: "src/dispatch.ts", expectedCount: 1, public: true },
|
|
19418
19508
|
{ id: "different-discriminants", scenarioId: "native-discriminant", title: "Use native identifier identity", outcome: "no-match", files: [{ path: "src/dispatch.ts", source: `function probe(kind){const other="other";if(kind==='a')return 1;else if(other==='b')return 2;else if(kind==='c')return 3;return 0;}
|
|
@@ -19428,10 +19518,7 @@ function discriminantName(test) {
|
|
|
19428
19518
|
return discriminant.type === AST_NODE_TYPES95.Identifier ? discriminant.name : null;
|
|
19429
19519
|
}
|
|
19430
19520
|
function isCaseValue(node) {
|
|
19431
|
-
|
|
19432
|
-
if (node.type === AST_NODE_TYPES95.Identifier) return /^[A-Z][A-Z0-9_]*$/u.test(node.name);
|
|
19433
|
-
if (node.type !== AST_NODE_TYPES95.MemberExpression || node.computed) return false;
|
|
19434
|
-
return node.property.type === AST_NODE_TYPES95.Identifier && (node.object.type === AST_NODE_TYPES95.Identifier || isCaseValue(node.object));
|
|
19521
|
+
return node.type === AST_NODE_TYPES95.Literal && !("regex" in node);
|
|
19435
19522
|
}
|
|
19436
19523
|
var prefer_switch_for_repeated_equality_default = createRule({
|
|
19437
19524
|
name: "prefer-switch-for-repeated-equality",
|
|
@@ -19446,11 +19533,16 @@ var prefer_switch_for_repeated_equality_default = createRule({
|
|
|
19446
19533
|
},
|
|
19447
19534
|
defaultOptions: [],
|
|
19448
19535
|
create(context) {
|
|
19536
|
+
if (isGeneratedFile(context.filename, context.sourceCode.text)) return {};
|
|
19449
19537
|
return {
|
|
19450
19538
|
IfStatement(node) {
|
|
19451
19539
|
if (node.parent.type === AST_NODE_TYPES95.IfStatement && node.parent.alternate === node) return;
|
|
19452
19540
|
const first = discriminantName(node.test);
|
|
19453
19541
|
if (first === null) return;
|
|
19542
|
+
const binding = ASTUtils57.findVariable(context.sourceCode.getScope(node), first);
|
|
19543
|
+
if (binding === null || binding.defs.length !== 1 || binding.scope.type === "global") return;
|
|
19544
|
+
const [definition] = binding.defs;
|
|
19545
|
+
if (definition?.type !== "Parameter" && definition?.type !== "Variable") return;
|
|
19454
19546
|
let count = 1;
|
|
19455
19547
|
let current = node.alternate;
|
|
19456
19548
|
while (current?.type === AST_NODE_TYPES95.IfStatement) {
|
|
@@ -19994,7 +20086,7 @@ function packageWorkspaceGlobs(parsed) {
|
|
|
19994
20086
|
}
|
|
19995
20087
|
|
|
19996
20088
|
// src/rules/prefer-server-actions.ts
|
|
19997
|
-
import { ASTUtils as
|
|
20089
|
+
import { ASTUtils as ASTUtils58 } from "@typescript-eslint/utils";
|
|
19998
20090
|
var PREFER_SERVER_ACTIONS_DOCUMENTATION = {
|
|
19999
20091
|
summary: "Prefer Next.js Server Actions over same-origin API mutations.",
|
|
20000
20092
|
rationale: "Server Actions can remove a hand-written internal API wrapper while retaining typed application calls. Client invocations still cross a network and serialization boundary.",
|
|
@@ -20027,7 +20119,7 @@ function resolveNode(node, context) {
|
|
|
20027
20119
|
node = node == null ? node : unwrapExpression(node);
|
|
20028
20120
|
if (!node) return null;
|
|
20029
20121
|
if (node.type !== "Identifier") return node;
|
|
20030
|
-
const variable =
|
|
20122
|
+
const variable = ASTUtils58.findVariable(getScope(context, node), node.name);
|
|
20031
20123
|
const definition = variable?.defs.length === 1 ? variable.defs[0] : void 0;
|
|
20032
20124
|
if (definition?.type !== "Variable" || definition.parent.kind !== "const" || definition.node.init === null || variable?.references.some((reference) => reference.isWrite() && reference.init !== true)) return node;
|
|
20033
20125
|
if (definition.node.init.type === "ObjectExpression" && variable?.references.some((reference) => reference.identifier !== node && reference.init !== true)) return node;
|
|
@@ -20036,7 +20128,7 @@ function resolveNode(node, context) {
|
|
|
20036
20128
|
function isAxiosClient(node, context, seen = /* @__PURE__ */ new Set()) {
|
|
20037
20129
|
if (node.type !== "Identifier" || seen.has(node)) return false;
|
|
20038
20130
|
seen.add(node);
|
|
20039
|
-
const variable =
|
|
20131
|
+
const variable = ASTUtils58.findVariable(getScope(context, node), node.name);
|
|
20040
20132
|
const definition = variable?.defs.length === 1 ? variable.defs[0] : void 0;
|
|
20041
20133
|
if (definition === void 0 || variable?.references.some((reference) => reference.isWrite() && reference.init !== true)) return false;
|
|
20042
20134
|
if (variable?.references.some((reference) => {
|
|
@@ -20120,10 +20212,10 @@ function isFunctionArgument(node, context) {
|
|
|
20120
20212
|
}
|
|
20121
20213
|
function getPropertyNode(objNode, propName2) {
|
|
20122
20214
|
if (!objNode || objNode.type !== "ObjectExpression") return null;
|
|
20123
|
-
if (objNode.properties.some((property) => property.type === "SpreadElement" ||
|
|
20215
|
+
if (objNode.properties.some((property) => property.type === "SpreadElement" || ASTUtils58.getPropertyName(property) === null)) return null;
|
|
20124
20216
|
for (const prop of [...objNode.properties].reverse()) {
|
|
20125
20217
|
if (prop.type !== "Property") continue;
|
|
20126
|
-
const keyName =
|
|
20218
|
+
const keyName = ASTUtils58.getPropertyName(prop);
|
|
20127
20219
|
if (keyName === propName2) {
|
|
20128
20220
|
if (prop.value.type === "AssignmentPattern" || prop.value.type === "ArrayPattern" || prop.value.type === "ObjectPattern") {
|
|
20129
20221
|
return null;
|
|
@@ -20247,7 +20339,7 @@ var prefer_server_actions_default = createRule({
|
|
|
20247
20339
|
});
|
|
20248
20340
|
|
|
20249
20341
|
// src/rules/prefer-whole-object-assertion.ts
|
|
20250
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES97, ASTUtils as
|
|
20342
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES97, ASTUtils as ASTUtils59 } from "@typescript-eslint/utils";
|
|
20251
20343
|
var MERGEABLE_MATCHERS = /* @__PURE__ */ new Set(["toBe", "toEqual", "toStrictEqual"]);
|
|
20252
20344
|
var SYNTHETIC_LITERAL_MATCHERS = /* @__PURE__ */ new Map([
|
|
20253
20345
|
["toBeNull", "null"]
|
|
@@ -20312,7 +20404,7 @@ function propertyAccess(node) {
|
|
|
20312
20404
|
const path = [];
|
|
20313
20405
|
let current = node;
|
|
20314
20406
|
while (current.type === AST_NODE_TYPES97.MemberExpression && !current.optional) {
|
|
20315
|
-
const name =
|
|
20407
|
+
const name = ASTUtils59.getPropertyName(current);
|
|
20316
20408
|
if (name === null || COLLECTION_PROPERTIES.has(name) || LITERAL_KEY_HAZARDS.has(name)) return null;
|
|
20317
20409
|
path.unshift(name);
|
|
20318
20410
|
current = unwrapExpression(current.object);
|
|
@@ -20459,7 +20551,7 @@ var prefer_whole_object_assertion_default = createRule({
|
|
|
20459
20551
|
const callee = unwrapExpression(call.callee);
|
|
20460
20552
|
const calleeReceiver = callee.type === AST_NODE_TYPES97.MemberExpression ? unwrapExpression(callee.object) : callee;
|
|
20461
20553
|
if (callee.type !== AST_NODE_TYPES97.MemberExpression) return null;
|
|
20462
|
-
const matcher =
|
|
20554
|
+
const matcher = ASTUtils59.getPropertyName(callee);
|
|
20463
20555
|
if (matcher === null) return null;
|
|
20464
20556
|
const expectCall = calleeReceiver;
|
|
20465
20557
|
const expectCallee = expectCall.type === AST_NODE_TYPES97.CallExpression ? unwrapExpression(expectCall.callee) : null;
|
|
@@ -20489,7 +20581,7 @@ var prefer_whole_object_assertion_default = createRule({
|
|
|
20489
20581
|
return assertionExpectation(statement, call, receiver, key, matcher);
|
|
20490
20582
|
}
|
|
20491
20583
|
function isTestExpect(callee) {
|
|
20492
|
-
const variable =
|
|
20584
|
+
const variable = ASTUtils59.findVariable(sourceCode.getScope(callee), callee.name);
|
|
20493
20585
|
if (variable !== null && variable.defs.some((definition) => {
|
|
20494
20586
|
if (definition.node.type !== AST_NODE_TYPES97.ImportSpecifier) return true;
|
|
20495
20587
|
const declaration = definition.node.parent;
|
|
@@ -20532,7 +20624,7 @@ var prefer_whole_object_assertion_default = createRule({
|
|
|
20532
20624
|
});
|
|
20533
20625
|
|
|
20534
20626
|
// src/rules/repeated-static-call-cases.ts
|
|
20535
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES98, ASTUtils as
|
|
20627
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES98, ASTUtils as ASTUtils60 } from "@typescript-eslint/utils";
|
|
20536
20628
|
var REPEATED_STATIC_CALL_CASES_DOCUMENTATION = {
|
|
20537
20629
|
summary: "Review three or more consecutive static-input call assertions as potential named cases.",
|
|
20538
20630
|
rationale: "Copy-pasted cases obscure the input table, and a thrown assertion can stop later cases from being reported.",
|
|
@@ -20553,7 +20645,7 @@ var EXPECT_MODIFIERS = /* @__PURE__ */ new Set(["not", "rejects", "resolves"]);
|
|
|
20553
20645
|
var SNAPSHOT_MATCHERS = /snapshot/iu;
|
|
20554
20646
|
var MIN_CASES2 = 3;
|
|
20555
20647
|
function importedName6(identifier, context, modules) {
|
|
20556
|
-
const variable =
|
|
20648
|
+
const variable = ASTUtils60.findVariable(context.sourceCode.getScope(identifier), identifier.name);
|
|
20557
20649
|
if (variable === null || variable.defs.length === 0) return identifier.name;
|
|
20558
20650
|
for (const definition of variable.defs) {
|
|
20559
20651
|
if (definition.node.type !== AST_NODE_TYPES98.ImportSpecifier) continue;
|
|
@@ -20575,7 +20667,7 @@ function testRoot2(callee) {
|
|
|
20575
20667
|
callee = unwrapExpression(callee);
|
|
20576
20668
|
if (callee.type === AST_NODE_TYPES98.Identifier) return callee;
|
|
20577
20669
|
if (callee.type !== AST_NODE_TYPES98.MemberExpression) return null;
|
|
20578
|
-
const modifier =
|
|
20670
|
+
const modifier = ASTUtils60.getPropertyName(callee);
|
|
20579
20671
|
return modifier !== null && TEST_MODIFIERS5.has(modifier) ? testRoot2(callee.object) : null;
|
|
20580
20672
|
}
|
|
20581
20673
|
function isStatic(input) {
|
|
@@ -20621,8 +20713,8 @@ function assertionShape(statement, context, callback) {
|
|
|
20621
20713
|
const matcherCall = unwrapExpression(statement.expression);
|
|
20622
20714
|
if (matcherCall.type !== AST_NODE_TYPES98.CallExpression) return null;
|
|
20623
20715
|
const matcherCallee = unwrapExpression(matcherCall.callee);
|
|
20624
|
-
if (matcherCallee.type !== AST_NODE_TYPES98.MemberExpression ||
|
|
20625
|
-
const matcher =
|
|
20716
|
+
if (matcherCallee.type !== AST_NODE_TYPES98.MemberExpression || ASTUtils60.getPropertyName(matcherCallee) === null || matcherCall.arguments.length !== 1) return null;
|
|
20717
|
+
const matcher = ASTUtils60.getPropertyName(matcherCallee) ?? "";
|
|
20626
20718
|
if (SNAPSHOT_MATCHERS.test(matcher)) return null;
|
|
20627
20719
|
const chain = expectCallFromMatcher(matcherCallee);
|
|
20628
20720
|
const expectCallee = chain === null ? null : unwrapExpression(chain.call.callee);
|
|
@@ -20632,7 +20724,7 @@ function assertionShape(statement, context, callback) {
|
|
|
20632
20724
|
const observedCallee = observed?.type === AST_NODE_TYPES98.CallExpression ? unwrapExpression(observed.callee) : null;
|
|
20633
20725
|
if (observed?.type !== AST_NODE_TYPES98.CallExpression || observedCallee?.type !== AST_NODE_TYPES98.Identifier || observed.arguments.length === 0 || observed.arguments.some((arg) => arg.type === AST_NODE_TYPES98.SpreadElement || !isStatic(arg)) || expected?.type === AST_NODE_TYPES98.SpreadElement || expected === void 0 || !isStatic(expected)) return null;
|
|
20634
20726
|
const skeleton = `${observedCallee.name}/${observed.arguments.map((item) => staticShape(item)).join(",")}/${chain.modifiers.join(".")}/${matcher}/${staticShape(expected)}`;
|
|
20635
|
-
const binding =
|
|
20727
|
+
const binding = ASTUtils60.findVariable(context.sourceCode.getScope(observedCallee), observedCallee.name);
|
|
20636
20728
|
if (binding?.defs.some(
|
|
20637
20729
|
(definition) => definition.node.range[0] >= callback.range[0] && definition.node.range[1] <= callback.range[1]
|
|
20638
20730
|
)) return null;
|
|
@@ -20643,7 +20735,7 @@ function expectCallFromMatcher(node) {
|
|
|
20643
20735
|
const modifiers = [];
|
|
20644
20736
|
let receiver = node.object;
|
|
20645
20737
|
while (receiver.type === AST_NODE_TYPES98.MemberExpression) {
|
|
20646
|
-
const modifier =
|
|
20738
|
+
const modifier = ASTUtils60.getPropertyName(receiver);
|
|
20647
20739
|
if (modifier === null || !EXPECT_MODIFIERS.has(modifier)) return null;
|
|
20648
20740
|
modifiers.unshift(modifier);
|
|
20649
20741
|
receiver = receiver.object;
|
|
@@ -20719,7 +20811,7 @@ var repeated_static_call_cases_default = createRule({
|
|
|
20719
20811
|
});
|
|
20720
20812
|
|
|
20721
20813
|
// src/rules/prefer-zod-infer.ts
|
|
20722
|
-
import { ASTUtils as
|
|
20814
|
+
import { ASTUtils as ASTUtils61, AST_NODE_TYPES as AST_NODE_TYPES99 } from "@typescript-eslint/utils";
|
|
20723
20815
|
var PREFER_ZOD_INFER_DOCUMENTATION = {
|
|
20724
20816
|
summary: "Derive a type from its Zod schema with `z.infer` instead of hand-writing a twin declaration beside it.",
|
|
20725
20817
|
rationale: "A derived type stays synchronized when the runtime schema changes.",
|
|
@@ -21037,7 +21129,7 @@ function twinCallChain(node, zodNamespaces) {
|
|
|
21037
21129
|
while (current.type === AST_NODE_TYPES99.CallExpression) {
|
|
21038
21130
|
const callee = unwrapExpression(current.callee);
|
|
21039
21131
|
const calleeReceiver = callee.type === AST_NODE_TYPES99.MemberExpression ? unwrapExpression(callee.object) : callee;
|
|
21040
|
-
if (callee.type !== AST_NODE_TYPES99.MemberExpression ||
|
|
21132
|
+
if (callee.type !== AST_NODE_TYPES99.MemberExpression || ASTUtils61.getPropertyName(callee) === null) {
|
|
21041
21133
|
return null;
|
|
21042
21134
|
}
|
|
21043
21135
|
chain.push(current);
|
|
@@ -21050,7 +21142,7 @@ function twinCallChain(node, zodNamespaces) {
|
|
|
21050
21142
|
}
|
|
21051
21143
|
function twinMethodName(call) {
|
|
21052
21144
|
const callee = unwrapExpression(call.callee);
|
|
21053
|
-
return callee.type === AST_NODE_TYPES99.MemberExpression &&
|
|
21145
|
+
return callee.type === AST_NODE_TYPES99.MemberExpression && ASTUtils61.getPropertyName(callee) !== null ? ASTUtils61.getPropertyName(callee) ?? "" : "";
|
|
21054
21146
|
}
|
|
21055
21147
|
function twinSchemaFields(initializer, zodNamespaces) {
|
|
21056
21148
|
const chain = twinCallChain(initializer, zodNamespaces);
|
|
@@ -21065,7 +21157,7 @@ function twinSchemaFields(initializer, zodNamespaces) {
|
|
|
21065
21157
|
const fields = /* @__PURE__ */ new Map();
|
|
21066
21158
|
for (const property of shape.properties) {
|
|
21067
21159
|
if (property.type !== AST_NODE_TYPES99.Property) return null;
|
|
21068
|
-
const name =
|
|
21160
|
+
const name = ASTUtils61.getPropertyName(property);
|
|
21069
21161
|
if (name === null) return null;
|
|
21070
21162
|
fields.set(name, twinSchemaField(property.value, zodNamespaces));
|
|
21071
21163
|
}
|
|
@@ -21079,16 +21171,16 @@ function twinSchemaField(node, zodNamespaces) {
|
|
|
21079
21171
|
while (current.type === AST_NODE_TYPES99.CallExpression) {
|
|
21080
21172
|
const callee = unwrapExpression(current.callee);
|
|
21081
21173
|
const calleeReceiver = callee.type === AST_NODE_TYPES99.MemberExpression ? unwrapExpression(callee.object) : callee;
|
|
21082
|
-
if (callee.type !== AST_NODE_TYPES99.MemberExpression ||
|
|
21174
|
+
if (callee.type !== AST_NODE_TYPES99.MemberExpression || ASTUtils61.getPropertyName(callee) === null) {
|
|
21083
21175
|
break;
|
|
21084
21176
|
}
|
|
21085
21177
|
const receiver = calleeReceiver;
|
|
21086
21178
|
if (receiver.type === AST_NODE_TYPES99.Identifier && zodNamespaces.has(receiver.name)) {
|
|
21087
|
-
leaf =
|
|
21179
|
+
leaf = ASTUtils61.getPropertyName(callee) ?? "";
|
|
21088
21180
|
leafCall = current;
|
|
21089
21181
|
break;
|
|
21090
21182
|
}
|
|
21091
|
-
modifiers.push(
|
|
21183
|
+
modifiers.push(ASTUtils61.getPropertyName(callee) ?? "");
|
|
21092
21184
|
current = receiver;
|
|
21093
21185
|
}
|
|
21094
21186
|
return {
|
|
@@ -21291,7 +21383,7 @@ var prefer_zod_infer_default = createRule({
|
|
|
21291
21383
|
},
|
|
21292
21384
|
/** Records `XSchema.transform(...)` and equivalent module-level reshaping. */
|
|
21293
21385
|
"MemberExpression"(node) {
|
|
21294
|
-
if (node.object.type === AST_NODE_TYPES99.Identifier &&
|
|
21386
|
+
if (node.object.type === AST_NODE_TYPES99.Identifier && ASTUtils61.getPropertyName(node) !== null && isPreferZodInferModuleReshaper(ASTUtils61.getPropertyName(node) ?? "")) {
|
|
21295
21387
|
reshapedSchemaNames.add(node.object.name);
|
|
21296
21388
|
}
|
|
21297
21389
|
},
|
|
@@ -21448,7 +21540,7 @@ function staticFieldName(key) {
|
|
|
21448
21540
|
}
|
|
21449
21541
|
|
|
21450
21542
|
// src/rules/named-child-schema-type.ts
|
|
21451
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES100, ASTUtils as
|
|
21543
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES100, ASTUtils as ASTUtils62 } from "@typescript-eslint/utils";
|
|
21452
21544
|
var UNRESOLVED_TYPE_NODES = /* @__PURE__ */ new Set([
|
|
21453
21545
|
AST_NODE_TYPES100.TSTypeQuery,
|
|
21454
21546
|
AST_NODE_TYPES100.TSImportType,
|
|
@@ -21457,17 +21549,17 @@ var UNRESOLVED_TYPE_NODES = /* @__PURE__ */ new Set([
|
|
|
21457
21549
|
AST_NODE_TYPES100.TSUnknownKeyword
|
|
21458
21550
|
]);
|
|
21459
21551
|
var NAMED_CHILD_SCHEMA_TYPE_DOCUMENTATION = {
|
|
21460
|
-
defaultLevel: "
|
|
21552
|
+
defaultLevel: "error",
|
|
21461
21553
|
summary: "Reference a named Zod record child's complete schema type instead of repeating its explicit annotation.",
|
|
21462
21554
|
rationale: "Repeating a child schema's generic contract creates a second maintained declaration even though the record already uses that child at runtime.",
|
|
21463
|
-
remediation: "Replace only the matching record type argument with `typeof ChildSchema
|
|
21555
|
+
remediation: "Replace only the matching record type argument with `typeof ChildSchema`, or share one explicit named schema type alias between child and record to retain an independently named public contract. Keep the outer annotation required by isolatedDeclarations and every runtime schema operation.",
|
|
21464
21556
|
category: "maintainability",
|
|
21465
21557
|
autofix: "none",
|
|
21466
21558
|
limitations: [
|
|
21467
21559
|
"Only direct module-level const z.record calls with two arguments, a ZodRecord annotation, and an earlier local const child with a complete explicit Zod type are inspected.",
|
|
21468
21560
|
"The entire generic child annotation must match token for token; input/output, defaults, transforms, readonly modifiers and brands are never compared by output shape alone.",
|
|
21469
21561
|
"Bare leaf types, broad ZodType constraints, type queries, imported or unqualified type references, annotation cycles, comments on the repeated argument, mutable bindings and generated files are excluded.",
|
|
21470
|
-
"Import aliases and namespace imports resolve through scope bindings. Independent public contract pins
|
|
21562
|
+
"Import aliases and namespace imports resolve through scope bindings. Independent public contract pins can use one shared named type alias or an exact reasoned suppression; runtime validation and outer annotations are preserved."
|
|
21471
21563
|
],
|
|
21472
21564
|
examples: [
|
|
21473
21565
|
{ id: "named-child", title: "Reference the named child contract", outcome: "no-match", files: [{ path: "src/record.ts", source: 'import { z } from "zod"; const KeySchema: z.ZodEnum<{ a: "a"; b: "b" }> = z.enum(["a", "b"]); export const RecordSchema: z.ZodRecord<typeof KeySchema, z.ZodString> = z.record(KeySchema, z.string());' }], focusPath: "src/record.ts", expectedCount: 0, public: true },
|
|
@@ -21486,14 +21578,14 @@ var named_child_schema_type_default = createRule({
|
|
|
21486
21578
|
type: "suggestion",
|
|
21487
21579
|
docs: { description: NAMED_CHILD_SCHEMA_TYPE_DOCUMENTATION.summary },
|
|
21488
21580
|
schema: [],
|
|
21489
|
-
messages: { namedChildType: "Use `typeof {{name}}` for this exact child contract; keep the outer schema annotation and runtime operations." }
|
|
21581
|
+
messages: { namedChildType: "Use `typeof {{name}}` or one shared named type alias for this exact child contract; keep the outer schema annotation and runtime operations." }
|
|
21490
21582
|
},
|
|
21491
21583
|
defaultOptions: [],
|
|
21492
21584
|
create(context) {
|
|
21493
21585
|
const source = context.sourceCode;
|
|
21494
21586
|
if (isGeneratedFile(context.filename, source.text)) return {};
|
|
21495
21587
|
const namespaces = /* @__PURE__ */ new Set();
|
|
21496
|
-
const bindingOf = (node) =>
|
|
21588
|
+
const bindingOf = (node) => ASTUtils62.findVariable(source.getScope(node), node.name);
|
|
21497
21589
|
function namespaceOf(type) {
|
|
21498
21590
|
if (type.typeName.type !== AST_NODE_TYPES100.TSQualifiedName || type.typeName.left.type !== AST_NODE_TYPES100.Identifier) return null;
|
|
21499
21591
|
const binding = bindingOf(type.typeName.left);
|
|
@@ -21537,7 +21629,7 @@ var named_child_schema_type_default = createRule({
|
|
|
21537
21629
|
VariableDeclarator(node) {
|
|
21538
21630
|
if (!isModuleConst(node) || node.id.type !== AST_NODE_TYPES100.Identifier || node.init?.type !== AST_NODE_TYPES100.CallExpression) return;
|
|
21539
21631
|
const call = node.init;
|
|
21540
|
-
if (call.arguments.length !== 2 || call.callee.type !== AST_NODE_TYPES100.MemberExpression || call.callee.object.type !== AST_NODE_TYPES100.Identifier ||
|
|
21632
|
+
if (call.arguments.length !== 2 || call.callee.type !== AST_NODE_TYPES100.MemberExpression || call.callee.object.type !== AST_NODE_TYPES100.Identifier || ASTUtils62.getPropertyName(call.callee) !== "record") return;
|
|
21541
21633
|
const annotation = node.id.typeAnnotation?.typeAnnotation;
|
|
21542
21634
|
if (annotation?.type !== AST_NODE_TYPES100.TSTypeReference || annotation.typeName.type !== AST_NODE_TYPES100.TSQualifiedName || annotation.typeName.right.name !== "ZodRecord") return;
|
|
21543
21635
|
const namespace = namespaceOf(annotation);
|
|
@@ -21553,7 +21645,7 @@ var named_child_schema_type_default = createRule({
|
|
|
21553
21645
|
|
|
21554
21646
|
// src/rules/prefer-zod-parse-output-type.ts
|
|
21555
21647
|
import {
|
|
21556
|
-
ASTUtils as
|
|
21648
|
+
ASTUtils as ASTUtils63,
|
|
21557
21649
|
AST_NODE_TYPES as AST_NODE_TYPES101,
|
|
21558
21650
|
ESLintUtils as ESLintUtils14
|
|
21559
21651
|
} from "@typescript-eslint/utils";
|
|
@@ -21623,11 +21715,11 @@ function isLocalZodObjectSchema(node, namespaces) {
|
|
|
21623
21715
|
while (current.type === AST_NODE_TYPES101.CallExpression) {
|
|
21624
21716
|
const callee = unwrapExpression(current.callee);
|
|
21625
21717
|
const calleeReceiver = callee.type === AST_NODE_TYPES101.MemberExpression ? unwrapExpression(callee.object) : callee;
|
|
21626
|
-
if (callee.type !== AST_NODE_TYPES101.MemberExpression ||
|
|
21718
|
+
if (callee.type !== AST_NODE_TYPES101.MemberExpression || ASTUtils63.getPropertyName(callee) === null) {
|
|
21627
21719
|
return false;
|
|
21628
21720
|
}
|
|
21629
21721
|
if (calleeReceiver.type === AST_NODE_TYPES101.Identifier) {
|
|
21630
|
-
return namespaces.has(calleeReceiver.name) && ((
|
|
21722
|
+
return namespaces.has(calleeReceiver.name) && ((ASTUtils63.getPropertyName(callee) ?? "") === "object" || (ASTUtils63.getPropertyName(callee) ?? "") === "strictObject");
|
|
21631
21723
|
}
|
|
21632
21724
|
current = calleeReceiver;
|
|
21633
21725
|
}
|
|
@@ -21636,10 +21728,10 @@ function isLocalZodObjectSchema(node, namespaces) {
|
|
|
21636
21728
|
function zodParseCall(node) {
|
|
21637
21729
|
const callee = unwrapExpression(node.callee);
|
|
21638
21730
|
const calleeReceiver = callee.type === AST_NODE_TYPES101.MemberExpression ? unwrapExpression(callee.object) : callee;
|
|
21639
|
-
if (callee.type !== AST_NODE_TYPES101.MemberExpression || calleeReceiver.type !== AST_NODE_TYPES101.Identifier ||
|
|
21731
|
+
if (callee.type !== AST_NODE_TYPES101.MemberExpression || calleeReceiver.type !== AST_NODE_TYPES101.Identifier || ASTUtils63.getPropertyName(callee) === null) {
|
|
21640
21732
|
return null;
|
|
21641
21733
|
}
|
|
21642
|
-
const method =
|
|
21734
|
+
const method = ASTUtils63.getPropertyName(callee);
|
|
21643
21735
|
if (method !== "parse" && method !== "safeParse") return null;
|
|
21644
21736
|
return {
|
|
21645
21737
|
call: node,
|
|
@@ -21681,7 +21773,7 @@ function localParseReturnCandidates(node, sourceCode) {
|
|
|
21681
21773
|
for (const reference of variable.references) {
|
|
21682
21774
|
const identifier = reference.identifier;
|
|
21683
21775
|
const parent = identifier.parent;
|
|
21684
|
-
const output = parsed.method === "parse" ? identifier : parent.type === AST_NODE_TYPES101.MemberExpression && parent.object === identifier &&
|
|
21776
|
+
const output = parsed.method === "parse" ? identifier : parent.type === AST_NODE_TYPES101.MemberExpression && parent.object === identifier && ASTUtils63.getPropertyName(parent) !== null && (ASTUtils63.getPropertyName(parent) ?? "") === "data" ? parent : null;
|
|
21685
21777
|
if (output === null) continue;
|
|
21686
21778
|
const candidate2 = returnedOutputCandidate(parsed, output);
|
|
21687
21779
|
if (candidate2 !== null) candidates.push(candidate2);
|
|
@@ -22064,7 +22156,7 @@ var require_assert_never_default = createRule({
|
|
|
22064
22156
|
});
|
|
22065
22157
|
|
|
22066
22158
|
// src/rules/require-fetch-timeout.ts
|
|
22067
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES103, ASTUtils as
|
|
22159
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES103, ASTUtils as ASTUtils64 } from "@typescript-eslint/utils";
|
|
22068
22160
|
var REQUIRE_FETCH_TIMEOUT_DOCUMENTATION = {
|
|
22069
22161
|
summary: "Require an explicit abort signal on locally analyzable global fetch calls.",
|
|
22070
22162
|
rationale: "An unbounded request can occupy work indefinitely when an upstream stalls.",
|
|
@@ -22148,7 +22240,7 @@ var require_fetch_timeout_default = createRule({
|
|
|
22148
22240
|
}
|
|
22149
22241
|
function resolvesToGlobal(identifier) {
|
|
22150
22242
|
const scope = context.sourceCode.getScope(identifier);
|
|
22151
|
-
const variable =
|
|
22243
|
+
const variable = ASTUtils64.findVariable(scope, identifier.name);
|
|
22152
22244
|
return variable === null || variable.defs.length === 0;
|
|
22153
22245
|
}
|
|
22154
22246
|
function isGlobalFetchCall2(callee) {
|
|
@@ -22158,7 +22250,7 @@ var require_fetch_timeout_default = createRule({
|
|
|
22158
22250
|
return callee.type === AST_NODE_TYPES103.MemberExpression && !callee.computed && callee.property.type === AST_NODE_TYPES103.Identifier && callee.property.name === "fetch" && callee.object.type === AST_NODE_TYPES103.Identifier && GLOBAL_OBJECTS2.has(callee.object.name) && resolvesToGlobal(callee.object);
|
|
22159
22251
|
}
|
|
22160
22252
|
function localConstInitProvablyLacksSignal(identifier) {
|
|
22161
|
-
const variable =
|
|
22253
|
+
const variable = ASTUtils64.findVariable(
|
|
22162
22254
|
context.sourceCode.getScope(identifier),
|
|
22163
22255
|
identifier.name
|
|
22164
22256
|
);
|
|
@@ -22180,7 +22272,7 @@ var require_fetch_timeout_default = createRule({
|
|
|
22180
22272
|
function isForwardedRequest(argument) {
|
|
22181
22273
|
let value = argument;
|
|
22182
22274
|
if (value.type === AST_NODE_TYPES103.Identifier) {
|
|
22183
|
-
const binding =
|
|
22275
|
+
const binding = ASTUtils64.findVariable(context.sourceCode.getScope(value), value.name);
|
|
22184
22276
|
const definition = binding?.defs.length === 1 ? binding.defs[0] : void 0;
|
|
22185
22277
|
if (definition?.type !== "Variable" || definition.parent.kind !== "const" || definition.node.init === null || binding?.references.some((reference) => reference.isWrite() && reference.init !== true)) return false;
|
|
22186
22278
|
value = definition.node.init;
|
|
@@ -22208,15 +22300,15 @@ var require_fetch_timeout_default = createRule({
|
|
|
22208
22300
|
// src/rules/require-interface-for-exported-class.ts
|
|
22209
22301
|
import { AST_NODE_TYPES as AST_NODE_TYPES104 } from "@typescript-eslint/utils";
|
|
22210
22302
|
var REQUIRE_INTERFACE_FOR_EXPORTED_CLASS_DOCUMENTATION = {
|
|
22211
|
-
defaultLevel: "
|
|
22303
|
+
defaultLevel: "error",
|
|
22212
22304
|
summary: "Require exported concrete classes with public behavior to declare a contract.",
|
|
22213
22305
|
rationale: "An explicit contract names the intended public capability separately from implementation details. TypeScript already supports structural compatibility; this is an architecture policy, not a prerequisite for substitution.",
|
|
22214
22306
|
remediation: "Declare a focused interface and add an implements clause, or inherit from an intentional base contract.",
|
|
22215
22307
|
category: "architecture",
|
|
22216
22308
|
limitations: [
|
|
22217
22309
|
"JavaScript files are excluded because implements is TypeScript syntax; imported framework base contracts still require manual policy review.",
|
|
22218
|
-
"An exported injected service may also receive require-port-for-service:
|
|
22219
|
-
"The
|
|
22310
|
+
"An exported injected service may also receive require-port-for-service: the two diagnostics intentionally enforce distinct service-boundary and general exported-contract policy scopes.",
|
|
22311
|
+
"The rule checks module-level class declarations and direct class-expression values exported directly, through local export specifiers, or through a default identifier; re-exports and expressions wrapped in other calls require review.",
|
|
22220
22312
|
"An extends clause satisfies the contract only when its target is a locally declared abstract class; imported base-class contracts require an explicit implements clause.",
|
|
22221
22313
|
"Static factories and data-only classes without public instance methods are outside the contract requirement."
|
|
22222
22314
|
],
|
|
@@ -22355,7 +22447,7 @@ function exportedClasses(program, classes) {
|
|
|
22355
22447
|
}
|
|
22356
22448
|
|
|
22357
22449
|
// src/rules/require-sql-access-class.ts
|
|
22358
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES105, ASTUtils as
|
|
22450
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES105, ASTUtils as ASTUtils65 } from "@typescript-eslint/utils";
|
|
22359
22451
|
var DIRECT_EXECUTION_METHODS = /* @__PURE__ */ new Set([
|
|
22360
22452
|
"all",
|
|
22361
22453
|
"batch",
|
|
@@ -22462,7 +22554,7 @@ function databaseReceiver(node) {
|
|
|
22462
22554
|
if (node.type === AST_NODE_TYPES105.Identifier)
|
|
22463
22555
|
return DATABASE_NAMES.test(node.name);
|
|
22464
22556
|
if (node.type !== AST_NODE_TYPES105.MemberExpression) return false;
|
|
22465
|
-
const name =
|
|
22557
|
+
const name = ASTUtils65.getPropertyName(node);
|
|
22466
22558
|
return name === "DB" || name !== null && DATABASE_NAMES.test(name);
|
|
22467
22559
|
}
|
|
22468
22560
|
function databaseRootMember(node) {
|
|
@@ -22480,7 +22572,7 @@ function databaseRootMember(node) {
|
|
|
22480
22572
|
}
|
|
22481
22573
|
if (current.type === AST_NODE_TYPES105.MemberExpression) {
|
|
22482
22574
|
if (current.object.type === AST_NODE_TYPES105.ThisExpression)
|
|
22483
|
-
return
|
|
22575
|
+
return ASTUtils65.getPropertyName(current);
|
|
22484
22576
|
current = current.object;
|
|
22485
22577
|
continue;
|
|
22486
22578
|
}
|
|
@@ -22501,7 +22593,7 @@ function expressionHasDatabaseMarker(node) {
|
|
|
22501
22593
|
continue;
|
|
22502
22594
|
}
|
|
22503
22595
|
if (current.type === AST_NODE_TYPES105.MemberExpression) {
|
|
22504
|
-
const name =
|
|
22596
|
+
const name = ASTUtils65.getPropertyName(current);
|
|
22505
22597
|
if (name === "DB" || name !== null && DATABASE_NAMES.test(name))
|
|
22506
22598
|
return true;
|
|
22507
22599
|
current = current.object;
|
|
@@ -22520,7 +22612,7 @@ function expressionCallsBuilder(node) {
|
|
|
22520
22612
|
}
|
|
22521
22613
|
if (current.type === AST_NODE_TYPES105.CallExpression) {
|
|
22522
22614
|
if (current.callee.type !== AST_NODE_TYPES105.MemberExpression) return false;
|
|
22523
|
-
const name =
|
|
22615
|
+
const name = ASTUtils65.getPropertyName(current.callee);
|
|
22524
22616
|
if (name !== null && BUILDER_METHODS.has(name)) return true;
|
|
22525
22617
|
current = current.callee.object;
|
|
22526
22618
|
continue;
|
|
@@ -22571,7 +22663,7 @@ function thisRootMember(node) {
|
|
|
22571
22663
|
let current = node;
|
|
22572
22664
|
let root = null;
|
|
22573
22665
|
while (current.type === AST_NODE_TYPES105.MemberExpression) {
|
|
22574
|
-
const name =
|
|
22666
|
+
const name = ASTUtils65.getPropertyName(current);
|
|
22575
22667
|
if (name === null) return null;
|
|
22576
22668
|
root = name;
|
|
22577
22669
|
current = current.object;
|
|
@@ -22615,19 +22707,19 @@ var require_sql_access_class_default = createRule({
|
|
|
22615
22707
|
if (seen.has(node)) return false;
|
|
22616
22708
|
seen.add(node);
|
|
22617
22709
|
if (node.type === AST_NODE_TYPES105.Identifier) {
|
|
22618
|
-
const binding =
|
|
22710
|
+
const binding = ASTUtils65.findVariable(context.sourceCode.getScope(node), node.name);
|
|
22619
22711
|
if (binding?.defs.length !== 1 || binding.references.some((reference) => reference.isWrite() && reference.init !== true)) return false;
|
|
22620
22712
|
const definition = binding.defs[0];
|
|
22621
22713
|
return definition?.type === "Variable" && definition.node.init !== null && knownNonDatabase(definition.node.init, seen);
|
|
22622
22714
|
}
|
|
22623
|
-
return node.type === AST_NODE_TYPES105.NewExpression && unwrappedNodeCallee?.type === AST_NODE_TYPES105.Identifier && ["Map", "WeakMap", "URLSearchParams"].includes(unwrappedNodeCallee.name) && (
|
|
22715
|
+
return node.type === AST_NODE_TYPES105.NewExpression && unwrappedNodeCallee?.type === AST_NODE_TYPES105.Identifier && ["Map", "WeakMap", "URLSearchParams"].includes(unwrappedNodeCallee.name) && (ASTUtils65.findVariable(context.sourceCode.getScope(unwrappedNodeCallee), unwrappedNodeCallee.name)?.defs.length ?? 0) === 0;
|
|
22624
22716
|
}
|
|
22625
22717
|
return {
|
|
22626
22718
|
CallExpression(node) {
|
|
22627
22719
|
const unwrappedNodeCallee = unwrapExpression(node.callee);
|
|
22628
22720
|
if (unwrappedNodeCallee.type !== AST_NODE_TYPES105.MemberExpression)
|
|
22629
22721
|
return;
|
|
22630
|
-
const method =
|
|
22722
|
+
const method = ASTUtils65.getPropertyName(unwrappedNodeCallee);
|
|
22631
22723
|
if (knownNonDatabase(unwrappedNodeCallee.object)) return;
|
|
22632
22724
|
if (method === null || !isDatabaseOperation(method, unwrappedNodeCallee.object))
|
|
22633
22725
|
return;
|
|
@@ -22727,7 +22819,7 @@ var require_static_next_matcher_default = createRule({
|
|
|
22727
22819
|
});
|
|
22728
22820
|
|
|
22729
22821
|
// src/rules/require-use-form-default-values.ts
|
|
22730
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES107, ASTUtils as
|
|
22822
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES107, ASTUtils as ASTUtils66 } from "@typescript-eslint/utils";
|
|
22731
22823
|
var REQUIRE_USE_FORM_DEFAULT_VALUES_DOCUMENTATION = {
|
|
22732
22824
|
summary: "Require explicit form-level initialization or a field default for directly bound Controller fields.",
|
|
22733
22825
|
rationale: "React Hook Form exposes form-level defaultValues/values and field-level defaultValue as its explicit initialization mechanisms. A directly bound controlled field should not omit both mechanisms.",
|
|
@@ -22778,7 +22870,7 @@ var require_use_form_default_values_default = createRule({
|
|
|
22778
22870
|
const imported = /* @__PURE__ */ new Map();
|
|
22779
22871
|
const uninitializedForms = /* @__PURE__ */ new Set();
|
|
22780
22872
|
const uninitializedControls = /* @__PURE__ */ new Set();
|
|
22781
|
-
const bindingNamed = (node, name) =>
|
|
22873
|
+
const bindingNamed = (node, name) => ASTUtils66.findVariable(context.sourceCode.getScope(node), name);
|
|
22782
22874
|
const bindingOf = (node) => bindingNamed(node, node.name);
|
|
22783
22875
|
const stable = (variable) => !variable.references.some((reference) => reference.isWrite() && reference.init !== true);
|
|
22784
22876
|
const importedKind = (node) => {
|
|
@@ -22824,7 +22916,7 @@ var require_use_form_default_values_default = createRule({
|
|
|
22824
22916
|
const variable = bindingOf(node);
|
|
22825
22917
|
return variable !== null && stable(variable) && uninitializedControls.has(variable);
|
|
22826
22918
|
}
|
|
22827
|
-
return node.type === AST_NODE_TYPES107.MemberExpression &&
|
|
22919
|
+
return node.type === AST_NODE_TYPES107.MemberExpression && ASTUtils66.getPropertyName(node) !== null && (ASTUtils66.getPropertyName(node) ?? "") === "control" && isUninitializedForm(node.object);
|
|
22828
22920
|
};
|
|
22829
22921
|
const fieldOptionsNeedDefault = (node) => {
|
|
22830
22922
|
if (node?.type !== AST_NODE_TYPES107.ObjectExpression) return false;
|
|
@@ -22880,7 +22972,7 @@ var require_use_form_default_values_default = createRule({
|
|
|
22880
22972
|
trackDestructuredControl(node.id);
|
|
22881
22973
|
return;
|
|
22882
22974
|
}
|
|
22883
|
-
if (node.id.type === AST_NODE_TYPES107.Identifier && node.init.type === AST_NODE_TYPES107.MemberExpression &&
|
|
22975
|
+
if (node.id.type === AST_NODE_TYPES107.Identifier && node.init.type === AST_NODE_TYPES107.MemberExpression && ASTUtils66.getPropertyName(node.init) !== null && (ASTUtils66.getPropertyName(node.init) ?? "") === "control" && isUninitializedForm(node.init.object)) {
|
|
22884
22976
|
const variable = bindingOf(node.id);
|
|
22885
22977
|
if (variable !== null) uninitializedControls.add(variable);
|
|
22886
22978
|
}
|
|
@@ -22973,7 +23065,7 @@ var require_use_server_in_actions_file_default = createRule({
|
|
|
22973
23065
|
// src/rules/require-zod-form-validation.ts
|
|
22974
23066
|
import {
|
|
22975
23067
|
AST_NODE_TYPES as AST_NODE_TYPES108,
|
|
22976
|
-
ASTUtils as
|
|
23068
|
+
ASTUtils as ASTUtils67
|
|
22977
23069
|
} from "@typescript-eslint/utils";
|
|
22978
23070
|
var REQUIRE_ZOD_FORM_VALIDATION_DOCUMENTATION = {
|
|
22979
23071
|
summary: "Require Zod validation (`Schema.parse(...)` / `Schema.safeParse(...)`) when reading values out of a `FormData` object.",
|
|
@@ -23021,7 +23113,7 @@ var isFormDataMethodCall = (node) => {
|
|
|
23021
23113
|
}
|
|
23022
23114
|
if (current.type !== AST_NODE_TYPES108.CallExpression) return false;
|
|
23023
23115
|
const callee = unwrapExpression(current.callee);
|
|
23024
|
-
return callee.type === AST_NODE_TYPES108.MemberExpression &&
|
|
23116
|
+
return callee.type === AST_NODE_TYPES108.MemberExpression && ASTUtils67.getPropertyName(callee) === "formData";
|
|
23025
23117
|
};
|
|
23026
23118
|
var require_zod_form_validation_default = createRule({
|
|
23027
23119
|
name: "require-zod-form-validation",
|
|
@@ -23042,7 +23134,7 @@ var require_zod_form_validation_default = createRule({
|
|
|
23042
23134
|
return {};
|
|
23043
23135
|
}
|
|
23044
23136
|
const zodBindings = /* @__PURE__ */ new Set();
|
|
23045
|
-
const resolvedBinding = (identifier) =>
|
|
23137
|
+
const resolvedBinding = (identifier) => ASTUtils67.findVariable(
|
|
23046
23138
|
context.sourceCode.getScope(identifier),
|
|
23047
23139
|
identifier.name
|
|
23048
23140
|
);
|
|
@@ -23050,7 +23142,7 @@ var require_zod_form_validation_default = createRule({
|
|
|
23050
23142
|
const callee = unwrapExpression(node.callee);
|
|
23051
23143
|
const calleeReceiver = callee.type === AST_NODE_TYPES108.MemberExpression ? unwrapExpression(callee.object) : callee;
|
|
23052
23144
|
if (callee.type !== AST_NODE_TYPES108.MemberExpression) return false;
|
|
23053
|
-
if (
|
|
23145
|
+
if (ASTUtils67.getPropertyName(callee) === null || !FORM_VALUE_METHODS.has(ASTUtils67.getPropertyName(callee) ?? "")) {
|
|
23054
23146
|
return false;
|
|
23055
23147
|
}
|
|
23056
23148
|
return isFormSourceIdentifier(calleeReceiver);
|
|
@@ -23081,7 +23173,7 @@ var require_zod_form_validation_default = createRule({
|
|
|
23081
23173
|
parent = parent.parent;
|
|
23082
23174
|
continue;
|
|
23083
23175
|
}
|
|
23084
|
-
if (parent.type === AST_NODE_TYPES108.CallExpression && parent.callee.type === AST_NODE_TYPES108.MemberExpression && parent.callee.object.type === AST_NODE_TYPES108.Identifier && parent.callee.object.name === "Object" &&
|
|
23176
|
+
if (parent.type === AST_NODE_TYPES108.CallExpression && parent.callee.type === AST_NODE_TYPES108.MemberExpression && parent.callee.object.type === AST_NODE_TYPES108.Identifier && parent.callee.object.name === "Object" && ASTUtils67.getPropertyName(parent.callee) === "fromEntries" && (resolvedBinding(parent.callee.object)?.defs.length ?? 0) === 0) {
|
|
23085
23177
|
parent = parent.parent;
|
|
23086
23178
|
continue;
|
|
23087
23179
|
}
|
|
@@ -23094,7 +23186,7 @@ var require_zod_form_validation_default = createRule({
|
|
|
23094
23186
|
if (node.type !== AST_NODE_TYPES108.CallExpression) return false;
|
|
23095
23187
|
const callee = unwrapExpression(node.callee);
|
|
23096
23188
|
const calleeReceiver = callee.type === AST_NODE_TYPES108.MemberExpression ? unwrapExpression(callee.object) : callee;
|
|
23097
|
-
if (callee.type !== AST_NODE_TYPES108.MemberExpression ||
|
|
23189
|
+
if (callee.type !== AST_NODE_TYPES108.MemberExpression || ASTUtils67.getPropertyName(callee) === null || !ZOD_PARSE_METHODS.has(ASTUtils67.getPropertyName(callee) ?? "")) {
|
|
23098
23190
|
return false;
|
|
23099
23191
|
}
|
|
23100
23192
|
const root = zodReceiverRoot(calleeReceiver);
|
|
@@ -23180,7 +23272,7 @@ var require_zod_form_validation_default = createRule({
|
|
|
23180
23272
|
};
|
|
23181
23273
|
const zodParseMethod = (call) => {
|
|
23182
23274
|
const callee = unwrapExpression(call.callee);
|
|
23183
|
-
return callee.type === AST_NODE_TYPES108.MemberExpression &&
|
|
23275
|
+
return callee.type === AST_NODE_TYPES108.MemberExpression && ASTUtils67.getPropertyName(callee) !== null ? ASTUtils67.getPropertyName(callee) ?? "" : null;
|
|
23184
23276
|
};
|
|
23185
23277
|
const isSafePrevalidationInspection = (identifier) => {
|
|
23186
23278
|
const parent = identifier.parent;
|
|
@@ -23356,7 +23448,7 @@ function expressionCallableName(current) {
|
|
|
23356
23448
|
}
|
|
23357
23449
|
|
|
23358
23450
|
// src/rules/stepdown.ts
|
|
23359
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES109, ASTUtils as
|
|
23451
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES109, ASTUtils as ASTUtils68 } from "@typescript-eslint/utils";
|
|
23360
23452
|
var STEPDOWN_DOCUMENTATION = {
|
|
23361
23453
|
summary: "Place a private helper below its sole direct same-scope caller.",
|
|
23362
23454
|
rationale: "Caller-first ordering lets a reader follow the main flow before descending into implementation details.",
|
|
@@ -23656,7 +23748,7 @@ function receiverOrigin(context, object, receivers) {
|
|
|
23656
23748
|
while (true) {
|
|
23657
23749
|
const unwrapped = unwrapExpression4(current);
|
|
23658
23750
|
if (unwrapped.type !== AST_NODE_TYPES109.Identifier) return unwrapped;
|
|
23659
|
-
const variable =
|
|
23751
|
+
const variable = ASTUtils68.findVariable(context.sourceCode.getScope(unwrapped), unwrapped.name);
|
|
23660
23752
|
if (variable === null) return null;
|
|
23661
23753
|
const known = receivers.get(variable);
|
|
23662
23754
|
if (known !== void 0) return known;
|
|
@@ -23837,11 +23929,11 @@ function classScope(context, node, computedReferences) {
|
|
|
23837
23929
|
function classReceiverBindings(context, node) {
|
|
23838
23930
|
const classReceivers = /* @__PURE__ */ new Map();
|
|
23839
23931
|
if (node.id !== null) {
|
|
23840
|
-
const internal =
|
|
23932
|
+
const internal = ASTUtils68.findVariable(context.sourceCode.getScope(node), node.id.name);
|
|
23841
23933
|
if (internal !== null && stableVariable(internal)) classReceivers.set(internal, true);
|
|
23842
23934
|
}
|
|
23843
23935
|
if (node.type === AST_NODE_TYPES109.ClassExpression && node.parent.type === AST_NODE_TYPES109.VariableDeclarator && node.parent.id.type === AST_NODE_TYPES109.Identifier && node.parent.parent.type === AST_NODE_TYPES109.VariableDeclaration && node.parent.parent.kind === "const") {
|
|
23844
|
-
const outer =
|
|
23936
|
+
const outer = ASTUtils68.findVariable(context.sourceCode.getScope(node.parent), node.parent.id.name);
|
|
23845
23937
|
if (outer !== null && stableVariable(outer)) classReceivers.set(outer, true);
|
|
23846
23938
|
}
|
|
23847
23939
|
return classReceivers;
|
|
@@ -23927,7 +24019,7 @@ function classMethodCounts(body2, methods) {
|
|
|
23927
24019
|
}
|
|
23928
24020
|
|
|
23929
24021
|
// src/rules/source-coupled-test.ts
|
|
23930
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES110, ASTUtils as
|
|
24022
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES110, ASTUtils as ASTUtils69 } from "@typescript-eslint/utils";
|
|
23931
24023
|
var GENERAL_SOURCE_SUFFIX_RE = /\.(?:bash|sh|ya?ml|jsonc?|toml|py|[cm]?[jt]s)$/iu;
|
|
23932
24024
|
var FS_MODULES = /* @__PURE__ */ new Set(["fs", "node:fs", "fs/promises", "node:fs/promises"]);
|
|
23933
24025
|
var FS_READERS = /* @__PURE__ */ new Set(["readFile", "readFileSync"]);
|
|
@@ -24044,7 +24136,7 @@ function createSourceCoupledRule(name, documentation, sourceSuffixRe) {
|
|
|
24044
24136
|
const scopes = [newScope()];
|
|
24045
24137
|
const reportedOrigins = /* @__PURE__ */ new Set();
|
|
24046
24138
|
const currentScope = () => scopes.at(-1) ?? scopes[0];
|
|
24047
|
-
const bindingOf = (node) =>
|
|
24139
|
+
const bindingOf = (node) => ASTUtils69.findVariable(context.sourceCode.getScope(node), node.name);
|
|
24048
24140
|
const assertionKind = (node) => {
|
|
24049
24141
|
const binding = bindingOf(node);
|
|
24050
24142
|
if (binding === null || binding.defs.length === 0) {
|
|
@@ -24097,7 +24189,7 @@ function createSourceCoupledRule(name, documentation, sourceSuffixRe) {
|
|
|
24097
24189
|
return visible("fsReaders", callee) && sourcePath(current.arguments[0]);
|
|
24098
24190
|
}
|
|
24099
24191
|
if (callee.type !== AST_NODE_TYPES110.MemberExpression) return false;
|
|
24100
|
-
const name2 =
|
|
24192
|
+
const name2 = ASTUtils69.getPropertyName(callee);
|
|
24101
24193
|
const object = unwrap6(calleeReceiver);
|
|
24102
24194
|
return name2 !== null && FS_READERS.has(name2) && object.type === AST_NODE_TYPES110.Identifier && visible("fsObjects", object) && sourcePath(current.arguments[0]);
|
|
24103
24195
|
};
|
|
@@ -24106,12 +24198,12 @@ function createSourceCoupledRule(name, documentation, sourceSuffixRe) {
|
|
|
24106
24198
|
if (current.type === AST_NODE_TYPES110.Identifier) return visibleRawOrigins(current);
|
|
24107
24199
|
if (rawRead(current)) return /* @__PURE__ */ new Set([`${current.range[0]}:${current.range[1]}`]);
|
|
24108
24200
|
if (current.type === AST_NODE_TYPES110.BinaryExpression && current.operator === "+") return /* @__PURE__ */ new Set([...rawOrigins(current.left), ...rawOrigins(current.right)]);
|
|
24109
|
-
if (current.type === AST_NODE_TYPES110.MemberExpression &&
|
|
24201
|
+
if (current.type === AST_NODE_TYPES110.MemberExpression && ASTUtils69.getPropertyName(current) === "length") return rawOrigins(current.object);
|
|
24110
24202
|
if (current.type !== AST_NODE_TYPES110.CallExpression) return /* @__PURE__ */ new Set();
|
|
24111
24203
|
const callee = unwrap6(current.callee);
|
|
24112
24204
|
const calleeReceiver = callee.type === AST_NODE_TYPES110.MemberExpression ? unwrapExpression(callee.object) : callee;
|
|
24113
24205
|
if (callee.type !== AST_NODE_TYPES110.MemberExpression) return /* @__PURE__ */ new Set();
|
|
24114
|
-
const name2 =
|
|
24206
|
+
const name2 = ASTUtils69.getPropertyName(callee);
|
|
24115
24207
|
return name2 !== null && TEXT_TRANSFORMS.has(name2) ? rawOrigins(calleeReceiver) : /* @__PURE__ */ new Set();
|
|
24116
24208
|
};
|
|
24117
24209
|
const evidenceOrigins = (node) => {
|
|
@@ -24124,7 +24216,7 @@ function createSourceCoupledRule(name, documentation, sourceSuffixRe) {
|
|
|
24124
24216
|
const callee = unwrap6(current.callee);
|
|
24125
24217
|
const calleeReceiver = callee.type === AST_NODE_TYPES110.MemberExpression ? unwrapExpression(callee.object) : callee;
|
|
24126
24218
|
if (callee.type !== AST_NODE_TYPES110.MemberExpression) return /* @__PURE__ */ new Set();
|
|
24127
|
-
const name2 =
|
|
24219
|
+
const name2 = ASTUtils69.getPropertyName(callee);
|
|
24128
24220
|
if (name2 !== null && TEXT_PREDICATES.has(name2)) return rawOrigins(calleeReceiver);
|
|
24129
24221
|
if (name2 !== null && REGEXP_PREDICATES.has(name2)) return new Set(current.arguments.flatMap((argument) => argument.type === AST_NODE_TYPES110.SpreadElement ? [] : [...rawOrigins(argument)]));
|
|
24130
24222
|
return /* @__PURE__ */ new Set();
|
|
@@ -24136,10 +24228,10 @@ function createSourceCoupledRule(name, documentation, sourceSuffixRe) {
|
|
|
24136
24228
|
return new Set(node.arguments.flatMap((argument) => argument.type === AST_NODE_TYPES110.SpreadElement ? [] : [...evidenceOrigins(argument)]));
|
|
24137
24229
|
}
|
|
24138
24230
|
if (callee.type !== AST_NODE_TYPES110.MemberExpression) return /* @__PURE__ */ new Set();
|
|
24139
|
-
const matcher =
|
|
24231
|
+
const matcher = ASTUtils69.getPropertyName(callee);
|
|
24140
24232
|
if (matcher === null) return /* @__PURE__ */ new Set();
|
|
24141
24233
|
let receiver = unwrap6(calleeReceiver);
|
|
24142
|
-
while (receiver.type === AST_NODE_TYPES110.MemberExpression && EXPECT_MODIFIERS2.has(
|
|
24234
|
+
while (receiver.type === AST_NODE_TYPES110.MemberExpression && EXPECT_MODIFIERS2.has(ASTUtils69.getPropertyName(receiver) ?? "")) receiver = unwrap6(receiver.object);
|
|
24143
24235
|
const expectCallee = receiver.type === AST_NODE_TYPES110.CallExpression ? unwrapExpression(receiver.callee) : null;
|
|
24144
24236
|
if (receiver.type === AST_NODE_TYPES110.CallExpression && expectCallee?.type === AST_NODE_TYPES110.Identifier && assertionKind(expectCallee) === "expect") {
|
|
24145
24237
|
if (!EXPECT_MATCHERS.has(matcher)) return /* @__PURE__ */ new Set();
|
|
@@ -24422,7 +24514,7 @@ var iac_source_coupled_test_default = createSourceCoupledRule(
|
|
|
24422
24514
|
// src/rules/require-pascal-case-zod-schema-name.ts
|
|
24423
24515
|
import {
|
|
24424
24516
|
AST_NODE_TYPES as AST_NODE_TYPES112,
|
|
24425
|
-
ASTUtils as
|
|
24517
|
+
ASTUtils as ASTUtils70
|
|
24426
24518
|
} from "@typescript-eslint/utils";
|
|
24427
24519
|
var REQUIRE_PASCAL_CASE_ZOD_SCHEMA_NAME_DOCUMENTATION = {
|
|
24428
24520
|
summary: "Require confirmed module-level Zod schema contracts to use PascalCase with a `Schema` suffix.",
|
|
@@ -24555,7 +24647,7 @@ var SCHEMA_RETURNING_METHODS = /* @__PURE__ */ new Set([
|
|
|
24555
24647
|
"superRefine",
|
|
24556
24648
|
"transform"
|
|
24557
24649
|
]);
|
|
24558
|
-
var terminalMethodName = (callee) =>
|
|
24650
|
+
var terminalMethodName = (callee) => ASTUtils70.getPropertyName(callee) !== null ? ASTUtils70.getPropertyName(callee) ?? "" : null;
|
|
24559
24651
|
var calleeChainRoot2 = (node) => {
|
|
24560
24652
|
let current = node;
|
|
24561
24653
|
for (; ; ) {
|
|
@@ -24580,8 +24672,8 @@ var chainMemberNames2 = (node) => {
|
|
|
24580
24672
|
for (; ; ) {
|
|
24581
24673
|
current = unwrapExpression(current);
|
|
24582
24674
|
if (current.type === AST_NODE_TYPES112.MemberExpression) {
|
|
24583
|
-
if (
|
|
24584
|
-
names.push(
|
|
24675
|
+
if (ASTUtils70.getPropertyName(current) === null) return [];
|
|
24676
|
+
names.push(ASTUtils70.getPropertyName(current) ?? "");
|
|
24585
24677
|
current = current.object;
|
|
24586
24678
|
continue;
|
|
24587
24679
|
}
|
|
@@ -24618,7 +24710,7 @@ var require_pascal_case_zod_schema_name_default = createRule({
|
|
|
24618
24710
|
const zodBindings = /* @__PURE__ */ new Set();
|
|
24619
24711
|
const schemaBindings = /* @__PURE__ */ new Set();
|
|
24620
24712
|
function resolvedBinding(identifier) {
|
|
24621
|
-
return
|
|
24713
|
+
return ASTUtils70.findVariable(
|
|
24622
24714
|
context.sourceCode.getScope(identifier),
|
|
24623
24715
|
identifier.name
|
|
24624
24716
|
);
|
|
@@ -24899,30 +24991,21 @@ var LIBRARY_IMPORT_POLICY = ["error", {
|
|
|
24899
24991
|
}];
|
|
24900
24992
|
var ADVISORY_RULES = [
|
|
24901
24993
|
"@sarj/excessive-commentary",
|
|
24902
|
-
"@sarj/named-child-schema-type",
|
|
24903
24994
|
"@sarj/no-bespoke-api-case-conversion",
|
|
24904
|
-
"@sarj/no-duplicate-test-case",
|
|
24905
|
-
"@sarj/no-json-stringify-object-equality",
|
|
24906
24995
|
"@sarj/no-restated-comment",
|
|
24907
24996
|
"@sarj/no-restated-jsdoc",
|
|
24908
24997
|
"@sarj/prefer-millisecond-control-duration-schema",
|
|
24909
24998
|
"@sarj/prefer-module-level-refined-schema",
|
|
24910
24999
|
"@sarj/prefer-multi-value-zod-literal",
|
|
24911
|
-
"@sarj/prefer-named-complex-return-type",
|
|
24912
25000
|
"@sarj/prefer-node-crypto-hash",
|
|
24913
25001
|
"@sarj/prefer-node-fs-promises",
|
|
24914
|
-
"@sarj/prefer-nominal-id-types",
|
|
24915
25002
|
"@sarj/prefer-shared-zod-enum",
|
|
24916
|
-
"@sarj/prefer-switch-for-repeated-equality",
|
|
24917
25003
|
"@sarj/prefer-whole-object-assertion",
|
|
24918
25004
|
"@sarj/require-camelcase-properties",
|
|
24919
|
-
"@sarj/require-explicit-contract-implementation",
|
|
24920
|
-
"@sarj/require-explicit-service-contract",
|
|
24921
|
-
"@sarj/require-interface-for-exported-class",
|
|
24922
25005
|
"@sarj/require-sql-access-class"
|
|
24923
25006
|
];
|
|
24924
25007
|
var RECOMMENDED_RULES = {
|
|
24925
|
-
"@sarj/named-child-schema-type": "
|
|
25008
|
+
"@sarj/named-child-schema-type": "error",
|
|
24926
25009
|
"@sarj/no-conditional-empty-object-spread": "error",
|
|
24927
25010
|
"@sarj/prefer-typed-reflection": "error",
|
|
24928
25011
|
"@sarj/no-broad-return-type": "error",
|
|
@@ -24960,7 +25043,7 @@ var RECOMMENDED_RULES = {
|
|
|
24960
25043
|
"@sarj/no-bare-return-from-test-catch": "error",
|
|
24961
25044
|
"@sarj/no-bespoke-api-case-conversion": "warn",
|
|
24962
25045
|
"@sarj/no-detached-global-fetch": "error",
|
|
24963
|
-
"@sarj/no-json-stringify-object-equality": "
|
|
25046
|
+
"@sarj/no-json-stringify-object-equality": "error",
|
|
24964
25047
|
"@sarj/no-dangerously-allow-svg": "error",
|
|
24965
25048
|
"@sarj/no-duplicate-lifecycle-refresh-listeners": "error",
|
|
24966
25049
|
"@sarj/no-long-comment": "error",
|
|
@@ -24982,7 +25065,7 @@ var RECOMMENDED_RULES = {
|
|
|
24982
25065
|
"@sarj/no-sleep-in-test-body": "error",
|
|
24983
25066
|
"@sarj/no-string-concat-in-loop": "error",
|
|
24984
25067
|
"@sarj/no-tautological-expect": "error",
|
|
24985
|
-
"@sarj/no-duplicate-test-case": "
|
|
25068
|
+
"@sarj/no-duplicate-test-case": "error",
|
|
24986
25069
|
"@sarj/no-typed-doc-sections": "error",
|
|
24987
25070
|
"@sarj/no-trailing-value-narration": "error",
|
|
24988
25071
|
"@sarj/no-declaration-comment-wall": "error",
|
|
@@ -25005,8 +25088,8 @@ var RECOMMENDED_RULES = {
|
|
|
25005
25088
|
"@sarj/prefer-module-level-refined-schema": "warn",
|
|
25006
25089
|
"@sarj/prefer-multi-value-zod-literal": ["warn", { zodMajorVersion: 4 }],
|
|
25007
25090
|
"@sarj/prefer-named-callback-domain": "error",
|
|
25008
|
-
"@sarj/prefer-nominal-id-types": "
|
|
25009
|
-
"@sarj/prefer-named-complex-return-type": "
|
|
25091
|
+
"@sarj/prefer-nominal-id-types": "error",
|
|
25092
|
+
"@sarj/prefer-named-complex-return-type": "error",
|
|
25010
25093
|
"@sarj/prefer-node-crypto-hash": "warn",
|
|
25011
25094
|
"@sarj/prefer-node-fs-promises": "warn",
|
|
25012
25095
|
"@sarj/prefer-non-nullable-collection": "error",
|
|
@@ -25014,7 +25097,7 @@ var RECOMMENDED_RULES = {
|
|
|
25014
25097
|
"@sarj/prefer-await-in-async-return": "error",
|
|
25015
25098
|
"@sarj/prefer-schema-for-api-payload": "error",
|
|
25016
25099
|
"@sarj/prefer-shared-zod-enum": "warn",
|
|
25017
|
-
"@sarj/prefer-switch-for-repeated-equality": "
|
|
25100
|
+
"@sarj/prefer-switch-for-repeated-equality": "error",
|
|
25018
25101
|
"@sarj/prefer-semantic-colors": ["error", { requireSemanticTokens: true }],
|
|
25019
25102
|
"@sarj/prefer-server-actions": "error",
|
|
25020
25103
|
"@sarj/prefer-whole-object-assertion": "warn",
|
|
@@ -25023,9 +25106,9 @@ var RECOMMENDED_RULES = {
|
|
|
25023
25106
|
"@sarj/prefer-zod-parse-output-type": "error",
|
|
25024
25107
|
"@sarj/require-assert-never": "error",
|
|
25025
25108
|
"@sarj/require-fetch-timeout": "error",
|
|
25026
|
-
"@sarj/require-explicit-contract-implementation": "
|
|
25027
|
-
"@sarj/require-explicit-service-contract": "
|
|
25028
|
-
"@sarj/require-interface-for-exported-class": "
|
|
25109
|
+
"@sarj/require-explicit-contract-implementation": "error",
|
|
25110
|
+
"@sarj/require-explicit-service-contract": "error",
|
|
25111
|
+
"@sarj/require-interface-for-exported-class": "error",
|
|
25029
25112
|
"@sarj/require-port-for-service": "error",
|
|
25030
25113
|
"@sarj/require-sql-access-class": "warn",
|
|
25031
25114
|
"@sarj/require-static-next-matcher": "error",
|
|
@@ -25040,7 +25123,7 @@ var RECOMMENDED_RULES = {
|
|
|
25040
25123
|
"@sarj/require-pascal-case-zod-schema-name": "error"
|
|
25041
25124
|
};
|
|
25042
25125
|
var STRICT_RULES = {
|
|
25043
|
-
"@sarj/named-child-schema-type": "
|
|
25126
|
+
"@sarj/named-child-schema-type": "error",
|
|
25044
25127
|
"@sarj/no-conditional-empty-object-spread": "error",
|
|
25045
25128
|
"@sarj/prefer-typed-reflection": "error",
|
|
25046
25129
|
"@sarj/no-broad-return-type": "error",
|
|
@@ -25079,7 +25162,7 @@ var STRICT_RULES = {
|
|
|
25079
25162
|
"@sarj/no-bare-return-from-test-catch": "error",
|
|
25080
25163
|
"@sarj/no-bespoke-api-case-conversion": "warn",
|
|
25081
25164
|
"@sarj/no-detached-global-fetch": "error",
|
|
25082
|
-
"@sarj/no-json-stringify-object-equality": "
|
|
25165
|
+
"@sarj/no-json-stringify-object-equality": "error",
|
|
25083
25166
|
"@sarj/no-dangerously-allow-svg": "error",
|
|
25084
25167
|
"@sarj/no-duplicate-lifecycle-refresh-listeners": "error",
|
|
25085
25168
|
"@sarj/no-long-comment": "error",
|
|
@@ -25104,7 +25187,7 @@ var STRICT_RULES = {
|
|
|
25104
25187
|
"@sarj/no-storage-in-stateless-modules": "error",
|
|
25105
25188
|
"@sarj/no-string-concat-in-loop": "error",
|
|
25106
25189
|
"@sarj/no-tautological-expect": "error",
|
|
25107
|
-
"@sarj/no-duplicate-test-case": "
|
|
25190
|
+
"@sarj/no-duplicate-test-case": "error",
|
|
25108
25191
|
"@sarj/no-typed-doc-sections": "error",
|
|
25109
25192
|
"@sarj/no-trailing-value-narration": "error",
|
|
25110
25193
|
"@sarj/no-declaration-comment-wall": "error",
|
|
@@ -25127,8 +25210,8 @@ var STRICT_RULES = {
|
|
|
25127
25210
|
"@sarj/prefer-module-level-refined-schema": "warn",
|
|
25128
25211
|
"@sarj/prefer-multi-value-zod-literal": ["warn", { zodMajorVersion: 4 }],
|
|
25129
25212
|
"@sarj/prefer-named-callback-domain": "error",
|
|
25130
|
-
"@sarj/prefer-nominal-id-types": "
|
|
25131
|
-
"@sarj/prefer-named-complex-return-type": "
|
|
25213
|
+
"@sarj/prefer-nominal-id-types": "error",
|
|
25214
|
+
"@sarj/prefer-named-complex-return-type": "error",
|
|
25132
25215
|
"@sarj/prefer-node-crypto-hash": "warn",
|
|
25133
25216
|
"@sarj/prefer-node-fs-promises": "warn",
|
|
25134
25217
|
"@sarj/prefer-non-nullable-collection": "error",
|
|
@@ -25136,7 +25219,7 @@ var STRICT_RULES = {
|
|
|
25136
25219
|
"@sarj/prefer-await-in-async-return": "error",
|
|
25137
25220
|
"@sarj/prefer-schema-for-api-payload": "error",
|
|
25138
25221
|
"@sarj/prefer-shared-zod-enum": "warn",
|
|
25139
|
-
"@sarj/prefer-switch-for-repeated-equality": "
|
|
25222
|
+
"@sarj/prefer-switch-for-repeated-equality": "error",
|
|
25140
25223
|
"@sarj/prefer-semantic-colors": ["error", { requireSemanticTokens: true }],
|
|
25141
25224
|
"@sarj/prefer-server-actions": "error",
|
|
25142
25225
|
"@sarj/prefer-whole-object-assertion": "warn",
|
|
@@ -25145,9 +25228,9 @@ var STRICT_RULES = {
|
|
|
25145
25228
|
"@sarj/prefer-zod-parse-output-type": "error",
|
|
25146
25229
|
"@sarj/require-assert-never": "error",
|
|
25147
25230
|
"@sarj/require-fetch-timeout": "error",
|
|
25148
|
-
"@sarj/require-explicit-contract-implementation": "
|
|
25149
|
-
"@sarj/require-explicit-service-contract": "
|
|
25150
|
-
"@sarj/require-interface-for-exported-class": "
|
|
25231
|
+
"@sarj/require-explicit-contract-implementation": "error",
|
|
25232
|
+
"@sarj/require-explicit-service-contract": "error",
|
|
25233
|
+
"@sarj/require-interface-for-exported-class": "error",
|
|
25151
25234
|
"@sarj/require-port-for-service": "error",
|
|
25152
25235
|
"@sarj/require-sql-access-class": "warn",
|
|
25153
25236
|
"@sarj/require-static-next-matcher": "error",
|