@sarj/eslint-plugin 16.5.3 → 16.7.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.js CHANGED
@@ -1,7 +1,7 @@
1
1
  // package.json
2
2
  var package_default = {
3
3
  name: "@sarj/eslint-plugin",
4
- version: "16.5.3",
4
+ version: "16.7.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: "warning",
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 actualType = checker.getTypeAtLocation(tsArgument);
586
- if (!checker.isTypeAssignableTo(actualType, contractType)) continue;
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
  }
@@ -7592,7 +7679,8 @@ var NO_IMPOSSIBLE_ZOD_LITERAL_BOUNDS_DOCUMENTATION = {
7592
7679
  remediation: "Choose compatible lower and upper bounds, or remove the constraint that does not express the intended domain.",
7593
7680
  category: "correctness",
7594
7681
  limitations: [
7595
- "Only finite numeric literals in a single number, string, or array schema chain are compared.",
7682
+ "Only finite numeric literals in a single number, string, or array schema chain are compared; explicit int() chains also require an admitted integer.",
7683
+ "Integer-domain comparisons abstain near the JavaScript safe-integer boundary.",
7596
7684
  "Chains with dynamic bounds, non-bound validators, transforms, pipes, or preprocessors are skipped.",
7597
7685
  "Test and generated files are excluded."
7598
7686
  ],
@@ -7631,6 +7719,7 @@ var KINDS = /* @__PURE__ */ new Set(["array", "number", "string"]);
7631
7719
  var NUMBER_METHODS = /* @__PURE__ */ new Set([
7632
7720
  "gt",
7633
7721
  "gte",
7722
+ "int",
7634
7723
  "lt",
7635
7724
  "lte",
7636
7725
  "max",
@@ -7672,9 +7761,20 @@ function strongerUpper(current, candidate2) {
7672
7761
  }
7673
7762
  return current;
7674
7763
  }
7675
- function isEmpty(lower, upper) {
7764
+ function isEmpty(lower, upper, integer) {
7676
7765
  if (lower === null || upper === null) return false;
7677
- return lower.value > upper.value || lower.value === upper.value && (lower.exclusive || upper.exclusive);
7766
+ const realEmpty = lower.value > upper.value || lower.value === upper.value && (lower.exclusive || upper.exclusive);
7767
+ if (integer) {
7768
+ if (realEmpty) return false;
7769
+ const safeMargin = Number.MAX_SAFE_INTEGER - 1;
7770
+ if (Math.abs(lower.value) >= safeMargin || Math.abs(upper.value) >= safeMargin) {
7771
+ return false;
7772
+ }
7773
+ const minimum = lower.exclusive ? Math.floor(lower.value) + 1 : Math.ceil(lower.value);
7774
+ const maximum = upper.exclusive ? Math.ceil(upper.value) - 1 : Math.floor(upper.value);
7775
+ return minimum > maximum;
7776
+ }
7777
+ return realEmpty;
7678
7778
  }
7679
7779
  function isOutermostCall(node) {
7680
7780
  const parent = node.parent;
@@ -7768,6 +7868,7 @@ var no_impossible_zod_literal_bounds_default = createRule({
7768
7868
  const allowed = chain.kind === "number" ? NUMBER_METHODS : LENGTH_METHODS;
7769
7869
  let lower = null;
7770
7870
  let upper = null;
7871
+ let integer = false;
7771
7872
  function addBound(method, semantic, value) {
7772
7873
  const label = `${method}(${String(value)})`;
7773
7874
  if (semantic !== null) {
@@ -7803,6 +7904,11 @@ var no_impossible_zod_literal_bounds_default = createRule({
7803
7904
  }
7804
7905
  for (const { method, node } of chain.calls) {
7805
7906
  if (!allowed.has(method)) return null;
7907
+ if (method === "int") {
7908
+ if (node.arguments.length !== 0) return null;
7909
+ integer = true;
7910
+ continue;
7911
+ }
7806
7912
  const semantic = zeroBoundSemantic(method);
7807
7913
  const value = semantic?.value ?? finiteNumber(node.arguments[0]);
7808
7914
  if (value === null) return null;
@@ -7812,7 +7918,7 @@ var no_impossible_zod_literal_bounds_default = createRule({
7812
7918
  if (semantic !== null && node.arguments.length !== 0) return null;
7813
7919
  addBound(method, semantic, value);
7814
7920
  }
7815
- return isEmpty(lower, upper) && lower !== null && upper !== null ? { lower, upper } : null;
7921
+ return isEmpty(lower, upper, integer) && lower !== null && upper !== null ? { lower, upper } : null;
7816
7922
  }
7817
7923
  return {
7818
7924
  ImportDeclaration(node) {
@@ -17698,14 +17804,14 @@ var prefer_named_callback_domain_default = createRule({
17698
17804
  // src/rules/prefer-named-complex-return-type.ts
17699
17805
  import { AST_NODE_TYPES as AST_NODE_TYPES86 } from "@typescript-eslint/utils";
17700
17806
  var PREFER_NAMED_COMPLEX_RETURN_TYPE_DOCUMENTATION = {
17701
- defaultLevel: "warning",
17807
+ defaultLevel: "error",
17702
17808
  summary: "Prefer a named contract for structurally complex function return types.",
17703
17809
  rationale: "A large inline return annotation hides a reusable domain concept and makes signatures difficult to scan.",
17704
17810
  remediation: "Name the complex nested shape while preserving its generic wrappers and type parameters; reference the named contract from the return annotation.",
17705
17811
  category: "maintainability",
17706
17812
  limitations: [
17707
17813
  "Only explicit object types with at least three members and unions with at least three object variants are reported.",
17708
- "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."
17709
17815
  ],
17710
17816
  examples: [
17711
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 },
@@ -17721,10 +17827,13 @@ function unwrap4(node) {
17721
17827
  }
17722
17828
  function report(context, node) {
17723
17829
  const annotation = node.returnType?.typeAnnotation;
17724
- if (annotation !== void 0 && isComplex(annotation)) {
17830
+ if (annotation !== void 0 && isComplex(annotation) && !hasValueDependency(annotation)) {
17725
17831
  context.report({ node: annotation, messageId: "nameComplexReturnType" });
17726
17832
  }
17727
17833
  }
17834
+ function hasValueDependency(node) {
17835
+ return node.type === AST_NODE_TYPES86.TSThisType || node.type === AST_NODE_TYPES86.TSTypeQuery || forEachOwnAstChild(node, hasValueDependency);
17836
+ }
17728
17837
  function isComplex(node) {
17729
17838
  const type = unwrap4(node);
17730
17839
  if (type.type === AST_NODE_TYPES86.TSTypeLiteral) return type.members.length >= 3;
@@ -19378,22 +19487,22 @@ var prefer_shared_zod_enum_default = createRule({
19378
19487
  });
19379
19488
 
19380
19489
  // src/rules/prefer-switch-for-repeated-equality.ts
19381
- 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";
19382
19491
  var PREFER_SWITCH_FOR_REPEATED_EQUALITY_DOCUMENTATION = {
19383
- defaultLevel: "warning",
19492
+ defaultLevel: "error",
19384
19493
  summary: "Prefer switch over long if/else-if chains that compare one value for strict equality.",
19385
19494
  rationale: "A switch makes finite dispatch cases visually uniform and easier to extend without duplicating the discriminant.",
19386
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.",
19387
19496
  category: "maintainability",
19388
19497
  limitations: [
19389
19498
  "Only direct if/else-if chains with at least three strict-equality tests are reported.",
19390
- "The discriminant must be a bare identifier; calls, getters, indexed reads and other repeatedly evaluated expressions are excluded. Review case-value effects, selector mutation, branch scoping, and break/continue targets when converting manually; this is not an equivalence proof.",
19391
- "Case values may be literals, enum-like member references, or upper-case named constants; dynamic expressions are excluded.",
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.",
19392
19501
  "The rule deliberately ignores compound predicates, loose equality, ranges, and chains that compare different discriminants."
19393
19502
  ],
19394
19503
  examples: [
19395
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 },
19396
- { 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 },
19397
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;}
19398
19507
  console.log(JSON.stringify(["a","b","c","d"].map(probe)));` }], focusPath: "src/dispatch.ts", expectedCount: 1, public: true },
19399
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;}
@@ -19409,10 +19518,7 @@ function discriminantName(test) {
19409
19518
  return discriminant.type === AST_NODE_TYPES95.Identifier ? discriminant.name : null;
19410
19519
  }
19411
19520
  function isCaseValue(node) {
19412
- if (node.type === AST_NODE_TYPES95.Literal) return true;
19413
- if (node.type === AST_NODE_TYPES95.Identifier) return /^[A-Z][A-Z0-9_]*$/u.test(node.name);
19414
- if (node.type !== AST_NODE_TYPES95.MemberExpression || node.computed) return false;
19415
- 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);
19416
19522
  }
19417
19523
  var prefer_switch_for_repeated_equality_default = createRule({
19418
19524
  name: "prefer-switch-for-repeated-equality",
@@ -19427,11 +19533,16 @@ var prefer_switch_for_repeated_equality_default = createRule({
19427
19533
  },
19428
19534
  defaultOptions: [],
19429
19535
  create(context) {
19536
+ if (isGeneratedFile(context.filename, context.sourceCode.text)) return {};
19430
19537
  return {
19431
19538
  IfStatement(node) {
19432
19539
  if (node.parent.type === AST_NODE_TYPES95.IfStatement && node.parent.alternate === node) return;
19433
19540
  const first = discriminantName(node.test);
19434
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;
19435
19546
  let count = 1;
19436
19547
  let current = node.alternate;
19437
19548
  while (current?.type === AST_NODE_TYPES95.IfStatement) {
@@ -19975,7 +20086,7 @@ function packageWorkspaceGlobs(parsed) {
19975
20086
  }
19976
20087
 
19977
20088
  // src/rules/prefer-server-actions.ts
19978
- import { ASTUtils as ASTUtils57 } from "@typescript-eslint/utils";
20089
+ import { ASTUtils as ASTUtils58 } from "@typescript-eslint/utils";
19979
20090
  var PREFER_SERVER_ACTIONS_DOCUMENTATION = {
19980
20091
  summary: "Prefer Next.js Server Actions over same-origin API mutations.",
19981
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.",
@@ -20008,7 +20119,7 @@ function resolveNode(node, context) {
20008
20119
  node = node == null ? node : unwrapExpression(node);
20009
20120
  if (!node) return null;
20010
20121
  if (node.type !== "Identifier") return node;
20011
- const variable = ASTUtils57.findVariable(getScope(context, node), node.name);
20122
+ const variable = ASTUtils58.findVariable(getScope(context, node), node.name);
20012
20123
  const definition = variable?.defs.length === 1 ? variable.defs[0] : void 0;
20013
20124
  if (definition?.type !== "Variable" || definition.parent.kind !== "const" || definition.node.init === null || variable?.references.some((reference) => reference.isWrite() && reference.init !== true)) return node;
20014
20125
  if (definition.node.init.type === "ObjectExpression" && variable?.references.some((reference) => reference.identifier !== node && reference.init !== true)) return node;
@@ -20017,7 +20128,7 @@ function resolveNode(node, context) {
20017
20128
  function isAxiosClient(node, context, seen = /* @__PURE__ */ new Set()) {
20018
20129
  if (node.type !== "Identifier" || seen.has(node)) return false;
20019
20130
  seen.add(node);
20020
- const variable = ASTUtils57.findVariable(getScope(context, node), node.name);
20131
+ const variable = ASTUtils58.findVariable(getScope(context, node), node.name);
20021
20132
  const definition = variable?.defs.length === 1 ? variable.defs[0] : void 0;
20022
20133
  if (definition === void 0 || variable?.references.some((reference) => reference.isWrite() && reference.init !== true)) return false;
20023
20134
  if (variable?.references.some((reference) => {
@@ -20101,10 +20212,10 @@ function isFunctionArgument(node, context) {
20101
20212
  }
20102
20213
  function getPropertyNode(objNode, propName2) {
20103
20214
  if (!objNode || objNode.type !== "ObjectExpression") return null;
20104
- if (objNode.properties.some((property) => property.type === "SpreadElement" || ASTUtils57.getPropertyName(property) === null)) return null;
20215
+ if (objNode.properties.some((property) => property.type === "SpreadElement" || ASTUtils58.getPropertyName(property) === null)) return null;
20105
20216
  for (const prop of [...objNode.properties].reverse()) {
20106
20217
  if (prop.type !== "Property") continue;
20107
- const keyName = ASTUtils57.getPropertyName(prop);
20218
+ const keyName = ASTUtils58.getPropertyName(prop);
20108
20219
  if (keyName === propName2) {
20109
20220
  if (prop.value.type === "AssignmentPattern" || prop.value.type === "ArrayPattern" || prop.value.type === "ObjectPattern") {
20110
20221
  return null;
@@ -20228,7 +20339,7 @@ var prefer_server_actions_default = createRule({
20228
20339
  });
20229
20340
 
20230
20341
  // src/rules/prefer-whole-object-assertion.ts
20231
- import { AST_NODE_TYPES as AST_NODE_TYPES97, ASTUtils as ASTUtils58 } from "@typescript-eslint/utils";
20342
+ import { AST_NODE_TYPES as AST_NODE_TYPES97, ASTUtils as ASTUtils59 } from "@typescript-eslint/utils";
20232
20343
  var MERGEABLE_MATCHERS = /* @__PURE__ */ new Set(["toBe", "toEqual", "toStrictEqual"]);
20233
20344
  var SYNTHETIC_LITERAL_MATCHERS = /* @__PURE__ */ new Map([
20234
20345
  ["toBeNull", "null"]
@@ -20293,7 +20404,7 @@ function propertyAccess(node) {
20293
20404
  const path = [];
20294
20405
  let current = node;
20295
20406
  while (current.type === AST_NODE_TYPES97.MemberExpression && !current.optional) {
20296
- const name = ASTUtils58.getPropertyName(current);
20407
+ const name = ASTUtils59.getPropertyName(current);
20297
20408
  if (name === null || COLLECTION_PROPERTIES.has(name) || LITERAL_KEY_HAZARDS.has(name)) return null;
20298
20409
  path.unshift(name);
20299
20410
  current = unwrapExpression(current.object);
@@ -20440,7 +20551,7 @@ var prefer_whole_object_assertion_default = createRule({
20440
20551
  const callee = unwrapExpression(call.callee);
20441
20552
  const calleeReceiver = callee.type === AST_NODE_TYPES97.MemberExpression ? unwrapExpression(callee.object) : callee;
20442
20553
  if (callee.type !== AST_NODE_TYPES97.MemberExpression) return null;
20443
- const matcher = ASTUtils58.getPropertyName(callee);
20554
+ const matcher = ASTUtils59.getPropertyName(callee);
20444
20555
  if (matcher === null) return null;
20445
20556
  const expectCall = calleeReceiver;
20446
20557
  const expectCallee = expectCall.type === AST_NODE_TYPES97.CallExpression ? unwrapExpression(expectCall.callee) : null;
@@ -20470,7 +20581,7 @@ var prefer_whole_object_assertion_default = createRule({
20470
20581
  return assertionExpectation(statement, call, receiver, key, matcher);
20471
20582
  }
20472
20583
  function isTestExpect(callee) {
20473
- const variable = ASTUtils58.findVariable(sourceCode.getScope(callee), callee.name);
20584
+ const variable = ASTUtils59.findVariable(sourceCode.getScope(callee), callee.name);
20474
20585
  if (variable !== null && variable.defs.some((definition) => {
20475
20586
  if (definition.node.type !== AST_NODE_TYPES97.ImportSpecifier) return true;
20476
20587
  const declaration = definition.node.parent;
@@ -20513,7 +20624,7 @@ var prefer_whole_object_assertion_default = createRule({
20513
20624
  });
20514
20625
 
20515
20626
  // src/rules/repeated-static-call-cases.ts
20516
- import { AST_NODE_TYPES as AST_NODE_TYPES98, ASTUtils as ASTUtils59 } from "@typescript-eslint/utils";
20627
+ import { AST_NODE_TYPES as AST_NODE_TYPES98, ASTUtils as ASTUtils60 } from "@typescript-eslint/utils";
20517
20628
  var REPEATED_STATIC_CALL_CASES_DOCUMENTATION = {
20518
20629
  summary: "Review three or more consecutive static-input call assertions as potential named cases.",
20519
20630
  rationale: "Copy-pasted cases obscure the input table, and a thrown assertion can stop later cases from being reported.",
@@ -20534,7 +20645,7 @@ var EXPECT_MODIFIERS = /* @__PURE__ */ new Set(["not", "rejects", "resolves"]);
20534
20645
  var SNAPSHOT_MATCHERS = /snapshot/iu;
20535
20646
  var MIN_CASES2 = 3;
20536
20647
  function importedName6(identifier, context, modules) {
20537
- const variable = ASTUtils59.findVariable(context.sourceCode.getScope(identifier), identifier.name);
20648
+ const variable = ASTUtils60.findVariable(context.sourceCode.getScope(identifier), identifier.name);
20538
20649
  if (variable === null || variable.defs.length === 0) return identifier.name;
20539
20650
  for (const definition of variable.defs) {
20540
20651
  if (definition.node.type !== AST_NODE_TYPES98.ImportSpecifier) continue;
@@ -20556,7 +20667,7 @@ function testRoot2(callee) {
20556
20667
  callee = unwrapExpression(callee);
20557
20668
  if (callee.type === AST_NODE_TYPES98.Identifier) return callee;
20558
20669
  if (callee.type !== AST_NODE_TYPES98.MemberExpression) return null;
20559
- const modifier = ASTUtils59.getPropertyName(callee);
20670
+ const modifier = ASTUtils60.getPropertyName(callee);
20560
20671
  return modifier !== null && TEST_MODIFIERS5.has(modifier) ? testRoot2(callee.object) : null;
20561
20672
  }
20562
20673
  function isStatic(input) {
@@ -20602,8 +20713,8 @@ function assertionShape(statement, context, callback) {
20602
20713
  const matcherCall = unwrapExpression(statement.expression);
20603
20714
  if (matcherCall.type !== AST_NODE_TYPES98.CallExpression) return null;
20604
20715
  const matcherCallee = unwrapExpression(matcherCall.callee);
20605
- if (matcherCallee.type !== AST_NODE_TYPES98.MemberExpression || ASTUtils59.getPropertyName(matcherCallee) === null || matcherCall.arguments.length !== 1) return null;
20606
- const matcher = ASTUtils59.getPropertyName(matcherCallee) ?? "";
20716
+ if (matcherCallee.type !== AST_NODE_TYPES98.MemberExpression || ASTUtils60.getPropertyName(matcherCallee) === null || matcherCall.arguments.length !== 1) return null;
20717
+ const matcher = ASTUtils60.getPropertyName(matcherCallee) ?? "";
20607
20718
  if (SNAPSHOT_MATCHERS.test(matcher)) return null;
20608
20719
  const chain = expectCallFromMatcher(matcherCallee);
20609
20720
  const expectCallee = chain === null ? null : unwrapExpression(chain.call.callee);
@@ -20613,7 +20724,7 @@ function assertionShape(statement, context, callback) {
20613
20724
  const observedCallee = observed?.type === AST_NODE_TYPES98.CallExpression ? unwrapExpression(observed.callee) : null;
20614
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;
20615
20726
  const skeleton = `${observedCallee.name}/${observed.arguments.map((item) => staticShape(item)).join(",")}/${chain.modifiers.join(".")}/${matcher}/${staticShape(expected)}`;
20616
- const binding = ASTUtils59.findVariable(context.sourceCode.getScope(observedCallee), observedCallee.name);
20727
+ const binding = ASTUtils60.findVariable(context.sourceCode.getScope(observedCallee), observedCallee.name);
20617
20728
  if (binding?.defs.some(
20618
20729
  (definition) => definition.node.range[0] >= callback.range[0] && definition.node.range[1] <= callback.range[1]
20619
20730
  )) return null;
@@ -20624,7 +20735,7 @@ function expectCallFromMatcher(node) {
20624
20735
  const modifiers = [];
20625
20736
  let receiver = node.object;
20626
20737
  while (receiver.type === AST_NODE_TYPES98.MemberExpression) {
20627
- const modifier = ASTUtils59.getPropertyName(receiver);
20738
+ const modifier = ASTUtils60.getPropertyName(receiver);
20628
20739
  if (modifier === null || !EXPECT_MODIFIERS.has(modifier)) return null;
20629
20740
  modifiers.unshift(modifier);
20630
20741
  receiver = receiver.object;
@@ -20700,7 +20811,7 @@ var repeated_static_call_cases_default = createRule({
20700
20811
  });
20701
20812
 
20702
20813
  // src/rules/prefer-zod-infer.ts
20703
- import { ASTUtils as ASTUtils60, AST_NODE_TYPES as AST_NODE_TYPES99 } from "@typescript-eslint/utils";
20814
+ import { ASTUtils as ASTUtils61, AST_NODE_TYPES as AST_NODE_TYPES99 } from "@typescript-eslint/utils";
20704
20815
  var PREFER_ZOD_INFER_DOCUMENTATION = {
20705
20816
  summary: "Derive a type from its Zod schema with `z.infer` instead of hand-writing a twin declaration beside it.",
20706
20817
  rationale: "A derived type stays synchronized when the runtime schema changes.",
@@ -21018,7 +21129,7 @@ function twinCallChain(node, zodNamespaces) {
21018
21129
  while (current.type === AST_NODE_TYPES99.CallExpression) {
21019
21130
  const callee = unwrapExpression(current.callee);
21020
21131
  const calleeReceiver = callee.type === AST_NODE_TYPES99.MemberExpression ? unwrapExpression(callee.object) : callee;
21021
- if (callee.type !== AST_NODE_TYPES99.MemberExpression || ASTUtils60.getPropertyName(callee) === null) {
21132
+ if (callee.type !== AST_NODE_TYPES99.MemberExpression || ASTUtils61.getPropertyName(callee) === null) {
21022
21133
  return null;
21023
21134
  }
21024
21135
  chain.push(current);
@@ -21031,7 +21142,7 @@ function twinCallChain(node, zodNamespaces) {
21031
21142
  }
21032
21143
  function twinMethodName(call) {
21033
21144
  const callee = unwrapExpression(call.callee);
21034
- return callee.type === AST_NODE_TYPES99.MemberExpression && ASTUtils60.getPropertyName(callee) !== null ? ASTUtils60.getPropertyName(callee) ?? "" : "";
21145
+ return callee.type === AST_NODE_TYPES99.MemberExpression && ASTUtils61.getPropertyName(callee) !== null ? ASTUtils61.getPropertyName(callee) ?? "" : "";
21035
21146
  }
21036
21147
  function twinSchemaFields(initializer, zodNamespaces) {
21037
21148
  const chain = twinCallChain(initializer, zodNamespaces);
@@ -21046,7 +21157,7 @@ function twinSchemaFields(initializer, zodNamespaces) {
21046
21157
  const fields = /* @__PURE__ */ new Map();
21047
21158
  for (const property of shape.properties) {
21048
21159
  if (property.type !== AST_NODE_TYPES99.Property) return null;
21049
- const name = ASTUtils60.getPropertyName(property);
21160
+ const name = ASTUtils61.getPropertyName(property);
21050
21161
  if (name === null) return null;
21051
21162
  fields.set(name, twinSchemaField(property.value, zodNamespaces));
21052
21163
  }
@@ -21060,16 +21171,16 @@ function twinSchemaField(node, zodNamespaces) {
21060
21171
  while (current.type === AST_NODE_TYPES99.CallExpression) {
21061
21172
  const callee = unwrapExpression(current.callee);
21062
21173
  const calleeReceiver = callee.type === AST_NODE_TYPES99.MemberExpression ? unwrapExpression(callee.object) : callee;
21063
- if (callee.type !== AST_NODE_TYPES99.MemberExpression || ASTUtils60.getPropertyName(callee) === null) {
21174
+ if (callee.type !== AST_NODE_TYPES99.MemberExpression || ASTUtils61.getPropertyName(callee) === null) {
21064
21175
  break;
21065
21176
  }
21066
21177
  const receiver = calleeReceiver;
21067
21178
  if (receiver.type === AST_NODE_TYPES99.Identifier && zodNamespaces.has(receiver.name)) {
21068
- leaf = ASTUtils60.getPropertyName(callee) ?? "";
21179
+ leaf = ASTUtils61.getPropertyName(callee) ?? "";
21069
21180
  leafCall = current;
21070
21181
  break;
21071
21182
  }
21072
- modifiers.push(ASTUtils60.getPropertyName(callee) ?? "");
21183
+ modifiers.push(ASTUtils61.getPropertyName(callee) ?? "");
21073
21184
  current = receiver;
21074
21185
  }
21075
21186
  return {
@@ -21272,7 +21383,7 @@ var prefer_zod_infer_default = createRule({
21272
21383
  },
21273
21384
  /** Records `XSchema.transform(...)` and equivalent module-level reshaping. */
21274
21385
  "MemberExpression"(node) {
21275
- if (node.object.type === AST_NODE_TYPES99.Identifier && ASTUtils60.getPropertyName(node) !== null && isPreferZodInferModuleReshaper(ASTUtils60.getPropertyName(node) ?? "")) {
21386
+ if (node.object.type === AST_NODE_TYPES99.Identifier && ASTUtils61.getPropertyName(node) !== null && isPreferZodInferModuleReshaper(ASTUtils61.getPropertyName(node) ?? "")) {
21276
21387
  reshapedSchemaNames.add(node.object.name);
21277
21388
  }
21278
21389
  },
@@ -21429,7 +21540,7 @@ function staticFieldName(key) {
21429
21540
  }
21430
21541
 
21431
21542
  // src/rules/named-child-schema-type.ts
21432
- import { AST_NODE_TYPES as AST_NODE_TYPES100, ASTUtils as ASTUtils61 } from "@typescript-eslint/utils";
21543
+ import { AST_NODE_TYPES as AST_NODE_TYPES100, ASTUtils as ASTUtils62 } from "@typescript-eslint/utils";
21433
21544
  var UNRESOLVED_TYPE_NODES = /* @__PURE__ */ new Set([
21434
21545
  AST_NODE_TYPES100.TSTypeQuery,
21435
21546
  AST_NODE_TYPES100.TSImportType,
@@ -21438,17 +21549,17 @@ var UNRESOLVED_TYPE_NODES = /* @__PURE__ */ new Set([
21438
21549
  AST_NODE_TYPES100.TSUnknownKeyword
21439
21550
  ]);
21440
21551
  var NAMED_CHILD_SCHEMA_TYPE_DOCUMENTATION = {
21441
- defaultLevel: "warning",
21552
+ defaultLevel: "error",
21442
21553
  summary: "Reference a named Zod record child's complete schema type instead of repeating its explicit annotation.",
21443
21554
  rationale: "Repeating a child schema's generic contract creates a second maintained declaration even though the record already uses that child at runtime.",
21444
- remediation: "Replace only the matching record type argument with `typeof ChildSchema`; retain the outer annotation required by isolatedDeclarations and every runtime schema operation.",
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.",
21445
21556
  category: "maintainability",
21446
21557
  autofix: "none",
21447
21558
  limitations: [
21448
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.",
21449
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.",
21450
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.",
21451
- "Import aliases and namespace imports resolve through scope bindings. Independent public contract pins require review; this warning does not remove annotations or change runtime validation."
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."
21452
21563
  ],
21453
21564
  examples: [
21454
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 },
@@ -21467,14 +21578,14 @@ var named_child_schema_type_default = createRule({
21467
21578
  type: "suggestion",
21468
21579
  docs: { description: NAMED_CHILD_SCHEMA_TYPE_DOCUMENTATION.summary },
21469
21580
  schema: [],
21470
- 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." }
21471
21582
  },
21472
21583
  defaultOptions: [],
21473
21584
  create(context) {
21474
21585
  const source = context.sourceCode;
21475
21586
  if (isGeneratedFile(context.filename, source.text)) return {};
21476
21587
  const namespaces = /* @__PURE__ */ new Set();
21477
- const bindingOf = (node) => ASTUtils61.findVariable(source.getScope(node), node.name);
21588
+ const bindingOf = (node) => ASTUtils62.findVariable(source.getScope(node), node.name);
21478
21589
  function namespaceOf(type) {
21479
21590
  if (type.typeName.type !== AST_NODE_TYPES100.TSQualifiedName || type.typeName.left.type !== AST_NODE_TYPES100.Identifier) return null;
21480
21591
  const binding = bindingOf(type.typeName.left);
@@ -21518,7 +21629,7 @@ var named_child_schema_type_default = createRule({
21518
21629
  VariableDeclarator(node) {
21519
21630
  if (!isModuleConst(node) || node.id.type !== AST_NODE_TYPES100.Identifier || node.init?.type !== AST_NODE_TYPES100.CallExpression) return;
21520
21631
  const call = node.init;
21521
- if (call.arguments.length !== 2 || call.callee.type !== AST_NODE_TYPES100.MemberExpression || call.callee.object.type !== AST_NODE_TYPES100.Identifier || ASTUtils61.getPropertyName(call.callee) !== "record") return;
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;
21522
21633
  const annotation = node.id.typeAnnotation?.typeAnnotation;
21523
21634
  if (annotation?.type !== AST_NODE_TYPES100.TSTypeReference || annotation.typeName.type !== AST_NODE_TYPES100.TSQualifiedName || annotation.typeName.right.name !== "ZodRecord") return;
21524
21635
  const namespace = namespaceOf(annotation);
@@ -21534,7 +21645,7 @@ var named_child_schema_type_default = createRule({
21534
21645
 
21535
21646
  // src/rules/prefer-zod-parse-output-type.ts
21536
21647
  import {
21537
- ASTUtils as ASTUtils62,
21648
+ ASTUtils as ASTUtils63,
21538
21649
  AST_NODE_TYPES as AST_NODE_TYPES101,
21539
21650
  ESLintUtils as ESLintUtils14
21540
21651
  } from "@typescript-eslint/utils";
@@ -21604,11 +21715,11 @@ function isLocalZodObjectSchema(node, namespaces) {
21604
21715
  while (current.type === AST_NODE_TYPES101.CallExpression) {
21605
21716
  const callee = unwrapExpression(current.callee);
21606
21717
  const calleeReceiver = callee.type === AST_NODE_TYPES101.MemberExpression ? unwrapExpression(callee.object) : callee;
21607
- if (callee.type !== AST_NODE_TYPES101.MemberExpression || ASTUtils62.getPropertyName(callee) === null) {
21718
+ if (callee.type !== AST_NODE_TYPES101.MemberExpression || ASTUtils63.getPropertyName(callee) === null) {
21608
21719
  return false;
21609
21720
  }
21610
21721
  if (calleeReceiver.type === AST_NODE_TYPES101.Identifier) {
21611
- return namespaces.has(calleeReceiver.name) && ((ASTUtils62.getPropertyName(callee) ?? "") === "object" || (ASTUtils62.getPropertyName(callee) ?? "") === "strictObject");
21722
+ return namespaces.has(calleeReceiver.name) && ((ASTUtils63.getPropertyName(callee) ?? "") === "object" || (ASTUtils63.getPropertyName(callee) ?? "") === "strictObject");
21612
21723
  }
21613
21724
  current = calleeReceiver;
21614
21725
  }
@@ -21617,10 +21728,10 @@ function isLocalZodObjectSchema(node, namespaces) {
21617
21728
  function zodParseCall(node) {
21618
21729
  const callee = unwrapExpression(node.callee);
21619
21730
  const calleeReceiver = callee.type === AST_NODE_TYPES101.MemberExpression ? unwrapExpression(callee.object) : callee;
21620
- if (callee.type !== AST_NODE_TYPES101.MemberExpression || calleeReceiver.type !== AST_NODE_TYPES101.Identifier || ASTUtils62.getPropertyName(callee) === null) {
21731
+ if (callee.type !== AST_NODE_TYPES101.MemberExpression || calleeReceiver.type !== AST_NODE_TYPES101.Identifier || ASTUtils63.getPropertyName(callee) === null) {
21621
21732
  return null;
21622
21733
  }
21623
- const method = ASTUtils62.getPropertyName(callee);
21734
+ const method = ASTUtils63.getPropertyName(callee);
21624
21735
  if (method !== "parse" && method !== "safeParse") return null;
21625
21736
  return {
21626
21737
  call: node,
@@ -21662,7 +21773,7 @@ function localParseReturnCandidates(node, sourceCode) {
21662
21773
  for (const reference of variable.references) {
21663
21774
  const identifier = reference.identifier;
21664
21775
  const parent = identifier.parent;
21665
- const output = parsed.method === "parse" ? identifier : parent.type === AST_NODE_TYPES101.MemberExpression && parent.object === identifier && ASTUtils62.getPropertyName(parent) !== null && (ASTUtils62.getPropertyName(parent) ?? "") === "data" ? parent : null;
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;
21666
21777
  if (output === null) continue;
21667
21778
  const candidate2 = returnedOutputCandidate(parsed, output);
21668
21779
  if (candidate2 !== null) candidates.push(candidate2);
@@ -22045,7 +22156,7 @@ var require_assert_never_default = createRule({
22045
22156
  });
22046
22157
 
22047
22158
  // src/rules/require-fetch-timeout.ts
22048
- import { AST_NODE_TYPES as AST_NODE_TYPES103, ASTUtils as ASTUtils63 } from "@typescript-eslint/utils";
22159
+ import { AST_NODE_TYPES as AST_NODE_TYPES103, ASTUtils as ASTUtils64 } from "@typescript-eslint/utils";
22049
22160
  var REQUIRE_FETCH_TIMEOUT_DOCUMENTATION = {
22050
22161
  summary: "Require an explicit abort signal on locally analyzable global fetch calls.",
22051
22162
  rationale: "An unbounded request can occupy work indefinitely when an upstream stalls.",
@@ -22129,7 +22240,7 @@ var require_fetch_timeout_default = createRule({
22129
22240
  }
22130
22241
  function resolvesToGlobal(identifier) {
22131
22242
  const scope = context.sourceCode.getScope(identifier);
22132
- const variable = ASTUtils63.findVariable(scope, identifier.name);
22243
+ const variable = ASTUtils64.findVariable(scope, identifier.name);
22133
22244
  return variable === null || variable.defs.length === 0;
22134
22245
  }
22135
22246
  function isGlobalFetchCall2(callee) {
@@ -22139,7 +22250,7 @@ var require_fetch_timeout_default = createRule({
22139
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);
22140
22251
  }
22141
22252
  function localConstInitProvablyLacksSignal(identifier) {
22142
- const variable = ASTUtils63.findVariable(
22253
+ const variable = ASTUtils64.findVariable(
22143
22254
  context.sourceCode.getScope(identifier),
22144
22255
  identifier.name
22145
22256
  );
@@ -22161,7 +22272,7 @@ var require_fetch_timeout_default = createRule({
22161
22272
  function isForwardedRequest(argument) {
22162
22273
  let value = argument;
22163
22274
  if (value.type === AST_NODE_TYPES103.Identifier) {
22164
- const binding = ASTUtils63.findVariable(context.sourceCode.getScope(value), value.name);
22275
+ const binding = ASTUtils64.findVariable(context.sourceCode.getScope(value), value.name);
22165
22276
  const definition = binding?.defs.length === 1 ? binding.defs[0] : void 0;
22166
22277
  if (definition?.type !== "Variable" || definition.parent.kind !== "const" || definition.node.init === null || binding?.references.some((reference) => reference.isWrite() && reference.init !== true)) return false;
22167
22278
  value = definition.node.init;
@@ -22336,7 +22447,7 @@ function exportedClasses(program, classes) {
22336
22447
  }
22337
22448
 
22338
22449
  // src/rules/require-sql-access-class.ts
22339
- import { AST_NODE_TYPES as AST_NODE_TYPES105, ASTUtils as ASTUtils64 } from "@typescript-eslint/utils";
22450
+ import { AST_NODE_TYPES as AST_NODE_TYPES105, ASTUtils as ASTUtils65 } from "@typescript-eslint/utils";
22340
22451
  var DIRECT_EXECUTION_METHODS = /* @__PURE__ */ new Set([
22341
22452
  "all",
22342
22453
  "batch",
@@ -22443,7 +22554,7 @@ function databaseReceiver(node) {
22443
22554
  if (node.type === AST_NODE_TYPES105.Identifier)
22444
22555
  return DATABASE_NAMES.test(node.name);
22445
22556
  if (node.type !== AST_NODE_TYPES105.MemberExpression) return false;
22446
- const name = ASTUtils64.getPropertyName(node);
22557
+ const name = ASTUtils65.getPropertyName(node);
22447
22558
  return name === "DB" || name !== null && DATABASE_NAMES.test(name);
22448
22559
  }
22449
22560
  function databaseRootMember(node) {
@@ -22461,7 +22572,7 @@ function databaseRootMember(node) {
22461
22572
  }
22462
22573
  if (current.type === AST_NODE_TYPES105.MemberExpression) {
22463
22574
  if (current.object.type === AST_NODE_TYPES105.ThisExpression)
22464
- return ASTUtils64.getPropertyName(current);
22575
+ return ASTUtils65.getPropertyName(current);
22465
22576
  current = current.object;
22466
22577
  continue;
22467
22578
  }
@@ -22482,7 +22593,7 @@ function expressionHasDatabaseMarker(node) {
22482
22593
  continue;
22483
22594
  }
22484
22595
  if (current.type === AST_NODE_TYPES105.MemberExpression) {
22485
- const name = ASTUtils64.getPropertyName(current);
22596
+ const name = ASTUtils65.getPropertyName(current);
22486
22597
  if (name === "DB" || name !== null && DATABASE_NAMES.test(name))
22487
22598
  return true;
22488
22599
  current = current.object;
@@ -22501,7 +22612,7 @@ function expressionCallsBuilder(node) {
22501
22612
  }
22502
22613
  if (current.type === AST_NODE_TYPES105.CallExpression) {
22503
22614
  if (current.callee.type !== AST_NODE_TYPES105.MemberExpression) return false;
22504
- const name = ASTUtils64.getPropertyName(current.callee);
22615
+ const name = ASTUtils65.getPropertyName(current.callee);
22505
22616
  if (name !== null && BUILDER_METHODS.has(name)) return true;
22506
22617
  current = current.callee.object;
22507
22618
  continue;
@@ -22552,7 +22663,7 @@ function thisRootMember(node) {
22552
22663
  let current = node;
22553
22664
  let root = null;
22554
22665
  while (current.type === AST_NODE_TYPES105.MemberExpression) {
22555
- const name = ASTUtils64.getPropertyName(current);
22666
+ const name = ASTUtils65.getPropertyName(current);
22556
22667
  if (name === null) return null;
22557
22668
  root = name;
22558
22669
  current = current.object;
@@ -22596,19 +22707,19 @@ var require_sql_access_class_default = createRule({
22596
22707
  if (seen.has(node)) return false;
22597
22708
  seen.add(node);
22598
22709
  if (node.type === AST_NODE_TYPES105.Identifier) {
22599
- const binding = ASTUtils64.findVariable(context.sourceCode.getScope(node), node.name);
22710
+ const binding = ASTUtils65.findVariable(context.sourceCode.getScope(node), node.name);
22600
22711
  if (binding?.defs.length !== 1 || binding.references.some((reference) => reference.isWrite() && reference.init !== true)) return false;
22601
22712
  const definition = binding.defs[0];
22602
22713
  return definition?.type === "Variable" && definition.node.init !== null && knownNonDatabase(definition.node.init, seen);
22603
22714
  }
22604
- return node.type === AST_NODE_TYPES105.NewExpression && unwrappedNodeCallee?.type === AST_NODE_TYPES105.Identifier && ["Map", "WeakMap", "URLSearchParams"].includes(unwrappedNodeCallee.name) && (ASTUtils64.findVariable(context.sourceCode.getScope(unwrappedNodeCallee), unwrappedNodeCallee.name)?.defs.length ?? 0) === 0;
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;
22605
22716
  }
22606
22717
  return {
22607
22718
  CallExpression(node) {
22608
22719
  const unwrappedNodeCallee = unwrapExpression(node.callee);
22609
22720
  if (unwrappedNodeCallee.type !== AST_NODE_TYPES105.MemberExpression)
22610
22721
  return;
22611
- const method = ASTUtils64.getPropertyName(unwrappedNodeCallee);
22722
+ const method = ASTUtils65.getPropertyName(unwrappedNodeCallee);
22612
22723
  if (knownNonDatabase(unwrappedNodeCallee.object)) return;
22613
22724
  if (method === null || !isDatabaseOperation(method, unwrappedNodeCallee.object))
22614
22725
  return;
@@ -22708,7 +22819,7 @@ var require_static_next_matcher_default = createRule({
22708
22819
  });
22709
22820
 
22710
22821
  // src/rules/require-use-form-default-values.ts
22711
- import { AST_NODE_TYPES as AST_NODE_TYPES107, ASTUtils as ASTUtils65 } from "@typescript-eslint/utils";
22822
+ import { AST_NODE_TYPES as AST_NODE_TYPES107, ASTUtils as ASTUtils66 } from "@typescript-eslint/utils";
22712
22823
  var REQUIRE_USE_FORM_DEFAULT_VALUES_DOCUMENTATION = {
22713
22824
  summary: "Require explicit form-level initialization or a field default for directly bound Controller fields.",
22714
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.",
@@ -22759,7 +22870,7 @@ var require_use_form_default_values_default = createRule({
22759
22870
  const imported = /* @__PURE__ */ new Map();
22760
22871
  const uninitializedForms = /* @__PURE__ */ new Set();
22761
22872
  const uninitializedControls = /* @__PURE__ */ new Set();
22762
- const bindingNamed = (node, name) => ASTUtils65.findVariable(context.sourceCode.getScope(node), name);
22873
+ const bindingNamed = (node, name) => ASTUtils66.findVariable(context.sourceCode.getScope(node), name);
22763
22874
  const bindingOf = (node) => bindingNamed(node, node.name);
22764
22875
  const stable = (variable) => !variable.references.some((reference) => reference.isWrite() && reference.init !== true);
22765
22876
  const importedKind = (node) => {
@@ -22805,7 +22916,7 @@ var require_use_form_default_values_default = createRule({
22805
22916
  const variable = bindingOf(node);
22806
22917
  return variable !== null && stable(variable) && uninitializedControls.has(variable);
22807
22918
  }
22808
- return node.type === AST_NODE_TYPES107.MemberExpression && ASTUtils65.getPropertyName(node) !== null && (ASTUtils65.getPropertyName(node) ?? "") === "control" && isUninitializedForm(node.object);
22919
+ return node.type === AST_NODE_TYPES107.MemberExpression && ASTUtils66.getPropertyName(node) !== null && (ASTUtils66.getPropertyName(node) ?? "") === "control" && isUninitializedForm(node.object);
22809
22920
  };
22810
22921
  const fieldOptionsNeedDefault = (node) => {
22811
22922
  if (node?.type !== AST_NODE_TYPES107.ObjectExpression) return false;
@@ -22861,7 +22972,7 @@ var require_use_form_default_values_default = createRule({
22861
22972
  trackDestructuredControl(node.id);
22862
22973
  return;
22863
22974
  }
22864
- if (node.id.type === AST_NODE_TYPES107.Identifier && node.init.type === AST_NODE_TYPES107.MemberExpression && ASTUtils65.getPropertyName(node.init) !== null && (ASTUtils65.getPropertyName(node.init) ?? "") === "control" && isUninitializedForm(node.init.object)) {
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)) {
22865
22976
  const variable = bindingOf(node.id);
22866
22977
  if (variable !== null) uninitializedControls.add(variable);
22867
22978
  }
@@ -22954,7 +23065,7 @@ var require_use_server_in_actions_file_default = createRule({
22954
23065
  // src/rules/require-zod-form-validation.ts
22955
23066
  import {
22956
23067
  AST_NODE_TYPES as AST_NODE_TYPES108,
22957
- ASTUtils as ASTUtils66
23068
+ ASTUtils as ASTUtils67
22958
23069
  } from "@typescript-eslint/utils";
22959
23070
  var REQUIRE_ZOD_FORM_VALIDATION_DOCUMENTATION = {
22960
23071
  summary: "Require Zod validation (`Schema.parse(...)` / `Schema.safeParse(...)`) when reading values out of a `FormData` object.",
@@ -23002,7 +23113,7 @@ var isFormDataMethodCall = (node) => {
23002
23113
  }
23003
23114
  if (current.type !== AST_NODE_TYPES108.CallExpression) return false;
23004
23115
  const callee = unwrapExpression(current.callee);
23005
- return callee.type === AST_NODE_TYPES108.MemberExpression && ASTUtils66.getPropertyName(callee) === "formData";
23116
+ return callee.type === AST_NODE_TYPES108.MemberExpression && ASTUtils67.getPropertyName(callee) === "formData";
23006
23117
  };
23007
23118
  var require_zod_form_validation_default = createRule({
23008
23119
  name: "require-zod-form-validation",
@@ -23023,7 +23134,7 @@ var require_zod_form_validation_default = createRule({
23023
23134
  return {};
23024
23135
  }
23025
23136
  const zodBindings = /* @__PURE__ */ new Set();
23026
- const resolvedBinding = (identifier) => ASTUtils66.findVariable(
23137
+ const resolvedBinding = (identifier) => ASTUtils67.findVariable(
23027
23138
  context.sourceCode.getScope(identifier),
23028
23139
  identifier.name
23029
23140
  );
@@ -23031,7 +23142,7 @@ var require_zod_form_validation_default = createRule({
23031
23142
  const callee = unwrapExpression(node.callee);
23032
23143
  const calleeReceiver = callee.type === AST_NODE_TYPES108.MemberExpression ? unwrapExpression(callee.object) : callee;
23033
23144
  if (callee.type !== AST_NODE_TYPES108.MemberExpression) return false;
23034
- if (ASTUtils66.getPropertyName(callee) === null || !FORM_VALUE_METHODS.has(ASTUtils66.getPropertyName(callee) ?? "")) {
23145
+ if (ASTUtils67.getPropertyName(callee) === null || !FORM_VALUE_METHODS.has(ASTUtils67.getPropertyName(callee) ?? "")) {
23035
23146
  return false;
23036
23147
  }
23037
23148
  return isFormSourceIdentifier(calleeReceiver);
@@ -23062,7 +23173,7 @@ var require_zod_form_validation_default = createRule({
23062
23173
  parent = parent.parent;
23063
23174
  continue;
23064
23175
  }
23065
- 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" && ASTUtils66.getPropertyName(parent.callee) === "fromEntries" && (resolvedBinding(parent.callee.object)?.defs.length ?? 0) === 0) {
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) {
23066
23177
  parent = parent.parent;
23067
23178
  continue;
23068
23179
  }
@@ -23075,7 +23186,7 @@ var require_zod_form_validation_default = createRule({
23075
23186
  if (node.type !== AST_NODE_TYPES108.CallExpression) return false;
23076
23187
  const callee = unwrapExpression(node.callee);
23077
23188
  const calleeReceiver = callee.type === AST_NODE_TYPES108.MemberExpression ? unwrapExpression(callee.object) : callee;
23078
- if (callee.type !== AST_NODE_TYPES108.MemberExpression || ASTUtils66.getPropertyName(callee) === null || !ZOD_PARSE_METHODS.has(ASTUtils66.getPropertyName(callee) ?? "")) {
23189
+ if (callee.type !== AST_NODE_TYPES108.MemberExpression || ASTUtils67.getPropertyName(callee) === null || !ZOD_PARSE_METHODS.has(ASTUtils67.getPropertyName(callee) ?? "")) {
23079
23190
  return false;
23080
23191
  }
23081
23192
  const root = zodReceiverRoot(calleeReceiver);
@@ -23161,7 +23272,7 @@ var require_zod_form_validation_default = createRule({
23161
23272
  };
23162
23273
  const zodParseMethod = (call) => {
23163
23274
  const callee = unwrapExpression(call.callee);
23164
- return callee.type === AST_NODE_TYPES108.MemberExpression && ASTUtils66.getPropertyName(callee) !== null ? ASTUtils66.getPropertyName(callee) ?? "" : null;
23275
+ return callee.type === AST_NODE_TYPES108.MemberExpression && ASTUtils67.getPropertyName(callee) !== null ? ASTUtils67.getPropertyName(callee) ?? "" : null;
23165
23276
  };
23166
23277
  const isSafePrevalidationInspection = (identifier) => {
23167
23278
  const parent = identifier.parent;
@@ -23337,7 +23448,7 @@ function expressionCallableName(current) {
23337
23448
  }
23338
23449
 
23339
23450
  // src/rules/stepdown.ts
23340
- import { AST_NODE_TYPES as AST_NODE_TYPES109, ASTUtils as ASTUtils67 } from "@typescript-eslint/utils";
23451
+ import { AST_NODE_TYPES as AST_NODE_TYPES109, ASTUtils as ASTUtils68 } from "@typescript-eslint/utils";
23341
23452
  var STEPDOWN_DOCUMENTATION = {
23342
23453
  summary: "Place a private helper below its sole direct same-scope caller.",
23343
23454
  rationale: "Caller-first ordering lets a reader follow the main flow before descending into implementation details.",
@@ -23637,7 +23748,7 @@ function receiverOrigin(context, object, receivers) {
23637
23748
  while (true) {
23638
23749
  const unwrapped = unwrapExpression4(current);
23639
23750
  if (unwrapped.type !== AST_NODE_TYPES109.Identifier) return unwrapped;
23640
- const variable = ASTUtils67.findVariable(context.sourceCode.getScope(unwrapped), unwrapped.name);
23751
+ const variable = ASTUtils68.findVariable(context.sourceCode.getScope(unwrapped), unwrapped.name);
23641
23752
  if (variable === null) return null;
23642
23753
  const known = receivers.get(variable);
23643
23754
  if (known !== void 0) return known;
@@ -23818,11 +23929,11 @@ function classScope(context, node, computedReferences) {
23818
23929
  function classReceiverBindings(context, node) {
23819
23930
  const classReceivers = /* @__PURE__ */ new Map();
23820
23931
  if (node.id !== null) {
23821
- const internal = ASTUtils67.findVariable(context.sourceCode.getScope(node), node.id.name);
23932
+ const internal = ASTUtils68.findVariable(context.sourceCode.getScope(node), node.id.name);
23822
23933
  if (internal !== null && stableVariable(internal)) classReceivers.set(internal, true);
23823
23934
  }
23824
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") {
23825
- const outer = ASTUtils67.findVariable(context.sourceCode.getScope(node.parent), node.parent.id.name);
23936
+ const outer = ASTUtils68.findVariable(context.sourceCode.getScope(node.parent), node.parent.id.name);
23826
23937
  if (outer !== null && stableVariable(outer)) classReceivers.set(outer, true);
23827
23938
  }
23828
23939
  return classReceivers;
@@ -23908,7 +24019,7 @@ function classMethodCounts(body2, methods) {
23908
24019
  }
23909
24020
 
23910
24021
  // src/rules/source-coupled-test.ts
23911
- import { AST_NODE_TYPES as AST_NODE_TYPES110, ASTUtils as ASTUtils68 } from "@typescript-eslint/utils";
24022
+ import { AST_NODE_TYPES as AST_NODE_TYPES110, ASTUtils as ASTUtils69 } from "@typescript-eslint/utils";
23912
24023
  var GENERAL_SOURCE_SUFFIX_RE = /\.(?:bash|sh|ya?ml|jsonc?|toml|py|[cm]?[jt]s)$/iu;
23913
24024
  var FS_MODULES = /* @__PURE__ */ new Set(["fs", "node:fs", "fs/promises", "node:fs/promises"]);
23914
24025
  var FS_READERS = /* @__PURE__ */ new Set(["readFile", "readFileSync"]);
@@ -24025,7 +24136,7 @@ function createSourceCoupledRule(name, documentation, sourceSuffixRe) {
24025
24136
  const scopes = [newScope()];
24026
24137
  const reportedOrigins = /* @__PURE__ */ new Set();
24027
24138
  const currentScope = () => scopes.at(-1) ?? scopes[0];
24028
- const bindingOf = (node) => ASTUtils68.findVariable(context.sourceCode.getScope(node), node.name);
24139
+ const bindingOf = (node) => ASTUtils69.findVariable(context.sourceCode.getScope(node), node.name);
24029
24140
  const assertionKind = (node) => {
24030
24141
  const binding = bindingOf(node);
24031
24142
  if (binding === null || binding.defs.length === 0) {
@@ -24078,7 +24189,7 @@ function createSourceCoupledRule(name, documentation, sourceSuffixRe) {
24078
24189
  return visible("fsReaders", callee) && sourcePath(current.arguments[0]);
24079
24190
  }
24080
24191
  if (callee.type !== AST_NODE_TYPES110.MemberExpression) return false;
24081
- const name2 = ASTUtils68.getPropertyName(callee);
24192
+ const name2 = ASTUtils69.getPropertyName(callee);
24082
24193
  const object = unwrap6(calleeReceiver);
24083
24194
  return name2 !== null && FS_READERS.has(name2) && object.type === AST_NODE_TYPES110.Identifier && visible("fsObjects", object) && sourcePath(current.arguments[0]);
24084
24195
  };
@@ -24087,12 +24198,12 @@ function createSourceCoupledRule(name, documentation, sourceSuffixRe) {
24087
24198
  if (current.type === AST_NODE_TYPES110.Identifier) return visibleRawOrigins(current);
24088
24199
  if (rawRead(current)) return /* @__PURE__ */ new Set([`${current.range[0]}:${current.range[1]}`]);
24089
24200
  if (current.type === AST_NODE_TYPES110.BinaryExpression && current.operator === "+") return /* @__PURE__ */ new Set([...rawOrigins(current.left), ...rawOrigins(current.right)]);
24090
- if (current.type === AST_NODE_TYPES110.MemberExpression && ASTUtils68.getPropertyName(current) === "length") return rawOrigins(current.object);
24201
+ if (current.type === AST_NODE_TYPES110.MemberExpression && ASTUtils69.getPropertyName(current) === "length") return rawOrigins(current.object);
24091
24202
  if (current.type !== AST_NODE_TYPES110.CallExpression) return /* @__PURE__ */ new Set();
24092
24203
  const callee = unwrap6(current.callee);
24093
24204
  const calleeReceiver = callee.type === AST_NODE_TYPES110.MemberExpression ? unwrapExpression(callee.object) : callee;
24094
24205
  if (callee.type !== AST_NODE_TYPES110.MemberExpression) return /* @__PURE__ */ new Set();
24095
- const name2 = ASTUtils68.getPropertyName(callee);
24206
+ const name2 = ASTUtils69.getPropertyName(callee);
24096
24207
  return name2 !== null && TEXT_TRANSFORMS.has(name2) ? rawOrigins(calleeReceiver) : /* @__PURE__ */ new Set();
24097
24208
  };
24098
24209
  const evidenceOrigins = (node) => {
@@ -24105,7 +24216,7 @@ function createSourceCoupledRule(name, documentation, sourceSuffixRe) {
24105
24216
  const callee = unwrap6(current.callee);
24106
24217
  const calleeReceiver = callee.type === AST_NODE_TYPES110.MemberExpression ? unwrapExpression(callee.object) : callee;
24107
24218
  if (callee.type !== AST_NODE_TYPES110.MemberExpression) return /* @__PURE__ */ new Set();
24108
- const name2 = ASTUtils68.getPropertyName(callee);
24219
+ const name2 = ASTUtils69.getPropertyName(callee);
24109
24220
  if (name2 !== null && TEXT_PREDICATES.has(name2)) return rawOrigins(calleeReceiver);
24110
24221
  if (name2 !== null && REGEXP_PREDICATES.has(name2)) return new Set(current.arguments.flatMap((argument) => argument.type === AST_NODE_TYPES110.SpreadElement ? [] : [...rawOrigins(argument)]));
24111
24222
  return /* @__PURE__ */ new Set();
@@ -24117,10 +24228,10 @@ function createSourceCoupledRule(name, documentation, sourceSuffixRe) {
24117
24228
  return new Set(node.arguments.flatMap((argument) => argument.type === AST_NODE_TYPES110.SpreadElement ? [] : [...evidenceOrigins(argument)]));
24118
24229
  }
24119
24230
  if (callee.type !== AST_NODE_TYPES110.MemberExpression) return /* @__PURE__ */ new Set();
24120
- const matcher = ASTUtils68.getPropertyName(callee);
24231
+ const matcher = ASTUtils69.getPropertyName(callee);
24121
24232
  if (matcher === null) return /* @__PURE__ */ new Set();
24122
24233
  let receiver = unwrap6(calleeReceiver);
24123
- while (receiver.type === AST_NODE_TYPES110.MemberExpression && EXPECT_MODIFIERS2.has(ASTUtils68.getPropertyName(receiver) ?? "")) receiver = unwrap6(receiver.object);
24234
+ while (receiver.type === AST_NODE_TYPES110.MemberExpression && EXPECT_MODIFIERS2.has(ASTUtils69.getPropertyName(receiver) ?? "")) receiver = unwrap6(receiver.object);
24124
24235
  const expectCallee = receiver.type === AST_NODE_TYPES110.CallExpression ? unwrapExpression(receiver.callee) : null;
24125
24236
  if (receiver.type === AST_NODE_TYPES110.CallExpression && expectCallee?.type === AST_NODE_TYPES110.Identifier && assertionKind(expectCallee) === "expect") {
24126
24237
  if (!EXPECT_MATCHERS.has(matcher)) return /* @__PURE__ */ new Set();
@@ -24403,7 +24514,7 @@ var iac_source_coupled_test_default = createSourceCoupledRule(
24403
24514
  // src/rules/require-pascal-case-zod-schema-name.ts
24404
24515
  import {
24405
24516
  AST_NODE_TYPES as AST_NODE_TYPES112,
24406
- ASTUtils as ASTUtils69
24517
+ ASTUtils as ASTUtils70
24407
24518
  } from "@typescript-eslint/utils";
24408
24519
  var REQUIRE_PASCAL_CASE_ZOD_SCHEMA_NAME_DOCUMENTATION = {
24409
24520
  summary: "Require confirmed module-level Zod schema contracts to use PascalCase with a `Schema` suffix.",
@@ -24536,7 +24647,7 @@ var SCHEMA_RETURNING_METHODS = /* @__PURE__ */ new Set([
24536
24647
  "superRefine",
24537
24648
  "transform"
24538
24649
  ]);
24539
- var terminalMethodName = (callee) => ASTUtils69.getPropertyName(callee) !== null ? ASTUtils69.getPropertyName(callee) ?? "" : null;
24650
+ var terminalMethodName = (callee) => ASTUtils70.getPropertyName(callee) !== null ? ASTUtils70.getPropertyName(callee) ?? "" : null;
24540
24651
  var calleeChainRoot2 = (node) => {
24541
24652
  let current = node;
24542
24653
  for (; ; ) {
@@ -24561,8 +24672,8 @@ var chainMemberNames2 = (node) => {
24561
24672
  for (; ; ) {
24562
24673
  current = unwrapExpression(current);
24563
24674
  if (current.type === AST_NODE_TYPES112.MemberExpression) {
24564
- if (ASTUtils69.getPropertyName(current) === null) return [];
24565
- names.push(ASTUtils69.getPropertyName(current) ?? "");
24675
+ if (ASTUtils70.getPropertyName(current) === null) return [];
24676
+ names.push(ASTUtils70.getPropertyName(current) ?? "");
24566
24677
  current = current.object;
24567
24678
  continue;
24568
24679
  }
@@ -24599,7 +24710,7 @@ var require_pascal_case_zod_schema_name_default = createRule({
24599
24710
  const zodBindings = /* @__PURE__ */ new Set();
24600
24711
  const schemaBindings = /* @__PURE__ */ new Set();
24601
24712
  function resolvedBinding(identifier) {
24602
- return ASTUtils69.findVariable(
24713
+ return ASTUtils70.findVariable(
24603
24714
  context.sourceCode.getScope(identifier),
24604
24715
  identifier.name
24605
24716
  );
@@ -24880,7 +24991,6 @@ var LIBRARY_IMPORT_POLICY = ["error", {
24880
24991
  }];
24881
24992
  var ADVISORY_RULES = [
24882
24993
  "@sarj/excessive-commentary",
24883
- "@sarj/named-child-schema-type",
24884
24994
  "@sarj/no-bespoke-api-case-conversion",
24885
24995
  "@sarj/no-duplicate-test-case",
24886
24996
  "@sarj/no-json-stringify-object-equality",
@@ -24889,21 +24999,18 @@ var ADVISORY_RULES = [
24889
24999
  "@sarj/prefer-millisecond-control-duration-schema",
24890
25000
  "@sarj/prefer-module-level-refined-schema",
24891
25001
  "@sarj/prefer-multi-value-zod-literal",
24892
- "@sarj/prefer-named-complex-return-type",
24893
25002
  "@sarj/prefer-node-crypto-hash",
24894
25003
  "@sarj/prefer-node-fs-promises",
24895
25004
  "@sarj/prefer-nominal-id-types",
24896
25005
  "@sarj/prefer-shared-zod-enum",
24897
- "@sarj/prefer-switch-for-repeated-equality",
24898
25006
  "@sarj/prefer-whole-object-assertion",
24899
25007
  "@sarj/require-camelcase-properties",
24900
- "@sarj/require-explicit-contract-implementation",
24901
25008
  "@sarj/require-explicit-service-contract",
24902
25009
  "@sarj/require-interface-for-exported-class",
24903
25010
  "@sarj/require-sql-access-class"
24904
25011
  ];
24905
25012
  var RECOMMENDED_RULES = {
24906
- "@sarj/named-child-schema-type": "warn",
25013
+ "@sarj/named-child-schema-type": "error",
24907
25014
  "@sarj/no-conditional-empty-object-spread": "error",
24908
25015
  "@sarj/prefer-typed-reflection": "error",
24909
25016
  "@sarj/no-broad-return-type": "error",
@@ -24987,7 +25094,7 @@ var RECOMMENDED_RULES = {
24987
25094
  "@sarj/prefer-multi-value-zod-literal": ["warn", { zodMajorVersion: 4 }],
24988
25095
  "@sarj/prefer-named-callback-domain": "error",
24989
25096
  "@sarj/prefer-nominal-id-types": "warn",
24990
- "@sarj/prefer-named-complex-return-type": "warn",
25097
+ "@sarj/prefer-named-complex-return-type": "error",
24991
25098
  "@sarj/prefer-node-crypto-hash": "warn",
24992
25099
  "@sarj/prefer-node-fs-promises": "warn",
24993
25100
  "@sarj/prefer-non-nullable-collection": "error",
@@ -24995,7 +25102,7 @@ var RECOMMENDED_RULES = {
24995
25102
  "@sarj/prefer-await-in-async-return": "error",
24996
25103
  "@sarj/prefer-schema-for-api-payload": "error",
24997
25104
  "@sarj/prefer-shared-zod-enum": "warn",
24998
- "@sarj/prefer-switch-for-repeated-equality": "warn",
25105
+ "@sarj/prefer-switch-for-repeated-equality": "error",
24999
25106
  "@sarj/prefer-semantic-colors": ["error", { requireSemanticTokens: true }],
25000
25107
  "@sarj/prefer-server-actions": "error",
25001
25108
  "@sarj/prefer-whole-object-assertion": "warn",
@@ -25004,7 +25111,7 @@ var RECOMMENDED_RULES = {
25004
25111
  "@sarj/prefer-zod-parse-output-type": "error",
25005
25112
  "@sarj/require-assert-never": "error",
25006
25113
  "@sarj/require-fetch-timeout": "error",
25007
- "@sarj/require-explicit-contract-implementation": "warn",
25114
+ "@sarj/require-explicit-contract-implementation": "error",
25008
25115
  "@sarj/require-explicit-service-contract": "warn",
25009
25116
  "@sarj/require-interface-for-exported-class": "warn",
25010
25117
  "@sarj/require-port-for-service": "error",
@@ -25021,7 +25128,7 @@ var RECOMMENDED_RULES = {
25021
25128
  "@sarj/require-pascal-case-zod-schema-name": "error"
25022
25129
  };
25023
25130
  var STRICT_RULES = {
25024
- "@sarj/named-child-schema-type": "warn",
25131
+ "@sarj/named-child-schema-type": "error",
25025
25132
  "@sarj/no-conditional-empty-object-spread": "error",
25026
25133
  "@sarj/prefer-typed-reflection": "error",
25027
25134
  "@sarj/no-broad-return-type": "error",
@@ -25109,7 +25216,7 @@ var STRICT_RULES = {
25109
25216
  "@sarj/prefer-multi-value-zod-literal": ["warn", { zodMajorVersion: 4 }],
25110
25217
  "@sarj/prefer-named-callback-domain": "error",
25111
25218
  "@sarj/prefer-nominal-id-types": "warn",
25112
- "@sarj/prefer-named-complex-return-type": "warn",
25219
+ "@sarj/prefer-named-complex-return-type": "error",
25113
25220
  "@sarj/prefer-node-crypto-hash": "warn",
25114
25221
  "@sarj/prefer-node-fs-promises": "warn",
25115
25222
  "@sarj/prefer-non-nullable-collection": "error",
@@ -25117,7 +25224,7 @@ var STRICT_RULES = {
25117
25224
  "@sarj/prefer-await-in-async-return": "error",
25118
25225
  "@sarj/prefer-schema-for-api-payload": "error",
25119
25226
  "@sarj/prefer-shared-zod-enum": "warn",
25120
- "@sarj/prefer-switch-for-repeated-equality": "warn",
25227
+ "@sarj/prefer-switch-for-repeated-equality": "error",
25121
25228
  "@sarj/prefer-semantic-colors": ["error", { requireSemanticTokens: true }],
25122
25229
  "@sarj/prefer-server-actions": "error",
25123
25230
  "@sarj/prefer-whole-object-assertion": "warn",
@@ -25126,7 +25233,7 @@ var STRICT_RULES = {
25126
25233
  "@sarj/prefer-zod-parse-output-type": "error",
25127
25234
  "@sarj/require-assert-never": "error",
25128
25235
  "@sarj/require-fetch-timeout": "error",
25129
- "@sarj/require-explicit-contract-implementation": "warn",
25236
+ "@sarj/require-explicit-contract-implementation": "error",
25130
25237
  "@sarj/require-explicit-service-contract": "warn",
25131
25238
  "@sarj/require-interface-for-exported-class": "warn",
25132
25239
  "@sarj/require-port-for-service": "error",