@sarj/eslint-plugin 18.2.0 → 18.3.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,6 +1,3 @@
1
- // src/rules/prefer-zod-enum-validator.ts
2
- import { AST_NODE_TYPES as AST_NODE_TYPES4 } from "@typescript-eslint/utils";
3
-
4
1
  // src/rules/_eslint-rule.ts
5
2
  import { ESLintUtils } from "@typescript-eslint/utils";
6
3
 
@@ -487,21 +484,21 @@ function validateExpectedSuggestion(value, exampleId, messageIds) {
487
484
  assertFields(value, ["messageId", "output"], exampleId);
488
485
  }
489
486
  function validateExpectedLocation(value, exampleId) {
490
- if (!isObject(value) || !("line" in value) || !positiveCoordinate(value.line) || !("column" in value) || !positiveCoordinate(value.column)) {
487
+ if (!isObject(value) || !("line" in value) || typeof value.line !== "number" || !positiveCoordinate(value.line) || !("column" in value) || typeof value.column !== "number" || !positiveCoordinate(value.column)) {
491
488
  throw new TypeError(`${exampleId}: expected diagnostic location requires positive integer coordinates`);
492
489
  }
493
490
  if (!("end" in value)) {
494
491
  assertFields(value, ["line", "column"], exampleId);
495
492
  return;
496
493
  }
497
- if (!isObject(value.end) || !("line" in value.end) || !positiveCoordinate(value.end.line) || !("column" in value.end) || !positiveCoordinate(value.end.column) || value.end.line < value.line || value.end.line === value.line && value.end.column < value.column) {
494
+ if (!isObject(value.end) || !("line" in value.end) || typeof value.end.line !== "number" || !positiveCoordinate(value.end.line) || !("column" in value.end) || typeof value.end.column !== "number" || !positiveCoordinate(value.end.column) || value.end.line < value.line || value.end.line === value.line && value.end.column < value.column) {
498
495
  throw new TypeError(`${exampleId}: expected diagnostic end point must be complete and ordered`);
499
496
  }
500
497
  assertFields(value.end, ["line", "column"], exampleId);
501
498
  assertFields(value, ["line", "column", "end"], exampleId);
502
499
  }
503
500
  function positiveCoordinate(value) {
504
- return typeof value === "number" && Number.isSafeInteger(value) && value >= 1;
501
+ return Number.isSafeInteger(value) && value >= 1;
505
502
  }
506
503
  function assertFields(value, expected, exampleId) {
507
504
  const fields2 = Object.keys(value);
@@ -653,6 +650,56 @@ function commentLineEnd(sourceText, start) {
653
650
  return end === -1 ? sourceText.length : start + end;
654
651
  }
655
652
 
653
+ // src/rules/no-explicit-type-predicate.ts
654
+ var NO_EXPLICIT_TYPE_PREDICATE_DOCUMENTATION = {
655
+ defaultLevel: "warning",
656
+ summary: "Use compiler-checked narrowing instead of handwritten type predicates.",
657
+ rationale: "TypeScript trusts an explicit value is Type annotation without proving that its implementation recognizes that type in both branches. A stale or partial predicate can make callers read properties that do not exist. Direct discriminator checks and inferred predicates keep narrowing tied to the implementation.",
658
+ remediation: "For owned variants, check the discriminated union's tag directly or let TypeScript infer a simple discriminator helper or null filter. Parse unknown external data with a specific schema and consume its validated value or discriminated result. Do not replace a predicate with a cast or a schema boolean wrapper that repeats the same unchecked type claim. If a native API cannot express the required static contract, isolate that boundary and use an exact-rule local suppression explaining the constraint.",
659
+ category: "maintainability",
660
+ autofix: "none",
661
+ requiresTypeInformation: false,
662
+ limitations: [
663
+ "This is an explicit design policy, including otherwise correct handwritten predicates. Reports every authored TypeScript is predicate, including asserts value is Type, method and callback annotations, function types, overloads, ambient signatures and predicates inside casts or satisfies expressions.",
664
+ "Direct discriminator checks, compiler-inferred predicates, ordinary boolean returns and plain asserts condition remain valid. A tag on unknown input does not validate its payload. Imported library guard calls and imported predicate types are not redeclarations and are not inspected.",
665
+ "Shared generated, vendored and declaration-file exclusions apply. Maintained test implementations remain checked; strings, comments and JSDoc text are not TypeScript predicate nodes. There is no exemption based on helper names, imports or body shape.",
666
+ "No automatic fix or suggestion removes an annotation: public and callback contracts, overloads, both narrowing branches, emitted declarations and existing TypeScript versions may depend on it. Review callers and preserve intentional runtime behavior when migrating. Existing partial and contradictory predicate rules retain their separate correctness checks."
667
+ ],
668
+ references: [
669
+ "https://www.typescriptlang.org/docs/handbook/2/narrowing.html#discriminated-unions",
670
+ "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html#inferred-type-predicates",
671
+ "https://zod.dev/basics"
672
+ ],
673
+ examples: [
674
+ { id: "manual-predicate", title: "Avoid an unchecked narrowing annotation", outcome: "match", files: [{ path: "src/job.ts", source: "type Job = { kind: 'queued'; queue: string } | { kind: 'done'; result: string }; type Done = Extract<Job, {kind: 'done'}>; function isDone(job: Job): job is Done { return job.kind === 'done'; } function render(job: Job) { return isDone(job) ? job.result : job.queue; }" }], focusPath: "src/job.ts", expectedCount: 1, public: true },
675
+ { id: "direct-discriminator", title: "Let the compiler narrow the tagged union", outcome: "no-match", files: [{ path: "src/job.ts", source: "type Job = { kind: 'queued'; queue: string } | { kind: 'done'; result: string }; function render(job: Job) { return job.kind === 'done' ? job.result : job.queue; }" }], focusPath: "src/job.ts", expectedCount: 0, public: true },
676
+ { id: "inferred-predicate", scenarioId: "inference", title: "Infer a discriminator helper from its body", outcome: "no-match", files: [{ path: "src/job.ts", source: "type Job = { kind: 'queued'; queue: string } | { kind: 'done'; result: string }; const isDone = (job: Job) => job.kind === 'done';" }], focusPath: "src/job.ts", expectedCount: 0, public: true },
677
+ { id: "written-predicate", scenarioId: "inference", title: "A written predicate remains an unchecked promise", outcome: "match", files: [{ path: "src/job.ts", source: "type Job = { kind: 'queued'; queue: string } | { kind: 'done'; result: string }; type Done = Extract<Job, {kind: 'done'}>; const isDone = (job: Job): job is Done => job.kind === 'done';" }], focusPath: "src/job.ts", expectedCount: 1, public: true }
678
+ ]
679
+ };
680
+ var no_explicit_type_predicate_default = createRule({
681
+ name: "no-explicit-type-predicate",
682
+ documentation: NO_EXPLICIT_TYPE_PREDICATE_DOCUMENTATION,
683
+ meta: {
684
+ type: "suggestion",
685
+ docs: { description: NO_EXPLICIT_TYPE_PREDICATE_DOCUMENTATION.summary },
686
+ schema: [],
687
+ messages: { noExplicitTypePredicate: "Replace this handwritten type predicate with a direct discriminator check or compiler-inferred narrowing. Parse unknown data with a schema and consume the validated result; preserve required external callable contracts." }
688
+ },
689
+ defaultOptions: [],
690
+ create(context) {
691
+ if (isGeneratedFile(context, context.sourceCode.text)) return {};
692
+ return {
693
+ TSTypePredicate(node) {
694
+ if (node.typeAnnotation != null) context.report({ node, messageId: "noExplicitTypePredicate" });
695
+ }
696
+ };
697
+ }
698
+ });
699
+
700
+ // src/rules/prefer-zod-enum-validator.ts
701
+ import { AST_NODE_TYPES as AST_NODE_TYPES4 } from "@typescript-eslint/utils";
702
+
656
703
  // src/rules/_static-string.ts
657
704
  import { AST_NODE_TYPES as AST_NODE_TYPES3, ASTUtils } from "@typescript-eslint/utils";
658
705
 
@@ -1782,19 +1829,19 @@ function firstParameterBindings(source, node) {
1782
1829
  function collectParameterBindings(source, node) {
1783
1830
  if (hasDirectEval(source)) return /* @__PURE__ */ new Set();
1784
1831
  const parameter = node.params[0];
1785
- const identifiers = [];
1832
+ const identifiers = /* @__PURE__ */ new Set();
1786
1833
  if (parameter?.type === AST_NODE_TYPES13.Identifier)
1787
- identifiers.push(parameter);
1834
+ identifiers.add(parameter);
1788
1835
  if (parameter?.type === AST_NODE_TYPES13.ObjectPattern) {
1789
1836
  for (const property of parameter.properties) {
1790
1837
  if (property.type === AST_NODE_TYPES13.Property && !property.computed && property.value.type === AST_NODE_TYPES13.Identifier)
1791
- identifiers.push(property.value);
1838
+ identifiers.add(property.value);
1792
1839
  }
1793
1840
  }
1794
1841
  return new Set(
1795
1842
  source.getDeclaredVariables(node).filter(
1796
- (variable) => identifiers.some(
1797
- (identifier) => variable.identifiers.includes(identifier)
1843
+ (variable) => variable.identifiers.some(
1844
+ (identifier) => identifiers.has(identifier)
1798
1845
  ) && stableValueBinding(variable)
1799
1846
  )
1800
1847
  );
@@ -1837,8 +1884,10 @@ function reactHook(source, callee, hook) {
1837
1884
  let identifier;
1838
1885
  let namespace = false;
1839
1886
  if (callee.type === AST_NODE_TYPES13.Identifier) identifier = callee;
1840
- else if (callee.type === AST_NODE_TYPES13.MemberExpression && !callee.optional && ASTUtils6.getPropertyName(callee) === hook && callee.object.type === AST_NODE_TYPES13.Identifier) {
1841
- identifier = callee.object;
1887
+ else if (callee.type === AST_NODE_TYPES13.MemberExpression && !callee.optional && ASTUtils6.getPropertyName(callee) === hook) {
1888
+ const object = unwrapExpression(callee.object);
1889
+ if (object.type !== AST_NODE_TYPES13.Identifier) return false;
1890
+ identifier = object;
1842
1891
  namespace = true;
1843
1892
  } else return false;
1844
1893
  const variable = ASTUtils6.findVariable(
@@ -1846,17 +1895,33 @@ function reactHook(source, callee, hook) {
1846
1895
  identifier.name
1847
1896
  );
1848
1897
  if (variable === null) return false;
1849
- const specifier = reactImportSpecifier(variable);
1850
- if (specifier === null) return false;
1851
- return namespace ? specifier.type === AST_NODE_TYPES13.ImportDefaultSpecifier || specifier.type === AST_NODE_TYPES13.ImportNamespaceSpecifier : specifier.type === AST_NODE_TYPES13.ImportSpecifier && specifier.importKind !== "type" && importSpecifierName(specifier) === hook;
1852
- }
1853
- function reactImportSpecifier(variable) {
1854
- let specifier = REACT_IMPORTS.get(variable);
1855
- if (specifier !== void 0) return specifier;
1898
+ const imported = reactImport(variable);
1899
+ if (imported === null) return false;
1900
+ const { specifier, replacedMembers } = imported;
1901
+ return namespace ? (specifier.type === AST_NODE_TYPES13.ImportDefaultSpecifier || specifier.type === AST_NODE_TYPES13.ImportNamespaceSpecifier) && replacedMembers?.has(null) !== true && replacedMembers?.has(hook) !== true : specifier.type === AST_NODE_TYPES13.ImportSpecifier && specifier.importKind !== "type" && importSpecifierName(specifier) === hook;
1902
+ }
1903
+ function reactImport(variable) {
1904
+ let imported = REACT_IMPORTS.get(variable);
1905
+ if (imported !== void 0) return imported;
1856
1906
  const definition = variable.defs[0];
1857
- specifier = variable.defs.length === 1 && definition?.type === "ImportBinding" && definition.parent.type === AST_NODE_TYPES13.ImportDeclaration && definition.parent.source.value === "react" && definition.parent.importKind !== "type" && stableValueBinding(variable) ? definition.node : null;
1858
- REACT_IMPORTS.set(variable, specifier);
1859
- return specifier;
1907
+ imported = null;
1908
+ if (variable.defs.length === 1 && definition?.type === "ImportBinding" && definition.parent.type === AST_NODE_TYPES13.ImportDeclaration && definition.parent.source.value === "react" && definition.parent.importKind !== "type") {
1909
+ const specifier = definition.node;
1910
+ const replacedMembers = specifier.type === AST_NODE_TYPES13.ImportSpecifier ? void 0 : /* @__PURE__ */ new Set();
1911
+ if (stableValueBinding(variable, replacedMembers === void 0 ? void 0 : (reference) => {
1912
+ const object = outerExpression(reference.identifier);
1913
+ const member3 = object.parent;
1914
+ if (member3?.type !== AST_NODE_TYPES13.MemberExpression || member3.object !== object)
1915
+ return true;
1916
+ const target = outerExpression(member3);
1917
+ if (target.parent?.type === AST_NODE_TYPES13.MemberExpression && target.parent.object === target)
1918
+ return true;
1919
+ if (writtenMember(member3)) replacedMembers.add(ASTUtils6.getPropertyName(member3));
1920
+ return true;
1921
+ })) imported = { specifier, replacedMembers };
1922
+ }
1923
+ REACT_IMPORTS.set(variable, imported);
1924
+ return imported;
1860
1925
  }
1861
1926
  function containsView(node) {
1862
1927
  if (node.type === AST_NODE_TYPES13.JSXElement || node.type === AST_NODE_TYPES13.JSXFragment)
@@ -1911,6 +1976,7 @@ var PREFER_SERVER_DATA_PREPARATION_DOCUMENTATION = {
1911
1976
  "Advisory only. Local syntax cannot establish whether a caller is a Server Component, whether props change interactively or whether server preparation reduces the total cost. This rule is a review lead, never proof that code can be moved to the server. No automatic fix is provided.",
1912
1977
  "Requires an explicit use client directive and parser-owned TypeScript services resolving map/filter/flatMap to the standard Array or ReadonlyArray library signature. The receiver beneath erased wrappers must itself have an Array, ReadonlyArray or tuple type after nullish narrowing; casts from opaque or custom collections do not establish this. Subclass and structural collection types outside those native array types are excluded. The containing view must have an independent React useState/useReducer call or a native callable type on an intrinsic DOM onClick/onChange/onInput/onSubmit handler. Nullish, noncallable and opaque handler types do not establish interaction. Noninteractive boundaries remain owned by no-unnecessary-use-client; custom hooks and indirect client requirements are unsupported.",
1913
1978
  "Every runtime reference to the source parameter binding must be a supported native data projection or a field-only JSX display loop. Inputs also needed for editing, whole-record forwarding, lookup, mutation, other fields or opaque helpers are excluded. Files containing direct eval are excluded because it can observe or change lexical bindings; indirect eval and properties named eval do not establish lexical access. Only direct first-parameter paths and synchronous single-expression callbacks are supported. Whole-row identity maps and constant maps are excluded; supported projections must read a fixed input field.",
1979
+ "Field-only object and dense array literals can form nested data shapes, including readonly tuples and flatMap outputs. Array holes, spreads, captured values and JSX outputs remain unsupported. Hook recognition follows erased namespace wrappers and excludes direct writes to the requested imported member; reflective or external API patches are not modeled.",
1914
1980
  "JSX-rendering callbacks are never reported as preparation findings. Callback calls, captured values, destructuring defaults/rest/nesting, async callbacks, event handlers, effects, memo callbacks, opaque helpers, dynamic/optional paths, custom collection signatures, missing type services, generated source and tests are excluded. First-parameter provenance is syntactic; annotations cannot prove absence of runtime getters or patched array methods. Analysis does not claim callback purity or preserve semantics of a hypothetical move.",
1915
1981
  "Reports the direct source projection once; chained operations with a call receiver are not independently reported. A static subprojection may still be prepared by its producer while a union with pending local edits remains in the client."
1916
1982
  ],
@@ -2065,6 +2131,10 @@ function projection(source, callback, mode = "data") {
2065
2131
  return inspect(node.left, depth + 1) && inspect(node.right, depth + 1);
2066
2132
  if (node.type === AST_NODE_TYPES14.ConditionalExpression)
2067
2133
  return inspect(node.test, depth + 1) && inspect(node.consequent, depth + 1) && inspect(node.alternate, depth + 1);
2134
+ if (node.type === AST_NODE_TYPES14.ArrayExpression)
2135
+ return node.elements.every(
2136
+ (element) => element !== null && element.type !== AST_NODE_TYPES14.SpreadElement && inspect(element, depth + 1)
2137
+ );
2068
2138
  if (node.type === AST_NODE_TYPES14.ObjectExpression)
2069
2139
  return node.properties.every(
2070
2140
  (property) => property.type === AST_NODE_TYPES14.Property && property.kind === "init" && !property.method && !property.computed && inspect(property.value, depth + 1)
@@ -2149,8 +2219,9 @@ var NO_READONLY_PROP_STATE_DOCUMENTATION = {
2149
2219
  category: "correctness",
2150
2220
  limitations: [
2151
2221
  "Advisory only: initial snapshots can be intentional. There is no automatic fix because replacing state with current props changes how later updates behave.",
2152
- "Recognizes direct React useState imports and default/namespace member calls, including renamed imports, through lexical binding identity. Checks a direct array destructure in a function containing its own JSX and a direct first-parameter property path, or a zero-argument synchronous lazy initializer returning that path.",
2222
+ "Recognizes direct React useState imports and default/namespace member calls, including renamed imports and erased wrappers around imported namespaces, through lexical binding identity. Checks a direct array destructure in a function containing its own JSX and a direct first-parameter property path, or a zero-argument synchronous lazy initializer returning that path.",
2153
2223
  "Eager initializers require parser-owned TypeScript services and primitive types, including unions composed entirely of primitives. Object and void types can hide callable values through structural assignment or ignored return values, so eager nonprimitive values, Any, unknown and unresolved generics are excluded. React executes function arguments as lazy initializers. Explicit zero-argument lazy callbacks returning a prop directly remain supported for all value types without type services. Opaque casts cannot prove runtime identity; lifecycle changes stay manual.",
2224
+ "Direct writes to the requested imported namespace member exclude its hook calls. Unknown computed writes exclude all namespace hooks; unrelated member writes and a hook function's own properties do not replace the callable. Reflective mutation and external API patches are not modeled.",
2154
2225
  "An updater read, escape, reassignment or nontrivial destructuring excludes the finding. Unused state values remain owned by unused-variable checks. Files containing direct eval are excluded because it can observe or change lexical bindings. Indirect eval and properties named eval do not establish lexical access. Opaque initialization, property aliases, optional/dynamic paths, rest/default bindings, non-JSX hooks, generated source and tests are outside scope. This does not ban interactive useState or replace the upstream set-state-in-effect rule."
2155
2226
  ],
2156
2227
  references: [
@@ -2439,18 +2510,8 @@ var FRONTEND_IMPORT = /^(?:react(?:-dom)?|next|preact|vue|svelte|@angular\/core|
2439
2510
  function isFrontendSource(context) {
2440
2511
  return /\.[jt]sx$/u.test(context.filename) || frontendModule(context.sourceCode.ast) || frontendPackage(context.filename);
2441
2512
  }
2442
- var FRONTEND_PACKAGE_BY_DIRECTORY = /* @__PURE__ */ new Map();
2443
2513
  function frontendPackage(filename) {
2444
- const directory = dirname(resolve(filename));
2445
- let cached = FRONTEND_PACKAGE_BY_DIRECTORY.get(directory);
2446
- if (cached === void 0) {
2447
- cached = nearestManifestDeclaresFrontend(directory);
2448
- FRONTEND_PACKAGE_BY_DIRECTORY.set(directory, cached);
2449
- }
2450
- return cached;
2451
- }
2452
- function nearestManifestDeclaresFrontend(start) {
2453
- let directory = start;
2514
+ let directory = dirname(resolve(filename));
2454
2515
  for (; ; ) {
2455
2516
  const manifestPath = join(directory, "package.json");
2456
2517
  if (existsSync(manifestPath)) {
@@ -2796,6 +2857,23 @@ function ownsTestComments(context) {
2796
2857
  const framework = context.sourceCode.ast.body.some((statement) => statement.type === AST_NODE_TYPES20.ImportDeclaration && statement.importKind !== "type" && (statement.specifiers.length === 0 || statement.specifiers.some((specifier) => specifier.type !== AST_NODE_TYPES20.ImportSpecifier || specifier.importKind !== "type")) && ["vitest", "@jest/globals", "@playwright/test", "bun:test", "node:test"].includes(statement.source.value));
2797
2858
  return unambiguous || framework;
2798
2859
  }
2860
+ function legalNoticeComments(comments) {
2861
+ const legal = /* @__PURE__ */ new Set();
2862
+ for (const [index, comment] of comments.entries()) {
2863
+ if (legal.has(comment) || comment.type !== "Line" || !LEGAL.test(comment.value)) continue;
2864
+ legal.add(comment);
2865
+ for (const direction of [-1, 1]) {
2866
+ let previous = comment;
2867
+ for (let next = index + direction; next >= 0 && next < comments.length; next += direction) {
2868
+ const neighbor = comments[next];
2869
+ if (neighbor?.type !== "Line" || Math.abs(neighbor.loc.start.line - previous.loc.start.line) !== 1) break;
2870
+ legal.add(neighbor);
2871
+ previous = neighbor;
2872
+ }
2873
+ }
2874
+ }
2875
+ return legal;
2876
+ }
2799
2877
  var no_test_comments_default = createRule({
2800
2878
  name: "no-test-comments",
2801
2879
  documentation: NO_TEST_COMMENTS_DOCUMENTATION,
@@ -2814,23 +2892,10 @@ var no_test_comments_default = createRule({
2814
2892
  return {
2815
2893
  Program() {
2816
2894
  const comments = context.sourceCode.getAllComments();
2817
- const legalLines = /* @__PURE__ */ new Set();
2818
- for (const [index, comment] of comments.entries()) {
2819
- if (comment.type !== "Line" || !LEGAL.test(comment.value)) continue;
2820
- legalLines.add(index);
2821
- for (const direction of [-1, 1]) {
2822
- let previous = comment;
2823
- for (let next = index + direction; next >= 0 && next < comments.length; next += direction) {
2824
- const neighbor = comments[next];
2825
- if (neighbor?.type !== "Line" || Math.abs(neighbor.loc.start.line - previous.loc.start.line) !== 1) break;
2826
- legalLines.add(next);
2827
- previous = neighbor;
2828
- }
2829
- }
2830
- }
2831
- for (const [index, comment] of comments.entries()) {
2895
+ const legal = frontend ? void 0 : legalNoticeComments(comments);
2896
+ for (const comment of comments) {
2832
2897
  const body3 = comment.value.trim().replace(/^\*\s*/u, "");
2833
- if (!frontend && (DIRECTIVE.test(body3) || BEHAVIORAL_DIRECTIVE.test(comment.value) || LEGAL.test(comment.value) || legalLines.has(index) || TYPE_CONTRACT.test(comment.value) || hasDetectSecretsPragma(comment, context.sourceCode.text))) continue;
2898
+ if (!frontend && (DIRECTIVE.test(body3) || BEHAVIORAL_DIRECTIVE.test(comment.value) || LEGAL.test(comment.value) || legal?.has(comment) || TYPE_CONTRACT.test(comment.value) || hasDetectSecretsPragma(comment, context.sourceCode.text))) continue;
2834
2899
  context.report({
2835
2900
  node: comment,
2836
2901
  messageId: "testComment",
@@ -3645,7 +3710,7 @@ function fixtureConstructor(source, value) {
3645
3710
  const use = value.params[1];
3646
3711
  if (use?.type !== AST_NODE_TYPES27.Identifier) return null;
3647
3712
  const binding3 = stableBinding(source, use);
3648
- const calls = scopeNodes(value.body, source).filter((node) => node.type === AST_NODE_TYPES27.CallExpression && !node.optional && node.arguments.length === 1 && node.callee.type === AST_NODE_TYPES27.Identifier && stableBinding(source, node.callee) === binding3);
3713
+ const calls = scopeNodes(value.body, source).filter((node) => node.type === AST_NODE_TYPES27.CallExpression).filter((node) => !node.optional && node.arguments.length === 1 && node.callee.type === AST_NODE_TYPES27.Identifier && stableBinding(source, node.callee) === binding3);
3649
3714
  if (calls.length !== 1 || binding3 === null) return null;
3650
3715
  const argument = calls[0]?.arguments[0];
3651
3716
  return argument === void 0 || argument.type === AST_NODE_TYPES27.SpreadElement ? null : newConstructor(source, argument);
@@ -3668,17 +3733,12 @@ function scopeNodes(root, source) {
3668
3733
  if (node === void 0) continue;
3669
3734
  result.push(node);
3670
3735
  if (node !== root && (node.type === AST_NODE_TYPES27.ArrowFunctionExpression || node.type === AST_NODE_TYPES27.FunctionExpression || node.type === AST_NODE_TYPES27.FunctionDeclaration || node.type === AST_NODE_TYPES27.ClassDeclaration || node.type === AST_NODE_TYPES27.ClassExpression)) continue;
3671
- for (const key of source.visitorKeys[node.type] ?? []) {
3672
- const value = Reflect.get(node, key);
3673
- if (Array.isArray(value)) pending.push(...value.filter(isNode2));
3674
- else if (isNode2(value)) pending.push(value);
3675
- }
3736
+ forEachAstChild(node, source.visitorKeys, (child) => {
3737
+ pending.push(child);
3738
+ });
3676
3739
  }
3677
3740
  return result;
3678
3741
  }
3679
- function isNode2(value) {
3680
- return typeof value === "object" && value !== null && "type" in value && typeof value.type === "string";
3681
- }
3682
3742
  function testApiCallee(expression) {
3683
3743
  let node = unwrapExpression(expression);
3684
3744
  while (node.type === AST_NODE_TYPES27.MemberExpression && !node.optional && TEST_MODIFIERS.has(ASTUtils14.getPropertyName(node) ?? "")) node = unwrapExpression(node.object);
@@ -6248,7 +6308,7 @@ function isSearchParamReceiver(call, services) {
6248
6308
  // package.json
6249
6309
  var package_default = {
6250
6310
  name: "@sarj/eslint-plugin",
6251
- version: "18.2.0",
6311
+ version: "18.3.0",
6252
6312
  packageManager: "npm@12.2.1",
6253
6313
  description: "Custom ESLint rules for hypermodern TypeScript / React / Next.js projects",
6254
6314
  type: "module",
@@ -6894,7 +6954,7 @@ function existingFactoryContractFix(sourceCode, candidate2) {
6894
6954
  const contract = contractStatement?.type === AST_NODE_TYPES46.ExportNamedDeclaration ? contractStatement.declaration : null;
6895
6955
  const implementation = classStatement?.type === AST_NODE_TYPES46.ExportNamedDeclaration ? classStatement.declaration : classStatement;
6896
6956
  const factory = factoryStatement?.type === AST_NODE_TYPES46.ExportNamedDeclaration ? factoryStatement.declaration : null;
6897
- if (contract?.type !== AST_NODE_TYPES46.TSTypeAliasDeclaration || worker?.type !== AST_NODE_TYPES46.TSInterfaceDeclaration || implementation?.type !== AST_NODE_TYPES46.ClassDeclaration || implementation !== candidate2 || !ordinaryClass(implementation) || !ordinaryFactory(factory))
6957
+ if (contract?.type !== AST_NODE_TYPES46.TSTypeAliasDeclaration || worker?.type !== AST_NODE_TYPES46.TSInterfaceDeclaration || implementation?.type !== AST_NODE_TYPES46.ClassDeclaration || implementation !== candidate2 || !ordinaryClass(implementation) || factory?.type !== AST_NODE_TYPES46.FunctionDeclaration || !ordinaryFactory(factory))
6898
6958
  return null;
6899
6959
  const operation2 = contractOperation(contract);
6900
6960
  if (operation2 === null || interfaceOperation(worker) !== operation2)
@@ -6913,7 +6973,7 @@ function ordinaryClass(node) {
6913
6973
  return node.id !== null && !node.declare && !node.abstract && node.decorators.length === 0 && node.superClass === null && node.implements.length === 0 && node.typeParameters === void 0 && node.body.body.length === 2;
6914
6974
  }
6915
6975
  function ordinaryFactory(node) {
6916
- return node?.type === AST_NODE_TYPES46.FunctionDeclaration && node.id !== null && !node.declare && !node.async && !node.generator && node.typeParameters === void 0 && node.params.length === 1 && node.body.body.length === 1;
6976
+ return node.id !== null && !node.declare && !node.async && !node.generator && node.typeParameters === void 0 && node.params.length === 1 && node.body.body.length === 1;
6917
6977
  }
6918
6978
  function interfaceOperation(node) {
6919
6979
  return !node.declare && node.extends.length === 0 && node.typeParameters === void 0 ? singletonOperation(node.body.body) : null;
@@ -7489,8 +7549,8 @@ var publicMethodNames = (body3, functionAliases) => {
7489
7549
  };
7490
7550
  var isFluentConstructionObject = (node, getText) => {
7491
7551
  if (node.id === null) return false;
7492
- const methods = node.body.body.filter(
7493
- (member3) => member3.type === AST_NODE_TYPES47.MethodDefinition && member3.kind === "method" && !member3.static && member3.accessibility !== "private" && member3.accessibility !== "protected" && member3.value.body !== null
7552
+ const methods = node.body.body.filter((member3) => member3.type === AST_NODE_TYPES47.MethodDefinition).filter(
7553
+ (member3) => member3.kind === "method" && !member3.static && member3.accessibility !== "private" && member3.accessibility !== "protected" && member3.value.body !== null
7494
7554
  );
7495
7555
  if (methods.length === 0) return false;
7496
7556
  return methods.every((member3) => {
@@ -7654,7 +7714,7 @@ var require_port_for_service_default = createRule({
7654
7714
  const ctor = node.body.body.find(
7655
7715
  (member3) => member3.type === AST_NODE_TYPES47.MethodDefinition && member3.kind === "constructor" && member3.value.body !== null && member3.value.body !== void 0
7656
7716
  );
7657
- if (ctor === void 0) return;
7717
+ if (ctor?.type !== AST_NODE_TYPES47.MethodDefinition) return;
7658
7718
  const constructorFacts = readConstructor(
7659
7719
  ctor,
7660
7720
  objectTypes,
@@ -7721,7 +7781,7 @@ function createServiceOperationResolver(program) {
7721
7781
  const ctor = node.body.body.find(
7722
7782
  (member3) => member3.type === AST_NODE_TYPES47.MethodDefinition && member3.kind === "constructor" && member3.value.body !== null
7723
7783
  );
7724
- if (ctor === void 0) return [];
7784
+ if (ctor?.type !== AST_NODE_TYPES47.MethodDefinition) return [];
7725
7785
  const declared = () => declaredTypes ??= fileTypeIndex(program);
7726
7786
  const facts = readConstructor(
7727
7787
  ctor,
@@ -9296,7 +9356,7 @@ function ordinaryHostReference(reference) {
9296
9356
  }
9297
9357
 
9298
9358
  // src/rules/no-contradictory-type-predicate.ts
9299
- var RUNTIME_KINDS = /* @__PURE__ */ new Set(["string", "number", "bigint", "boolean", "symbol", "undefined", "object", "function"]);
9359
+ var RUNTIME_KINDS = ["string", "number", "bigint", "boolean", "symbol", "undefined", "object", "function"];
9300
9360
  var PRIMITIVE_KINDS = [
9301
9361
  [ts24.TypeFlags.String, "string"],
9302
9362
  [ts24.TypeFlags.Number, "number"],
@@ -9375,7 +9435,7 @@ var no_contradictory_type_predicate_default = createRule({
9375
9435
  if (hasSeparatePredicateContract(services.esTreeNodeToTSNodeMap.get(node), checker)) return;
9376
9436
  const parameter = node.params.find((candidate2) => candidate2.type === AST_NODE_TYPES56.Identifier && candidate2.name === name);
9377
9437
  const expression = singleReturn(node);
9378
- if (parameter?.typeAnnotation === void 0 || expression === void 0) return;
9438
+ if (parameter?.type !== AST_NODE_TYPES56.Identifier || parameter.typeAnnotation === void 0 || expression === void 0) return;
9379
9439
  const check = typeofCheck(expression);
9380
9440
  if (check !== void 0 && !sameParameter(parameter, check.parameter, context.sourceCode)) return;
9381
9441
  const input = checker.getTypeAtLocation(services.esTreeNodeToTSNodeMap.get(check?.parameter ?? parameter));
@@ -9466,15 +9526,13 @@ function typeofCheck(expression) {
9466
9526
  if (value.type !== AST_NODE_TYPES56.BinaryExpression || value.operator !== "===" && value.operator !== "==") return void 0;
9467
9527
  for (const [tested, expected] of [[value.left, value.right], [value.right, value.left]]) {
9468
9528
  const operand = unwrapExpression(tested);
9469
- const kind = staticString(expected);
9470
- if (operand.type !== AST_NODE_TYPES56.UnaryExpression || operand.operator !== "typeof" || operand.argument.type !== AST_NODE_TYPES56.Identifier || kind === null || !isRuntimeKind(kind)) continue;
9529
+ const expectedKind = staticString(expected);
9530
+ const kind = RUNTIME_KINDS.find((candidate2) => candidate2 === expectedKind);
9531
+ if (operand.type !== AST_NODE_TYPES56.UnaryExpression || operand.operator !== "typeof" || operand.argument.type !== AST_NODE_TYPES56.Identifier || kind === void 0) continue;
9471
9532
  return { parameter: operand.argument, kind };
9472
9533
  }
9473
9534
  return void 0;
9474
9535
  }
9475
- function isRuntimeKind(value) {
9476
- return RUNTIME_KINDS.has(value);
9477
- }
9478
9536
  function sameParameter(declared, tested, sourceCode) {
9479
9537
  const parameter = ASTUtils35.findVariable(sourceCode.getScope(declared), declared.name);
9480
9538
  return parameter !== null && parameter === ASTUtils35.findVariable(sourceCode.getScope(tested), tested.name);
@@ -9523,9 +9581,9 @@ import { AST_NODE_TYPES as AST_NODE_TYPES57, ASTUtils as ASTUtils36 } from "@typ
9523
9581
  import ts25 from "typescript";
9524
9582
  function uuidPredicateWitness(expression, parameter, sourceCode, services) {
9525
9583
  const success = unwrapExpression(expression);
9526
- if (!member(success, "success")) return void 0;
9584
+ if (success.type !== AST_NODE_TYPES57.MemberExpression || !member(success, "success")) return void 0;
9527
9585
  const parse2 = unwrapExpression(success.object);
9528
- if (parse2.type !== AST_NODE_TYPES57.CallExpression || parse2.optional || parse2.arguments.length !== 1 || !member(parse2.callee, "safeParse")) return void 0;
9586
+ if (parse2.type !== AST_NODE_TYPES57.CallExpression || parse2.optional || parse2.arguments.length !== 1 || parse2.callee.type !== AST_NODE_TYPES57.MemberExpression || !member(parse2.callee, "safeParse")) return void 0;
9529
9587
  const argument = parse2.arguments[0];
9530
9588
  if (argument === void 0 || unwrapExpression(argument).type !== AST_NODE_TYPES57.Identifier) return void 0;
9531
9589
  const value = unwrapExpression(argument);
@@ -9544,13 +9602,13 @@ function binding(node, sourceCode) {
9544
9602
  return ASTUtils36.findVariable(sourceCode.getScope(node), node.name);
9545
9603
  }
9546
9604
  function member(node, name) {
9547
- return node?.type === AST_NODE_TYPES57.MemberExpression && !node.optional && !node.computed && node.property.type === AST_NODE_TYPES57.Identifier && node.property.name === name;
9605
+ return !node.optional && !node.computed && node.property.type === AST_NODE_TYPES57.Identifier && node.property.name === name;
9548
9606
  }
9549
9607
  function uuidNamespace(initializer, sourceCode, services) {
9550
- if (!noArguments(initializer) || !member(initializer.callee, "uuid")) return null;
9608
+ if (initializer.type !== AST_NODE_TYPES57.CallExpression || !noArguments(initializer) || initializer.callee.type !== AST_NODE_TYPES57.MemberExpression || !member(initializer.callee, "uuid")) return null;
9551
9609
  let receiver = unwrapExpression(initializer.callee.object);
9552
9610
  let legacy = false;
9553
- if (noArguments(receiver) && member(receiver.callee, "string")) {
9611
+ if (receiver.type === AST_NODE_TYPES57.CallExpression && noArguments(receiver) && receiver.callee.type === AST_NODE_TYPES57.MemberExpression && member(receiver.callee, "string")) {
9554
9612
  receiver = unwrapExpression(receiver.callee.object);
9555
9613
  legacy = true;
9556
9614
  }
@@ -9566,7 +9624,7 @@ function uuidNamespace(initializer, sourceCode, services) {
9566
9624
  return namespace ?? null;
9567
9625
  }
9568
9626
  function noArguments(node) {
9569
- return node.type === AST_NODE_TYPES57.CallExpression && !node.optional && node.arguments.length === 0;
9627
+ return !node.optional && node.arguments.length === 0;
9570
9628
  }
9571
9629
  function installedZod(node, services) {
9572
9630
  const checker = services.program.getTypeChecker();
@@ -9586,7 +9644,7 @@ function closedSchema(schema) {
9586
9644
  const receiver = outerExpression(reference.identifier);
9587
9645
  const property = receiver.parent;
9588
9646
  if (property?.type === AST_NODE_TYPES57.ExportSpecifier && property.local === receiver) return true;
9589
- if (!member(property, "safeParse") || property.object !== receiver) return false;
9647
+ if (property?.type !== AST_NODE_TYPES57.MemberExpression || !member(property, "safeParse") || property.object !== receiver) return false;
9590
9648
  const call = property.parent;
9591
9649
  return call?.type === AST_NODE_TYPES57.CallExpression && call.callee === property && !call.optional && call.arguments.length === 1 && call.arguments[0]?.type !== AST_NODE_TYPES57.SpreadElement;
9592
9650
  });
@@ -10052,10 +10110,10 @@ function literalSelectorFix(sourceCode, parameter) {
10052
10110
  if (sourceCode.ast.body.length !== 4 || sourceCode.getAllComments().length > 0)
10053
10111
  return null;
10054
10112
  const [first, second, declaration, statement] = sourceCode.ast.body;
10055
- if (!isLiteralOperation(first) || !isLiteralOperation(second) || declaration?.type !== AST_NODE_TYPES60.VariableDeclaration || declaration.declare || declaration.kind !== "const" || declaration.declarations.length !== 1 || statement?.type !== AST_NODE_TYPES60.ExportNamedDeclaration || statement.declaration?.type !== AST_NODE_TYPES60.FunctionDeclaration)
10113
+ if (first?.type !== AST_NODE_TYPES60.FunctionDeclaration || !isLiteralOperation(first) || second?.type !== AST_NODE_TYPES60.FunctionDeclaration || !isLiteralOperation(second) || declaration?.type !== AST_NODE_TYPES60.VariableDeclaration || declaration.declare || declaration.kind !== "const" || declaration.declarations.length !== 1 || statement?.type !== AST_NODE_TYPES60.ExportNamedDeclaration || statement.declaration?.type !== AST_NODE_TYPES60.FunctionDeclaration)
10056
10114
  return null;
10057
10115
  const binding3 = declaration.declarations[0];
10058
- if (binding3?.id.type !== AST_NODE_TYPES60.Identifier || binding3.id.typeAnnotation !== void 0 || !isSelector(binding3.init, parameter))
10116
+ if (binding3?.id.type !== AST_NODE_TYPES60.Identifier || binding3.id.typeAnnotation !== void 0 || binding3.init?.type !== AST_NODE_TYPES60.ArrowFunctionExpression || binding3.init.body.type !== AST_NODE_TYPES60.ConditionalExpression || !isSelector(binding3.init, parameter))
10059
10117
  return null;
10060
10118
  const branch = binding3.init.body;
10061
10119
  const whenTrue = operation(sourceCode, branch.consequent, first, second);
@@ -10077,13 +10135,12 @@ function literalSelectorFix(sourceCode, parameter) {
10077
10135
  ];
10078
10136
  }
10079
10137
  function isLiteralOperation(node) {
10080
- if (node?.type !== AST_NODE_TYPES60.FunctionDeclaration || node.id === null || node.declare || node.async || node.generator || node.params.length !== 0 || node.typeParameters !== void 0 || node.returnType !== void 0 || node.body.body.length !== 1)
10138
+ if (node.id === null || node.declare || node.async || node.generator || node.params.length !== 0 || node.typeParameters !== void 0 || node.returnType !== void 0 || node.body.body.length !== 1)
10081
10139
  return false;
10082
10140
  const returned2 = node.body.body[0];
10083
10141
  return returned2?.type === AST_NODE_TYPES60.ReturnStatement && returned2.argument?.type === AST_NODE_TYPES60.Literal && typeof returned2.argument.value === "string";
10084
10142
  }
10085
10143
  function isSelector(node, parameter) {
10086
- if (node?.type !== AST_NODE_TYPES60.ArrowFunctionExpression) return false;
10087
10144
  const actual = node.params[0];
10088
10145
  return actual?.type === AST_NODE_TYPES60.Identifier && actual.name === parameter.name && !node.async && node.typeParameters === void 0 && node.returnType === void 0 && node.params.length === 1 && !actual.optional && actual.typeAnnotation?.typeAnnotation.type === AST_NODE_TYPES60.TSBooleanKeyword && node.body.type === AST_NODE_TYPES60.ConditionalExpression && node.body.test === parameter;
10089
10146
  }
@@ -11910,10 +11967,6 @@ import { AST_NODE_TYPES as AST_NODE_TYPES74 } from "@typescript-eslint/utils";
11910
11967
  var TEST_CALLERS = /* @__PURE__ */ new Set(["it", "test"]);
11911
11968
  var ASSERTION_NAMES = /* @__PURE__ */ new Set(["assert", "expect"]);
11912
11969
  var TEST_MODIFIERS2 = /* @__PURE__ */ new Set(["concurrent", "fails", "only", "sequential", "skip"]);
11913
- var FUNCTION_TYPES = /* @__PURE__ */ new Set([
11914
- AST_NODE_TYPES74.FunctionExpression,
11915
- AST_NODE_TYPES74.ArrowFunctionExpression
11916
- ]);
11917
11970
  var OMITTED_AST_KEYS = /* @__PURE__ */ new Set([
11918
11971
  "end",
11919
11972
  "loc",
@@ -12095,7 +12148,7 @@ function testBody(call, sourceCode) {
12095
12148
  return null;
12096
12149
  }
12097
12150
  const callback = call.arguments.map(unwrapExpression).find(
12098
- (argument) => argument.type !== AST_NODE_TYPES74.SpreadElement && FUNCTION_TYPES.has(argument.type)
12151
+ (argument) => argument.type === AST_NODE_TYPES74.FunctionExpression || argument.type === AST_NODE_TYPES74.ArrowFunctionExpression
12099
12152
  );
12100
12153
  if (callback === void 0 || call.arguments.length !== 2 || containsInlineSnapshot(callback.body)) {
12101
12154
  return null;
@@ -15389,7 +15442,7 @@ function uuidModule(sourceCode, kind) {
15389
15442
  const native = statements[offset + 1];
15390
15443
  const legacy = statements[offset + 2];
15391
15444
  const exported = statements[offset + 3];
15392
- if (imported !== null && imported?.type !== AST_NODE_TYPES87.ImportDeclaration || declaration?.type !== AST_NODE_TYPES87.VariableDeclaration || declaration.kind !== "const" || declaration.declare || declaration.declarations.length !== 1 || !stringFunction(native) || !stringFunction(legacy) || exported?.type !== AST_NODE_TYPES87.ExportNamedDeclaration || exported.specifiers.length !== 0 || exported.source !== null || !arrayFunction(exported.declaration))
15445
+ if (imported !== null && imported?.type !== AST_NODE_TYPES87.ImportDeclaration || declaration?.type !== AST_NODE_TYPES87.VariableDeclaration || declaration.kind !== "const" || declaration.declare || declaration.declarations.length !== 1 || native?.type !== AST_NODE_TYPES87.FunctionDeclaration || !stringFunction(native) || legacy?.type !== AST_NODE_TYPES87.FunctionDeclaration || !stringFunction(legacy) || exported?.type !== AST_NODE_TYPES87.ExportNamedDeclaration || exported.specifiers.length !== 0 || exported.source !== null || exported.declaration?.type !== AST_NODE_TYPES87.FunctionDeclaration || !arrayFunction(exported.declaration))
15393
15446
  return null;
15394
15447
  const provider = declaration.declarations[0];
15395
15448
  if (provider === void 0 || !nativeProvider(sourceCode, provider) || !providerRead(sourceCode, returned(native), provider) || !exportedReads(
@@ -15411,7 +15464,7 @@ function arrayFunction(node) {
15411
15464
  return annotation?.type === AST_NODE_TYPES87.TSArrayType && annotation.elementType.type === AST_NODE_TYPES87.TSStringKeyword;
15412
15465
  }
15413
15466
  function ordinaryFunction(node) {
15414
- return node?.type === AST_NODE_TYPES87.FunctionDeclaration && node.id !== null && !node.declare && !node.async && !node.generator && node.typeParameters === void 0 && node.params.length === 0 && node.body.body.length === 1 && node.body.body[0]?.type === AST_NODE_TYPES87.ReturnStatement && node.body.body[0].argument !== null;
15467
+ return node.id !== null && !node.declare && !node.async && !node.generator && node.typeParameters === void 0 && node.params.length === 0 && node.body.body.length === 1 && node.body.body[0]?.type === AST_NODE_TYPES87.ReturnStatement && node.body.body[0].argument !== null;
15415
15468
  }
15416
15469
  function returned(node) {
15417
15470
  const statement = node.body.body[0];
@@ -15423,14 +15476,14 @@ function nativeProvider(sourceCode, node) {
15423
15476
  if (node.id.type !== AST_NODE_TYPES87.Identifier || node.id.typeAnnotation !== void 0)
15424
15477
  return false;
15425
15478
  const call = node.init;
15426
- if (call?.type !== AST_NODE_TYPES87.CallExpression || call.optional || call.typeArguments !== void 0 || call.arguments.length !== 1 || !member2(call.callee, "bind") || !member2(call.callee.object, "randomUUID"))
15479
+ if (call?.type !== AST_NODE_TYPES87.CallExpression || call.optional || call.typeArguments !== void 0 || call.arguments.length !== 1 || call.callee.type !== AST_NODE_TYPES87.MemberExpression || !member2(call.callee, "bind") || call.callee.object.type !== AST_NODE_TYPES87.MemberExpression || !member2(call.callee.object, "randomUUID"))
15427
15480
  return false;
15428
15481
  const receiver = call.callee.object.object;
15429
15482
  const argument = call.arguments[0];
15430
15483
  return receiver.type === AST_NODE_TYPES87.Identifier && receiver.name === "crypto" && argument?.type === AST_NODE_TYPES87.Identifier && argument.name === "crypto" && (ASTUtils49.findVariable(sourceCode.getScope(receiver), "crypto")?.defs.length ?? 0) === 0 && (ASTUtils49.findVariable(sourceCode.getScope(argument), "crypto")?.defs.length ?? 0) === 0;
15431
15484
  }
15432
15485
  function member2(node, property) {
15433
- return node.type === AST_NODE_TYPES87.MemberExpression && !node.computed && !node.optional && node.property.type === AST_NODE_TYPES87.Identifier && node.property.name === property;
15486
+ return !node.computed && !node.optional && node.property.type === AST_NODE_TYPES87.Identifier && node.property.name === property;
15434
15487
  }
15435
15488
  function providerRead(sourceCode, node, declaration) {
15436
15489
  return node.type === AST_NODE_TYPES87.CallExpression && !node.optional && node.typeArguments === void 0 && node.arguments.length === 0 && node.callee.type === AST_NODE_TYPES87.Identifier && sameBinding2(sourceCode, node.callee, declaration);
@@ -15459,7 +15512,7 @@ function exportedReads(sourceCode, node, native, legacy, imported) {
15459
15512
  return nilImport !== void 0 && sameBinding2(sourceCode, nil, nilImport);
15460
15513
  }
15461
15514
  function isUuidRecipe(sourceCode, node, reported) {
15462
- if (node.type !== AST_NODE_TYPES87.CallExpression || node.optional || node.typeArguments !== void 0 || !member2(node.callee, "replace") || node.callee.object.type !== AST_NODE_TYPES87.Literal || node.callee.object.value !== UUID_TEMPLATE || node.arguments.length !== IMPORT_COUNT)
15515
+ if (node.type !== AST_NODE_TYPES87.CallExpression || node.optional || node.typeArguments !== void 0 || node.callee.type !== AST_NODE_TYPES87.MemberExpression || !member2(node.callee, "replace") || node.callee.object.type !== AST_NODE_TYPES87.Literal || node.callee.object.value !== UUID_TEMPLATE || node.arguments.length !== IMPORT_COUNT)
15463
15516
  return false;
15464
15517
  const [pattern, callback] = node.arguments;
15465
15518
  if (pattern?.type !== AST_NODE_TYPES87.Literal || !("regex" in pattern) || pattern.regex.pattern !== "[xy]" || pattern.regex.flags !== "g" || callback?.type !== AST_NODE_TYPES87.ArrowFunctionExpression || callback.async || callback.typeParameters !== void 0 || callback.returnType !== void 0 || callback.params.length !== 1 || callback.params[0]?.type !== AST_NODE_TYPES87.Identifier || callback.params[0].typeAnnotation !== void 0 || callback.params[0].optional || callback.body.type !== AST_NODE_TYPES87.BlockStatement || callback.body.body.length !== IMPORT_COUNT)
@@ -16011,8 +16064,8 @@ function serverActionErrorResults(sourceCode) {
16011
16064
  if (nodes.some((node) => node.type === AST_NODE_TYPES91.CallExpression && node.callee.type === AST_NODE_TYPES91.Identifier && node.callee.name === "eval")) return [];
16012
16065
  const analysis = new ActionResults(sourceCode);
16013
16066
  const actionSet = new Set(actions);
16014
- return nodes.filter((node) => {
16015
- if (node.type !== AST_NODE_TYPES91.ReturnStatement || node.argument === null) return false;
16067
+ return nodes.filter((node) => node.type === AST_NODE_TYPES91.ReturnStatement).filter((node) => {
16068
+ if (node.argument === null) return false;
16016
16069
  const owner = functionOwner(node);
16017
16070
  return owner !== null && actionSet.has(owner) && escapingActionReturn(node, owner, sourceCode) && analysis.payload(node.argument, owner);
16018
16071
  });
@@ -16994,7 +17047,7 @@ function existingDomainComparisonFix(sourceCode, comparison2) {
16994
17047
  if (comparison2.operator !== "===" || sourceCode.ast.body.length !== 2 || sourceCode.getAllComments().length !== 0)
16995
17048
  return null;
16996
17049
  const [comparator, exported] = sourceCode.ast.body;
16997
- if (!isOrdinary(comparator) || comparator.id === null || exported?.type !== AST_NODE_TYPES93.ExportNamedDeclaration || exported.exportKind !== "value" || !isOrdinary(exported.declaration))
17050
+ if (comparator?.type !== AST_NODE_TYPES93.FunctionDeclaration || !isOrdinary(comparator) || comparator.id === null || exported?.type !== AST_NODE_TYPES93.ExportNamedDeclaration || exported.exportKind !== "value" || exported.declaration?.type !== AST_NODE_TYPES93.FunctionDeclaration || !isOrdinary(exported.declaration))
16998
17051
  return null;
16999
17052
  const fields2 = comparatorFields(comparator);
17000
17053
  const elements = callerElements(exported.declaration);
@@ -17013,7 +17066,7 @@ function existingDomainComparisonFix(sourceCode, comparison2) {
17013
17066
  );
17014
17067
  }
17015
17068
  function isOrdinary(node) {
17016
- return node?.type === AST_NODE_TYPES93.FunctionDeclaration && node.id !== null && !node.declare && !node.async && !node.generator && node.typeParameters === void 0 && node.body.body.length === 1;
17069
+ return node.id !== null && !node.declare && !node.async && !node.generator && node.typeParameters === void 0 && node.body.body.length === 1;
17017
17070
  }
17018
17071
  function comparatorFields(node) {
17019
17072
  const [left, right] = node.params;
@@ -18251,7 +18304,7 @@ function reportClass(context, services, owner) {
18251
18304
  if (contract === null) return;
18252
18305
  const groups = /* @__PURE__ */ new Map();
18253
18306
  for (const member3 of owner.body.body) {
18254
- if (!candidate(member3)) continue;
18307
+ if (member3.type !== AST_NODE_TYPES100.MethodDefinition || !candidate(member3)) continue;
18255
18308
  const name = convertibleMemberName(member3);
18256
18309
  if (name === null || contract.has(name)) continue;
18257
18310
  if (member3.accessibility === "private" || member3.key.type === AST_NODE_TYPES100.PrivateIdentifier) continue;
@@ -18271,7 +18324,7 @@ function reportClass(context, services, owner) {
18271
18324
  }
18272
18325
  }
18273
18326
  function candidate(member3) {
18274
- return member3.type === AST_NODE_TYPES100.MethodDefinition && member3.kind !== "constructor" && !member3.static && member3.accessibility !== "protected" && !member3.override && !member3.computed && member3.key.type === AST_NODE_TYPES100.Identifier && member3.value.body !== null;
18327
+ return member3.kind !== "constructor" && !member3.static && member3.accessibility !== "protected" && !member3.override && !member3.computed && member3.key.type === AST_NODE_TYPES100.Identifier && member3.value.body !== null;
18275
18328
  }
18276
18329
  function interfaceNames(services, owner) {
18277
18330
  const tsOwner = services.esTreeNodeToTSNodeMap.get(owner);
@@ -18443,7 +18496,7 @@ var SINGLE_STATEMENT_HOSTS = /* @__PURE__ */ new Set([
18443
18496
  AST_NODE_TYPES102.IfStatement,
18444
18497
  AST_NODE_TYPES102.WhileStatement
18445
18498
  ]);
18446
- var FUNCTION_TYPES2 = /* @__PURE__ */ new Set([
18499
+ var FUNCTION_TYPES = /* @__PURE__ */ new Set([
18447
18500
  AST_NODE_TYPES102.ArrowFunctionExpression,
18448
18501
  AST_NODE_TYPES102.FunctionDeclaration,
18449
18502
  AST_NODE_TYPES102.FunctionExpression
@@ -18473,7 +18526,7 @@ function fallbackFollowsTry(tryStatement) {
18473
18526
  return last?.type === AST_NODE_TYPES102.ReturnStatement && hasFollowingStatement(tryStatement);
18474
18527
  }
18475
18528
  function hasFollowingStatement(node) {
18476
- for (let current = node; current !== void 0 && !FUNCTION_TYPES2.has(current.type); current = current.parent) {
18529
+ for (let current = node; current !== void 0 && !FUNCTION_TYPES.has(current.type); current = current.parent) {
18477
18530
  const slot = statementSlot(current);
18478
18531
  if (slot !== null && slot.index < slot.list.length - 1) return true;
18479
18532
  }
@@ -18561,7 +18614,7 @@ var no_log_only_catch_default = createRule({
18561
18614
  function hasFollowingCoercionCheck(owner, left, coercion) {
18562
18615
  let current = owner;
18563
18616
  let slot = statementSlot(current);
18564
- while (slot === null && current.parent !== void 0 && !FUNCTION_TYPES2.has(current.parent.type)) {
18617
+ while (slot === null && current.parent !== void 0 && !FUNCTION_TYPES.has(current.parent.type)) {
18565
18618
  current = current.parent;
18566
18619
  slot = statementSlot(current);
18567
18620
  }
@@ -18646,7 +18699,7 @@ var TEST_NAMES = /* @__PURE__ */ new Set(["it", "test"]);
18646
18699
  var TEST_MODIFIERS3 = /* @__PURE__ */ new Set(["concurrent", "fails", "only", "sequential", "skip"]);
18647
18700
  var TEST_BUILDERS = /* @__PURE__ */ new Set(["each", "for", "runIf", "skipIf"]);
18648
18701
  var ASSERTION_NAMES2 = /* @__PURE__ */ new Set(["assert", "assertType", "expect", "expectTypeOf"]);
18649
- var FUNCTION_TYPES3 = /* @__PURE__ */ new Set([AST_NODE_TYPES103.ArrowFunctionExpression, AST_NODE_TYPES103.FunctionExpression, AST_NODE_TYPES103.FunctionDeclaration]);
18702
+ var FUNCTION_TYPES2 = /* @__PURE__ */ new Set([AST_NODE_TYPES103.ArrowFunctionExpression, AST_NODE_TYPES103.FunctionExpression, AST_NODE_TYPES103.FunctionDeclaration]);
18650
18703
  function staticMemberName3(node) {
18651
18704
  if (!node.computed && node.property.type === AST_NODE_TYPES103.Identifier) return node.property.name;
18652
18705
  if (node.computed && node.property.type === AST_NODE_TYPES103.Literal && typeof node.property.value === "string") return node.property.value;
@@ -18659,7 +18712,6 @@ function rootIdentifier2(callee) {
18659
18712
  return null;
18660
18713
  }
18661
18714
  function isDirectTestCallback(node, context) {
18662
- if (node.type !== AST_NODE_TYPES103.ArrowFunctionExpression && node.type !== AST_NODE_TYPES103.FunctionExpression) return false;
18663
18715
  const call = directArgumentCall(node);
18664
18716
  if (call === null) return false;
18665
18717
  const root = testRoot(call.callee);
@@ -18679,12 +18731,12 @@ function testRoot(callee) {
18679
18731
  return modifier !== null && TEST_MODIFIERS3.has(modifier) ? testRoot(callee.object) : null;
18680
18732
  }
18681
18733
  function nearestFunction(node) {
18682
- for (let current = node.parent; current !== void 0 && current !== null; current = current.parent) if (FUNCTION_TYPES3.has(current.type)) return current;
18734
+ for (let current = node.parent; current !== void 0 && current !== null; current = current.parent) if (FUNCTION_TYPES2.has(current.type)) return current;
18683
18735
  return null;
18684
18736
  }
18685
18737
  function walkOwnScope(node, predicate) {
18686
18738
  if (predicate(node)) return true;
18687
- return forEachOwnAstChild(node, (child) => !FUNCTION_TYPES3.has(child.type) && walkOwnScope(child, predicate));
18739
+ return forEachOwnAstChild(node, (child) => !FUNCTION_TYPES2.has(child.type) && walkOwnScope(child, predicate));
18688
18740
  }
18689
18741
  function isAssertion(node, context) {
18690
18742
  if (node.type !== AST_NODE_TYPES103.CallExpression) return false;
@@ -18776,7 +18828,7 @@ var no_bare_return_from_test_catch_default = createRule({
18776
18828
  ReturnStatement(node) {
18777
18829
  if (node.argument !== null) return;
18778
18830
  const owner = nearestFunction(node);
18779
- if (owner === null || !isDirectTestCallback(owner, context)) return;
18831
+ if (owner?.type !== AST_NODE_TYPES103.ArrowFunctionExpression && owner?.type !== AST_NODE_TYPES103.FunctionExpression || !isDirectTestCallback(owner, context)) return;
18780
18832
  let catchClause = null;
18781
18833
  for (let current = node.parent; current !== owner; current = current?.parent) {
18782
18834
  if (current?.type === AST_NODE_TYPES103.CatchClause) {
@@ -19406,7 +19458,7 @@ function labeledTupleObjectFix(sourceCode, annotation) {
19406
19458
  if (sourceCode.ast.body.length !== 2 || sourceCode.getAllComments().length > 0)
19407
19459
  return null;
19408
19460
  const [helper, statement] = sourceCode.ast.body;
19409
- if (!isOrdinary2(helper) || statement?.type !== AST_NODE_TYPES107.ExportNamedDeclaration || !isOrdinary2(statement.declaration) || helper.returnType?.typeAnnotation !== annotation)
19461
+ if (helper?.type !== AST_NODE_TYPES107.FunctionDeclaration || !isOrdinary2(helper) || statement?.type !== AST_NODE_TYPES107.ExportNamedDeclaration || statement.declaration?.type !== AST_NODE_TYPES107.FunctionDeclaration || !isOrdinary2(statement.declaration) || helper.returnType?.typeAnnotation !== annotation)
19410
19462
  return null;
19411
19463
  const caller = statement.declaration;
19412
19464
  const fields2 = tupleFields(helper);
@@ -19431,7 +19483,7 @@ function labeledTupleObjectFix(sourceCode, annotation) {
19431
19483
  ];
19432
19484
  }
19433
19485
  function isOrdinary2(node) {
19434
- return node?.type === AST_NODE_TYPES107.FunctionDeclaration && node.id !== null && !node.declare && !node.async && !node.generator && node.params.length === 0 && node.typeParameters === void 0;
19486
+ return node.id !== null && !node.declare && !node.async && !node.generator && node.params.length === 0 && node.typeParameters === void 0;
19435
19487
  }
19436
19488
  function tupleFields(helper) {
19437
19489
  const tuple = helper.returnType?.typeAnnotation;
@@ -20762,7 +20814,7 @@ var PREVIEW_LENGTH = 40;
20762
20814
  var SQL_KEYWORD_RE = /\b(SELECT|INSERT|UPDATE|DELETE|FROM|WHERE|JOIN|VALUES|ON CONFLICT|RETURNING|GROUP BY|ORDER BY)\b/;
20763
20815
  var IDENTIFIER_RE = /^[a-z_][a-z0-9_.]*$/;
20764
20816
  var URL_PATH_RE = /^\/(?=[^\s]*[A-Za-z0-9])[A-Za-z0-9._~!$&'()*+,;=:@%/?#{}\u005B\u005D-]+$/;
20765
- var FUNCTION_TYPES4 = /* @__PURE__ */ new Set([
20817
+ var FUNCTION_TYPES3 = /* @__PURE__ */ new Set([
20766
20818
  AST_NODE_TYPES114.FunctionDeclaration,
20767
20819
  AST_NODE_TYPES114.FunctionExpression,
20768
20820
  AST_NODE_TYPES114.ArrowFunctionExpression
@@ -20836,7 +20888,7 @@ function preview(value) {
20836
20888
  }
20837
20889
  function enclosingFunction4(node) {
20838
20890
  for (let current = node.parent; current != null; current = current.parent) {
20839
- if (FUNCTION_TYPES4.has(current.type)) {
20891
+ if (FUNCTION_TYPES3.has(current.type)) {
20840
20892
  return current;
20841
20893
  }
20842
20894
  }
@@ -22301,9 +22353,6 @@ function isSentinelArgument(arg) {
22301
22353
  function isFunctionNode(node) {
22302
22354
  return node.type === AST_NODE_TYPES119.FunctionDeclaration || node.type === AST_NODE_TYPES119.FunctionExpression || node.type === AST_NODE_TYPES119.ArrowFunctionExpression;
22303
22355
  }
22304
- function isNode3(value) {
22305
- return typeof value === "object" && value !== null && typeof value.type === "string";
22306
- }
22307
22356
  function walkWithinScope(node, visit) {
22308
22357
  let found = false;
22309
22358
  const recurse = (current) => {
@@ -22430,7 +22479,7 @@ function enclosingFunctionName(node) {
22430
22479
  let current = node.parent;
22431
22480
  while (current !== void 0 && current !== null) {
22432
22481
  if (isFunctionNode(current)) {
22433
- if ("id" in current && isNode3(current.id) && current.id.type === AST_NODE_TYPES119.Identifier) {
22482
+ if ("id" in current && current.id !== null && current.id.type === AST_NODE_TYPES119.Identifier) {
22434
22483
  return current.id.name;
22435
22484
  }
22436
22485
  const parent = current.parent;
@@ -22531,7 +22580,7 @@ function functionReturnsSameSentinelKindElsewhere(catchNode, kind) {
22531
22580
  function enclosingFunctionBody(node) {
22532
22581
  let current = node.parent;
22533
22582
  while (current !== void 0 && current !== null) {
22534
- if (isFunctionNode(current) && "body" in current && isNode3(current.body) && current.body.type === AST_NODE_TYPES119.BlockStatement) {
22583
+ if (isFunctionNode(current) && current.body?.type === AST_NODE_TYPES119.BlockStatement) {
22535
22584
  return current.body;
22536
22585
  }
22537
22586
  current = current.parent;
@@ -22938,7 +22987,7 @@ var TEST_CALLERS2 = /* @__PURE__ */ new Set([
22938
22987
  "beforeEach",
22939
22988
  "afterEach"
22940
22989
  ]);
22941
- var FUNCTION_TYPES5 = /* @__PURE__ */ new Set([
22990
+ var FUNCTION_TYPES4 = /* @__PURE__ */ new Set([
22942
22991
  AST_NODE_TYPES121.FunctionDeclaration,
22943
22992
  AST_NODE_TYPES121.FunctionExpression,
22944
22993
  AST_NODE_TYPES121.ArrowFunctionExpression
@@ -22973,7 +23022,7 @@ function isHelperSleep(node) {
22973
23022
  }
22974
23023
  function nearestEnclosingFunction(node) {
22975
23024
  for (let current = node.parent; current != null; current = current.parent) {
22976
- if (!FUNCTION_TYPES5.has(current.type)) {
23025
+ if (!FUNCTION_TYPES4.has(current.type)) {
22977
23026
  continue;
22978
23027
  }
22979
23028
  const grandparent = current.parent;
@@ -25980,7 +26029,7 @@ var ASSERTION_ROOTS = /* @__PURE__ */ new Set([
25980
26029
  "expect",
25981
26030
  "expectTypeOf"
25982
26031
  ]);
25983
- var FUNCTION_TYPES6 = /* @__PURE__ */ new Set([
26032
+ var FUNCTION_TYPES5 = /* @__PURE__ */ new Set([
25984
26033
  AST_NODE_TYPES135.FunctionDeclaration,
25985
26034
  AST_NODE_TYPES135.FunctionExpression,
25986
26035
  AST_NODE_TYPES135.ArrowFunctionExpression
@@ -26015,7 +26064,7 @@ function isTestCaller(callee, isFrameworkTest) {
26015
26064
  }
26016
26065
  function nearestEnclosingFunction2(node) {
26017
26066
  for (let current = node.parent; current != null; current = current.parent) {
26018
- if (FUNCTION_TYPES6.has(current.type)) {
26067
+ if (FUNCTION_TYPES5.has(current.type)) {
26019
26068
  return current;
26020
26069
  }
26021
26070
  }
@@ -26048,7 +26097,7 @@ function walkOwnScope2(node, predicate) {
26048
26097
  if (predicate(node)) {
26049
26098
  return true;
26050
26099
  }
26051
- return forEachOwnAstChild(node, (child) => !FUNCTION_TYPES6.has(child.type) && walkOwnScope2(child, predicate));
26100
+ return forEachOwnAstChild(node, (child) => !FUNCTION_TYPES5.has(child.type) && walkOwnScope2(child, predicate));
26052
26101
  }
26053
26102
  function isAssertion2(node, isFrameworkAssertion) {
26054
26103
  if (node.type !== AST_NODE_TYPES135.CallExpression) return false;
@@ -26061,7 +26110,7 @@ function opensSubtest(node, callbackParameters) {
26061
26110
  }
26062
26111
  const callee = unwrapExpression(node.callee);
26063
26112
  return callee.type === AST_NODE_TYPES135.MemberExpression && staticMemberName6(callee) === "test" && callee.object.type === AST_NODE_TYPES135.Identifier && callbackParameters.has(callee.object.name) && node.arguments.some(
26064
- (argument) => argument.type !== AST_NODE_TYPES135.SpreadElement && FUNCTION_TYPES6.has(argument.type)
26113
+ (argument) => argument.type !== AST_NODE_TYPES135.SpreadElement && FUNCTION_TYPES5.has(argument.type)
26065
26114
  );
26066
26115
  }
26067
26116
  var LOOP_CARRIED_CONTROL = /* @__PURE__ */ new Set([
@@ -26427,7 +26476,7 @@ var PREFER_ECMASCRIPT_PRIVATE_MEMBERS_DOCUMENTATION = {
26427
26476
  function reportClass2(context, owner, services) {
26428
26477
  const groups = /* @__PURE__ */ new Map();
26429
26478
  for (const member3 of owner.body.body) {
26430
- if (!isConvertible(member3)) continue;
26479
+ if (member3.type !== AST_NODE_TYPES138.MethodDefinition && member3.type !== AST_NODE_TYPES138.PropertyDefinition && member3.type !== AST_NODE_TYPES138.AccessorProperty || !isConvertible(member3)) continue;
26431
26480
  const name = convertibleMemberName(member3);
26432
26481
  if (name === null) continue;
26433
26482
  const members = groups.get(name) ?? [];
@@ -26446,7 +26495,6 @@ function reportClass2(context, owner, services) {
26446
26495
  }
26447
26496
  }
26448
26497
  function isConvertible(member3) {
26449
- if (member3.type !== AST_NODE_TYPES138.MethodDefinition && member3.type !== AST_NODE_TYPES138.PropertyDefinition && member3.type !== AST_NODE_TYPES138.AccessorProperty) return false;
26450
26498
  return member3.accessibility === "private" && !(member3.type === AST_NODE_TYPES138.MethodDefinition && member3.kind === "constructor") && !member3.computed && member3.key.type === AST_NODE_TYPES138.Identifier && member3.decorators.length === 0 && !("declare" in member3 && member3.declare) && !member3.override && !(member3.type === AST_NODE_TYPES138.MethodDefinition && member3.value.body === null);
26451
26499
  }
26452
26500
  var prefer_ecmascript_private_members_default = createRule({
@@ -28141,7 +28189,7 @@ var MUTATING_METHODS2 = /* @__PURE__ */ new Set([
28141
28189
  // Object-ish escape hatches
28142
28190
  "assign"
28143
28191
  ]);
28144
- var FUNCTION_TYPES7 = /* @__PURE__ */ new Set([
28192
+ var FUNCTION_TYPES6 = /* @__PURE__ */ new Set([
28145
28193
  AST_NODE_TYPES146.FunctionDeclaration,
28146
28194
  AST_NODE_TYPES146.FunctionExpression,
28147
28195
  AST_NODE_TYPES146.ArrowFunctionExpression
@@ -28163,8 +28211,8 @@ function unwrap3(node) {
28163
28211
  return node;
28164
28212
  }
28165
28213
  var HAS_STATEFUL_FLAG_RE = /[gy]/;
28166
- function isRegexLiteral(node) {
28167
- return node.type === AST_NODE_TYPES146.Literal && "regex" in node && node.regex !== void 0;
28214
+ function literalRegex(node) {
28215
+ return node.type === AST_NODE_TYPES146.Literal && "regex" in node ? node.regex : void 0;
28168
28216
  }
28169
28217
  function isLiteralOnly(node, depth) {
28170
28218
  if (depth > MAX_LITERAL_DEPTH) {
@@ -28173,7 +28221,7 @@ function isLiteralOnly(node, depth) {
28173
28221
  const inner = unwrap3(node);
28174
28222
  switch (inner.type) {
28175
28223
  case AST_NODE_TYPES146.Literal: {
28176
- return !(isRegexLiteral(inner) && HAS_STATEFUL_FLAG_RE.test(inner.regex.flags));
28224
+ return !HAS_STATEFUL_FLAG_RE.test(literalRegex(inner)?.flags ?? "");
28177
28225
  }
28178
28226
  case AST_NODE_TYPES146.TemplateLiteral: {
28179
28227
  return inner.expressions.length === 0;
@@ -28207,11 +28255,12 @@ function isLiteralOnly(node, depth) {
28207
28255
  }
28208
28256
  function classify(init, checkRegex, sourceCode) {
28209
28257
  const node = unwrapObjectFreeze(init, sourceCode);
28210
- if (isRegexLiteral(node)) {
28258
+ const regex = literalRegex(node);
28259
+ if (regex !== void 0) {
28211
28260
  if (!checkRegex) {
28212
28261
  return null;
28213
28262
  }
28214
- if (HAS_STATEFUL_FLAG_RE.test(node.regex.flags)) {
28263
+ if (HAS_STATEFUL_FLAG_RE.test(regex.flags)) {
28215
28264
  return null;
28216
28265
  }
28217
28266
  return { kind: "regex", size: 1 };
@@ -28238,7 +28287,7 @@ function unwrapObjectFreeze(node, sourceCode) {
28238
28287
  function enclosingFunction5(node) {
28239
28288
  let current = node.parent;
28240
28289
  while (current !== void 0 && current !== null) {
28241
- if (FUNCTION_TYPES7.has(current.type)) {
28290
+ if (FUNCTION_TYPES6.has(current.type)) {
28242
28291
  return current;
28243
28292
  }
28244
28293
  current = current.parent;
@@ -28542,7 +28591,7 @@ var I18N_RECEIVER_NAMES = /* @__PURE__ */ new Set([
28542
28591
  "i18n",
28543
28592
  "intl"
28544
28593
  ]);
28545
- var FUNCTION_TYPES8 = /* @__PURE__ */ new Set([
28594
+ var FUNCTION_TYPES7 = /* @__PURE__ */ new Set([
28546
28595
  AST_NODE_TYPES147.ArrowFunctionExpression,
28547
28596
  AST_NODE_TYPES147.FunctionDeclaration,
28548
28597
  AST_NODE_TYPES147.FunctionExpression
@@ -28568,7 +28617,7 @@ function outermostEnclosingFunction(node) {
28568
28617
  let outermost;
28569
28618
  let current = node.parent ?? void 0;
28570
28619
  while (current !== void 0) {
28571
- if (FUNCTION_TYPES8.has(current.type)) {
28620
+ if (FUNCTION_TYPES7.has(current.type)) {
28572
28621
  outermost = current;
28573
28622
  }
28574
28623
  current = current.parent ?? void 0;
@@ -28591,7 +28640,7 @@ function subtreeSome(root, predicate, skipDeferredFunctions = false) {
28591
28640
  if (typeof candidate2.type !== "string") {
28592
28641
  return;
28593
28642
  }
28594
- if (skipDeferredFunctions && FUNCTION_TYPES8.has(candidate2.type)) return;
28643
+ if (skipDeferredFunctions && FUNCTION_TYPES7.has(candidate2.type)) return;
28595
28644
  if (predicate(candidate2)) {
28596
28645
  found = true;
28597
28646
  return;
@@ -28706,7 +28755,7 @@ var prefer_module_level_schema_default = createRule({
28706
28755
  function isCovered(node) {
28707
28756
  let current = node.parent ?? void 0;
28708
28757
  while (current !== void 0) {
28709
- if (current !== node && isZodCall(current) && current.callee.type === AST_NODE_TYPES147.MemberExpression && ASTUtils94.getPropertyName(current.callee) !== null && factories.has(ASTUtils94.getPropertyName(current.callee) ?? "")) {
28758
+ if (current !== node && current.type === AST_NODE_TYPES147.CallExpression && isZodCall(current) && current.callee.type === AST_NODE_TYPES147.MemberExpression && ASTUtils94.getPropertyName(current.callee) !== null && factories.has(ASTUtils94.getPropertyName(current.callee) ?? "")) {
28710
28759
  return true;
28711
28760
  }
28712
28761
  if (current.type === AST_NODE_TYPES147.CallExpression && (current.callee.type === AST_NODE_TYPES147.Identifier && memoCallees.has(current.callee.name) || current.callee.type === AST_NODE_TYPES147.MemberExpression && ASTUtils94.getPropertyName(current.callee) !== null && memoCallees.has(ASTUtils94.getPropertyName(current.callee) ?? ""))) {
@@ -28965,7 +29014,7 @@ var I18N_RECEIVER_NAMES2 = /* @__PURE__ */ new Set([
28965
29014
  "i18n",
28966
29015
  "intl"
28967
29016
  ]);
28968
- var FUNCTION_TYPES9 = /* @__PURE__ */ new Set([
29017
+ var FUNCTION_TYPES8 = /* @__PURE__ */ new Set([
28969
29018
  AST_NODE_TYPES148.ArrowFunctionExpression,
28970
29019
  AST_NODE_TYPES148.FunctionDeclaration,
28971
29020
  AST_NODE_TYPES148.FunctionExpression
@@ -29013,7 +29062,7 @@ function outermostEnclosingFunction2(node) {
29013
29062
  let outermost;
29014
29063
  let current = node.parent ?? void 0;
29015
29064
  while (current !== void 0) {
29016
- if (FUNCTION_TYPES9.has(current.type)) outermost = current;
29065
+ if (FUNCTION_TYPES8.has(current.type)) outermost = current;
29017
29066
  current = current.parent ?? void 0;
29018
29067
  }
29019
29068
  return outermost;
@@ -29032,7 +29081,7 @@ function subtreeSome2(root, predicate, skipDeferredFunctions = false) {
29032
29081
  }
29033
29082
  const candidate2 = value;
29034
29083
  if (typeof candidate2.type !== "string") return;
29035
- if (skipDeferredFunctions && FUNCTION_TYPES9.has(candidate2.type)) return;
29084
+ if (skipDeferredFunctions && FUNCTION_TYPES8.has(candidate2.type)) return;
29036
29085
  if (predicate(candidate2)) {
29037
29086
  found = true;
29038
29087
  return;
@@ -29178,7 +29227,7 @@ var prefer_module_level_refined_schema_default = createRule({
29178
29227
  let current = node;
29179
29228
  while (current.parent != null) {
29180
29229
  current = current.parent;
29181
- if (FUNCTION_TYPES9.has(current.type)) return false;
29230
+ if (FUNCTION_TYPES8.has(current.type)) return false;
29182
29231
  if (current.type === AST_NODE_TYPES148.CallExpression && (factoryName(current, FACTORIES) !== null || factoryName(current, COMPOSITE_FACTORIES) !== null))
29183
29232
  return true;
29184
29233
  }
@@ -31054,7 +31103,7 @@ var prefer_non_nullable_collection_default = createRule({
31054
31103
  const bindingProperty = parameter.properties.find(
31055
31104
  (entry) => entry.type === AST_NODE_TYPES158.Property && !entry.computed && ASTUtils102.getPropertyName(entry) === property.name
31056
31105
  );
31057
- if (bindingProperty === void 0) continue;
31106
+ if (bindingProperty?.type !== AST_NODE_TYPES158.Property) continue;
31058
31107
  const value = bindingProperty.value;
31059
31108
  const binding3 = value.type === AST_NODE_TYPES158.AssignmentPattern ? value.left : value;
31060
31109
  if (binding3.type !== AST_NODE_TYPES158.Identifier) {
@@ -35867,7 +35916,7 @@ function injectedMembers(owner) {
35867
35916
  const constructor = owner.body.body.find(
35868
35917
  (member3) => member3.type === AST_NODE_TYPES174.MethodDefinition && member3.kind === "constructor"
35869
35918
  );
35870
- if (constructor === void 0) return injected;
35919
+ if (constructor?.type !== AST_NODE_TYPES174.MethodDefinition) return injected;
35871
35920
  const parameters = /* @__PURE__ */ new Set();
35872
35921
  for (const parameter of constructor.value.params) {
35873
35922
  for (const name of parameterNames(parameter)) parameters.add(name);
@@ -38610,6 +38659,7 @@ var RETIRED_RULES = {
38610
38659
 
38611
38660
  // src/index.ts
38612
38661
  var RULES = {
38662
+ "no-explicit-type-predicate": no_explicit_type_predicate_default,
38613
38663
  "prefer-zod-enum-validator": prefer_zod_enum_validator_default,
38614
38664
  "no-growing-array-spread-in-loop": no_growing_array_spread_in_loop_default,
38615
38665
  "no-logical-or-fallback": no_logical_or_fallback_default,
@@ -38792,6 +38842,7 @@ var RULE_POLICY = {
38792
38842
  "@sarj/no-invalid-typed-mutation": ["error", "both"],
38793
38843
  "@sarj/no-contradictory-type-predicate": ["error", "both"],
38794
38844
  "@sarj/no-partial-type-predicate": ["error", "both"],
38845
+ "@sarj/no-explicit-type-predicate": ["warn", "both"],
38795
38846
  "@sarj/no-boolean-selector-parameter": ["warn", "both"],
38796
38847
  "@sarj/no-invalid-zod-custom-parse": ["error", "both"],
38797
38848
  "@sarj/no-contradictory-overload-return": ["error", "both"],