@sarj/eslint-plugin 15.8.1 → 15.9.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
@@ -4679,11 +4679,11 @@ var no_offset_pagination_default = createRule({
4679
4679
  // src/rules/no-positional-tuple-return.ts
4680
4680
  import { AST_NODE_TYPES as AST_NODE_TYPES18 } from "@typescript-eslint/utils";
4681
4681
  var noPositionalTupleReturnDocumentation = {
4682
- summary: "Disallow returning a multi-field tuple from an exported function; return a named object so call sites cannot mismatch slots.",
4683
- rationale: "Public tuple fields are identified only by position, so reordering can preserve types while changing meaning.",
4682
+ summary: "Disallow returning a multi-field tuple from a named function; return a named object so call sites cannot mismatch slots.",
4683
+ rationale: "Tuple fields are identified only by position, so reordering can preserve types while changing meaning.",
4684
4684
  remediation: "Return an object whose property names describe each value.",
4685
4685
  category: "maintainability",
4686
- limitations: ["Only declared multi-field tuple returns on public TypeScript surfaces are inspected."],
4686
+ limitations: ["Declared or syntax-proven multi-field tuple returns on named functions and public type surfaces are inspected; anonymous inline callbacks and syntax-proven TanStack Query key factories are excluded."],
4687
4687
  examples: [
4688
4688
  { id: "named-object-return", title: "Return named fields", outcome: "no-match", files: [{ path: "src/download.ts", source: "export function download(): { body: string; status: number } { return impl(); }" }], focusPath: "src/download.ts", expectedCount: 0, public: true },
4689
4689
  { id: "tuple-return", title: "Do not expose positional fields", outcome: "match", files: [{ path: "src/download.ts", source: "export function download(): [string, number] { return impl(); }" }], focusPath: "src/download.ts", expectedCount: 1, public: true }
@@ -4721,6 +4721,16 @@ function tupleReturnType(node, aliases, resolving = /* @__PURE__ */ new Set()) {
4721
4721
  }
4722
4722
  return null;
4723
4723
  }
4724
+ function tupleExpression(node, aliases) {
4725
+ if (node.type !== AST_NODE_TYPES18.TSAsExpression && node.type !== AST_NODE_TYPES18.TSSatisfiesExpression) {
4726
+ return null;
4727
+ }
4728
+ if (node.expression.type !== AST_NODE_TYPES18.ArrayExpression || node.expression.elements.length < MIN_ELEMENTS) {
4729
+ return null;
4730
+ }
4731
+ if (node.type === AST_NODE_TYPES18.TSAsExpression && node.typeAnnotation.type === AST_NODE_TYPES18.TSTypeReference && node.typeAnnotation.typeName.type === AST_NODE_TYPES18.Identifier && node.typeAnnotation.typeName.name === "const") return node.expression;
4732
+ return tupleReturnType(node.typeAnnotation, aliases) === null ? null : node.expression;
4733
+ }
4724
4734
  function functionName(node) {
4725
4735
  if (node.type === AST_NODE_TYPES18.FunctionDeclaration) {
4726
4736
  if (node.id !== null) return node.id.name;
@@ -4736,60 +4746,25 @@ function functionName(node) {
4736
4746
  return parent.id.name;
4737
4747
  }
4738
4748
  if ((parent?.type === AST_NODE_TYPES18.MethodDefinition || parent?.type === AST_NODE_TYPES18.TSAbstractMethodDefinition || parent?.type === AST_NODE_TYPES18.PropertyDefinition || parent?.type === AST_NODE_TYPES18.Property) && parent.key.type === AST_NODE_TYPES18.Identifier) {
4739
- if ((parent.type === AST_NODE_TYPES18.MethodDefinition || parent.type === AST_NODE_TYPES18.TSAbstractMethodDefinition || parent.type === AST_NODE_TYPES18.PropertyDefinition) && (parent.accessibility === "private" || parent.accessibility === "protected")) return null;
4740
4749
  return parent.key.name;
4741
4750
  }
4742
4751
  return null;
4743
4752
  }
4744
- function isInlineExported(node) {
4745
- if (moduleScopeBindingName(node) === null) return false;
4746
- for (let current = node; current != null; current = current.parent) {
4747
- const parent = current.parent;
4748
- if (parent?.type === AST_NODE_TYPES18.ExportNamedDeclaration || parent?.type === AST_NODE_TYPES18.ExportDefaultDeclaration) {
4749
- return true;
4750
- }
4751
- }
4752
- return false;
4753
- }
4754
- function moduleScopeBindingName(node) {
4755
- let current = node;
4756
- while (current.parent != null && current.parent.type !== AST_NODE_TYPES18.Program) {
4757
- current = current.parent;
4758
- }
4759
- if (current.parent?.type !== AST_NODE_TYPES18.Program) {
4760
- return null;
4761
- }
4762
- let topLevel = current;
4763
- if (current.type === AST_NODE_TYPES18.ExportNamedDeclaration || current.type === AST_NODE_TYPES18.ExportDefaultDeclaration) {
4764
- topLevel = current.declaration;
4765
- }
4766
- if (topLevel === null) return null;
4767
- if (topLevel.type === AST_NODE_TYPES18.FunctionDeclaration) {
4768
- if (topLevel !== node) return null;
4769
- return topLevel.id?.name ?? (current.type === AST_NODE_TYPES18.ExportDefaultDeclaration ? "default" : null);
4770
- }
4771
- if ((topLevel.type === AST_NODE_TYPES18.ArrowFunctionExpression || topLevel.type === AST_NODE_TYPES18.FunctionExpression) && topLevel === node && current.type === AST_NODE_TYPES18.ExportDefaultDeclaration) {
4772
- return "default";
4773
- }
4774
- if (topLevel.type === AST_NODE_TYPES18.ClassDeclaration) {
4775
- let owner = node.parent;
4776
- while (owner != null && owner.parent !== topLevel.body) owner = owner.parent;
4777
- return (owner?.type === AST_NODE_TYPES18.MethodDefinition || owner?.type === AST_NODE_TYPES18.TSAbstractMethodDefinition || owner?.type === AST_NODE_TYPES18.PropertyDefinition) && owner.value === node ? topLevel.id?.name ?? (current.type === AST_NODE_TYPES18.ExportDefaultDeclaration ? "default" : null) : null;
4778
- }
4779
- if (topLevel.type === AST_NODE_TYPES18.VariableDeclaration) {
4780
- for (const declarator of topLevel.declarations) {
4781
- let initializer = declarator.init;
4782
- while (initializer?.type === AST_NODE_TYPES18.TSAsExpression || initializer?.type === AST_NODE_TYPES18.TSSatisfiesExpression || initializer?.type === AST_NODE_TYPES18.TSNonNullExpression) initializer = initializer.expression;
4783
- if (declarator.id.type === AST_NODE_TYPES18.Identifier && initializer === node) return declarator.id.name;
4784
- if (declarator.id.type === AST_NODE_TYPES18.Identifier && (initializer?.type === AST_NODE_TYPES18.ClassExpression || initializer?.type === AST_NODE_TYPES18.ObjectExpression)) {
4785
- let owner = node.parent;
4786
- const container = initializer.type === AST_NODE_TYPES18.ClassExpression ? initializer.body : initializer;
4787
- while (owner != null && owner.parent !== container) owner = owner.parent;
4788
- if ((owner?.type === AST_NODE_TYPES18.MethodDefinition || owner?.type === AST_NODE_TYPES18.PropertyDefinition || owner?.type === AST_NODE_TYPES18.Property) && owner.value === node) return declarator.id.name;
4789
- }
4790
- }
4791
- }
4792
- return null;
4753
+ function isQueryKeyFactory(node) {
4754
+ let wrapped = node;
4755
+ while ((wrapped.parent?.type === AST_NODE_TYPES18.TSAsExpression || wrapped.parent?.type === AST_NODE_TYPES18.TSSatisfiesExpression || wrapped.parent?.type === AST_NODE_TYPES18.TSNonNullExpression) && wrapped.parent.expression === wrapped) wrapped = wrapped.parent;
4756
+ const property = wrapped.parent;
4757
+ if (property?.type !== AST_NODE_TYPES18.Property || property.value !== wrapped) return false;
4758
+ const object = property.parent;
4759
+ if (object.type !== AST_NODE_TYPES18.ObjectExpression) return false;
4760
+ const assertion = object.parent;
4761
+ if (assertion.type !== AST_NODE_TYPES18.TSAsExpression || assertion.expression !== object || assertion.typeAnnotation.type !== AST_NODE_TYPES18.TSTypeReference || assertion.typeAnnotation.typeName.type !== AST_NODE_TYPES18.Identifier || assertion.typeAnnotation.typeName.name !== "const") return false;
4762
+ const declarator = assertion.parent;
4763
+ if (declarator.type !== AST_NODE_TYPES18.VariableDeclarator || declarator.id.type !== AST_NODE_TYPES18.Identifier || !/Keys$/i.test(declarator.id.name) || declarator.parent.type !== AST_NODE_TYPES18.VariableDeclaration || declarator.parent.kind !== "const") return false;
4764
+ return object.properties.some((candidate) => {
4765
+ if (candidate.type !== AST_NODE_TYPES18.Property || staticMemberName3(candidate.key) !== "all") return false;
4766
+ return candidate.value.type === AST_NODE_TYPES18.TSAsExpression && candidate.value.expression.type === AST_NODE_TYPES18.ArrayExpression && candidate.value.typeAnnotation.type === AST_NODE_TYPES18.TSTypeReference && candidate.value.typeAnnotation.typeName.type === AST_NODE_TYPES18.Identifier && candidate.value.typeAnnotation.typeName.name === "const";
4767
+ });
4793
4768
  }
4794
4769
  function specifierExportedNames(program) {
4795
4770
  const names = /* @__PURE__ */ new Set();
@@ -4898,18 +4873,52 @@ function isExportedClass(node, specifierExports) {
4898
4873
  if (node.parent.type === AST_NODE_TYPES18.VariableDeclarator && node.parent.id.type === AST_NODE_TYPES18.Identifier) return specifierExports.has(node.parent.id.name) || isInlineExported(node);
4899
4874
  return false;
4900
4875
  }
4901
- function isExportedInterface(node, exports) {
4902
- return node.parent.type === AST_NODE_TYPES18.ExportNamedDeclaration || node.parent.type === AST_NODE_TYPES18.ExportDefaultDeclaration || node.parent.type === AST_NODE_TYPES18.Program && exports.has(node.id.name);
4876
+ function isInlineExported(node) {
4877
+ if (moduleScopeBindingName(node) === null) return false;
4878
+ for (let current = node; current != null; current = current.parent) {
4879
+ const parent = current.parent;
4880
+ if (parent?.type === AST_NODE_TYPES18.ExportNamedDeclaration || parent?.type === AST_NODE_TYPES18.ExportDefaultDeclaration) {
4881
+ return true;
4882
+ }
4883
+ }
4884
+ return false;
4903
4885
  }
4904
- function isExported(node, specifierExports) {
4905
- if (isInlineExported(node)) {
4906
- return true;
4886
+ function moduleScopeBindingName(node) {
4887
+ let current = node;
4888
+ while (current.parent != null && current.parent.type !== AST_NODE_TYPES18.Program) {
4889
+ current = current.parent;
4907
4890
  }
4908
- if (specifierExports.size === 0) {
4909
- return false;
4891
+ if (current.parent?.type !== AST_NODE_TYPES18.Program) return null;
4892
+ let topLevel = current;
4893
+ if (current.type === AST_NODE_TYPES18.ExportNamedDeclaration || current.type === AST_NODE_TYPES18.ExportDefaultDeclaration) topLevel = current.declaration;
4894
+ if (topLevel === null) return null;
4895
+ if (topLevel.type === AST_NODE_TYPES18.FunctionDeclaration) {
4896
+ if (topLevel !== node) return null;
4897
+ return topLevel.id?.name ?? (current.type === AST_NODE_TYPES18.ExportDefaultDeclaration ? "default" : null);
4910
4898
  }
4911
- const binding = moduleScopeBindingName(node);
4912
- return binding !== null && specifierExports.has(binding);
4899
+ if ((topLevel.type === AST_NODE_TYPES18.ArrowFunctionExpression || topLevel.type === AST_NODE_TYPES18.FunctionExpression) && topLevel === node && current.type === AST_NODE_TYPES18.ExportDefaultDeclaration) return "default";
4900
+ if (topLevel.type === AST_NODE_TYPES18.ClassDeclaration) {
4901
+ let owner = node.parent;
4902
+ while (owner != null && owner.parent !== topLevel.body) owner = owner.parent;
4903
+ return (owner?.type === AST_NODE_TYPES18.MethodDefinition || owner?.type === AST_NODE_TYPES18.TSAbstractMethodDefinition || owner?.type === AST_NODE_TYPES18.PropertyDefinition) && owner.value === node ? topLevel.id?.name ?? (current.type === AST_NODE_TYPES18.ExportDefaultDeclaration ? "default" : null) : null;
4904
+ }
4905
+ if (topLevel.type === AST_NODE_TYPES18.VariableDeclaration) {
4906
+ for (const declarator of topLevel.declarations) {
4907
+ let initializer = declarator.init;
4908
+ while (initializer?.type === AST_NODE_TYPES18.TSAsExpression || initializer?.type === AST_NODE_TYPES18.TSSatisfiesExpression || initializer?.type === AST_NODE_TYPES18.TSNonNullExpression) initializer = initializer.expression;
4909
+ if (declarator.id.type === AST_NODE_TYPES18.Identifier && initializer === node) return declarator.id.name;
4910
+ if (declarator.id.type === AST_NODE_TYPES18.Identifier && (initializer?.type === AST_NODE_TYPES18.ClassExpression || initializer?.type === AST_NODE_TYPES18.ObjectExpression)) {
4911
+ let owner = node.parent;
4912
+ const container = initializer.type === AST_NODE_TYPES18.ClassExpression ? initializer.body : initializer;
4913
+ while (owner != null && owner.parent !== container) owner = owner.parent;
4914
+ if ((owner?.type === AST_NODE_TYPES18.MethodDefinition || owner?.type === AST_NODE_TYPES18.PropertyDefinition || owner?.type === AST_NODE_TYPES18.Property) && owner.value === node) return declarator.id.name;
4915
+ }
4916
+ }
4917
+ }
4918
+ return null;
4919
+ }
4920
+ function isExportedInterface(node, exports) {
4921
+ return node.parent.type === AST_NODE_TYPES18.ExportNamedDeclaration || node.parent.type === AST_NODE_TYPES18.ExportDefaultDeclaration || node.parent.type === AST_NODE_TYPES18.Program && exports.has(node.id.name);
4913
4922
  }
4914
4923
  var no_positional_tuple_return_default = createRule({
4915
4924
  name: "no-positional-tuple-return",
@@ -4917,11 +4926,11 @@ var no_positional_tuple_return_default = createRule({
4917
4926
  meta: {
4918
4927
  type: "suggestion",
4919
4928
  docs: {
4920
- description: "Disallow returning a multi-field tuple from an exported function; return a named object so call sites cannot mismatch slots."
4929
+ description: "Disallow returning a multi-field tuple from a named function; return a named object so call sites cannot mismatch slots."
4921
4930
  },
4922
4931
  schema: [],
4923
4932
  messages: {
4924
- noPositionalTupleReturn: "Exported `{{name}}` returns a {{count}}-field tuple, so consumers depend on positional slots that can be reordered silently. Return a named object instead."
4933
+ noPositionalTupleReturn: "`{{name}}` returns a {{count}}-field tuple, so callers depend on positional slots that can be reordered silently. Return a named object instead."
4925
4934
  }
4926
4935
  },
4927
4936
  defaultOptions: [],
@@ -4933,6 +4942,8 @@ var no_positional_tuple_return_default = createRule({
4933
4942
  exportedTypeNames(context.sourceCode.ast)
4934
4943
  );
4935
4944
  const aliases = typeAliases(context.sourceCode.ast);
4945
+ const reportedFunctions = /* @__PURE__ */ new WeakSet();
4946
+ const functionStack = [];
4936
4947
  const report = (annotation, name) => {
4937
4948
  const tuple = tupleReturnType(annotation, aliases);
4938
4949
  if (tuple === null || tuple.elementTypes.length < MIN_ELEMENTS) return;
@@ -4942,25 +4953,54 @@ var no_positional_tuple_return_default = createRule({
4942
4953
  data: { name, count: String(tuple.elementTypes.length) }
4943
4954
  });
4944
4955
  };
4956
+ const reportExpression = (node, expression) => {
4957
+ if (reportedFunctions.has(node)) return;
4958
+ const tuple = tupleExpression(expression, aliases);
4959
+ const name = functionName(node);
4960
+ if (tuple === null || name === null) return;
4961
+ reportedFunctions.add(node);
4962
+ context.report({
4963
+ node: tuple,
4964
+ messageId: "noPositionalTupleReturn",
4965
+ data: { name, count: String(tuple.elements.length) }
4966
+ });
4967
+ };
4945
4968
  const check = (node) => {
4969
+ if (isQueryKeyFactory(node)) return;
4946
4970
  const annotation = node.returnType?.typeAnnotation;
4947
4971
  if (annotation === void 0) {
4972
+ if (node.type === AST_NODE_TYPES18.ArrowFunctionExpression && node.expression) {
4973
+ reportExpression(node, node.body);
4974
+ }
4948
4975
  return;
4949
4976
  }
4950
4977
  const name = functionName(node);
4951
4978
  if (name === null) {
4952
4979
  return;
4953
4980
  }
4954
- if (!isExported(node, specifierExports)) {
4955
- return;
4956
- }
4957
4981
  report(annotation, name);
4958
4982
  };
4983
+ const enterFunction = (node) => {
4984
+ functionStack.push(node);
4985
+ check(node);
4986
+ };
4987
+ const exitFunction = () => {
4988
+ functionStack.pop();
4989
+ };
4959
4990
  return {
4960
- FunctionDeclaration: check,
4961
- FunctionExpression: check,
4962
- ArrowFunctionExpression: check,
4963
- TSEmptyBodyFunctionExpression: check,
4991
+ FunctionDeclaration: enterFunction,
4992
+ "FunctionDeclaration:exit": exitFunction,
4993
+ FunctionExpression: enterFunction,
4994
+ "FunctionExpression:exit": exitFunction,
4995
+ ArrowFunctionExpression: enterFunction,
4996
+ "ArrowFunctionExpression:exit": exitFunction,
4997
+ TSEmptyBodyFunctionExpression: enterFunction,
4998
+ "TSEmptyBodyFunctionExpression:exit": exitFunction,
4999
+ ReturnStatement(node) {
5000
+ const owner = functionStack.at(-1);
5001
+ if (owner === void 0 || owner.returnType !== void 0 || node.argument === null) return;
5002
+ reportExpression(owner, node.argument);
5003
+ },
4964
5004
  TSDeclareFunction(node) {
4965
5005
  if (node.id === null || node.returnType === void 0 || node.parent.type !== AST_NODE_TYPES18.ExportNamedDeclaration && node.parent.type !== AST_NODE_TYPES18.ExportDefaultDeclaration && !specifierExports.has(node.id.name)) return;
4966
5006
  report(node.returnType.typeAnnotation, node.id.name);
@@ -5586,6 +5626,38 @@ var no_repeated_string_literal_default = createRule({
5586
5626
 
5587
5627
  // src/rules/no-restated-comment.ts
5588
5628
  import { AST_NODE_TYPES as AST_NODE_TYPES22 } from "@typescript-eslint/utils";
5629
+
5630
+ // src/rules/_comment-edits.ts
5631
+ import "@typescript-eslint/utils";
5632
+ function physicalLineEnd(text, offset) {
5633
+ const newline = text.indexOf("\n", offset);
5634
+ return newline < 0 ? text.length : newline;
5635
+ }
5636
+ function contentLineEnd(text, offset) {
5637
+ const end = physicalLineEnd(text, offset);
5638
+ return end > offset && text[end - 1] === "\r" ? end - 1 : end;
5639
+ }
5640
+ function wholeLineRemovalRange(text, comment) {
5641
+ if (comment.loc.start.line !== comment.loc.end.line) return null;
5642
+ const lineStart = text.lastIndexOf("\n", Math.max(0, comment.range[0] - 1)) + 1;
5643
+ if (!/^[\t ]*$/u.test(text.slice(lineStart, comment.range[0]))) return null;
5644
+ const contentEnd = contentLineEnd(text, comment.range[1]);
5645
+ if (!/^[\t ]*$/u.test(text.slice(comment.range[1], contentEnd))) return null;
5646
+ const physicalEnd = physicalLineEnd(text, comment.range[1]);
5647
+ return { range: [lineStart, physicalEnd < text.length ? physicalEnd + 1 : physicalEnd] };
5648
+ }
5649
+ function trailingCommentRemovalRange(text, comment) {
5650
+ if (comment.loc.start.line !== comment.loc.end.line) return null;
5651
+ const contentEnd = contentLineEnd(text, comment.range[1]);
5652
+ if (!/^[\t ]*$/u.test(text.slice(comment.range[1], contentEnd))) return null;
5653
+ let start = comment.range[0];
5654
+ while (start > 0 && (text[start - 1] === " " || text[start - 1] === " ")) {
5655
+ start -= 1;
5656
+ }
5657
+ return { range: [start, contentEnd] };
5658
+ }
5659
+
5660
+ // src/rules/no-restated-comment.ts
5589
5661
  var MAX_WORDS = 8;
5590
5662
  var MIN_CONTENT_TOKENS = 2;
5591
5663
  var DIRECTIVE_RE3 = /^(eslint\b|eslint-|sarj-noqa\b|@ts-|prettier-ignore|prettier\b|biome-|c8\b|v8\b|istanbul\b|@type\b|@vite|webpack|<reference|<amd|global\b|noinspection|todo\b|fixme\b|hack\b|xxx\b)/i;
@@ -5605,6 +5677,7 @@ var noRestatedCommentDocumentation = {
5605
5677
  rationale: "A comment that only repeats code adds no context and can become stale independently.",
5606
5678
  remediation: "Delete the comment or replace it with the reason, constraint, or consequence absent from the code.",
5607
5679
  category: "maintainability",
5680
+ autofix: "suggestion",
5608
5681
  limitations: ["Directives, protected references, questions, multi-line prose, comments with novel content, and generated files are excluded."],
5609
5682
  examples: [
5610
5683
  { id: "reason-comment", title: "Keep the reason the code cannot express", outcome: "no-match", files: [{ path: "src/cache.ts", source: "// Serialize because the cache key is stable across deploys.\nconst key = serialize(input);" }], focusPath: "src/cache.ts", expectedCount: 0, public: true },
@@ -5628,11 +5701,13 @@ var no_restated_comment_default = createRule({
5628
5701
  documentation: noRestatedCommentDocumentation,
5629
5702
  meta: {
5630
5703
  type: "suggestion",
5704
+ hasSuggestions: true,
5631
5705
  docs: {
5632
5706
  description: "Flag a single-line comment whose every word already appears on the statement below it."
5633
5707
  },
5634
5708
  schema: [],
5635
5709
  messages: {
5710
+ deleteComment: "Delete the redundant comment.",
5636
5711
  restatesLineBelow: "Comment restates the statement below it \u2014 delete it, or replace it with the *why*; the code already carries the *what*."
5637
5712
  }
5638
5713
  },
@@ -5701,7 +5776,17 @@ var no_restated_comment_default = createRule({
5701
5776
  if (!ACTION_STMT_RE.test(line)) continue;
5702
5777
  if (labelsASiblingRun(comment)) continue;
5703
5778
  if (restates(tokens, codeTokens(line))) {
5704
- context.report({ node: comment, messageId: "restatesLineBelow" });
5779
+ const removal = wholeLineRemovalRange(sourceCode.text, comment);
5780
+ context.report({
5781
+ node: comment,
5782
+ messageId: "restatesLineBelow",
5783
+ suggest: removal === null ? null : [
5784
+ {
5785
+ messageId: "deleteComment",
5786
+ fix: (fixer) => fixer.removeRange(removal.range)
5787
+ }
5788
+ ]
5789
+ });
5705
5790
  }
5706
5791
  }
5707
5792
  }
@@ -7729,6 +7814,7 @@ var noTrailingValueNarrationDocumentation = {
7729
7814
  rationale: "A repeated value can disagree with the expression after either the code or comment changes.",
7730
7815
  remediation: "Put the unit in the identifier and keep comments only when they explain a constraint or non-obvious conversion.",
7731
7816
  category: "maintainability",
7817
+ autofix: "suggestion",
7732
7818
  aliases: ["trailing-value-narration"],
7733
7819
  limitations: ["Only trailing comments with numeric values and recognized unit words are inspected."],
7734
7820
  examples: [
@@ -7845,13 +7931,15 @@ var no_trailing_value_narration_default = createRule({
7845
7931
  documentation: noTrailingValueNarrationDocumentation,
7846
7932
  meta: {
7847
7933
  type: "suggestion",
7934
+ hasSuggestions: true,
7848
7935
  docs: {
7849
7936
  description: "Flag a trailing comment that repeats the line's numeric value only to name its unit."
7850
7937
  },
7851
7938
  schema: [],
7852
7939
  messages: {
7853
7940
  deleteNarration: "Trailing comment restates the literal and the identifier already names its unit \u2014 delete the comment so it cannot drift.",
7854
- narratesValue: "Trailing comment restates the literal on this line \u2014 put the unit in the name (STALE_TIME_MS) so it cannot drift."
7941
+ narratesValue: "Trailing comment restates the literal on this line \u2014 put the unit in the name (STALE_TIME_MS) so it cannot drift.",
7942
+ removeNarration: "Delete the redundant trailing narration."
7855
7943
  }
7856
7944
  },
7857
7945
  defaultOptions: [],
@@ -7883,9 +7971,17 @@ var no_trailing_value_narration_default = createRule({
7883
7971
  const code = line.slice(0, comment.loc.start.column);
7884
7972
  const body2 = comment.value.replace(/^\*+/, "").replace(/\*+$/, "").trim();
7885
7973
  if (narratesValue(body2, code)) {
7974
+ const canDelete = nameAlreadyCarriesUnit(code);
7975
+ const removal = canDelete ? trailingCommentRemovalRange(sourceCode.text, comment) : null;
7886
7976
  context.report({
7887
7977
  node: comment,
7888
- messageId: nameAlreadyCarriesUnit(code) ? "deleteNarration" : "narratesValue"
7978
+ messageId: canDelete ? "deleteNarration" : "narratesValue",
7979
+ suggest: removal === null ? null : [
7980
+ {
7981
+ messageId: "removeNarration",
7982
+ fix: (fixer) => fixer.removeRange(removal.range)
7983
+ }
7984
+ ]
7889
7985
  });
7890
7986
  }
7891
7987
  }
@@ -11083,6 +11179,7 @@ var prefer_non_nullable_collection_default = createRule({
11083
11179
 
11084
11180
  // src/rules/prefer-await-in-async-return.ts
11085
11181
  import {
11182
+ ASTUtils as ASTUtils14,
11086
11183
  ESLintUtils as ESLintUtils3,
11087
11184
  AST_NODE_TYPES as AST_NODE_TYPES46
11088
11185
  } from "@typescript-eslint/utils";
@@ -11095,7 +11192,8 @@ var preferAwaitInAsyncReturnDocumentation = {
11095
11192
  since: "15.6.3",
11096
11193
  limitations: [
11097
11194
  "Only a single directly returned `.then` call with an inline callback is checked.",
11098
- "The receiver must be proven Promise-like by TypeScript; untyped files and larger chains are intentionally ignored."
11195
+ "The receiver must be proven Promise-like by TypeScript; untyped files and larger chains are intentionally ignored.",
11196
+ "Direct loader callbacks passed to resolved `React.lazy` and `next/dynamic` imports are excluded because returning the module Promise is their framework contract."
11099
11197
  ],
11100
11198
  examples: [
11101
11199
  {
@@ -11124,19 +11222,19 @@ var preferAwaitInAsyncReturnDocumentation = {
11124
11222
  }
11125
11223
  ]
11126
11224
  };
11127
- function isDirectAsyncReturn(node) {
11225
+ function directAsyncReturnOwner(node) {
11128
11226
  const parent = node.parent;
11129
11227
  if (parent.type === AST_NODE_TYPES46.ArrowFunctionExpression && parent.body === node) {
11130
- return parent.async && !parent.generator;
11228
+ return parent.async && !parent.generator ? parent : null;
11131
11229
  }
11132
11230
  if (parent.type !== AST_NODE_TYPES46.ReturnStatement || parent.argument !== node) {
11133
- return false;
11231
+ return null;
11134
11232
  }
11135
11233
  let owner = parent.parent;
11136
11234
  while (owner !== void 0 && !isRuntimeFunction(owner)) {
11137
11235
  owner = owner.parent;
11138
11236
  }
11139
- return owner !== void 0 && owner.async && !owner.generator;
11237
+ return owner !== void 0 && owner.async && !owner.generator ? owner : null;
11140
11238
  }
11141
11239
  function isRuntimeFunction(node) {
11142
11240
  return node.type === AST_NODE_TYPES46.ArrowFunctionExpression || node.type === AST_NODE_TYPES46.FunctionDeclaration || node.type === AST_NODE_TYPES46.FunctionExpression;
@@ -11193,9 +11291,33 @@ var prefer_await_in_async_return_default = createRule({
11193
11291
  services = null;
11194
11292
  }
11195
11293
  if (services === null) return {};
11294
+ const frameworkLoaders = /* @__PURE__ */ new Set();
11295
+ const rememberFrameworkLoader = (identifier) => {
11296
+ const variable = ASTUtils14.findVariable(context.sourceCode.getScope(identifier), identifier.name);
11297
+ if (variable !== null) frameworkLoaders.add(variable);
11298
+ };
11299
+ const isFrameworkLoaderCallback = (owner) => {
11300
+ const parent = owner.parent;
11301
+ if (parent.type !== AST_NODE_TYPES46.CallExpression || parent.arguments[0] !== owner || parent.callee.type !== AST_NODE_TYPES46.Identifier) return false;
11302
+ const variable = ASTUtils14.findVariable(context.sourceCode.getScope(parent.callee), parent.callee.name);
11303
+ return variable !== null && frameworkLoaders.has(variable);
11304
+ };
11196
11305
  return {
11306
+ ImportDeclaration(node) {
11307
+ if (node.source.value === "react") {
11308
+ for (const specifier of node.specifiers) {
11309
+ if (specifier.type === AST_NODE_TYPES46.ImportSpecifier && (specifier.imported.type === AST_NODE_TYPES46.Identifier ? specifier.imported.name : specifier.imported.value) === "lazy") rememberFrameworkLoader(specifier.local);
11310
+ }
11311
+ }
11312
+ if (node.source.value === "next/dynamic") {
11313
+ for (const specifier of node.specifiers) {
11314
+ if (specifier.type === AST_NODE_TYPES46.ImportDefaultSpecifier) rememberFrameworkLoader(specifier.local);
11315
+ }
11316
+ }
11317
+ },
11197
11318
  CallExpression(node) {
11198
- if (!isDirectAsyncReturn(node)) return;
11319
+ const owner = directAsyncReturnOwner(node);
11320
+ if (owner === null || isFrameworkLoaderCallback(owner)) return;
11199
11321
  const receiver = promiseThenReceiver(node);
11200
11322
  if (receiver === null || !isProvenPromiseLike(receiver, services)) {
11201
11323
  return;
@@ -12404,6 +12526,16 @@ function literalIndex(node) {
12404
12526
  }
12405
12527
  return Number.isInteger(node.value) && node.value >= 0 ? node.value : null;
12406
12528
  }
12529
+ function propertyAccess(node) {
12530
+ const path = [];
12531
+ let current = node;
12532
+ while (current.type === AST_NODE_TYPES49.MemberExpression && !current.computed && !current.optional) {
12533
+ if (current.property.type !== AST_NODE_TYPES49.Identifier || COLLECTION_PROPERTIES.has(current.property.name) || LITERAL_KEY_HAZARDS.has(current.property.name)) return null;
12534
+ path.unshift(current.property.name);
12535
+ current = current.object;
12536
+ }
12537
+ return path.length > 0 && isPureReceiver(current) ? { receiver: current, path } : null;
12538
+ }
12407
12539
  var prefer_whole_object_assertion_default = createRule({
12408
12540
  name: "prefer-whole-object-assertion",
12409
12541
  documentation: preferWholeObjectAssertionDocumentation,
@@ -12450,21 +12582,23 @@ var prefer_whole_object_assertion_default = createRule({
12450
12582
  return null;
12451
12583
  }
12452
12584
  let key;
12585
+ let receiver;
12453
12586
  if (actual.computed) {
12454
12587
  const index = literalIndex(actual.property);
12455
12588
  if (index === null) {
12456
12589
  return null;
12457
12590
  }
12458
12591
  key = { kind: "index", index };
12592
+ receiver = actual.object;
12459
12593
  } else {
12460
- if (actual.property.type !== AST_NODE_TYPES49.Identifier || COLLECTION_PROPERTIES.has(actual.property.name) || LITERAL_KEY_HAZARDS.has(actual.property.name)) {
12461
- return null;
12462
- }
12463
- key = { kind: "property", name: actual.property.name };
12594
+ const access = propertyAccess(actual);
12595
+ if (access === null) return null;
12596
+ key = { kind: "property", path: access.path };
12597
+ receiver = access.receiver;
12464
12598
  }
12465
12599
  const synthetic = SYNTHETIC_LITERAL_MATCHERS.get(matcher);
12466
12600
  if (synthetic !== void 0 && call.arguments.length === 0) {
12467
- return { statement, receiver: actual.object, key, matcher, expectedText: synthetic, expectedIsLiteral: true };
12601
+ return { statement, receiver, key, matcher, expectedText: synthetic, expectedIsLiteral: true };
12468
12602
  }
12469
12603
  if (!MERGEABLE_MATCHERS.has(matcher)) {
12470
12604
  return null;
@@ -12476,7 +12610,7 @@ var prefer_whole_object_assertion_default = createRule({
12476
12610
  const literal = literalText(expected, (node) => sourceCode.getText(node));
12477
12611
  return {
12478
12612
  statement,
12479
- receiver: actual.object,
12613
+ receiver,
12480
12614
  key,
12481
12615
  matcher,
12482
12616
  expectedText: literal ?? sourceCode.getText(expected),
@@ -12489,7 +12623,8 @@ var prefer_whole_object_assertion_default = createRule({
12489
12623
  );
12490
12624
  }
12491
12625
  function reportPropertyRun(run) {
12492
- const names = /* @__PURE__ */ new Set();
12626
+ const tree = /* @__PURE__ */ new Map();
12627
+ const paths = [];
12493
12628
  for (const assertion of run) {
12494
12629
  if (assertion.key.kind !== "property" || !assertion.expectedIsLiteral) {
12495
12630
  return;
@@ -12497,19 +12632,44 @@ var prefer_whole_object_assertion_default = createRule({
12497
12632
  if (!MERGEABLE_MATCHERS.has(assertion.matcher) && !SYNTHETIC_LITERAL_MATCHERS.has(assertion.matcher)) {
12498
12633
  return;
12499
12634
  }
12500
- if (names.has(assertion.key.name)) {
12501
- return;
12635
+ paths.push([...assertion.key.path]);
12636
+ }
12637
+ const commonPrefix = [];
12638
+ for (let index = 0; ; index += 1) {
12639
+ const candidate = paths[0]?.[index];
12640
+ if (candidate === void 0 || paths.some((path) => path[index] !== candidate || path.length === index + 1)) {
12641
+ break;
12642
+ }
12643
+ commonPrefix.push(candidate);
12644
+ }
12645
+ for (const [assertionIndex, assertion] of run.entries()) {
12646
+ if (assertion.key.kind !== "property") return;
12647
+ let branch = tree;
12648
+ const relativePath = paths[assertionIndex]?.slice(commonPrefix.length) ?? [];
12649
+ for (const [index, name] of relativePath.entries()) {
12650
+ const leaf = index === relativePath.length - 1;
12651
+ const existing = branch.get(name);
12652
+ if (leaf) {
12653
+ if (existing !== void 0) return;
12654
+ branch.set(name, assertion.expectedText);
12655
+ } else if (existing === void 0) {
12656
+ const nested = /* @__PURE__ */ new Map();
12657
+ branch.set(name, nested);
12658
+ branch = nested;
12659
+ } else if (existing instanceof Map) {
12660
+ branch = existing;
12661
+ } else {
12662
+ return;
12663
+ }
12502
12664
  }
12503
- names.add(assertion.key.name);
12504
12665
  }
12505
12666
  const first = run[0];
12506
12667
  if (first === void 0) {
12507
12668
  return;
12508
12669
  }
12509
- const receiverText = sourceCode.getText(first.receiver);
12510
- const properties = run.map(
12511
- (assertion) => assertion.key.kind === "property" ? `${assertion.key.name}: ${assertion.expectedText}` : ""
12512
- ).join(", ");
12670
+ const receiverText = `${sourceCode.getText(first.receiver)}${commonPrefix.map((name) => `.${name}`).join("")}`;
12671
+ const renderTree = (value) => [...value.entries()].map(([name, child]) => `${name}: ${child instanceof Map ? `{ ${renderTree(child)} }` : child}`).join(", ");
12672
+ const properties = renderTree(tree);
12513
12673
  context.report({
12514
12674
  node: first.statement,
12515
12675
  messageId: "combineAssertions",
@@ -12585,7 +12745,7 @@ var prefer_whole_object_assertion_default = createRule({
12585
12745
  });
12586
12746
 
12587
12747
  // src/rules/repeated-static-call-cases.ts
12588
- import { AST_NODE_TYPES as AST_NODE_TYPES50, ASTUtils as ASTUtils14 } from "@typescript-eslint/utils";
12748
+ import { AST_NODE_TYPES as AST_NODE_TYPES50, ASTUtils as ASTUtils15 } from "@typescript-eslint/utils";
12589
12749
  var repeatedStaticCallCasesDocumentation = {
12590
12750
  summary: "Report three or more consecutive literal call assertions that should be independently named test cases.",
12591
12751
  rationale: "Copy-pasted cases obscure the input table and stop later cases from being reported after the first failure.",
@@ -12611,7 +12771,7 @@ function staticMemberName5(node) {
12611
12771
  return null;
12612
12772
  }
12613
12773
  function importedName3(identifier, context, modules) {
12614
- const variable = ASTUtils14.findVariable(context.sourceCode.getScope(identifier), identifier.name);
12774
+ const variable = ASTUtils15.findVariable(context.sourceCode.getScope(identifier), identifier.name);
12615
12775
  if (variable === null || variable.defs.length === 0) return identifier.name;
12616
12776
  for (const definition of variable.defs) {
12617
12777
  if (definition.node.type !== AST_NODE_TYPES50.ImportSpecifier) continue;
@@ -13612,7 +13772,7 @@ var require_assert_never_default = createRule({
13612
13772
  });
13613
13773
 
13614
13774
  // src/rules/require-fetch-timeout.ts
13615
- import { AST_NODE_TYPES as AST_NODE_TYPES53, ASTUtils as ASTUtils15 } from "@typescript-eslint/utils";
13775
+ import { AST_NODE_TYPES as AST_NODE_TYPES53, ASTUtils as ASTUtils16 } from "@typescript-eslint/utils";
13616
13776
  var requireFetchTimeoutDocumentation = {
13617
13777
  summary: "Require an abort `signal` (e.g. `AbortSignal.timeout(ms)`) on global `fetch()` calls so stalled upstreams cannot hang the caller forever.",
13618
13778
  rationale: "An unbounded request can occupy work indefinitely when an upstream stalls.",
@@ -13693,7 +13853,7 @@ var require_fetch_timeout_default = createRule({
13693
13853
  }
13694
13854
  function resolvesToGlobal(identifier) {
13695
13855
  const scope = context.sourceCode.getScope(identifier);
13696
- const variable = ASTUtils15.findVariable(scope, identifier.name);
13856
+ const variable = ASTUtils16.findVariable(scope, identifier.name);
13697
13857
  return variable === null || variable.defs.length === 0;
13698
13858
  }
13699
13859
  function isGlobalFetchCall2(callee) {
@@ -13703,7 +13863,7 @@ var require_fetch_timeout_default = createRule({
13703
13863
  return callee.type === AST_NODE_TYPES53.MemberExpression && !callee.computed && callee.property.type === AST_NODE_TYPES53.Identifier && callee.property.name === "fetch" && callee.object.type === AST_NODE_TYPES53.Identifier && GLOBAL_OBJECTS2.has(callee.object.name) && resolvesToGlobal(callee.object);
13704
13864
  }
13705
13865
  function localConstInitProvablyLacksSignal(identifier) {
13706
- const variable = ASTUtils15.findVariable(
13866
+ const variable = ASTUtils16.findVariable(
13707
13867
  context.sourceCode.getScope(identifier),
13708
13868
  identifier.name
13709
13869
  );
@@ -14347,7 +14507,7 @@ var require_static_next_matcher_default = createRule({
14347
14507
  // src/rules/require-zod-form-validation.ts
14348
14508
  import {
14349
14509
  AST_NODE_TYPES as AST_NODE_TYPES56,
14350
- ASTUtils as ASTUtils16
14510
+ ASTUtils as ASTUtils17
14351
14511
  } from "@typescript-eslint/utils";
14352
14512
  var requireZodFormValidationDocumentation = {
14353
14513
  summary: "Require Zod validation (`Schema.parse(...)` / `Schema.safeParse(...)`) when reading values out of a `FormData` object.",
@@ -14415,7 +14575,7 @@ var require_zod_form_validation_default = createRule({
14415
14575
  return {};
14416
14576
  }
14417
14577
  const zodBindings = /* @__PURE__ */ new Set();
14418
- const resolvedBinding = (identifier) => ASTUtils16.findVariable(
14578
+ const resolvedBinding = (identifier) => ASTUtils17.findVariable(
14419
14579
  context.sourceCode.getScope(identifier),
14420
14580
  identifier.name
14421
14581
  );
@@ -14712,7 +14872,7 @@ var store_insert_requires_on_conflict_default = createRule({
14712
14872
  });
14713
14873
 
14714
14874
  // src/rules/stepdown.ts
14715
- import { AST_NODE_TYPES as AST_NODE_TYPES57, ASTUtils as ASTUtils17 } from "@typescript-eslint/utils";
14875
+ import { AST_NODE_TYPES as AST_NODE_TYPES57, ASTUtils as ASTUtils18 } from "@typescript-eslint/utils";
14716
14876
  var stepdownDocumentation = {
14717
14877
  summary: "Place a private helper below its sole direct same-scope caller.",
14718
14878
  rationale: "Caller-first ordering lets a reader follow the main flow before descending into implementation details.",
@@ -14912,7 +15072,7 @@ function methodName(node) {
14912
15072
  return !node.computed && node.key.type === AST_NODE_TYPES57.Identifier ? node.key.name : null;
14913
15073
  }
14914
15074
  function referencedMethod(context, node, classVariables) {
14915
- const objectVariable = node.object.type === AST_NODE_TYPES57.Identifier ? ASTUtils17.findVariable(context.sourceCode.getScope(node.object), node.object.name) : null;
15075
+ const objectVariable = node.object.type === AST_NODE_TYPES57.Identifier ? ASTUtils18.findVariable(context.sourceCode.getScope(node.object), node.object.name) : null;
14916
15076
  const isClassReference = objectVariable !== null && classVariables.has(objectVariable);
14917
15077
  if (node.object.type !== AST_NODE_TYPES57.ThisExpression && !isClassReference) return null;
14918
15078
  if (node.property.type === AST_NODE_TYPES57.PrivateIdentifier) return `#${node.property.name}`;
@@ -14965,11 +15125,11 @@ function classScope(context, node, computedReferenceNames) {
14965
15125
  const pinned = /* @__PURE__ */ new Set();
14966
15126
  const classVariables = /* @__PURE__ */ new Set();
14967
15127
  if (node.id !== null) {
14968
- const internal = ASTUtils17.findVariable(context.sourceCode.getScope(node), node.id.name);
15128
+ const internal = ASTUtils18.findVariable(context.sourceCode.getScope(node), node.id.name);
14969
15129
  if (internal !== null) classVariables.add(internal);
14970
15130
  }
14971
15131
  if (node.type === AST_NODE_TYPES57.ClassExpression && node.parent.type === AST_NODE_TYPES57.VariableDeclarator && node.parent.id.type === AST_NODE_TYPES57.Identifier) {
14972
- const outer = ASTUtils17.findVariable(context.sourceCode.getScope(node.parent), node.parent.id.name);
15132
+ const outer = ASTUtils18.findVariable(context.sourceCode.getScope(node.parent), node.parent.id.name);
14973
15133
  if (outer !== null) classVariables.add(outer);
14974
15134
  }
14975
15135
  for (const method of methods) {
@@ -15005,7 +15165,7 @@ function classScope(context, node, computedReferenceNames) {
15005
15165
  return;
15006
15166
  }
15007
15167
  if (binding.type !== AST_NODE_TYPES57.Identifier) return;
15008
- const variable = ASTUtils17.findVariable(context.sourceCode.getScope(binding), binding.name);
15168
+ const variable = ASTUtils18.findVariable(context.sourceCode.getScope(binding), binding.name);
15009
15169
  if (variable !== null) {
15010
15170
  methodClassVariables.add(variable);
15011
15171
  methodAliases.add(variable);
@@ -15035,7 +15195,7 @@ function classScope(context, node, computedReferenceNames) {
15035
15195
  return;
15036
15196
  }
15037
15197
  if (!privateNames.has(target)) return;
15038
- const objectVariable = current.object.type === AST_NODE_TYPES57.Identifier ? ASTUtils17.findVariable(context.sourceCode.getScope(current.object), current.object.name) : null;
15198
+ const objectVariable = current.object.type === AST_NODE_TYPES57.Identifier ? ASTUtils18.findVariable(context.sourceCode.getScope(current.object), current.object.name) : null;
15039
15199
  if (objectVariable !== null && methodAliases.has(objectVariable)) {
15040
15200
  pinned.add(target);
15041
15201
  return;
@@ -15143,7 +15303,7 @@ var stepdown_default = createRule({
15143
15303
 
15144
15304
  // src/rules/source-coupled-test.ts
15145
15305
  import { AST_NODE_TYPES as AST_NODE_TYPES58 } from "@typescript-eslint/utils";
15146
- var GENERAL_SOURCE_SUFFIX_RE = /\.(?:bash|sh|ya?ml|py|[cm]?[jt]s)$/iu;
15306
+ var GENERAL_SOURCE_SUFFIX_RE = /\.(?:bash|sh|ya?ml|jsonc|py|[cm]?[jt]s)$/iu;
15147
15307
  var FS_MODULES = /* @__PURE__ */ new Set(["fs", "node:fs", "fs/promises", "node:fs/promises"]);
15148
15308
  var FS_READERS = /* @__PURE__ */ new Set(["readFile", "readFileSync"]);
15149
15309
  var TEXT_TRANSFORMS = /* @__PURE__ */ new Set([
@@ -15338,6 +15498,13 @@ function createSourceCoupledRule(name, documentation, sourceSuffixRe) {
15338
15498
  if (receiver.type !== AST_NODE_TYPES58.Identifier || receiver.name !== "assert" || !ASSERT_MATCHERS.has(matcher)) return /* @__PURE__ */ new Set();
15339
15499
  return new Set(node.arguments.flatMap((argument) => argument.type === AST_NODE_TYPES58.SpreadElement ? [] : [...evidenceOrigins(argument)]));
15340
15500
  };
15501
+ const rawRegexExtractionOrigins = (node) => {
15502
+ const callee = unwrap5(node.callee);
15503
+ if (callee.type !== AST_NODE_TYPES58.MemberExpression || staticMemberName7(callee) !== "matchAll" || node.arguments.length !== 1) return /* @__PURE__ */ new Set();
15504
+ const argument = node.arguments[0];
15505
+ if (argument?.type !== AST_NODE_TYPES58.Literal || !(argument.value instanceof RegExp)) return /* @__PURE__ */ new Set();
15506
+ return rawOrigins(callee.object);
15507
+ };
15341
15508
  const declare = (name2, state) => {
15342
15509
  const scope = currentScope();
15343
15510
  scope.declared.add(name2);
@@ -15417,7 +15584,10 @@ function createSourceCoupledRule(name, documentation, sourceSuffixRe) {
15417
15584
  if (collection && left?.type === AST_NODE_TYPES58.Identifier) declare(left.name, { path: true });
15418
15585
  },
15419
15586
  CallExpression(node) {
15420
- const origins = rawAssertionOrigins(node);
15587
+ const origins = /* @__PURE__ */ new Set([
15588
+ ...rawAssertionOrigins(node),
15589
+ ...rawRegexExtractionOrigins(node)
15590
+ ]);
15421
15591
  if (origins.size === 0 || [...origins].every((origin) => reportedOrigins.has(origin))) return;
15422
15592
  for (const origin of origins) reportedOrigins.add(origin);
15423
15593
  context.report({ node, messageId: "rawSourceOracle" });
@@ -15473,7 +15643,7 @@ var iac_source_coupled_test_default = createSourceCoupledRule(
15473
15643
  // src/rules/zod-naming-convention.ts
15474
15644
  import {
15475
15645
  AST_NODE_TYPES as AST_NODE_TYPES59,
15476
- ASTUtils as ASTUtils18
15646
+ ASTUtils as ASTUtils19
15477
15647
  } from "@typescript-eslint/utils";
15478
15648
  var zodNamingConventionDocumentation = {
15479
15649
  summary: "Enforce a consistent Zod schema naming convention \u2014 a `Z` prefix (`ZUser`) or a `Schema` suffix (`userSchema`); both are accepted by default.",
@@ -15566,7 +15736,7 @@ var zod_naming_convention_default = createRule({
15566
15736
  const acceptsSchemaWord = convention !== "prefix";
15567
15737
  const zodBindings = /* @__PURE__ */ new Set();
15568
15738
  function resolvedBinding(identifier) {
15569
- return ASTUtils18.findVariable(
15739
+ return ASTUtils19.findVariable(
15570
15740
  context.sourceCode.getScope(identifier),
15571
15741
  identifier.name
15572
15742
  );
@@ -15768,7 +15938,7 @@ var rules = {
15768
15938
  };
15769
15939
  var meta = {
15770
15940
  name: "@sarj/eslint-plugin",
15771
- version: "15.8.1"
15941
+ version: "15.9.0"
15772
15942
  };
15773
15943
  var applicationOnlyRules = [
15774
15944
  "no-restricted-library-load",