@sarj/eslint-plugin 15.28.1 → 16.1.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
@@ -442,8 +442,8 @@ var prefer_typed_reflection_default = createRule({
442
442
  const services = ESLintUtils2.getParserServices(context);
443
443
  if (!services.program) return {};
444
444
  const checker = services.program.getTypeChecker();
445
- const globalName = (node, name) => node.type === AST_NODE_TYPES2.Identifier && node.name === name && !ASTUtils.findVariable(context.sourceCode.getScope(node), name)?.defs.length;
446
445
  const isReflect = (node) => globalName(node, "Reflect") || node.type === AST_NODE_TYPES2.MemberExpression && propertyName(node) === "Reflect" && globalName(node.object, "globalThis");
446
+ const globalName = (node, name) => node.type === AST_NODE_TYPES2.Identifier && node.name === name && !ASTUtils.findVariable(context.sourceCode.getScope(node), name)?.defs.length;
447
447
  const closedObject = (type) => {
448
448
  if (type.isUnion()) return type.types.every(closedObject);
449
449
  return knownType(type) && type.getProperties().length > 0 && checker.getIndexInfosOfType(type).length === 0;
@@ -683,6 +683,14 @@ var no_reduce_accumulator_copy_default = createRule({
683
683
  const accumulator = context.sourceCode.getDeclaredVariables(callback).find((variable) => variable.identifiers.includes(parameter));
684
684
  if (!accumulator || accumulator.references.some((reference) => reference.isWrite())) return;
685
685
  const referencesAccumulator = (value) => value.type === AST_NODE_TYPES4.Identifier && ASTUtils2.findVariable(context.sourceCode.getScope(value), value.name) === accumulator;
686
+ const inspect = (current) => {
687
+ if (current !== callback.body && [AST_NODE_TYPES4.ArrowFunctionExpression, AST_NODE_TYPES4.FunctionExpression, AST_NODE_TYPES4.FunctionDeclaration].some((kind) => kind === current.type)) return;
688
+ if (current.type === AST_NODE_TYPES4.SpreadElement && (arraySeed && current.parent.type === AST_NODE_TYPES4.ArrayExpression || objectSeed && current.parent.type === AST_NODE_TYPES4.ObjectExpression) && referencesAccumulator(current.argument)) {
689
+ context.report({ node: current, messageId: "copy" });
690
+ }
691
+ if (current.type === AST_NODE_TYPES4.CallExpression) inspectCall(current);
692
+ forEachAstChild(current, context.sourceCode.visitorKeys, inspect);
693
+ };
686
694
  const inspectCall = (current) => {
687
695
  if (current.callee.type !== AST_NODE_TYPES4.MemberExpression) return;
688
696
  const member = current.callee;
@@ -695,14 +703,6 @@ var no_reduce_accumulator_copy_default = createRule({
695
703
  const assignCopy = objectSeed && name === "assign" && globalObject && target?.type === AST_NODE_TYPES4.ObjectExpression && current.arguments.slice(1).some(referencesAccumulator);
696
704
  if (directCopy || fromCopy || assignCopy) context.report({ node: current, messageId: "copy" });
697
705
  };
698
- const inspect = (current) => {
699
- if (current !== callback.body && [AST_NODE_TYPES4.ArrowFunctionExpression, AST_NODE_TYPES4.FunctionExpression, AST_NODE_TYPES4.FunctionDeclaration].some((kind) => kind === current.type)) return;
700
- if (current.type === AST_NODE_TYPES4.SpreadElement && (arraySeed && current.parent.type === AST_NODE_TYPES4.ArrayExpression || objectSeed && current.parent.type === AST_NODE_TYPES4.ObjectExpression) && referencesAccumulator(current.argument)) {
701
- context.report({ node: current, messageId: "copy" });
702
- }
703
- if (current.type === AST_NODE_TYPES4.CallExpression) inspectCall(current);
704
- forEachAstChild(current, context.sourceCode.visitorKeys, inspect);
705
- };
706
706
  inspect(callback.body);
707
707
  }
708
708
  };
@@ -3614,28 +3614,6 @@ var no_cors_wildcard_with_credentials_default = createRule({
3614
3614
  const scopeHeaderSets = /* @__PURE__ */ new Map();
3615
3615
  const variableIds = /* @__PURE__ */ new WeakMap();
3616
3616
  let nextVariableId = 0;
3617
- function variableId(variable) {
3618
- const existing = variableIds.get(variable);
3619
- if (existing !== void 0) return existing;
3620
- const value = nextVariableId++;
3621
- variableIds.set(variable, value);
3622
- return value;
3623
- }
3624
- function receiverIdentity(node) {
3625
- if (node.type === AST_NODE_TYPES22.Identifier) {
3626
- const variable = ASTUtils5.findVariable(
3627
- context.sourceCode.getScope(node),
3628
- node.name
3629
- );
3630
- return variable === null ? `global:${node.name}` : `variable:${variableId(variable)}`;
3631
- }
3632
- if (node.type === AST_NODE_TYPES22.ThisExpression) return "this";
3633
- if (node.type === AST_NODE_TYPES22.MemberExpression && !node.computed && node.property.type === AST_NODE_TYPES22.Identifier) {
3634
- const owner = receiverIdentity(node.object);
3635
- return owner === null ? null : `${owner}.${node.property.name}`;
3636
- }
3637
- return null;
3638
- }
3639
3617
  function recordHeaderSet(node, kind) {
3640
3618
  if (node.callee.type !== AST_NODE_TYPES22.MemberExpression) return;
3641
3619
  const receiver = receiverIdentity(node.callee.object);
@@ -3657,6 +3635,28 @@ var no_cors_wildcard_with_credentials_default = createRule({
3657
3635
  entry.credentialsNodes.push(node);
3658
3636
  }
3659
3637
  }
3638
+ function receiverIdentity(node) {
3639
+ if (node.type === AST_NODE_TYPES22.Identifier) {
3640
+ const variable = ASTUtils5.findVariable(
3641
+ context.sourceCode.getScope(node),
3642
+ node.name
3643
+ );
3644
+ return variable === null ? `global:${node.name}` : `variable:${variableId(variable)}`;
3645
+ }
3646
+ if (node.type === AST_NODE_TYPES22.ThisExpression) return "this";
3647
+ if (node.type === AST_NODE_TYPES22.MemberExpression && !node.computed && node.property.type === AST_NODE_TYPES22.Identifier) {
3648
+ const owner = receiverIdentity(node.object);
3649
+ return owner === null ? null : `${owner}.${node.property.name}`;
3650
+ }
3651
+ return null;
3652
+ }
3653
+ function variableId(variable) {
3654
+ const existing = variableIds.get(variable);
3655
+ if (existing !== void 0) return existing;
3656
+ const value = nextVariableId++;
3657
+ variableIds.set(variable, value);
3658
+ return value;
3659
+ }
3660
3660
  return {
3661
3661
  NewExpression(node) {
3662
3662
  if (isCorsWildcardCredentialsCall(node)) {
@@ -4446,20 +4446,6 @@ function functionComplexity(fn, visitorKeys) {
4446
4446
  function add(node, nesting, construct) {
4447
4447
  points.push({ line: node.loc.start.line, amount: nesting + 1, construct });
4448
4448
  }
4449
- function logical(node, nesting) {
4450
- let previous;
4451
- function flatten(expression) {
4452
- if (expression.type !== AST_NODE_TYPES26.LogicalExpression || expression.operator === "??") {
4453
- visit(expression, nesting);
4454
- return;
4455
- }
4456
- flatten(expression.left);
4457
- if (previous !== expression.operator) add(expression, 0, expression.operator);
4458
- previous = expression.operator;
4459
- flatten(expression.right);
4460
- }
4461
- flatten(node);
4462
- }
4463
4449
  function conditional(node, nesting) {
4464
4450
  add(node, nesting, "if");
4465
4451
  let branch = node;
@@ -4538,6 +4524,20 @@ function functionComplexity(fn, visitorKeys) {
4538
4524
  }
4539
4525
  visitChildren(node, nesting);
4540
4526
  }
4527
+ function logical(node, nesting) {
4528
+ let previous;
4529
+ function flatten(expression) {
4530
+ if (expression.type !== AST_NODE_TYPES26.LogicalExpression || expression.operator === "??") {
4531
+ visit(expression, nesting);
4532
+ return;
4533
+ }
4534
+ flatten(expression.left);
4535
+ if (previous !== expression.operator) add(expression, 0, expression.operator);
4536
+ previous = expression.operator;
4537
+ flatten(expression.right);
4538
+ }
4539
+ flatten(node);
4540
+ }
4541
4541
  function visitChildren(node, nesting) {
4542
4542
  forEachAstChild(node, visitorKeys, (child) => visit(child, nesting));
4543
4543
  }
@@ -5160,6 +5160,14 @@ var no_hand_rolled_sleep_default = createRule({
5160
5160
  const callee = callback.type === AST_NODE_TYPES28.Identifier ? callback : callback.type === AST_NODE_TYPES28.ArrowFunctionExpression || callback.type === AST_NODE_TYPES28.FunctionExpression ? soleCall(callback)?.callee : null;
5161
5161
  return callee?.type === AST_NODE_TYPES28.Identifier && bindingOf(callee) === bindingOf(parameter);
5162
5162
  };
5163
+ let clientModule = null;
5164
+ const reportsSleepHere = () => {
5165
+ if (checkClientModules) {
5166
+ return true;
5167
+ }
5168
+ clientModule ??= isClientModule2();
5169
+ return !clientModule;
5170
+ };
5163
5171
  function isClientModule2() {
5164
5172
  if (/\.[cm]?[jt]sx$/.test(filename)) {
5165
5173
  return true;
@@ -5175,14 +5183,6 @@ var no_hand_rolled_sleep_default = createRule({
5175
5183
  }
5176
5184
  return false;
5177
5185
  }
5178
- let clientModule = null;
5179
- const reportsSleepHere = () => {
5180
- if (checkClientModules) {
5181
- return true;
5182
- }
5183
- clientModule ??= isClientModule2();
5184
- return !clientModule;
5185
- };
5186
5186
  return {
5187
5187
  NewExpression(node) {
5188
5188
  if (node.callee.type !== AST_NODE_TYPES28.Identifier || node.callee.name !== "Promise" || !isGlobal(node.callee)) {
@@ -5615,13 +5615,6 @@ var no_detached_global_fetch_default = createRule({
5615
5615
  const variable = bindingOf(identifier);
5616
5616
  if (variable !== null && isStableAlias(variable)) aliases.add(variable);
5617
5617
  }
5618
- function isGlobalFetchMember(node) {
5619
- if (!isGlobalReceiver(node.object)) return false;
5620
- if (!node.computed) {
5621
- return node.property.type === AST_NODE_TYPES30.Identifier && node.property.name === "fetch";
5622
- }
5623
- return node.property.type === AST_NODE_TYPES30.Literal && node.property.value === "fetch";
5624
- }
5625
5618
  function staticMemberName9(node) {
5626
5619
  if (!node.computed) {
5627
5620
  return node.property.type === AST_NODE_TYPES30.Identifier ? node.property.name : null;
@@ -5650,6 +5643,13 @@ var no_detached_global_fetch_default = createRule({
5650
5643
  }
5651
5644
  return false;
5652
5645
  }
5646
+ function isGlobalFetchMember(node) {
5647
+ if (!isGlobalReceiver(node.object)) return false;
5648
+ if (!node.computed) {
5649
+ return node.property.type === AST_NODE_TYPES30.Identifier && node.property.name === "fetch";
5650
+ }
5651
+ return node.property.type === AST_NODE_TYPES30.Literal && node.property.value === "fetch";
5652
+ }
5653
5653
  function recordAliasFromValue(identifier, value) {
5654
5654
  if (mayBeRawFetch(value)) recordAlias(identifier);
5655
5655
  }
@@ -6214,17 +6214,6 @@ var no_impossible_zod_literal_bounds_default = createRule({
6214
6214
  }
6215
6215
  return false;
6216
6216
  }
6217
- function baseKind(node) {
6218
- const callee = node.callee;
6219
- if (callee.type === AST_NODE_TYPES32.Identifier) {
6220
- return resolvesToTrackedImport(callee) ? constructors.get(callee.name) ?? null : null;
6221
- }
6222
- if (callee.type !== AST_NODE_TYPES32.MemberExpression || callee.object.type !== AST_NODE_TYPES32.Identifier || !namespaces.has(callee.object.name) || !resolvesToTrackedImport(callee.object)) {
6223
- return null;
6224
- }
6225
- const name = memberName(callee);
6226
- return name !== null && KINDS.has(name) ? name : null;
6227
- }
6228
6217
  function readChain(node) {
6229
6218
  const calls = [];
6230
6219
  let current = node;
@@ -6241,6 +6230,17 @@ var no_impossible_zod_literal_bounds_default = createRule({
6241
6230
  current = callee.object;
6242
6231
  }
6243
6232
  }
6233
+ function baseKind(node) {
6234
+ const callee = node.callee;
6235
+ if (callee.type === AST_NODE_TYPES32.Identifier) {
6236
+ return resolvesToTrackedImport(callee) ? constructors.get(callee.name) ?? null : null;
6237
+ }
6238
+ if (callee.type !== AST_NODE_TYPES32.MemberExpression || callee.object.type !== AST_NODE_TYPES32.Identifier || !namespaces.has(callee.object.name) || !resolvesToTrackedImport(callee.object)) {
6239
+ return null;
6240
+ }
6241
+ const name = memberName(callee);
6242
+ return name !== null && KINDS.has(name) ? name : null;
6243
+ }
6244
6244
  function isInsideReshapingCall(node) {
6245
6245
  let child = node;
6246
6246
  let parent = child.parent;
@@ -6558,30 +6558,30 @@ var no_redundant_optional_array_default_default = createRule({
6558
6558
  }
6559
6559
  return false;
6560
6560
  }
6561
- function isZodSchemaExpression(node) {
6561
+ function isArraySchemaExpression(node) {
6562
6562
  if (node.type !== AST_NODE_TYPES33.CallExpression) return false;
6563
6563
  const { callee } = node;
6564
6564
  if (callee.type === AST_NODE_TYPES33.Identifier) {
6565
- return resolvesToTrackedImport(callee);
6565
+ return arrayConstructors.has(callee.name) && resolvesToTrackedImport(callee);
6566
6566
  }
6567
6567
  if (callee.type !== AST_NODE_TYPES33.MemberExpression) return false;
6568
- if (callee.object.type === AST_NODE_TYPES33.Identifier && namespaces.has(callee.object.name) && resolvesToTrackedImport(callee.object)) {
6568
+ const method = memberName2(callee);
6569
+ if (method === "array" && (callee.object.type === AST_NODE_TYPES33.Identifier ? namespaces.has(callee.object.name) && resolvesToTrackedImport(callee.object) : isZodSchemaExpression(callee.object))) {
6569
6570
  return true;
6570
6571
  }
6571
- return isZodSchemaExpression(callee.object);
6572
+ return isArraySchemaExpression(callee.object);
6572
6573
  }
6573
- function isArraySchemaExpression(node) {
6574
+ function isZodSchemaExpression(node) {
6574
6575
  if (node.type !== AST_NODE_TYPES33.CallExpression) return false;
6575
6576
  const { callee } = node;
6576
6577
  if (callee.type === AST_NODE_TYPES33.Identifier) {
6577
- return arrayConstructors.has(callee.name) && resolvesToTrackedImport(callee);
6578
+ return resolvesToTrackedImport(callee);
6578
6579
  }
6579
6580
  if (callee.type !== AST_NODE_TYPES33.MemberExpression) return false;
6580
- const method = memberName2(callee);
6581
- if (method === "array" && (callee.object.type === AST_NODE_TYPES33.Identifier ? namespaces.has(callee.object.name) && resolvesToTrackedImport(callee.object) : isZodSchemaExpression(callee.object))) {
6581
+ if (callee.object.type === AST_NODE_TYPES33.Identifier && namespaces.has(callee.object.name) && resolvesToTrackedImport(callee.object)) {
6582
6582
  return true;
6583
6583
  }
6584
- return isArraySchemaExpression(callee.object);
6584
+ return isZodSchemaExpression(callee.object);
6585
6585
  }
6586
6586
  return {
6587
6587
  ImportDeclaration(node) {
@@ -7018,10 +7018,6 @@ var no_log_only_catch_default = createRule({
7018
7018
  }
7019
7019
  return matcher.isLoggingCall(statement.expression);
7020
7020
  }
7021
- function hasCommentDirectlyAbove(node) {
7022
- const above = sourceCode.getCommentsBefore(node).at(-1);
7023
- return above !== void 0 && above.loc.end.line === node.loc.start.line - 1;
7024
- }
7025
7021
  function hasAdjacentRationale(node) {
7026
7022
  const tryStatement = node.parent;
7027
7023
  if (hasCommentDirectlyAbove(tryStatement) || hasCommentDirectlyAbove(node)) return true;
@@ -7031,6 +7027,10 @@ var no_log_only_catch_default = createRule({
7031
7027
  }
7032
7028
  return hasCommentDirectlyAbove(block.parent);
7033
7029
  }
7030
+ function hasCommentDirectlyAbove(node) {
7031
+ const above = sourceCode.getCommentsBefore(node).at(-1);
7032
+ return above !== void 0 && above.loc.end.line === node.loc.start.line - 1;
7033
+ }
7034
7034
  if (isTestFile(filename) || BENCHMARK_DIR_RE.test(filename.replaceAll("\\", "/"))) {
7035
7035
  return {};
7036
7036
  }
@@ -7503,20 +7503,9 @@ var no_vague_suppression_description_default = createRule({
7503
7503
  }
7504
7504
  });
7505
7505
 
7506
- // src/rules/no-generic-single-export-module.ts
7506
+ // src/rules/_runtime-exports.ts
7507
7507
  import { AST_NODE_TYPES as AST_NODE_TYPES40, ASTUtils as ASTUtils16 } from "@typescript-eslint/utils";
7508
- var NO_GENERIC_SINGLE_EXPORT_MODULE_DOCUMENTATION = {
7509
- summary: "Disallow generic module stems when one runtime export already names the responsibility.",
7510
- rationale: "A generic filename hides the sole exported responsibility and makes navigation less descriptive.",
7511
- remediation: "Choose a responsibility-bearing module name or colocate the export with its domain.",
7512
- category: "maintainability",
7513
- limitations: ["Only the fixed generic-stem vocabulary with exactly one public runtime export is checked; exported destructuring patterns are excluded rather than undercounted."],
7514
- examples: [
7515
- { id: "responsibility-named-module", title: "Name the module after its export", outcome: "no-match", files: [{ path: "src/parse-order.ts", source: "export function parseOrder() { return {}; }" }], focusPath: "src/parse-order.ts", expectedCount: 0, public: true },
7516
- { id: "generic-module-name", title: "Do not hide one export in a generic module", outcome: "match", files: [{ path: "src/utils.ts", source: "export function parseOrder() { return {}; }" }], focusPath: "src/utils.ts", expectedCount: 1, public: true }
7517
- ]
7518
- };
7519
- var GENERIC_STEMS = /* @__PURE__ */ new Set([
7508
+ var GENERIC_MODULE_STEMS = /* @__PURE__ */ new Set([
7520
7509
  "common",
7521
7510
  "helper",
7522
7511
  "helpers",
@@ -7527,164 +7516,172 @@ var GENERIC_STEMS = /* @__PURE__ */ new Set([
7527
7516
  "utils"
7528
7517
  ]);
7529
7518
  var CJS_OBJECT_EXPORT_METHODS = /* @__PURE__ */ new Set(["assign", "defineProperties", "defineProperty"]);
7530
- function fileParts(filename) {
7531
- const base = filename.replaceAll("\\", "/").split("/").at(-1) ?? "";
7532
- const extension = base.match(/(\.[cm]?[jt]sx?)$/u)?.[1] ?? ".ts";
7533
- const [stem4 = "", ...suffixes] = base.slice(0, -extension.length).split(".");
7534
- return { stem: stem4, suffixes: suffixes.map((suffix) => suffix.toLowerCase()) };
7535
- }
7536
- function declaredNames(declaration) {
7537
- if (declaration.declare === true) return [];
7538
- if (declaration.type === AST_NODE_TYPES40.FunctionDeclaration || declaration.type === AST_NODE_TYPES40.ClassDeclaration || declaration.type === AST_NODE_TYPES40.TSEnumDeclaration) {
7539
- if (declaration.type === AST_NODE_TYPES40.TSEnumDeclaration && declaration.const) return [];
7540
- return declaration.id === null ? [] : [declaration.id.name];
7541
- }
7542
- if (declaration.type === AST_NODE_TYPES40.TSModuleDeclaration && declaration.id.type === AST_NODE_TYPES40.Identifier) {
7543
- return [declaration.id.name];
7544
- }
7545
- if (declaration.type !== AST_NODE_TYPES40.VariableDeclaration) return [];
7546
- return declaration.declarations.flatMap(
7547
- (item) => item.id.type === AST_NODE_TYPES40.Identifier ? [item.id.name] : []
7548
- );
7549
- }
7550
7519
  function runtimeExports(program) {
7551
- const exports = [];
7552
- const typeBindings = typeOnlyBindings(program);
7520
+ const bindings = localBindings(program);
7521
+ const exports = /* @__PURE__ */ new Map();
7553
7522
  let ambiguous = false;
7554
- function collectRuntimeExport(statement) {
7555
- if (statement.type === AST_NODE_TYPES40.ExportAllDeclaration) {
7556
- if (statement.exportKind !== "type") ambiguous = true;
7557
- return;
7558
- }
7559
- if (statement.type === AST_NODE_TYPES40.ExportDefaultDeclaration) {
7560
- collectDefaultExport(statement);
7561
- return;
7562
- }
7563
- if (statement.type !== AST_NODE_TYPES40.ExportNamedDeclaration || statement.exportKind === "type") return;
7523
+ function add(key, name, node, emission) {
7524
+ if (emission === "unknown") ambiguous = true;
7525
+ if (emission === "runtime") exports.set(key, { key, name, node });
7526
+ }
7527
+ function collectDefault(statement) {
7528
+ const declaration = statement.declaration;
7529
+ if (declaration.type === AST_NODE_TYPES40.Identifier) {
7530
+ add("default", declaration.name, statement, bindings.get(declaration.name) ?? "unknown");
7531
+ } else if ("id" in declaration && declaration.id?.type === AST_NODE_TYPES40.Identifier) {
7532
+ add("default", declaration.id.name, declaration, declarationEmission(declaration));
7533
+ } else ambiguous = true;
7534
+ }
7535
+ function collectNamed(statement) {
7536
+ if (statement.exportKind === "type") return;
7564
7537
  if (statement.source !== null) {
7565
7538
  if (statement.specifiers.some((specifier) => specifier.exportKind !== "type")) ambiguous = true;
7566
7539
  return;
7567
7540
  }
7568
- if (statement.declaration !== null) {
7569
- const declaration = statement.declaration;
7541
+ const declaration = statement.declaration;
7542
+ if (declaration !== null) {
7570
7543
  if (declaration.type === AST_NODE_TYPES40.VariableDeclaration && declaration.declarations.some((item) => item.id.type !== AST_NODE_TYPES40.Identifier)) ambiguous = true;
7571
- exports.push(...declaredNames(declaration).map((name) => ({ key: name, name, node: declaration })));
7544
+ const names = declarationNames(declaration);
7545
+ if (names.length === 0 && declarationEmission(declaration) !== "erased") ambiguous = true;
7546
+ for (const name of names) add(name, name, declaration, bindings.get(name) ?? "unknown");
7572
7547
  }
7573
- collectExportSpecifiers(statement);
7574
- }
7575
- function collectExportSpecifiers(statement) {
7576
7548
  for (const specifier of statement.specifiers) {
7577
- if (specifier.exportKind === "type" || typeBindings.has(specifier.local.name)) continue;
7578
- const exported = specifier.exported.type === AST_NODE_TYPES40.Identifier ? specifier.exported.name : specifier.exported.value;
7549
+ if (specifier.exportKind === "type") continue;
7550
+ const key = specifier.exported.type === AST_NODE_TYPES40.Identifier ? specifier.exported.name : specifier.exported.value;
7579
7551
  const local = specifier.local.name;
7580
- exports.push({ key: exported, name: exported === "default" ? local : exported, node: specifier });
7552
+ add(key, key === "default" ? local : key, specifier, bindings.get(local) ?? "unknown");
7581
7553
  }
7582
7554
  }
7583
- function collectDefaultExport(statement) {
7584
- const declaration = statement.declaration;
7585
- if (declaration.type === AST_NODE_TYPES40.Identifier) {
7586
- if (!typeBindings.has(declaration.name)) {
7587
- exports.push({ key: "default", name: declaration.name, node: statement });
7588
- }
7589
- } else if ((declaration.type === AST_NODE_TYPES40.FunctionDeclaration || declaration.type === AST_NODE_TYPES40.ClassDeclaration) && declaration.id !== null && declaration.declare !== true) exports.push({ key: "default", name: declaration.id.name, node: declaration });
7590
- else if (declaration.type !== AST_NODE_TYPES40.TSInterfaceDeclaration && declaration.type !== AST_NODE_TYPES40.TSTypeAliasDeclaration) ambiguous = true;
7591
- }
7592
7555
  for (const statement of program.body) {
7593
- collectRuntimeExport(statement);
7556
+ if (statement.type === AST_NODE_TYPES40.ExportAllDeclaration && statement.exportKind !== "type") ambiguous = true;
7557
+ if (statement.type === AST_NODE_TYPES40.TSExportAssignment) ambiguous = true;
7558
+ if (statement.type === AST_NODE_TYPES40.ExportDefaultDeclaration) collectDefault(statement);
7559
+ if (statement.type === AST_NODE_TYPES40.ExportNamedDeclaration) collectNamed(statement);
7594
7560
  }
7595
- const unique = new Map(exports.map((entry) => [entry.key, entry]));
7596
- return { exports: [...unique.values()], ambiguous };
7561
+ return { exports: [...exports.values()], ambiguous };
7597
7562
  }
7598
- function typeOnlyBindings(program) {
7599
- const names = /* @__PURE__ */ new Set();
7600
- const runtimeNames = /* @__PURE__ */ new Set();
7601
- function collectTypeBinding(statement) {
7602
- const declaration = statement.type === AST_NODE_TYPES40.ExportNamedDeclaration ? statement.declaration : statement;
7603
- if (declaration?.type === AST_NODE_TYPES40.TSInterfaceDeclaration || declaration?.type === AST_NODE_TYPES40.TSTypeAliasDeclaration) {
7604
- names.add(declaration.id.name);
7605
- return;
7606
- }
7607
- if (declaration?.type === AST_NODE_TYPES40.TSEnumDeclaration && declaration.const) {
7608
- names.add(declaration.id.name);
7609
- return;
7610
- }
7611
- if (statement.type === AST_NODE_TYPES40.ImportDeclaration) {
7612
- collectImportBindings(statement);
7613
- return;
7614
- }
7615
- if (declaration?.type === AST_NODE_TYPES40.TSDeclareFunction && declaration.id !== null) {
7616
- names.add(declaration.id.name);
7617
- return;
7618
- }
7619
- if (declaration !== null && declaration.declare === true) {
7620
- collectDeclaredNames(declaration);
7621
- return;
7622
- }
7623
- if (declaration !== null && "type" in declaration) {
7624
- for (const name of declaredNames(declaration)) {
7625
- runtimeNames.add(name);
7626
- }
7627
- }
7563
+ function localBindings(program) {
7564
+ const bindings = /* @__PURE__ */ new Map();
7565
+ function register(name, emission) {
7566
+ const previous = bindings.get(name);
7567
+ if (previous === "runtime" || emission === "runtime") bindings.set(name, "runtime");
7568
+ else if (previous === "unknown" || emission === "unknown") bindings.set(name, "unknown");
7569
+ else bindings.set(name, "erased");
7628
7570
  }
7629
- function collectImportBindings(statement) {
7630
- for (const specifier of statement.specifiers) {
7631
- if (statement.importKind === "type" || specifier.type === AST_NODE_TYPES40.ImportSpecifier && specifier.importKind === "type") {
7632
- names.add(specifier.local.name);
7633
- } else {
7634
- runtimeNames.add(specifier.local.name);
7571
+ for (const statement of program.body) {
7572
+ if (statement.type === AST_NODE_TYPES40.ImportDeclaration) {
7573
+ for (const specifier of statement.specifiers) {
7574
+ const typeOnly = statement.importKind === "type" || specifier.type === AST_NODE_TYPES40.ImportSpecifier && specifier.importKind === "type";
7575
+ register(specifier.local.name, typeOnly ? "erased" : "unknown");
7635
7576
  }
7577
+ continue;
7636
7578
  }
7579
+ const declaration = statement.type === AST_NODE_TYPES40.ExportNamedDeclaration || statement.type === AST_NODE_TYPES40.ExportDefaultDeclaration ? statement.declaration : statement;
7580
+ if (declaration === null) continue;
7581
+ for (const name of declarationNames(declaration)) register(name, declarationEmission(declaration));
7637
7582
  }
7638
- function collectDeclaredNames(declaration) {
7639
- if ((declaration.type === AST_NODE_TYPES40.ClassDeclaration || declaration.type === AST_NODE_TYPES40.FunctionDeclaration || declaration.type === AST_NODE_TYPES40.TSEnumDeclaration || declaration.type === AST_NODE_TYPES40.TSModuleDeclaration) && declaration.id !== null && declaration.id.type === AST_NODE_TYPES40.Identifier) names.add(declaration.id.name);
7640
- if (declaration.type === AST_NODE_TYPES40.VariableDeclaration) {
7641
- for (const item of declaration.declarations) {
7642
- if (item.id.type === AST_NODE_TYPES40.Identifier) names.add(item.id.name);
7643
- }
7644
- }
7583
+ return bindings;
7584
+ }
7585
+ function declarationNames(declaration) {
7586
+ if ("id" in declaration && declaration.id !== null) {
7587
+ let id = declaration.id;
7588
+ while (id.type === AST_NODE_TYPES40.TSQualifiedName) id = id.left;
7589
+ if (id.type === AST_NODE_TYPES40.Identifier) return [id.name];
7645
7590
  }
7646
- for (const statement of program.body) {
7647
- collectTypeBinding(statement);
7591
+ if (declaration.type !== AST_NODE_TYPES40.VariableDeclaration) return [];
7592
+ return declaration.declarations.flatMap((item) => item.id.type === AST_NODE_TYPES40.Identifier ? [item.id.name] : []);
7593
+ }
7594
+ function declarationEmission(declaration) {
7595
+ if ("declare" in declaration && declaration.declare === true) return "erased";
7596
+ switch (declaration.type) {
7597
+ case AST_NODE_TYPES40.TSInterfaceDeclaration:
7598
+ case AST_NODE_TYPES40.TSTypeAliasDeclaration:
7599
+ case AST_NODE_TYPES40.TSDeclareFunction:
7600
+ return "erased";
7601
+ case AST_NODE_TYPES40.ClassDeclaration:
7602
+ case AST_NODE_TYPES40.FunctionDeclaration:
7603
+ case AST_NODE_TYPES40.VariableDeclaration:
7604
+ return "runtime";
7605
+ case AST_NODE_TYPES40.TSEnumDeclaration:
7606
+ return declaration.const ? "unknown" : "runtime";
7607
+ case AST_NODE_TYPES40.TSModuleDeclaration:
7608
+ return namespaceEmission(declaration);
7609
+ default:
7610
+ return "unknown";
7648
7611
  }
7649
- return new Set([...names].filter((name) => !runtimeNames.has(name)));
7650
7612
  }
7651
- function isGlobalIdentifier2(context, node) {
7652
- const variable = ASTUtils16.findVariable(context.sourceCode.getScope(node), node.name);
7653
- return variable === null || variable.defs.length === 0;
7613
+ function namespaceEmission(declaration) {
7614
+ const { body: body2 } = declaration;
7615
+ if (body2 === void 0) return "unknown";
7616
+ if (body2.body.length === 0) return "unknown";
7617
+ let ambiguous = false;
7618
+ for (const statement of body2.body) {
7619
+ if (statement.type === AST_NODE_TYPES40.ExportNamedDeclaration && statement.exportKind === "type") continue;
7620
+ const inner = statement.type === AST_NODE_TYPES40.ExportNamedDeclaration ? statement.declaration : statement;
7621
+ const emission = inner === null ? "unknown" : declarationEmission(inner);
7622
+ if (emission === "runtime") return "runtime";
7623
+ if (emission === "unknown") ambiguous = true;
7624
+ }
7625
+ return ambiguous ? "unknown" : "erased";
7654
7626
  }
7655
- function isConventionalFrameworkUtility(filename, exported) {
7656
- const normalized = filename.replaceAll("\\", "/");
7657
- return exported === "cn" && /(?:^|\/)lib\/utils\.[cm]?[jt]sx?$/u.test(normalized);
7627
+ function isCommonJsExportReference(node, sourceCode) {
7628
+ function isGlobal(node2) {
7629
+ const variable = ASTUtils16.findVariable(sourceCode.getScope(node2), node2.name);
7630
+ return variable === null || variable.defs.length === 0;
7631
+ }
7632
+ if (node.type === AST_NODE_TYPES40.MemberExpression) {
7633
+ return node.object.type === AST_NODE_TYPES40.Identifier && isGlobal(node.object) && (node.object.name === "exports" || node.object.name === "module" && memberPropertyName(node) === "exports");
7634
+ }
7635
+ const first = node.arguments[0];
7636
+ return first?.type === AST_NODE_TYPES40.Identifier && first.name === "exports" && isGlobal(first) && node.callee.type === AST_NODE_TYPES40.MemberExpression && node.callee.object.type === AST_NODE_TYPES40.Identifier && node.callee.object.name === "Object" && isGlobal(node.callee.object) && CJS_OBJECT_EXPORT_METHODS.has(memberPropertyName(node.callee) ?? "");
7658
7637
  }
7659
7638
  function memberPropertyName(node) {
7660
7639
  if (!node.computed && node.property.type === AST_NODE_TYPES40.Identifier) return node.property.name;
7661
7640
  return node.computed && node.property.type === AST_NODE_TYPES40.Literal && typeof node.property.value === "string" ? node.property.value : null;
7662
7641
  }
7663
- var no_generic_single_export_module_default = createRule({
7664
- name: "no-generic-single-export-module",
7665
- documentation: NO_GENERIC_SINGLE_EXPORT_MODULE_DOCUMENTATION,
7666
- meta: {
7667
- type: "suggestion",
7668
- docs: { description: "Disallow generic module stems when one runtime export already names the responsibility." },
7669
- schema: [],
7670
- messages: {
7671
- genericSingleExport: "Module stem `{{stem}}` is generic and its only runtime export is `{{exported}}`; choose a responsibility-bearing module name or colocate the export with its domain."
7672
- }
7642
+
7643
+ // src/rules/no-generic-single-export-module.ts
7644
+ var NO_GENERIC_SINGLE_EXPORT_MODULE_DOCUMENTATION = {
7645
+ summary: "Disallow generic module stems when one runtime export already names the responsibility.",
7646
+ rationale: "A generic filename hides the sole exported responsibility and makes navigation less descriptive.",
7647
+ remediation: "Choose a responsibility-bearing module name or colocate the export with its domain.",
7648
+ category: "maintainability",
7649
+ limitations: ["Only the fixed generic-stem vocabulary with exactly one public runtime export is checked; exported destructuring patterns are excluded rather than undercounted."],
7650
+ examples: [
7651
+ { id: "responsibility-named-module", title: "Name the module after its export", outcome: "no-match", files: [{ path: "src/parse-order.ts", source: "export function parseOrder() { return {}; }" }], focusPath: "src/parse-order.ts", expectedCount: 0, public: true },
7652
+ { id: "generic-module-name", title: "Do not hide one export in a generic module", outcome: "match", files: [{ path: "src/utils.ts", source: "export function parseOrder() { return {}; }" }], focusPath: "src/utils.ts", expectedCount: 1, public: true }
7653
+ ]
7654
+ };
7655
+ function fileParts(filename) {
7656
+ const base = filename.replaceAll("\\", "/").split("/").at(-1) ?? "";
7657
+ const extension = base.match(/(\.[cm]?[jt]sx?)$/u)?.[1] ?? ".ts";
7658
+ const [stem4 = "", ...suffixes] = base.slice(0, -extension.length).split(".");
7659
+ return { stem: stem4, suffixes: suffixes.map((suffix) => suffix.toLowerCase()) };
7660
+ }
7661
+ function isConventionalFrameworkUtility(filename, exported) {
7662
+ const normalized = filename.replaceAll("\\", "/");
7663
+ return exported === "cn" && /(?:^|\/)lib\/utils\.[cm]?[jt]sx?$/u.test(normalized);
7664
+ }
7665
+ var no_generic_single_export_module_default = createRule({
7666
+ name: "no-generic-single-export-module",
7667
+ documentation: NO_GENERIC_SINGLE_EXPORT_MODULE_DOCUMENTATION,
7668
+ meta: {
7669
+ type: "suggestion",
7670
+ docs: { description: "Disallow generic module stems when one runtime export already names the responsibility." },
7671
+ schema: [],
7672
+ messages: {
7673
+ genericSingleExport: "Module stem `{{stem}}` is generic and its only runtime export is `{{exported}}`; choose a responsibility-bearing module name or colocate the export with its domain."
7674
+ }
7673
7675
  },
7674
7676
  defaultOptions: [],
7675
7677
  create(context) {
7676
7678
  const file = fileParts(context.filename);
7677
7679
  const { stem: stem4 } = file;
7678
- if (!GENERIC_STEMS.has(stem4) || isTestFile(context.filename) || isGeneratedFile(context.filename, context.sourceCode.text)) return {};
7680
+ if (!GENERIC_MODULE_STEMS.has(stem4) || isTestFile(context.filename) || isGeneratedFile(context.filename, context.sourceCode.text)) return {};
7679
7681
  let hasCommonJsExport = false;
7680
7682
  return {
7681
- CallExpression(node) {
7682
- const first = node.arguments[0];
7683
- if (first?.type === AST_NODE_TYPES40.Identifier && first.name === "exports" && isGlobalIdentifier2(context, first) && node.callee.type === AST_NODE_TYPES40.MemberExpression && node.callee.object.type === AST_NODE_TYPES40.Identifier && node.callee.object.name === "Object" && isGlobalIdentifier2(context, node.callee.object) && memberPropertyName(node.callee) !== null && CJS_OBJECT_EXPORT_METHODS.has(memberPropertyName(node.callee))) hasCommonJsExport = true;
7684
- },
7685
- MemberExpression(node) {
7686
- if (node.object.type === AST_NODE_TYPES40.Identifier && node.object.name === "exports" && isGlobalIdentifier2(context, node.object)) hasCommonJsExport = true;
7687
- if (node.object.type === AST_NODE_TYPES40.Identifier && node.object.name === "module" && isGlobalIdentifier2(context, node.object) && memberPropertyName(node) === "exports") hasCommonJsExport = true;
7683
+ "CallExpression, MemberExpression"(node) {
7684
+ if (isCommonJsExportReference(node, context.sourceCode)) hasCommonJsExport = true;
7688
7685
  },
7689
7686
  "Program:exit"(program) {
7690
7687
  if (hasCommonJsExport) return;
@@ -8034,6 +8031,10 @@ var no_positional_tuple_return_default = createRule({
8034
8031
  data: { name, count: String(tuple.elements.length) }
8035
8032
  });
8036
8033
  };
8034
+ const enterFunction = (node) => {
8035
+ functionStack.push(node);
8036
+ check(node);
8037
+ };
8037
8038
  const check = (node) => {
8038
8039
  if (isQueryKeyFactory(node)) return;
8039
8040
  const annotation = node.returnType?.typeAnnotation;
@@ -8049,10 +8050,6 @@ var no_positional_tuple_return_default = createRule({
8049
8050
  }
8050
8051
  report2(annotation, name);
8051
8052
  };
8052
- const enterFunction = (node) => {
8053
- functionStack.push(node);
8054
- check(node);
8055
- };
8056
8053
  const exitFunction = () => {
8057
8054
  functionStack.pop();
8058
8055
  };
@@ -8499,32 +8496,16 @@ var no_raw_fetch_outside_clients_default = createRule({
8499
8496
  const definition = variable.defs[0];
8500
8497
  return definition?.type === "Variable" && definition.parent.kind === "const" && definition.node.init !== null && !variable.references.some((reference) => reference.isWrite() && reference.init !== true) && !(definition.node.init.type === AST_NODE_TYPES42.ObjectExpression && variable.references.some((reference) => reference.identifier !== node && reference.init !== true)) ? definition.node.init : node;
8501
8498
  }
8502
- function propertyValue(node, name) {
8503
- if (node?.type !== AST_NODE_TYPES42.ObjectExpression) return null;
8504
- if (node.properties.some((property) => property.type !== AST_NODE_TYPES42.Property || property.computed)) return null;
8505
- for (const property of [...node.properties].reverse()) {
8506
- if (property.type !== AST_NODE_TYPES42.Property || property.computed) continue;
8507
- const key = property.key;
8508
- const keyName = key.type === AST_NODE_TYPES42.Identifier ? key.name : key.type === AST_NODE_TYPES42.Literal && typeof key.value === "string" ? key.value : null;
8509
- if (keyName !== name) continue;
8510
- return property.value.type === AST_NODE_TYPES42.AssignmentPattern || property.value.type === AST_NODE_TYPES42.ArrayPattern || property.value.type === AST_NODE_TYPES42.ObjectPattern ? null : property.value;
8511
- }
8512
- return null;
8513
- }
8514
- function isInternalApiUrl(node) {
8515
- const resolved = resolveNode2(node ?? void 0);
8516
- if (resolved?.type === AST_NODE_TYPES42.Literal) {
8517
- return typeof resolved.value === "string" && internalApiPrefixes.some(
8518
- (prefix) => resolved.value === prefix || resolved.value.startsWith(`${prefix}/`)
8519
- );
8499
+ function serverActionOwns(node) {
8500
+ if (node.callee.type !== AST_NODE_TYPES42.Identifier || !hasUseClientDirective || hasUseServerDirective || importsServerOnly || SERVER_ACTION_SKIP_FILE_RE.test(filename) || nonReactFramework) {
8501
+ return false;
8520
8502
  }
8521
- if (resolved?.type === AST_NODE_TYPES42.TemplateLiteral) {
8522
- const prefix = resolved.quasis[0]?.value.cooked;
8523
- return typeof prefix === "string" && internalApiPrefixes.some(
8524
- (apiPrefix) => prefix === apiPrefix || prefix.startsWith(`${apiPrefix}/`)
8525
- );
8503
+ const url = node.arguments[0];
8504
+ const init = node.arguments[1];
8505
+ if (url === void 0 || url.type === AST_NODE_TYPES42.SpreadElement || init === void 0 || init.type === AST_NODE_TYPES42.SpreadElement || !isInternalApiUrl(url)) {
8506
+ return false;
8526
8507
  }
8527
- return resolved?.type === AST_NODE_TYPES42.BinaryExpression && resolved.operator === "+" && isInternalApiUrl(resolved.left);
8508
+ return isMutationMethod2(propertyValue(resolveNode2(init), "method"));
8528
8509
  }
8529
8510
  function isMutationMethod2(node) {
8530
8511
  const resolved = resolveNode2(node ?? void 0);
@@ -8541,16 +8522,32 @@ var no_raw_fetch_outside_clients_default = createRule({
8541
8522
  }
8542
8523
  return resolved?.type === AST_NODE_TYPES42.LogicalExpression && resolved.operator === "||" && (isMutationMethod2(resolved.left) || isMutationMethod2(resolved.right));
8543
8524
  }
8544
- function serverActionOwns(node) {
8545
- if (node.callee.type !== AST_NODE_TYPES42.Identifier || !hasUseClientDirective || hasUseServerDirective || importsServerOnly || SERVER_ACTION_SKIP_FILE_RE.test(filename) || nonReactFramework) {
8546
- return false;
8525
+ function isInternalApiUrl(node) {
8526
+ const resolved = resolveNode2(node ?? void 0);
8527
+ if (resolved?.type === AST_NODE_TYPES42.Literal) {
8528
+ return typeof resolved.value === "string" && internalApiPrefixes.some(
8529
+ (prefix) => resolved.value === prefix || resolved.value.startsWith(`${prefix}/`)
8530
+ );
8547
8531
  }
8548
- const url = node.arguments[0];
8549
- const init = node.arguments[1];
8550
- if (url === void 0 || url.type === AST_NODE_TYPES42.SpreadElement || init === void 0 || init.type === AST_NODE_TYPES42.SpreadElement || !isInternalApiUrl(url)) {
8551
- return false;
8532
+ if (resolved?.type === AST_NODE_TYPES42.TemplateLiteral) {
8533
+ const prefix = resolved.quasis[0]?.value.cooked;
8534
+ return typeof prefix === "string" && internalApiPrefixes.some(
8535
+ (apiPrefix) => prefix === apiPrefix || prefix.startsWith(`${apiPrefix}/`)
8536
+ );
8552
8537
  }
8553
- return isMutationMethod2(propertyValue(resolveNode2(init), "method"));
8538
+ return resolved?.type === AST_NODE_TYPES42.BinaryExpression && resolved.operator === "+" && isInternalApiUrl(resolved.left);
8539
+ }
8540
+ function propertyValue(node, name) {
8541
+ if (node?.type !== AST_NODE_TYPES42.ObjectExpression) return null;
8542
+ if (node.properties.some((property) => property.type !== AST_NODE_TYPES42.Property || property.computed)) return null;
8543
+ for (const property of [...node.properties].reverse()) {
8544
+ if (property.type !== AST_NODE_TYPES42.Property || property.computed) continue;
8545
+ const key = property.key;
8546
+ const keyName = key.type === AST_NODE_TYPES42.Identifier ? key.name : key.type === AST_NODE_TYPES42.Literal && typeof key.value === "string" ? key.value : null;
8547
+ if (keyName !== name) continue;
8548
+ return property.value.type === AST_NODE_TYPES42.AssignmentPattern || property.value.type === AST_NODE_TYPES42.ArrayPattern || property.value.type === AST_NODE_TYPES42.ObjectPattern ? null : property.value;
8549
+ }
8550
+ return null;
8554
8551
  }
8555
8552
  if (allowed.some((re) => re.test(filename))) {
8556
8553
  return {};
@@ -9225,19 +9222,19 @@ var no_restated_jsdoc_default = createRule({
9225
9222
  function enclosingDeclarationNames(node) {
9226
9223
  let declaration = null;
9227
9224
  while (node != null && node.type !== AST_NODE_TYPES47.Program) {
9228
- declaration = declarationNames(node);
9225
+ declaration = declarationNames2(node);
9229
9226
  if (declaration !== null) break;
9230
9227
  node = node.parent ?? null;
9231
9228
  }
9232
9229
  return declaration;
9233
9230
  }
9234
- function declarationNames(node) {
9231
+ function declarationNames2(node) {
9235
9232
  switch (node.type) {
9236
9233
  // `export function f()` — the JSDoc sits above the `export`, so the token
9237
9234
  // after it resolves to the wrapper, not to the thing being documented.
9238
9235
  case AST_NODE_TYPES47.ExportNamedDeclaration:
9239
9236
  case AST_NODE_TYPES47.ExportDefaultDeclaration:
9240
- return node.declaration == null ? null : declarationNames(node.declaration);
9237
+ return node.declaration == null ? null : declarationNames2(node.declaration);
9241
9238
  case AST_NODE_TYPES47.FunctionDeclaration:
9242
9239
  case AST_NODE_TYPES47.TSDeclareFunction:
9243
9240
  return node.id === null ? null : { name: node.id.name, params: paramNames(node.params) };
@@ -9649,35 +9646,30 @@ var no_secret_in_log_default = createRule({
9649
9646
  create(context, [loggingOptions]) {
9650
9647
  const matcher = createLogMatcher(loggingOptions);
9651
9648
  const blobArmApplies = !isTestFile(context.filename);
9652
- function reportSecretArgument(arg) {
9653
- const name = valueName(arg);
9654
- if (name === null || !isSecretKeyword(name)) {
9655
- return false;
9649
+ function inspectLoggedValue(value) {
9650
+ if (value.type === "ObjectExpression") {
9651
+ for (const property of literalProperties(value)) {
9652
+ if (reportSecretProperty(property) || reportRawBlob(property, property.value)) continue;
9653
+ inspectLoggedValue(property.value);
9654
+ }
9655
+ return;
9656
9656
  }
9657
- context.report({ node: arg, messageId: "noSecretInLog", data: { name } });
9658
- return true;
9659
- }
9660
- function reportSecretProperty(prop) {
9661
- const keyName = propertyKeyName2(prop);
9662
- const value = valueName(prop.value);
9663
- if (value !== null && hasRedactionMarker(value)) return false;
9664
- const name = value !== null && isSecretKeyword(value) ? value : keyName;
9665
- if (name === null || !isSecretKeyword(name) || !isRawSecretValue(prop)) {
9666
- return false;
9657
+ if (value.type === "ArrayExpression") {
9658
+ for (const element of value.elements) {
9659
+ if (element !== null && element.type !== "SpreadElement") inspectLoggedValue(element);
9660
+ }
9661
+ return;
9667
9662
  }
9668
- context.report({ node: prop, messageId: "noSecretInLog", data: { name } });
9669
- return true;
9670
- }
9671
- function reportRawBlob(node, value) {
9672
- if (!blobArmApplies) {
9673
- return false;
9663
+ if (value.type === "TemplateLiteral") {
9664
+ for (const expression of value.expressions) inspectLoggedValue(expression);
9665
+ return;
9674
9666
  }
9675
- const name = rawBlobValueName(value);
9676
- if (name !== null) {
9677
- context.report({ node, messageId: "noRawBodyInLog", data: { name } });
9678
- return true;
9667
+ if (value.type === "BinaryExpression" && value.operator === "+") {
9668
+ inspectLoggedValue(value.left);
9669
+ inspectLoggedValue(value.right);
9670
+ return;
9679
9671
  }
9680
- return false;
9672
+ if (!reportSecretArgument(value)) reportRawBlob(value, value);
9681
9673
  }
9682
9674
  function literalProperties(value) {
9683
9675
  const effective = /* @__PURE__ */ new Map();
@@ -9702,30 +9694,35 @@ var no_secret_in_log_default = createRule({
9702
9694
  }
9703
9695
  return [...effective.values()];
9704
9696
  }
9705
- function inspectLoggedValue(value) {
9706
- if (value.type === "ObjectExpression") {
9707
- for (const property of literalProperties(value)) {
9708
- if (reportSecretProperty(property) || reportRawBlob(property, property.value)) continue;
9709
- inspectLoggedValue(property.value);
9710
- }
9711
- return;
9697
+ function reportRawBlob(node, value) {
9698
+ if (!blobArmApplies) {
9699
+ return false;
9712
9700
  }
9713
- if (value.type === "ArrayExpression") {
9714
- for (const element of value.elements) {
9715
- if (element !== null && element.type !== "SpreadElement") inspectLoggedValue(element);
9716
- }
9717
- return;
9701
+ const name = rawBlobValueName(value);
9702
+ if (name !== null) {
9703
+ context.report({ node, messageId: "noRawBodyInLog", data: { name } });
9704
+ return true;
9718
9705
  }
9719
- if (value.type === "TemplateLiteral") {
9720
- for (const expression of value.expressions) inspectLoggedValue(expression);
9721
- return;
9706
+ return false;
9707
+ }
9708
+ function reportSecretProperty(prop) {
9709
+ const keyName = propertyKeyName2(prop);
9710
+ const value = valueName(prop.value);
9711
+ if (value !== null && hasRedactionMarker(value)) return false;
9712
+ const name = value !== null && isSecretKeyword(value) ? value : keyName;
9713
+ if (name === null || !isSecretKeyword(name) || !isRawSecretValue(prop)) {
9714
+ return false;
9722
9715
  }
9723
- if (value.type === "BinaryExpression" && value.operator === "+") {
9724
- inspectLoggedValue(value.left);
9725
- inspectLoggedValue(value.right);
9726
- return;
9716
+ context.report({ node: prop, messageId: "noSecretInLog", data: { name } });
9717
+ return true;
9718
+ }
9719
+ function reportSecretArgument(arg) {
9720
+ const name = valueName(arg);
9721
+ if (name === null || !isSecretKeyword(name)) {
9722
+ return false;
9727
9723
  }
9728
- if (!reportSecretArgument(value)) reportRawBlob(value, value);
9724
+ context.report({ node: arg, messageId: "noSecretInLog", data: { name } });
9725
+ return true;
9729
9726
  }
9730
9727
  return {
9731
9728
  CallExpression(node) {
@@ -10023,9 +10020,6 @@ function bindsName(param, name) {
10023
10020
  }
10024
10021
  function subtreeReadsName(node, name) {
10025
10022
  let found = false;
10026
- const shadowsName = (fn) => isFunctionNode(fn) && fn.params.some(
10027
- (param) => bindsName(param, name)
10028
- );
10029
10023
  const recurse = (current) => {
10030
10024
  if (found) {
10031
10025
  return;
@@ -10042,6 +10036,9 @@ function subtreeReadsName(node, name) {
10042
10036
  return found;
10043
10037
  }, (key) => !isNonReadingProperty(current, key));
10044
10038
  };
10039
+ const shadowsName = (fn) => isFunctionNode(fn) && fn.params.some(
10040
+ (param) => bindsName(param, name)
10041
+ );
10045
10042
  recurse(node);
10046
10043
  return found;
10047
10044
  }
@@ -11903,14 +11900,6 @@ var no_declaration_comment_wall_default = createRule({
11903
11900
  const trail = startingOn.get(member.loc.end.line);
11904
11901
  return trail !== void 0 && trail.range[0] > member.range[0] ? trail : void 0;
11905
11902
  }
11906
- function isGroupLabel(comment, member, headsRun) {
11907
- if (comment.loc.end.line >= member.node.loc.start.line) return false;
11908
- const body2 = commentBody(comment);
11909
- if (!BARE_LABEL_RE.test(body2)) return false;
11910
- if (labelStems(body2) === labelStems(sourceCode.getText(member.key))) return false;
11911
- const lineAbove = sourceCode.lines[comment.loc.start.line - 2];
11912
- return headsRun || lineAbove !== void 0 && lineAbove.trim().length === 0;
11913
- }
11914
11903
  function check(node, members) {
11915
11904
  const judged = members.map(named).filter((member) => member !== void 0);
11916
11905
  if (judged.length === 0) return;
@@ -11949,6 +11938,14 @@ var no_declaration_comment_wall_default = createRule({
11949
11938
  data: { restated: String(restated), commented: String(commented) }
11950
11939
  });
11951
11940
  }
11941
+ function isGroupLabel(comment, member, headsRun) {
11942
+ if (comment.loc.end.line >= member.node.loc.start.line) return false;
11943
+ const body2 = commentBody(comment);
11944
+ if (!BARE_LABEL_RE.test(body2)) return false;
11945
+ if (labelStems(body2) === labelStems(sourceCode.getText(member.key))) return false;
11946
+ const lineAbove = sourceCode.lines[comment.loc.start.line - 2];
11947
+ return headsRun || lineAbove !== void 0 && lineAbove.trim().length === 0;
11948
+ }
11952
11949
  return {
11953
11950
  ClassBody: (node) => {
11954
11951
  check(node, node.body);
@@ -12184,14 +12181,6 @@ var no_type_member_comment_wall_default = createRule({
12184
12181
  const trail = startingOn.get(member.loc.end.line);
12185
12182
  return trail !== void 0 && trail.range[0] > member.range[0] ? trail : void 0;
12186
12183
  }
12187
- function isGroupLabel(comment, member, headsRun) {
12188
- if (comment.loc.end.line >= member.loc.start.line) return false;
12189
- const body2 = commentBody(comment);
12190
- if (!BARE_LABEL_RE.test(body2)) return false;
12191
- if (labelStems(body2) === labelStems(sourceCode.getText(member.key))) return false;
12192
- const lineAbove = sourceCode.lines[comment.loc.start.line - 2];
12193
- return headsRun || lineAbove !== void 0 && lineAbove.trim().length === 0;
12194
- }
12195
12184
  function check(node) {
12196
12185
  const members = node.type === AST_NODE_TYPES56.TSInterfaceBody ? node.body : node.members;
12197
12186
  const named2 = members.filter(isNamedMember);
@@ -12227,6 +12216,14 @@ var no_type_member_comment_wall_default = createRule({
12227
12216
  data: { restated: String(restated), commented: String(commented) }
12228
12217
  });
12229
12218
  }
12219
+ function isGroupLabel(comment, member, headsRun) {
12220
+ if (comment.loc.end.line >= member.loc.start.line) return false;
12221
+ const body2 = commentBody(comment);
12222
+ if (!BARE_LABEL_RE.test(body2)) return false;
12223
+ if (labelStems(body2) === labelStems(sourceCode.getText(member.key))) return false;
12224
+ const lineAbove = sourceCode.lines[comment.loc.start.line - 2];
12225
+ return headsRun || lineAbove !== void 0 && lineAbove.trim().length === 0;
12226
+ }
12230
12227
  return {
12231
12228
  TSInterfaceBody: check,
12232
12229
  TSTypeLiteral: check
@@ -12545,6 +12542,11 @@ var no_unsafe_mock_casting_default = createRule({
12545
12542
  const binding = resolve2(identifier);
12546
12543
  if (binding !== null) destination.add(binding);
12547
12544
  }
12545
+ function checkAssertion(node) {
12546
+ if (isMockTypeReference(node.typeAnnotation)) {
12547
+ context.report({ node, messageId: "unsafeMockCast" });
12548
+ }
12549
+ }
12548
12550
  function isMockTypeReference(node) {
12549
12551
  if (node.type !== AST_NODE_TYPES58.TSTypeReference) return false;
12550
12552
  const typeName = node.typeName;
@@ -12558,11 +12560,6 @@ var no_unsafe_mock_casting_default = createRule({
12558
12560
  }
12559
12561
  return false;
12560
12562
  }
12561
- function checkAssertion(node) {
12562
- if (isMockTypeReference(node.typeAnnotation)) {
12563
- context.report({ node, messageId: "unsafeMockCast" });
12564
- }
12565
- }
12566
12563
  return {
12567
12564
  ImportDeclaration(node) {
12568
12565
  if (!MOCK_MODULES.has(node.source.value)) return;
@@ -17897,7 +17894,7 @@ var staticallyImportsExternalRenderer = (program) => program.body.some((statemen
17897
17894
  var semanticForegroundRoles = (filename) => {
17898
17895
  const packageRoot = nearestPackageRoot(dirname2(filename));
17899
17896
  if (packageRoot === null) return /* @__PURE__ */ new Set();
17900
- const candidates = CSS_DETECTION_FILES.map((relative2) => join2(packageRoot, relative2));
17897
+ const candidates = CSS_DETECTION_FILES.map((relative3) => join2(packageRoot, relative3));
17901
17898
  const fingerprint = candidates.map(fileFingerprint2).join("|");
17902
17899
  const cached = SEMANTIC_DECLARATIONS_CACHE.get(packageRoot);
17903
17900
  if (cached?.fingerprint === fingerprint) return cached.value;
@@ -17980,37 +17977,6 @@ var prefer_semantic_colors_default = createRule({
17980
17977
  const key = `${node.range[0]}:${node.range[1]}:${messageId}:${JSON.stringify(data)}`;
17981
17978
  pendingReports.set(key, { node, messageId, data });
17982
17979
  };
17983
- const reportClasses = (value, node) => {
17984
- const tokens = classTokens(value);
17985
- for (const token of tokens) {
17986
- const base = tailwindBase(token);
17987
- if (RAW_PALETTE_RE.test(base)) {
17988
- report2(node, "rawPalette", { class: token });
17989
- } else if (ARBITRARY_COLOR_RE.test(base) && !CSS_VAR_REFERENCE_RE.test(base)) {
17990
- report2(node, "arbitraryColor", { class: token });
17991
- }
17992
- }
17993
- if (!checkOpaqueForegroundPairs || isInsideSvg(node)) return;
17994
- for (const token of tokens) {
17995
- const prefix = tailwindVariantPrefix(token);
17996
- if (prefix.split(":").includes("print")) continue;
17997
- const base = tailwindBase(token);
17998
- if (!OPAQUE_FOREGROUND_RE.test(base)) continue;
17999
- const semanticBackground = tokens.find((candidate2) => {
18000
- if (tailwindVariantPrefix(candidate2) !== prefix) return false;
18001
- const match = SEMANTIC_BACKGROUND_RE.exec(tailwindBase(candidate2));
18002
- return match?.[1] !== void 0 && foregroundRoles.has(match[1]);
18003
- });
18004
- if (semanticBackground === void 0) continue;
18005
- const role = SEMANTIC_BACKGROUND_RE.exec(tailwindBase(semanticBackground))?.[1];
18006
- if (role === void 0) continue;
18007
- report2(node, "opaqueForegroundPair", {
18008
- background: semanticBackground,
18009
- class: token,
18010
- replacement: `${prefix}text-${role}-foreground`
18011
- });
18012
- }
18013
- };
18014
17980
  const checkClassNode = (node, objectKeys = false) => {
18015
17981
  if (node === null) return;
18016
17982
  switch (node.type) {
@@ -18039,6 +18005,37 @@ var prefer_semantic_colors_default = createRule({
18039
18005
  break;
18040
18006
  }
18041
18007
  };
18008
+ const reportClasses = (value, node) => {
18009
+ const tokens = classTokens(value);
18010
+ for (const token of tokens) {
18011
+ const base = tailwindBase(token);
18012
+ if (RAW_PALETTE_RE.test(base)) {
18013
+ report2(node, "rawPalette", { class: token });
18014
+ } else if (ARBITRARY_COLOR_RE.test(base) && !CSS_VAR_REFERENCE_RE.test(base)) {
18015
+ report2(node, "arbitraryColor", { class: token });
18016
+ }
18017
+ }
18018
+ if (!checkOpaqueForegroundPairs || isInsideSvg(node)) return;
18019
+ for (const token of tokens) {
18020
+ const prefix = tailwindVariantPrefix(token);
18021
+ if (prefix.split(":").includes("print")) continue;
18022
+ const base = tailwindBase(token);
18023
+ if (!OPAQUE_FOREGROUND_RE.test(base)) continue;
18024
+ const semanticBackground = tokens.find((candidate2) => {
18025
+ if (tailwindVariantPrefix(candidate2) !== prefix) return false;
18026
+ const match = SEMANTIC_BACKGROUND_RE.exec(tailwindBase(candidate2));
18027
+ return match?.[1] !== void 0 && foregroundRoles.has(match[1]);
18028
+ });
18029
+ if (semanticBackground === void 0) continue;
18030
+ const role = SEMANTIC_BACKGROUND_RE.exec(tailwindBase(semanticBackground))?.[1];
18031
+ if (role === void 0) continue;
18032
+ report2(node, "opaqueForegroundPair", {
18033
+ background: semanticBackground,
18034
+ class: token,
18035
+ replacement: `${prefix}text-${role}-foreground`
18036
+ });
18037
+ }
18038
+ };
18042
18039
  function checkClassProperties(node, objectKeys) {
18043
18040
  for (const property of node.properties) {
18044
18041
  if (property.type !== AST_NODE_TYPES87.Property) continue;
@@ -18472,80 +18469,6 @@ var prefer_whole_object_assertion_default = createRule({
18472
18469
  return {};
18473
18470
  }
18474
18471
  const { sourceCode } = context;
18475
- function parseAssertion(statement) {
18476
- if (statement.type !== AST_NODE_TYPES88.ExpressionStatement) {
18477
- return null;
18478
- }
18479
- const call = statement.expression;
18480
- if (call.type !== AST_NODE_TYPES88.CallExpression) {
18481
- return null;
18482
- }
18483
- const callee = call.callee;
18484
- if (callee.type !== AST_NODE_TYPES88.MemberExpression || callee.computed || callee.property.type !== AST_NODE_TYPES88.Identifier) {
18485
- return null;
18486
- }
18487
- const matcher = callee.property.name;
18488
- const expectCall = callee.object;
18489
- if (expectCall.type !== AST_NODE_TYPES88.CallExpression || expectCall.callee.type !== AST_NODE_TYPES88.Identifier || expectCall.callee.name !== "expect" || expectCall.arguments.length !== 1) {
18490
- return null;
18491
- }
18492
- const actual = expectCall.arguments[0];
18493
- if (!isTestExpect(expectCall.callee)) return null;
18494
- if (actual === void 0 || actual.type !== AST_NODE_TYPES88.MemberExpression || actual.optional) {
18495
- return null;
18496
- }
18497
- if (!isPureReceiver(actual.object)) {
18498
- return null;
18499
- }
18500
- let key;
18501
- let receiver;
18502
- if (actual.computed) {
18503
- const index = literalIndex(actual.property);
18504
- if (index === null) {
18505
- return null;
18506
- }
18507
- key = { kind: "index", index };
18508
- receiver = actual.object;
18509
- } else {
18510
- const access = propertyAccess(actual);
18511
- if (access === null) return null;
18512
- key = { kind: "property", path: access.path };
18513
- receiver = access.receiver;
18514
- }
18515
- return assertionExpectation(statement, call, receiver, key, matcher);
18516
- }
18517
- function assertionExpectation(statement, call, receiver, key, matcher) {
18518
- const synthetic = SYNTHETIC_LITERAL_MATCHERS.get(matcher);
18519
- if (synthetic !== void 0 && call.arguments.length === 0) {
18520
- return { statement, receiver, key, matcher, expectedText: synthetic, expectedIsLiteral: true };
18521
- }
18522
- if (!MERGEABLE_MATCHERS.has(matcher)) {
18523
- return null;
18524
- }
18525
- const expected = call.arguments[0];
18526
- if (call.arguments.length !== 1 || expected === void 0 || expected.type === AST_NODE_TYPES88.SpreadElement) {
18527
- return null;
18528
- }
18529
- const literal = literalText(expected, (node) => sourceCode.getText(node));
18530
- return {
18531
- statement,
18532
- receiver,
18533
- key,
18534
- matcher,
18535
- expectedText: literal ?? sourceCode.getText(expected),
18536
- expectedIsLiteral: literal !== null
18537
- };
18538
- }
18539
- function isTestExpect(callee) {
18540
- const variable = ASTUtils45.findVariable(sourceCode.getScope(callee), callee.name);
18541
- if (variable !== null && variable.defs.some((definition) => {
18542
- if (definition.node.type !== AST_NODE_TYPES88.ImportSpecifier) return true;
18543
- const declaration = definition.node.parent;
18544
- const imported = definition.node.imported;
18545
- return declaration.type !== AST_NODE_TYPES88.ImportDeclaration || !["vitest", "@jest/globals", "@playwright/test", "bun:test"].includes(String(declaration.source.value)) || (imported.type === AST_NODE_TYPES88.Identifier ? imported.name : imported.value) !== "expect";
18546
- })) return false;
18547
- return true;
18548
- }
18549
18472
  function reportPropertyRun(run) {
18550
18473
  const tree = /* @__PURE__ */ new Map();
18551
18474
  const paths = [];
@@ -18655,6 +18578,80 @@ var prefer_whole_object_assertion_default = createRule({
18655
18578
  }
18656
18579
  flush();
18657
18580
  }
18581
+ function parseAssertion(statement) {
18582
+ if (statement.type !== AST_NODE_TYPES88.ExpressionStatement) {
18583
+ return null;
18584
+ }
18585
+ const call = statement.expression;
18586
+ if (call.type !== AST_NODE_TYPES88.CallExpression) {
18587
+ return null;
18588
+ }
18589
+ const callee = call.callee;
18590
+ if (callee.type !== AST_NODE_TYPES88.MemberExpression || callee.computed || callee.property.type !== AST_NODE_TYPES88.Identifier) {
18591
+ return null;
18592
+ }
18593
+ const matcher = callee.property.name;
18594
+ const expectCall = callee.object;
18595
+ if (expectCall.type !== AST_NODE_TYPES88.CallExpression || expectCall.callee.type !== AST_NODE_TYPES88.Identifier || expectCall.callee.name !== "expect" || expectCall.arguments.length !== 1) {
18596
+ return null;
18597
+ }
18598
+ const actual = expectCall.arguments[0];
18599
+ if (!isTestExpect(expectCall.callee)) return null;
18600
+ if (actual === void 0 || actual.type !== AST_NODE_TYPES88.MemberExpression || actual.optional) {
18601
+ return null;
18602
+ }
18603
+ if (!isPureReceiver(actual.object)) {
18604
+ return null;
18605
+ }
18606
+ let key;
18607
+ let receiver;
18608
+ if (actual.computed) {
18609
+ const index = literalIndex(actual.property);
18610
+ if (index === null) {
18611
+ return null;
18612
+ }
18613
+ key = { kind: "index", index };
18614
+ receiver = actual.object;
18615
+ } else {
18616
+ const access = propertyAccess(actual);
18617
+ if (access === null) return null;
18618
+ key = { kind: "property", path: access.path };
18619
+ receiver = access.receiver;
18620
+ }
18621
+ return assertionExpectation(statement, call, receiver, key, matcher);
18622
+ }
18623
+ function isTestExpect(callee) {
18624
+ const variable = ASTUtils45.findVariable(sourceCode.getScope(callee), callee.name);
18625
+ if (variable !== null && variable.defs.some((definition) => {
18626
+ if (definition.node.type !== AST_NODE_TYPES88.ImportSpecifier) return true;
18627
+ const declaration = definition.node.parent;
18628
+ const imported = definition.node.imported;
18629
+ return declaration.type !== AST_NODE_TYPES88.ImportDeclaration || !["vitest", "@jest/globals", "@playwright/test", "bun:test"].includes(String(declaration.source.value)) || (imported.type === AST_NODE_TYPES88.Identifier ? imported.name : imported.value) !== "expect";
18630
+ })) return false;
18631
+ return true;
18632
+ }
18633
+ function assertionExpectation(statement, call, receiver, key, matcher) {
18634
+ const synthetic = SYNTHETIC_LITERAL_MATCHERS.get(matcher);
18635
+ if (synthetic !== void 0 && call.arguments.length === 0) {
18636
+ return { statement, receiver, key, matcher, expectedText: synthetic, expectedIsLiteral: true };
18637
+ }
18638
+ if (!MERGEABLE_MATCHERS.has(matcher)) {
18639
+ return null;
18640
+ }
18641
+ const expected = call.arguments[0];
18642
+ if (call.arguments.length !== 1 || expected === void 0 || expected.type === AST_NODE_TYPES88.SpreadElement) {
18643
+ return null;
18644
+ }
18645
+ const literal = literalText(expected, (node) => sourceCode.getText(node));
18646
+ return {
18647
+ statement,
18648
+ receiver,
18649
+ key,
18650
+ matcher,
18651
+ expectedText: literal ?? sourceCode.getText(expected),
18652
+ expectedIsLiteral: literal !== null
18653
+ };
18654
+ }
18658
18655
  return {
18659
18656
  BlockStatement: (node) => {
18660
18657
  checkBody(node.body);
@@ -21400,6 +21397,11 @@ var require_use_form_default_values_default = createRule({
21400
21397
  const value = unwrapExpression6(node);
21401
21398
  return value.type === AST_NODE_TYPES98.UnaryExpression && value.operator === "void" || value.type === AST_NODE_TYPES98.Identifier && value.name === "undefined" && (bindingOf(value)?.defs.length ?? 0) === 0;
21402
21399
  };
21400
+ const uninitializedUseFormCall = (node) => {
21401
+ if (node.type !== AST_NODE_TYPES98.CallExpression || node.callee.type !== AST_NODE_TYPES98.Identifier || importedKind(node.callee) !== "useForm") return false;
21402
+ const options = node.arguments[0];
21403
+ return options?.type !== AST_NODE_TYPES98.SpreadElement && initializationState(options) === "uninitialized";
21404
+ };
21403
21405
  const initializationState = (node) => {
21404
21406
  if (node === void 0) return "uninitialized";
21405
21407
  if (node.type !== AST_NODE_TYPES98.ObjectExpression) return "unknown";
@@ -21412,11 +21414,6 @@ var require_use_form_default_values_default = createRule({
21412
21414
  }
21413
21415
  return [...initialization.values()].some(Boolean) ? "initialized" : "uninitialized";
21414
21416
  };
21415
- const uninitializedUseFormCall = (node) => {
21416
- if (node.type !== AST_NODE_TYPES98.CallExpression || node.callee.type !== AST_NODE_TYPES98.Identifier || importedKind(node.callee) !== "useForm") return false;
21417
- const options = node.arguments[0];
21418
- return options?.type !== AST_NODE_TYPES98.SpreadElement && initializationState(options) === "uninitialized";
21419
- };
21420
21417
  const isUninitializedForm = (node) => {
21421
21418
  if (node.type !== AST_NODE_TYPES98.Identifier) return false;
21422
21419
  const variable = bindingOf(node);
@@ -21648,28 +21645,13 @@ var require_zod_form_validation_default = createRule({
21648
21645
  context.sourceCode.getScope(identifier),
21649
21646
  identifier.name
21650
21647
  );
21651
- const isProvablyNonZodLocal = (identifier) => {
21652
- const binding = resolvedBinding(identifier);
21653
- if (binding === null || zodBindings.has(binding) || binding.defs.length !== 1) {
21654
- return false;
21655
- }
21656
- const definition = binding.defs[0];
21657
- if (definition?.type !== "Variable" || definition.node.type !== AST_NODE_TYPES99.VariableDeclarator) {
21658
- return false;
21659
- }
21660
- const init = definition.node.init;
21661
- return init?.type === AST_NODE_TYPES99.ObjectExpression || init?.type === AST_NODE_TYPES99.ArrayExpression || init?.type === AST_NODE_TYPES99.Literal || init?.type === AST_NODE_TYPES99.ArrowFunctionExpression || init?.type === AST_NODE_TYPES99.FunctionExpression;
21662
- };
21663
- const isZodParseCall = (node) => {
21664
- if (node.type !== AST_NODE_TYPES99.CallExpression) return false;
21648
+ const isFormDataGetCall = (node) => {
21665
21649
  const callee = node.callee;
21666
- if (callee.type !== AST_NODE_TYPES99.MemberExpression || callee.computed || callee.property.type !== AST_NODE_TYPES99.Identifier || !ZOD_PARSE_METHODS.has(callee.property.name)) {
21650
+ if (callee.type !== AST_NODE_TYPES99.MemberExpression) return false;
21651
+ if (callee.property.type !== AST_NODE_TYPES99.Identifier || !FORM_VALUE_METHODS.has(callee.property.name)) {
21667
21652
  return false;
21668
21653
  }
21669
- const root = zodReceiverRoot(callee.object);
21670
- if (root === null) return false;
21671
- const binding = resolvedBinding(root);
21672
- return binding !== null && zodBindings.has(binding) || (root.name === "z" || ZOD_SCHEMA_NAME_RE.test(root.name)) && !isProvablyNonZodLocal(root);
21654
+ return isFormSourceIdentifier(callee.object);
21673
21655
  };
21674
21656
  const isFormSourceIdentifier = (node) => {
21675
21657
  if (node.type !== AST_NODE_TYPES99.Identifier) return false;
@@ -21688,14 +21670,6 @@ var require_zod_form_validation_default = createRule({
21688
21670
  }
21689
21671
  return conventionalName;
21690
21672
  };
21691
- const isFormDataGetCall = (node) => {
21692
- const callee = node.callee;
21693
- if (callee.type !== AST_NODE_TYPES99.MemberExpression) return false;
21694
- if (callee.property.type !== AST_NODE_TYPES99.Identifier || !FORM_VALUE_METHODS.has(callee.property.name)) {
21695
- return false;
21696
- }
21697
- return isFormSourceIdentifier(callee.object);
21698
- };
21699
21673
  const zodParseAncestor = (node) => {
21700
21674
  let parent = node.parent;
21701
21675
  while (parent !== null && parent !== void 0) {
@@ -21713,6 +21687,29 @@ var require_zod_form_validation_default = createRule({
21713
21687
  }
21714
21688
  return null;
21715
21689
  };
21690
+ const isZodParseCall = (node) => {
21691
+ if (node.type !== AST_NODE_TYPES99.CallExpression) return false;
21692
+ const callee = node.callee;
21693
+ if (callee.type !== AST_NODE_TYPES99.MemberExpression || callee.computed || callee.property.type !== AST_NODE_TYPES99.Identifier || !ZOD_PARSE_METHODS.has(callee.property.name)) {
21694
+ return false;
21695
+ }
21696
+ const root = zodReceiverRoot(callee.object);
21697
+ if (root === null) return false;
21698
+ const binding = resolvedBinding(root);
21699
+ return binding !== null && zodBindings.has(binding) || (root.name === "z" || ZOD_SCHEMA_NAME_RE.test(root.name)) && !isProvablyNonZodLocal(root);
21700
+ };
21701
+ const isProvablyNonZodLocal = (identifier) => {
21702
+ const binding = resolvedBinding(identifier);
21703
+ if (binding === null || zodBindings.has(binding) || binding.defs.length !== 1) {
21704
+ return false;
21705
+ }
21706
+ const definition = binding.defs[0];
21707
+ if (definition?.type !== "Variable" || definition.node.type !== AST_NODE_TYPES99.VariableDeclarator) {
21708
+ return false;
21709
+ }
21710
+ const init = definition.node.init;
21711
+ return init?.type === AST_NODE_TYPES99.ObjectExpression || init?.type === AST_NODE_TYPES99.ArrayExpression || init?.type === AST_NODE_TYPES99.Literal || init?.type === AST_NODE_TYPES99.ArrowFunctionExpression || init?.type === AST_NODE_TYPES99.FunctionExpression;
21712
+ };
21716
21713
  const hasZodParseAncestor = (node) => zodParseAncestor(node) !== null;
21717
21714
  const isInstanceofNarrowing = (node) => {
21718
21715
  const parent = node.parent;
@@ -21741,28 +21738,6 @@ var require_zod_form_validation_default = createRule({
21741
21738
  }
21742
21739
  return null;
21743
21740
  };
21744
- const zodParseMethod = (call) => {
21745
- const callee = call.callee;
21746
- return callee.type === AST_NODE_TYPES99.MemberExpression && !callee.computed && callee.property.type === AST_NODE_TYPES99.Identifier ? callee.property.name : null;
21747
- };
21748
- const hasConditionalAncestorBeforeStatement = (node, statement) => {
21749
- let current = node.parent;
21750
- while (current !== void 0 && current !== statement) {
21751
- if (current.type === AST_NODE_TYPES99.LogicalExpression || current.type === AST_NODE_TYPES99.ConditionalExpression) {
21752
- return true;
21753
- }
21754
- current = current.parent;
21755
- }
21756
- return false;
21757
- };
21758
- const isAwaitedBeforeStatement = (node, statement) => {
21759
- let current = node.parent;
21760
- while (current !== void 0 && current !== statement) {
21761
- if (current.type === AST_NODE_TYPES99.AwaitExpression) return true;
21762
- current = current.parent;
21763
- }
21764
- return false;
21765
- };
21766
21741
  const guaranteedValidationStatement = (declarator, reference) => {
21767
21742
  const parse2 = zodParseAncestor(reference);
21768
21743
  if (parse2 === null) return null;
@@ -21781,6 +21756,28 @@ var require_zod_form_validation_default = createRule({
21781
21756
  }
21782
21757
  return null;
21783
21758
  };
21759
+ const isAwaitedBeforeStatement = (node, statement) => {
21760
+ let current = node.parent;
21761
+ while (current !== void 0 && current !== statement) {
21762
+ if (current.type === AST_NODE_TYPES99.AwaitExpression) return true;
21763
+ current = current.parent;
21764
+ }
21765
+ return false;
21766
+ };
21767
+ const hasConditionalAncestorBeforeStatement = (node, statement) => {
21768
+ let current = node.parent;
21769
+ while (current !== void 0 && current !== statement) {
21770
+ if (current.type === AST_NODE_TYPES99.LogicalExpression || current.type === AST_NODE_TYPES99.ConditionalExpression) {
21771
+ return true;
21772
+ }
21773
+ current = current.parent;
21774
+ }
21775
+ return false;
21776
+ };
21777
+ const zodParseMethod = (call) => {
21778
+ const callee = call.callee;
21779
+ return callee.type === AST_NODE_TYPES99.MemberExpression && !callee.computed && callee.property.type === AST_NODE_TYPES99.Identifier ? callee.property.name : null;
21780
+ };
21784
21781
  const isSafePrevalidationInspection = (identifier) => {
21785
21782
  const parent = identifier.parent;
21786
21783
  if (parent.type === AST_NODE_TYPES99.UnaryExpression && parent.operator === "typeof") {
@@ -21961,9 +21958,9 @@ var STEPDOWN_DOCUMENTATION = {
21961
21958
  remediation: "Consider moving the private helper below its sole caller after reviewing initialization and reflection dependencies.",
21962
21959
  category: "maintainability",
21963
21960
  limitations: [
21964
- "Generated and test files, cycles, dynamic references, overload targets, and helpers with multiple callers are excluded.",
21961
+ "Generated and test files, cycles, dynamic or escaped references, overload targets, and helpers with multiple callers are excluded; immutable local callable aliases are followed only when every use stays in the caller. Function bodies include nested sibling helpers.",
21965
21962
  "Class helpers must be private; their sole caller may be public, protected, or private.",
21966
- "Runtime class-field, static-block, computed-member, and decorator barriers are never crossed.",
21963
+ "Runtime class-field, static-block, computed-member, and decorator barriers are never crossed; non-hoisted module helpers also cannot cross eager execution or unrelated initialization.",
21967
21964
  "This rule is report-only: reordering methods can change reflective property order, and moving module declarations can change initialization behavior or introduce temporal-dead-zone failures. Review module cycles and eager callers manually."
21968
21965
  ],
21969
21966
  examples: [
@@ -21975,7 +21972,7 @@ function isFunction(node) {
21975
21972
  return node.type === AST_NODE_TYPES100.ArrowFunctionExpression || node.type === AST_NODE_TYPES100.FunctionDeclaration || node.type === AST_NODE_TYPES100.FunctionExpression;
21976
21973
  }
21977
21974
  function reportMisordered(context, candidates, scopeDefinitions, calls, pinned, canMove = () => true) {
21978
- const byName = new Map(scopeDefinitions.map((definition) => [definition.name, definition]));
21975
+ const byName = new Map(scopeDefinitions.map((definition) => [definition.key, definition]));
21979
21976
  const cycles = cycleComponents(calls);
21980
21977
  const callers = /* @__PURE__ */ new Map();
21981
21978
  for (const [caller, callees] of calls) {
@@ -21987,16 +21984,16 @@ function reportMisordered(context, candidates, scopeDefinitions, calls, pinned,
21987
21984
  }
21988
21985
  }
21989
21986
  for (const helper of candidates) {
21990
- const helperCallers = [...callers.get(helper.name) ?? []];
21991
- if (pinned.has(helper.name) || helperCallers.length !== 1) continue;
21987
+ const helperCallers = [...callers.get(helper.key) ?? []];
21988
+ if (pinned.has(helper.key) || helperCallers.length !== 1) continue;
21992
21989
  const callerName2 = helperCallers[0];
21993
- if (callerName2 === void 0 || cycles.has(helper.name) && cycles.get(helper.name) === cycles.get(callerName2)) continue;
21990
+ if (callerName2 === void 0 || cycles.has(helper.key) && cycles.get(helper.key) === cycles.get(callerName2)) continue;
21994
21991
  const caller = byName.get(callerName2);
21995
21992
  if (caller === void 0 || helper.node.range[0] >= caller.node.range[0] || !canMove(helper, caller)) continue;
21996
21993
  context.report({
21997
21994
  node: helper.node,
21998
21995
  messageId: "helperAboveOnlyCaller",
21999
- data: { helper: helper.name, caller: callerName2 }
21996
+ data: { helper: helper.name, caller: caller.name }
22000
21997
  });
22001
21998
  }
22002
21999
  }
@@ -22067,8 +22064,46 @@ function cycleComponents(graph) {
22067
22064
  }
22068
22065
  return components;
22069
22066
  }
22070
- function moduleScope(context, program) {
22067
+ function isErasedExpression(node) {
22068
+ return node.type === AST_NODE_TYPES100.TSAsExpression || node.type === AST_NODE_TYPES100.TSTypeAssertion || node.type === AST_NODE_TYPES100.TSSatisfiesExpression || node.type === AST_NODE_TYPES100.TSNonNullExpression || node.type === AST_NODE_TYPES100.TSInstantiationExpression;
22069
+ }
22070
+ function unwrapExpression7(node) {
22071
+ let current = node;
22072
+ while (isErasedExpression(current)) current = current.expression;
22073
+ return current;
22074
+ }
22075
+ function wrappedExpression(node) {
22076
+ let current = node;
22077
+ while (current.parent !== void 0 && isErasedExpression(current.parent) && current.parent.expression === current) current = current.parent;
22078
+ return current;
22079
+ }
22080
+ function enclosingFunction5(context, node) {
22081
+ return [...context.sourceCode.getAncestors(node)].reverse().find(isFunction);
22082
+ }
22083
+ function localCallCount(context, node, owner) {
22084
+ const seen = /* @__PURE__ */ new Set();
22085
+ const pending = [node];
22086
+ let count = 0;
22087
+ while (pending.length > 0) {
22088
+ const current = pending.pop();
22089
+ if (current === void 0 || enclosingFunction5(context, current) !== owner) return null;
22090
+ const expression = wrappedExpression(current);
22091
+ const parent = expression.parent;
22092
+ if (parent?.type === AST_NODE_TYPES100.CallExpression && parent.callee === expression) {
22093
+ count += 1;
22094
+ continue;
22095
+ }
22096
+ if (parent?.type !== AST_NODE_TYPES100.VariableDeclarator || parent.init !== expression || parent.id.type !== AST_NODE_TYPES100.Identifier || parent.parent.type !== AST_NODE_TYPES100.VariableDeclaration || parent.parent.kind !== "const") return null;
22097
+ const variable = context.sourceCode.getDeclaredVariables(parent)[0];
22098
+ if (variable === void 0 || seen.has(variable) || !stableVariable(variable)) return null;
22099
+ seen.add(variable);
22100
+ pending.push(...variable.references.filter((reference) => reference.isRead()).map((reference) => reference.identifier));
22101
+ }
22102
+ return count;
22103
+ }
22104
+ function declarationScope(context, program) {
22071
22105
  const declarations = moduleDefinitions(program);
22106
+ if (declarations.length < 2) return;
22072
22107
  const counts = /* @__PURE__ */ new Map();
22073
22108
  for (const node of declarations) counts.set(node.name, (counts.get(node.name) ?? 0) + 1);
22074
22109
  const overloadNames = new Set(
@@ -22077,11 +22112,31 @@ function moduleScope(context, program) {
22077
22112
  return node?.type === AST_NODE_TYPES100.TSDeclareFunction && node.id !== null ? [node.id.name] : [];
22078
22113
  })
22079
22114
  );
22080
- const exported = exportedNames(program);
22115
+ const exported = program.type === AST_NODE_TYPES100.Program ? exportedNames(program) : /* @__PURE__ */ new Set();
22081
22116
  const scopeDefinitions = declarations.filter((node) => counts.get(node.name) === 1);
22082
22117
  const definitions = scopeDefinitions.filter(
22083
22118
  (definition) => !exported.has(definition.name) && !overloadNames.has(definition.name)
22084
22119
  );
22120
+ const { calls, pinned } = moduleCallGraph(context, scopeDefinitions);
22121
+ const statementIndexes = new Map(program.body.map((statement, index) => [statement, index]));
22122
+ const runtimeBarrierPrefix = [0];
22123
+ for (const statement of program.body) {
22124
+ runtimeBarrierPrefix.push((runtimeBarrierPrefix.at(-1) ?? 0) + (isDeferredModuleStatement(statement) ? 0 : 1));
22125
+ }
22126
+ const canMove = (helper, caller) => {
22127
+ if (helper.node.type === AST_NODE_TYPES100.FunctionDeclaration) return true;
22128
+ const helperIndex = statementIndex(helper);
22129
+ const callerIndex = statementIndex(caller);
22130
+ return helperIndex !== void 0 && callerIndex !== void 0 && runtimeBarrierPrefix[callerIndex + 1] === runtimeBarrierPrefix[helperIndex + 1];
22131
+ };
22132
+ const statementIndex = (definition) => {
22133
+ let current = definition.node;
22134
+ while (current.parent !== void 0 && current.parent !== program) current = current.parent;
22135
+ return statementIndexes.get(current);
22136
+ };
22137
+ reportMisordered(context, definitions, scopeDefinitions, calls, pinned, canMove);
22138
+ }
22139
+ function moduleCallGraph(context, scopeDefinitions) {
22085
22140
  const byFunction = new Map(scopeDefinitions.map((definition) => [definition.functionNode, definition]));
22086
22141
  const calls = /* @__PURE__ */ new Map();
22087
22142
  const pinned = /* @__PURE__ */ new Set();
@@ -22089,26 +22144,33 @@ function moduleScope(context, program) {
22089
22144
  const variable = context.sourceCode.getDeclaredVariables(definition.bindingNode)[0];
22090
22145
  for (const reference of variable?.references ?? []) {
22091
22146
  if (reference.isWrite() && reference.init !== true) {
22092
- pinned.add(definition.name);
22147
+ pinned.add(definition.key);
22093
22148
  continue;
22094
22149
  }
22095
22150
  if (!reference.isRead()) continue;
22096
- const identifier = reference.identifier;
22097
- const ancestors = context.sourceCode.getAncestors(identifier);
22098
- const nearestFunction2 = [...ancestors].reverse().find(isFunction);
22099
- const parent = identifier.parent;
22100
- const callerDefinition = nearestFunction2 === void 0 ? void 0 : byFunction.get(nearestFunction2);
22101
- if (callerDefinition === void 0 || parent.type !== AST_NODE_TYPES100.CallExpression || parent.callee !== identifier) {
22102
- pinned.add(definition.name);
22151
+ const callerDefinition = byFunction.get(enclosingFunction5(context, reference.identifier));
22152
+ if (callerDefinition?.functionNode === void 0) {
22153
+ pinned.add(definition.key);
22103
22154
  continue;
22104
22155
  }
22105
- const caller = callerDefinition.name;
22106
- const callees = calls.get(caller) ?? /* @__PURE__ */ new Set();
22107
- callees.add(definition.name);
22108
- calls.set(caller, callees);
22156
+ const count = localCallCount(context, reference.identifier, callerDefinition.functionNode);
22157
+ if (count === null) {
22158
+ pinned.add(definition.key);
22159
+ } else if (count > 0) {
22160
+ const callees = calls.get(callerDefinition.key) ?? /* @__PURE__ */ new Set();
22161
+ callees.add(definition.key);
22162
+ calls.set(callerDefinition.key, callees);
22163
+ }
22109
22164
  }
22110
22165
  }
22111
- reportMisordered(context, definitions, scopeDefinitions, calls, pinned);
22166
+ return { calls, pinned };
22167
+ }
22168
+ function isDeferredModuleStatement(statement) {
22169
+ const node = statement.type === AST_NODE_TYPES100.ExportNamedDeclaration || statement.type === AST_NODE_TYPES100.ExportDefaultDeclaration ? statement.declaration : statement;
22170
+ if (node === null || node.type === AST_NODE_TYPES100.FunctionDeclaration || node.type === AST_NODE_TYPES100.TSDeclareFunction || node.type === AST_NODE_TYPES100.TSInterfaceDeclaration || node.type === AST_NODE_TYPES100.TSTypeAliasDeclaration || node.type === AST_NODE_TYPES100.ImportDeclaration || node.type === AST_NODE_TYPES100.ExportAllDeclaration || node.type === AST_NODE_TYPES100.EmptyStatement) return true;
22171
+ return node.type === AST_NODE_TYPES100.VariableDeclaration && node.declarations.every(
22172
+ (declaration) => declaration.id.type === AST_NODE_TYPES100.Identifier && declaration.init !== null && isFunction(unwrapExpression7(declaration.init))
22173
+ );
22112
22174
  }
22113
22175
  function exportedNames(program) {
22114
22176
  const names = /* @__PURE__ */ new Set();
@@ -22142,16 +22204,18 @@ function moduleDefinitions(program) {
22142
22204
  for (const statement of program.body) {
22143
22205
  const node = statement.type === AST_NODE_TYPES100.ExportNamedDeclaration || statement.type === AST_NODE_TYPES100.ExportDefaultDeclaration ? statement.declaration : statement;
22144
22206
  if (node?.type === AST_NODE_TYPES100.FunctionDeclaration && node.id !== null && node.body !== null) {
22145
- definitions.push({ name: node.id.name, node, functionNode: node, bindingNode: node });
22207
+ definitions.push({ key: node.id.name, name: node.id.name, node, functionNode: node, bindingNode: node });
22146
22208
  continue;
22147
22209
  }
22148
- if (node?.type !== AST_NODE_TYPES100.VariableDeclaration || node.kind !== "const") continue;
22210
+ if (node?.type !== AST_NODE_TYPES100.VariableDeclaration || node.kind !== "const" || node.declarations.length !== 1) continue;
22149
22211
  for (const declarator of node.declarations) {
22150
- if (declarator.id.type === AST_NODE_TYPES100.Identifier && declarator.init !== null && isFunction(declarator.init)) {
22212
+ const initializer = declarator.init === null ? null : unwrapExpression7(declarator.init);
22213
+ if (declarator.id.type === AST_NODE_TYPES100.Identifier && initializer !== null && isFunction(initializer)) {
22151
22214
  definitions.push({
22215
+ key: declarator.id.name,
22152
22216
  name: declarator.id.name,
22153
22217
  node: declarator,
22154
- functionNode: declarator.init,
22218
+ functionNode: initializer,
22155
22219
  bindingNode: declarator
22156
22220
  });
22157
22221
  }
@@ -22161,15 +22225,50 @@ function moduleDefinitions(program) {
22161
22225
  }
22162
22226
  function methodName2(node) {
22163
22227
  if (node.key.type === AST_NODE_TYPES100.PrivateIdentifier) return `#${node.key.name}`;
22164
- return !node.computed && node.key.type === AST_NODE_TYPES100.Identifier ? node.key.name : null;
22228
+ if (!node.computed && node.key.type === AST_NODE_TYPES100.Identifier) return node.key.name;
22229
+ return node.key.type === AST_NODE_TYPES100.Literal && typeof node.key.value === "string" ? node.key.value : null;
22165
22230
  }
22166
- function referencedMethod(context, node, classVariables) {
22167
- const objectVariable = node.object.type === AST_NODE_TYPES100.Identifier ? ASTUtils51.findVariable(context.sourceCode.getScope(node.object), node.object.name) : null;
22168
- const isClassReference = objectVariable !== null && classVariables.has(objectVariable);
22169
- if (node.object.type !== AST_NODE_TYPES100.ThisExpression && !isClassReference) return null;
22170
- if (node.property.type === AST_NODE_TYPES100.PrivateIdentifier) return `#${node.property.name}`;
22171
- if (!node.computed && node.property.type === AST_NODE_TYPES100.Identifier) return node.property.name;
22172
- return node.computed && node.property.type === AST_NODE_TYPES100.Literal && typeof node.property.value === "string" ? node.property.value : null;
22231
+ function methodKey(name, isStatic2) {
22232
+ return `${isStatic2 ? "static" : "instance"}:${name}`;
22233
+ }
22234
+ function receiverDomain(context, object, receivers, thisIsStatic) {
22235
+ const unwrapped = unwrapExpression7(object);
22236
+ if (unwrapped.type === AST_NODE_TYPES100.ThisExpression) return thisIsStatic;
22237
+ return externalReceiverDomain(context, unwrapped, receivers);
22238
+ }
22239
+ function externalReceiverDomain(context, object, receivers) {
22240
+ const origin = receiverOrigin(context, object, receivers);
22241
+ if (origin === null || typeof origin === "boolean") return origin;
22242
+ if (origin.type === AST_NODE_TYPES100.NewExpression) {
22243
+ return receiverOrigin(context, origin.callee, receivers) === true ? false : null;
22244
+ }
22245
+ if (origin.type === AST_NODE_TYPES100.ObjectExpression || origin.type === AST_NODE_TYPES100.ArrayExpression || origin.type === AST_NODE_TYPES100.Literal || origin.type === AST_NODE_TYPES100.ArrowFunctionExpression || origin.type === AST_NODE_TYPES100.FunctionExpression) return "unrelated";
22246
+ return null;
22247
+ }
22248
+ function receiverOrigin(context, object, receivers) {
22249
+ let current = object;
22250
+ const seen = /* @__PURE__ */ new Set();
22251
+ while (true) {
22252
+ const unwrapped = unwrapExpression7(current);
22253
+ if (unwrapped.type !== AST_NODE_TYPES100.Identifier) return unwrapped;
22254
+ const variable = ASTUtils51.findVariable(context.sourceCode.getScope(unwrapped), unwrapped.name);
22255
+ if (variable === null) return null;
22256
+ const known = receivers.get(variable);
22257
+ if (known !== void 0) return known;
22258
+ const initializer = immutableInitializer(variable, seen);
22259
+ if (initializer === null) return null;
22260
+ current = initializer;
22261
+ }
22262
+ }
22263
+ function immutableInitializer(variable, seen) {
22264
+ if (seen.has(variable) || !stableVariable(variable) || variable.defs.length !== 1) return null;
22265
+ seen.add(variable);
22266
+ const definition = variable.defs[0];
22267
+ if (definition?.node.type !== AST_NODE_TYPES100.VariableDeclarator || definition.node.parent.type !== AST_NODE_TYPES100.VariableDeclaration || definition.node.parent.kind !== "const") return null;
22268
+ return definition.node.init;
22269
+ }
22270
+ function stableVariable(variable) {
22271
+ return !variable.references.some((reference) => reference.isWrite() && reference.init !== true);
22173
22272
  }
22174
22273
  function referencedPropertyName(node) {
22175
22274
  if (node.property.type === AST_NODE_TYPES100.PrivateIdentifier) return `#${node.property.name}`;
@@ -22178,131 +22277,145 @@ function referencedPropertyName(node) {
22178
22277
  }
22179
22278
  function walk(node, visitorKeys, visit, nestedFunction = false) {
22180
22279
  visit(node, nestedFunction);
22181
- const nested = nestedFunction || isFunction(node);
22280
+ const nested = nestedFunction || isFunction(node) || node.type === AST_NODE_TYPES100.ClassDeclaration || node.type === AST_NODE_TYPES100.ClassExpression;
22182
22281
  forEachAstChild(node, visitorKeys, (child) => walk(child, visitorKeys, visit, nested));
22183
22282
  }
22184
- function classScope(context, node, computedReferenceNames) {
22283
+ function classScope(context, node, computedReferences) {
22185
22284
  const methods = node.body.body.filter(
22186
22285
  (member) => member.type === AST_NODE_TYPES100.MethodDefinition
22187
22286
  );
22188
22287
  const counts = classMethodCounts(node.body, methods);
22189
- const scopeDefinitions = methods.flatMap((method) => {
22190
- const name = methodName2(method);
22191
- return name !== null && counts.get(name) === 1 ? [{ name, node: method }] : [];
22192
- });
22193
- const definitions = methods.flatMap((method) => {
22288
+ const implementations = methods.filter((method) => isFunction(method.value));
22289
+ const implementationCounts = classMethodCounts(node.body, implementations);
22290
+ const scopeDefinitions = implementations.flatMap((method) => {
22194
22291
  const name = methodName2(method);
22195
- const isPrivate = method.accessibility === "private" || method.key.type === AST_NODE_TYPES100.PrivateIdentifier;
22196
- return name !== null && isPrivate && counts.get(name) === 1 && method.decorators.length === 0 ? [{ name, node: method }] : [];
22292
+ const key = name === null ? null : methodKey(name, method.static);
22293
+ return name !== null && key !== null && implementationCounts.get(key) === 1 ? [{ key, name, node: method }] : [];
22197
22294
  });
22295
+ const definitions = scopeDefinitions.filter(
22296
+ ({ key, node: method }) => (method.accessibility === "private" || method.key.type === AST_NODE_TYPES100.PrivateIdentifier) && counts.get(key) === 1 && method.decorators.length === 0 && !method.computed && method.kind === "method"
22297
+ );
22198
22298
  if (definitions.length === 0) return;
22199
- const privateNames = new Set(definitions.map((definition) => definition.name));
22299
+ const methodKeys = new Set(scopeDefinitions.map((definition) => definition.key));
22200
22300
  const calls = /* @__PURE__ */ new Map();
22201
22301
  const pinned = /* @__PURE__ */ new Set();
22202
- const classVariables = /* @__PURE__ */ new Set();
22203
- if (node.id !== null) {
22204
- const internal = ASTUtils51.findVariable(context.sourceCode.getScope(node), node.id.name);
22205
- if (internal !== null) classVariables.add(internal);
22206
- }
22207
- if (node.type === AST_NODE_TYPES100.ClassExpression && node.parent.type === AST_NODE_TYPES100.VariableDeclarator && node.parent.id.type === AST_NODE_TYPES100.Identifier) {
22208
- const outer = ASTUtils51.findVariable(context.sourceCode.getScope(node.parent), node.parent.id.name);
22209
- if (outer !== null) classVariables.add(outer);
22302
+ const classReceivers = classReceiverBindings(context, node);
22303
+ const pinNames = (name, domain = null) => {
22304
+ for (const definition of definitions) {
22305
+ if ((name === null || definition.name === name) && (domain === null || definition.node.static === domain)) {
22306
+ pinned.add(definition.key);
22307
+ }
22308
+ }
22309
+ };
22310
+ function pinDestructuredMembers(binding, domain) {
22311
+ for (const property of binding.properties) {
22312
+ if (property.type === AST_NODE_TYPES100.RestElement || property.computed) {
22313
+ pinNames(null, domain);
22314
+ } else if (property.key.type === AST_NODE_TYPES100.Identifier) {
22315
+ pinNames(property.key.name, domain);
22316
+ } else if (property.key.type === AST_NODE_TYPES100.Literal && typeof property.key.value === "string") {
22317
+ pinNames(property.key.value, domain);
22318
+ }
22319
+ }
22210
22320
  }
22211
22321
  function collectMethodCalls(method) {
22212
- const caller = methodName2(method);
22213
- if (caller === null || method.value.body === null) return;
22214
- const methodClassVariables = new Set(classVariables);
22215
- const methodAliases = /* @__PURE__ */ new Set();
22322
+ const name = methodName2(method);
22323
+ if (name === null) {
22324
+ pinNames(null);
22325
+ return;
22326
+ }
22327
+ if (!isFunction(method.value)) return;
22328
+ const methodFunction = method.value;
22329
+ const caller = methodKey(name, method.static);
22330
+ const receivers = new Map(classReceivers);
22216
22331
  const parameterDecoratorNodes = /* @__PURE__ */ new Set();
22217
22332
  for (const parameter of method.value.params) {
22218
22333
  for (const decorator of parameter.decorators) {
22219
22334
  walk(decorator, context.sourceCode.visitorKeys, (current) => parameterDecoratorNodes.add(current));
22220
22335
  }
22221
22336
  }
22222
- const thisValue = (value) => {
22223
- let current = value;
22224
- while (current?.type === AST_NODE_TYPES100.TSAsExpression || current?.type === AST_NODE_TYPES100.TSSatisfiesExpression || current?.type === AST_NODE_TYPES100.TSNonNullExpression) current = current.expression;
22225
- return current?.type === AST_NODE_TYPES100.ThisExpression;
22226
- };
22227
22337
  const collectAlias = (current, nestedFunction) => {
22228
- if (nestedFunction || current.type !== AST_NODE_TYPES100.VariableDeclarator && current.type !== AST_NODE_TYPES100.AssignmentPattern) return;
22229
- if (current.type === AST_NODE_TYPES100.VariableDeclarator && (current.parent.type !== AST_NODE_TYPES100.VariableDeclaration || current.parent.kind !== "const")) return;
22230
- const binding = current.type === AST_NODE_TYPES100.VariableDeclarator ? current.id : current.left;
22231
- const value = current.type === AST_NODE_TYPES100.VariableDeclarator ? current.init : current.right;
22232
- if (!thisValue(value)) return;
22233
- if (binding.type === AST_NODE_TYPES100.ObjectPattern) {
22234
- pinDestructuredMembers(binding);
22338
+ if (nestedFunction || current.type !== AST_NODE_TYPES100.VariableDeclarator || current.init === null) return;
22339
+ const domain = receiverDomain(context, current.init, receivers, method.static);
22340
+ if (domain === null || domain === "unrelated") return;
22341
+ if (current.id.type === AST_NODE_TYPES100.ObjectPattern) {
22342
+ pinDestructuredMembers(current.id, domain);
22235
22343
  return;
22236
22344
  }
22237
- if (binding.type !== AST_NODE_TYPES100.Identifier) return;
22238
- const variable = ASTUtils51.findVariable(context.sourceCode.getScope(binding), binding.name);
22239
- if (variable !== null) {
22240
- methodClassVariables.add(variable);
22241
- methodAliases.add(variable);
22345
+ if (current.id.type !== AST_NODE_TYPES100.Identifier) return;
22346
+ if (current.parent.type !== AST_NODE_TYPES100.VariableDeclaration || current.parent.kind !== "const") {
22347
+ pinNames(null, domain);
22348
+ return;
22242
22349
  }
22350
+ const variable = context.sourceCode.getDeclaredVariables(current)[0];
22351
+ if (variable === void 0 || !stableVariable(variable)) return;
22352
+ const local = variable.references.every((reference) => {
22353
+ if (!reference.isRead()) return true;
22354
+ const expression = wrappedExpression(reference.identifier);
22355
+ return enclosingFunction5(context, reference.identifier) === methodFunction && expression.parent?.type === AST_NODE_TYPES100.MemberExpression && expression.parent.object === expression;
22356
+ });
22357
+ if (local) receivers.set(variable, domain);
22358
+ else pinNames(null, domain);
22243
22359
  };
22244
- for (const parameter of method.value.params) {
22245
- walk(parameter, context.sourceCode.visitorKeys, collectAlias);
22246
- }
22247
- for (const statement of method.value.body.body) {
22248
- walk(statement, context.sourceCode.visitorKeys, collectAlias);
22249
- }
22250
- function pinDestructuredMembers(binding) {
22251
- for (const property of binding.properties) {
22252
- if (property.type === AST_NODE_TYPES100.RestElement) {
22253
- for (const name of privateNames) pinned.add(name);
22254
- } else if (property.key.type === AST_NODE_TYPES100.Identifier && privateNames.has(property.key.name)) {
22255
- pinned.add(property.key.name);
22256
- }
22257
- }
22258
- }
22360
+ for (const statement of method.value.body.body) walk(statement, context.sourceCode.visitorKeys, collectAlias);
22259
22361
  const visitCall = (current, nestedFunction) => {
22260
- if (current.type === AST_NODE_TYPES100.VariableDeclarator && current.id.type === AST_NODE_TYPES100.ObjectPattern && thisValue(current.init)) {
22261
- pinDestructuredMembers(current.id);
22362
+ const destructuring = receiverDestructuring(current);
22363
+ if (destructuring !== null) {
22364
+ const domain2 = receiverDomain(context, destructuring.value, receivers, method.static);
22365
+ if (domain2 !== "unrelated") pinDestructuredMembers(destructuring.binding, domain2);
22262
22366
  }
22263
22367
  if (current.type !== AST_NODE_TYPES100.MemberExpression) return;
22264
- const target = referencedMethod(context, current, methodClassVariables);
22265
- if (target === null) {
22266
- const possibleTarget = referencedPropertyName(current);
22267
- if (possibleTarget !== null && privateNames.has(possibleTarget)) pinned.add(possibleTarget);
22368
+ const domain = receiverDomain(context, current.object, receivers, method.static);
22369
+ const targetName = referencedPropertyName(current);
22370
+ if (domain === "unrelated") return;
22371
+ if (domain === null) {
22372
+ pinNames(targetName);
22268
22373
  return;
22269
22374
  }
22270
- if (!privateNames.has(target)) return;
22271
- const objectVariable = current.object.type === AST_NODE_TYPES100.Identifier ? ASTUtils51.findVariable(context.sourceCode.getScope(current.object), current.object.name) : null;
22272
- if (objectVariable !== null && methodAliases.has(objectVariable)) {
22273
- pinned.add(target);
22375
+ if (targetName === null) {
22376
+ if (current.computed) pinNames(null, domain);
22274
22377
  return;
22275
22378
  }
22276
- if (current.computed || nestedFunction || parameterDecoratorNodes.has(current) || current.parent.type !== AST_NODE_TYPES100.CallExpression || current.parent.callee !== current) {
22379
+ const target = methodKey(targetName, domain);
22380
+ if (!methodKeys.has(target)) return;
22381
+ if (current.computed || nestedFunction || parameterDecoratorNodes.has(current)) {
22277
22382
  pinned.add(target);
22278
22383
  return;
22279
22384
  }
22280
- const callees = calls.get(caller) ?? /* @__PURE__ */ new Set();
22281
- callees.add(target);
22282
- calls.set(caller, callees);
22385
+ const count = localCallCount(context, current, methodFunction);
22386
+ if (count === null) {
22387
+ pinned.add(target);
22388
+ } else if (count > 0) {
22389
+ const callees = calls.get(caller) ?? /* @__PURE__ */ new Set();
22390
+ callees.add(target);
22391
+ calls.set(caller, callees);
22392
+ }
22283
22393
  };
22284
- for (const decorator of method.decorators) {
22285
- walk(decorator, context.sourceCode.visitorKeys, visitCall, true);
22286
- }
22394
+ for (const decorator of method.decorators) walk(decorator, context.sourceCode.visitorKeys, visitCall, true);
22287
22395
  if (method.computed) walk(method.key, context.sourceCode.visitorKeys, visitCall, true);
22288
- for (const parameter of method.value.params) {
22289
- walk(parameter, context.sourceCode.visitorKeys, visitCall);
22290
- }
22291
- for (const statement of method.value.body.body) {
22292
- walk(statement, context.sourceCode.visitorKeys, visitCall);
22293
- }
22396
+ for (const parameter of method.value.params) walk(parameter, context.sourceCode.visitorKeys, visitCall);
22397
+ for (const statement of method.value.body.body) walk(statement, context.sourceCode.visitorKeys, visitCall);
22294
22398
  }
22295
22399
  for (const method of methods) collectMethodCalls(method);
22296
22400
  for (const member of node.body.body) {
22297
22401
  if (member.type === AST_NODE_TYPES100.MethodDefinition || member.type === AST_NODE_TYPES100.TSAbstractMethodDefinition) continue;
22298
22402
  walk(member, context.sourceCode.visitorKeys, (current) => {
22299
22403
  if (current.type !== AST_NODE_TYPES100.MemberExpression) return;
22300
- const target = referencedMethod(context, current, classVariables);
22301
- const possibleTarget = target ?? referencedPropertyName(current);
22302
- if (possibleTarget !== null && privateNames.has(possibleTarget)) pinned.add(possibleTarget);
22404
+ if (externalReceiverDomain(context, current.object, classReceivers) === "unrelated") return;
22405
+ pinNames(referencedPropertyName(current));
22303
22406
  });
22304
22407
  }
22305
- for (const name of privateNames) if (computedReferenceNames.has(name)) pinned.add(name);
22408
+ const externalReceivers = new Map(classReceivers);
22409
+ for (const variable of context.sourceCode.getDeclaredVariables(node)) {
22410
+ if (stableVariable(variable)) externalReceivers.set(variable, true);
22411
+ }
22412
+ for (const reference of computedReferences) {
22413
+ if (context.sourceCode.getAncestors(reference).includes(node)) continue;
22414
+ const domain = externalReceiverDomain(context, reference.object, externalReceivers);
22415
+ if (domain === "unrelated") continue;
22416
+ const name = referencedPropertyName(reference);
22417
+ if (name !== null || domain !== null) pinNames(name, domain);
22418
+ }
22306
22419
  const memberIndexes = new Map(node.body.body.map((member, index) => [member, index]));
22307
22420
  const runtimeBarrierPrefix = [0];
22308
22421
  for (const member of node.body.body) {
@@ -22316,6 +22429,27 @@ function classScope(context, node, computedReferenceNames) {
22316
22429
  };
22317
22430
  reportMisordered(context, definitions, scopeDefinitions, calls, pinned, canMove);
22318
22431
  }
22432
+ function classReceiverBindings(context, node) {
22433
+ const classReceivers = /* @__PURE__ */ new Map();
22434
+ if (node.id !== null) {
22435
+ const internal = ASTUtils51.findVariable(context.sourceCode.getScope(node), node.id.name);
22436
+ if (internal !== null && stableVariable(internal)) classReceivers.set(internal, true);
22437
+ }
22438
+ if (node.type === AST_NODE_TYPES100.ClassExpression && node.parent.type === AST_NODE_TYPES100.VariableDeclarator && node.parent.id.type === AST_NODE_TYPES100.Identifier && node.parent.parent.type === AST_NODE_TYPES100.VariableDeclaration && node.parent.parent.kind === "const") {
22439
+ const outer = ASTUtils51.findVariable(context.sourceCode.getScope(node.parent), node.parent.id.name);
22440
+ if (outer !== null && stableVariable(outer)) classReceivers.set(outer, true);
22441
+ }
22442
+ return classReceivers;
22443
+ }
22444
+ function receiverDestructuring(node) {
22445
+ if (node.type === AST_NODE_TYPES100.VariableDeclarator && node.id.type === AST_NODE_TYPES100.ObjectPattern && node.init !== null) {
22446
+ return { binding: node.id, value: node.init };
22447
+ }
22448
+ if ((node.type === AST_NODE_TYPES100.AssignmentPattern || node.type === AST_NODE_TYPES100.AssignmentExpression) && node.left.type === AST_NODE_TYPES100.ObjectPattern) {
22449
+ return { binding: node.left, value: node.right };
22450
+ }
22451
+ return null;
22452
+ }
22319
22453
  function isClassRuntimeBarrier(member) {
22320
22454
  switch (member.type) {
22321
22455
  case AST_NODE_TYPES100.StaticBlock:
@@ -22344,6 +22478,7 @@ var stepdown_default = createRule({
22344
22478
  create(context) {
22345
22479
  if (isTestFile(context.filename) || isGeneratedFile(context.filename, context.sourceCode.text)) return {};
22346
22480
  const classes = [];
22481
+ const functionBodies = [];
22347
22482
  return {
22348
22483
  ClassDeclaration: (node) => {
22349
22484
  classes.push(node);
@@ -22351,13 +22486,17 @@ var stepdown_default = createRule({
22351
22486
  ClassExpression: (node) => {
22352
22487
  classes.push(node);
22353
22488
  },
22489
+ "FunctionDeclaration, FunctionExpression, ArrowFunctionExpression": (node) => {
22490
+ if (isFunction(node) && node.body?.type === AST_NODE_TYPES100.BlockStatement) functionBodies.push(node.body);
22491
+ },
22354
22492
  "Program:exit": (program) => {
22355
- moduleScope(context, program);
22356
- const computedReferenceNames = /* @__PURE__ */ new Set();
22493
+ declarationScope(context, program);
22494
+ for (const body2 of functionBodies) declarationScope(context, body2);
22495
+ const computedReferences = [];
22357
22496
  walk(program, context.sourceCode.visitorKeys, (node) => {
22358
- if (node.type === AST_NODE_TYPES100.MemberExpression && node.computed && node.property.type === AST_NODE_TYPES100.Literal && typeof node.property.value === "string") computedReferenceNames.add(node.property.value);
22497
+ if (node.type === AST_NODE_TYPES100.MemberExpression && node.computed) computedReferences.push(node);
22359
22498
  });
22360
- for (const node of classes) classScope(context, node, computedReferenceNames);
22499
+ for (const node of classes) classScope(context, node, computedReferences);
22361
22500
  }
22362
22501
  };
22363
22502
  }
@@ -22366,12 +22505,18 @@ function classMethodCounts(body2, methods) {
22366
22505
  const counts = /* @__PURE__ */ new Map();
22367
22506
  for (const method of methods) {
22368
22507
  const name = methodName2(method);
22369
- if (name !== null) counts.set(name, (counts.get(name) ?? 0) + 1);
22508
+ if (name !== null) {
22509
+ const key = methodKey(name, method.static);
22510
+ counts.set(key, (counts.get(key) ?? 0) + 1);
22511
+ }
22370
22512
  }
22371
22513
  for (const member of body2.body) {
22372
22514
  if (member.type !== AST_NODE_TYPES100.TSAbstractMethodDefinition) continue;
22373
22515
  const name = !member.computed && member.key.type === AST_NODE_TYPES100.Identifier ? member.key.name : null;
22374
- if (name !== null) counts.set(name, (counts.get(name) ?? 0) + 1);
22516
+ if (name !== null) {
22517
+ const key = methodKey(name, member.static);
22518
+ counts.set(key, (counts.get(key) ?? 0) + 1);
22519
+ }
22375
22520
  }
22376
22521
  return counts;
22377
22522
  }
@@ -22703,16 +22848,70 @@ function importedAssertionKind(specifier) {
22703
22848
 
22704
22849
  // src/rules/sole-export-matches-filename.ts
22705
22850
  import { AST_NODE_TYPES as AST_NODE_TYPES102 } from "@typescript-eslint/utils";
22851
+
22852
+ // src/rules/_is-framework-entrypoint.ts
22853
+ import { readFileSync as readFileSync3 } from "fs";
22854
+ import { dirname as dirname3, join as join3, relative as relative2 } from "path";
22855
+ var HTTP_METHODS = /* @__PURE__ */ new Set(["GET", "HEAD", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"]);
22856
+ var NEXT_COMPONENT = /^(?:src\/)?app\/(?:.*\/)?(?:page|layout|loading|not-found|template|error|global-error|default|forbidden|unauthorized)\.[jt]sx?$/u;
22857
+ var NEXT_ROUTE = /^(?:src\/)?app\/(?:.*\/)?route\.[jt]s$/u;
22858
+ function isFrameworkEntrypoint(filename, exportKey) {
22859
+ const normalized = filename.replaceAll("\\", "/");
22860
+ if (!/(?:^|\/)(?:app|pages)\/|(?:^|\/)(?:middleware|proxy)\.[jt]s$/u.test(normalized)) return false;
22861
+ const owner = packageOwner(normalized);
22862
+ if (owner === null) return false;
22863
+ const path = relative2(owner.root, normalized).replaceAll("\\", "/");
22864
+ if (declaresFramework(owner.metadata, "next") && isNextEntrypoint(path, exportKey)) return true;
22865
+ return declaresFramework(owner.metadata, "astro") && isAstroEntrypoint(path, exportKey);
22866
+ }
22867
+ function isNextEntrypoint(path, exportKey) {
22868
+ const privateAppFolder = /^(?:src\/)?app\/(?:.*\/)?_[^/]+\//u.test(path);
22869
+ if (!privateAppFolder && NEXT_COMPONENT.test(path) && exportKey === "default") return true;
22870
+ if (!privateAppFolder && NEXT_ROUTE.test(path) && HTTP_METHODS.has(exportKey)) return true;
22871
+ if (/^(?:src\/)?pages\/.*\.[jt]sx?$/u.test(path) && exportKey === "default") return true;
22872
+ const middleware = /^(?:src\/)?(middleware|proxy)\.[jt]s$/u.exec(path);
22873
+ return middleware !== null && (exportKey === "default" || exportKey === middleware[1]);
22874
+ }
22875
+ function isAstroEntrypoint(path, exportKey) {
22876
+ return (
22877
+ // Astro pages implicitly export their rendered component, including when only a routing hook is explicit.
22878
+ /^src\/pages\/.*\.astro$/u.test(path) || /^src\/pages\/.*\.[jt]s$/u.test(path) && (HTTP_METHODS.has(exportKey) || exportKey === "ALL") || /^src\/middleware\.[jt]s$/u.test(path) && exportKey === "onRequest"
22879
+ );
22880
+ }
22881
+ function packageOwner(filename) {
22882
+ let root = dirname3(filename);
22883
+ while (true) {
22884
+ try {
22885
+ return { root, metadata: JSON.parse(readFileSync3(join3(root, "package.json"), "utf8")) };
22886
+ } catch (error) {
22887
+ if (typeof error !== "object" || error === null || !("code" in error) || error.code !== "ENOENT") return null;
22888
+ }
22889
+ const parent = dirname3(root);
22890
+ if (parent === root) return null;
22891
+ root = parent;
22892
+ }
22893
+ }
22894
+ function declaresFramework(metadata, name) {
22895
+ if (typeof metadata !== "object" || metadata === null) return false;
22896
+ for (const section of ["dependencies", "devDependencies", "peerDependencies", "optionalDependencies"]) {
22897
+ const dependencies = Reflect.get(metadata, section);
22898
+ if (typeof dependencies === "object" && dependencies !== null && typeof Reflect.get(dependencies, name) === "string") return true;
22899
+ }
22900
+ return false;
22901
+ }
22902
+
22903
+ // src/rules/sole-export-matches-filename.ts
22706
22904
  var SOLE_EXPORT_MATCHES_FILENAME_DOCUMENTATION = {
22707
- defaultLevel: "warning",
22905
+ defaultLevel: "error",
22708
22906
  summary: "Make a module filename reflect its sole named public runtime export.",
22709
22907
  rationale: "When a module owns one runtime responsibility, matching names make that responsibility directly discoverable.",
22710
- remediation: "Name the module for the exported responsibility, using either the full export name or a clear leading or trailing domain phrase; otherwise colocate genuinely related exports.",
22908
+ remediation: "Name the module for the exported responsibility, using the full kebab-case export name; otherwise colocate genuinely related exports.",
22711
22909
  category: "maintainability",
22712
22910
  limitations: [
22713
- "Framework entrypoints, generic stems covered by no-generic-single-export-module, tests, generated files, anonymous defaults, CommonJS, and re-exports are excluded.",
22714
- "The rule compares the primary filename stem and preserves a single private underscore prefix and conventional suffixes such as .server or .worker. A leading or trailing export-name phrase is accepted only at token boundaries; multi-token stems also tolerate established acronym spelling such as github versus GitHub.",
22715
- "Exported destructuring patterns are excluded rather than undercounted as public exports."
22911
+ "Framework entrypoints, generic stems covered by no-generic-single-export-module, tests, generated files, anonymous defaults, CommonJS, unresolved re-exports, and emission-dependent exports are excluded.",
22912
+ "The rule compares the primary filename stem and preserves a single private underscore prefix and conventional suffixes such as .server or .worker. Supporting types do not exempt a sole runtime export; public runtime aliases count as distinct exports.",
22913
+ "Exported destructuring patterns are excluded rather than undercounted as public exports.",
22914
+ "Next.js and Astro routing exemptions require the nearest package.json to declare the framework, a conventional entrypoint path, and its expected runtime export. Custom routing roots and pageExtensions are not inferred."
22716
22915
  ],
22717
22916
  examples: [
22718
22917
  { id: "matching-class", title: "Match a class and module", outcome: "no-match", files: [{ path: "src/artifact-store.ts", source: "export class ArtifactStore {}" }], focusPath: "src/artifact-store.ts", expectedCount: 0, public: true },
@@ -22720,39 +22919,9 @@ var SOLE_EXPORT_MATCHES_FILENAME_DOCUMENTATION = {
22720
22919
  ]
22721
22920
  };
22722
22921
  var EXCLUDED_STEMS = /* @__PURE__ */ new Set([
22723
- "common",
22724
22922
  "global",
22725
- "helpers",
22726
22923
  "index",
22727
- "layout",
22728
- "loading",
22729
- "middleware",
22730
- "misc",
22731
- "not-found",
22732
- "page",
22733
- "route",
22734
- "shared",
22735
- "template",
22736
- "types",
22737
- "util",
22738
- "utils"
22739
- ]);
22740
- var WEAK_DOMAIN_TOKENS = /* @__PURE__ */ new Set([
22741
- "adapter",
22742
- "client",
22743
- "config",
22744
- "controller",
22745
- "factory",
22746
- "handler",
22747
- "manager",
22748
- "provider",
22749
- "record",
22750
- "repository",
22751
- "router",
22752
- "schema",
22753
- "service",
22754
- "store",
22755
- "worker"
22924
+ "types"
22756
22925
  ]);
22757
22926
  function stem3(filename) {
22758
22927
  const base = filename.replaceAll("\\", "/").split("/").at(-1) ?? "";
@@ -22761,34 +22930,6 @@ function stem3(filename) {
22761
22930
  function kebabCase(name) {
22762
22931
  return name.replace(/([A-Z]{2,})([A-Z][a-z])/gu, "$1-$2").replace(/([a-z0-9])([A-Z])/gu, "$1-$2").replaceAll(/[^a-z0-9]+/giu, "-").replaceAll(/^-+|-+$/gu, "").toLowerCase();
22763
22932
  }
22764
- function reflectsExportName(fileStem, exportedStem) {
22765
- if (fileStem.startsWith("_")) return false;
22766
- const visibleFileStem = fileStem.toLowerCase();
22767
- const fileTokens = visibleFileStem.split("-").filter(Boolean);
22768
- const exportTokens = exportedStem.split("-").filter(Boolean);
22769
- if (fileTokens.length === 0 || exportTokens.length === 0) return false;
22770
- if (fileTokens.length === 1) {
22771
- const [token] = fileTokens;
22772
- return token !== void 0 && token.length >= 4 && !WEAK_DOMAIN_TOKENS.has(token) && (exportTokens[0] === token || exportTokens.at(-1) === token);
22773
- }
22774
- const compactFile = fileTokens.join("");
22775
- if (compactFile.length < 6) return false;
22776
- const boundaryPhrases = /* @__PURE__ */ new Set();
22777
- for (let index = 1; index <= exportTokens.length; index += 1) {
22778
- boundaryPhrases.add(exportTokens.slice(0, index).join(""));
22779
- boundaryPhrases.add(exportTokens.slice(-index).join(""));
22780
- }
22781
- return boundaryPhrases.has(compactFile);
22782
- }
22783
- function declarationExport(statement) {
22784
- const declaration = statement.declaration;
22785
- if (declaration === null || declaration.declare === true) return [];
22786
- if (declaration.type === AST_NODE_TYPES102.ClassDeclaration || declaration.type === AST_NODE_TYPES102.FunctionDeclaration || declaration.type === AST_NODE_TYPES102.TSEnumDeclaration) return declaration.id === null ? [] : [{ name: declaration.id.name, node: declaration }];
22787
- if (declaration.type !== AST_NODE_TYPES102.VariableDeclaration) return [];
22788
- return declaration.declarations.flatMap(
22789
- (item) => item.id.type === AST_NODE_TYPES102.Identifier ? [{ name: item.id.name, node: item }] : []
22790
- );
22791
- }
22792
22933
  var sole_export_matches_filename_default = createRule({
22793
22934
  name: "sole-export-matches-filename",
22794
22935
  documentation: SOLE_EXPORT_MATCHES_FILENAME_DOCUMENTATION,
@@ -22804,64 +22945,25 @@ var sole_export_matches_filename_default = createRule({
22804
22945
  create(context) {
22805
22946
  const fileStem = stem3(context.filename);
22806
22947
  const normalizedFilename = context.filename.replaceAll("\\", "/");
22807
- if (EXCLUDED_STEMS.has(fileStem) || /(?:^|\/)app\/(?:.*\/)?(?:global-)?error\.[jt]sx?$/u.test(normalizedFilename) || normalizedFilename.includes("/pages/") || context.filename.endsWith(".d.ts") || isTestFile(context.filename) || isGeneratedFile(context.filename, context.sourceCode.text)) return {};
22948
+ if (EXCLUDED_STEMS.has(fileStem) || GENERIC_MODULE_STEMS.has(fileStem) || context.filename.endsWith(".d.ts") || isTestFile(context.filename) || isGeneratedFile(context.filename, context.sourceCode.text)) return {};
22949
+ let hasCommonJsExport = false;
22808
22950
  return {
22951
+ "CallExpression, MemberExpression"(node) {
22952
+ if (isCommonJsExportReference(node, context.sourceCode)) hasCommonJsExport = true;
22953
+ },
22809
22954
  "Program:exit"(program) {
22810
- const exports = [];
22811
- const publicExports = /* @__PURE__ */ new Set();
22812
- function collectPublicExport(statement) {
22813
- if (statement.type === AST_NODE_TYPES102.ExportAllDeclaration || statement.type === AST_NODE_TYPES102.ExportNamedDeclaration && statement.source !== null) return false;
22814
- if (statement.type === AST_NODE_TYPES102.ExportDefaultDeclaration) {
22815
- publicExports.add("default");
22816
- const declaration = statement.declaration;
22817
- if ((declaration.type === AST_NODE_TYPES102.ClassDeclaration || declaration.type === AST_NODE_TYPES102.FunctionDeclaration) && declaration.id !== null) exports.push({ name: declaration.id.name, node: declaration });
22818
- else return false;
22819
- }
22820
- if (statement.type !== AST_NODE_TYPES102.ExportNamedDeclaration) return true;
22821
- return collectNamedExport(statement);
22822
- }
22823
- function collectNamedExport(statement) {
22824
- const declaration = statement.declaration;
22825
- if (declaration !== null && "id" in declaration && declaration.id?.type === AST_NODE_TYPES102.Identifier) {
22826
- publicExports.add(declaration.id.name);
22827
- }
22828
- if (declaration?.type === AST_NODE_TYPES102.VariableDeclaration) {
22829
- if (declaration.declarations.some((item) => item.id.type !== AST_NODE_TYPES102.Identifier)) return false;
22830
- for (const item of declaration.declarations) {
22831
- if (item.id.type === AST_NODE_TYPES102.Identifier) publicExports.add(item.id.name);
22832
- }
22833
- }
22834
- for (const specifier of statement.specifiers) {
22835
- const exported = specifier.exported.type === AST_NODE_TYPES102.Identifier ? specifier.exported.name : specifier.exported.value;
22836
- publicExports.add(String(exported));
22837
- }
22838
- if (statement.exportKind === "type") return true;
22839
- exports.push(...declarationExport(statement));
22840
- collectRuntimeSpecifiers(statement);
22841
- return true;
22842
- }
22843
- function collectRuntimeSpecifiers(statement) {
22844
- for (const specifier of statement.specifiers) {
22845
- const exported = specifier.exported.type === AST_NODE_TYPES102.Identifier ? specifier.exported.name : specifier.exported.value;
22846
- publicExports.add(String(exported));
22847
- if (specifier.exportKind === "type") continue;
22848
- if (exported === "default") exports.push({ name: specifier.local.name, node: specifier });
22849
- else exports.push({ name: String(exported), node: specifier });
22850
- }
22851
- }
22852
- for (const statement of program.body) {
22853
- if (!collectPublicExport(statement)) return;
22854
- }
22855
- const unique = new Map(exports.map((item) => [item.name, item]));
22856
- if (unique.size !== 1 || publicExports.size !== 1) return;
22857
- const only = [...unique.values()][0];
22955
+ if (hasCommonJsExport) return;
22956
+ const exports = runtimeExports(program);
22957
+ if (exports.ambiguous || exports.exports.length !== 1) return;
22958
+ const only = exports.exports[0];
22858
22959
  if (only === void 0) return;
22960
+ if (isFrameworkEntrypoint(normalizedFilename, only.key)) return;
22859
22961
  if (only.name === "onRouterTransitionStart" && /(?:^|\/)instrumentation-client\.[jt]s$/u.test(normalizedFilename)) return;
22860
22962
  if (only.name === "collections" && /(?:^|\/)src\/content\.config\.(?:ts|js|mjs)$/u.test(normalizedFilename) && program.body.some((statement) => statement.type === AST_NODE_TYPES102.ImportDeclaration && statement.source.value === "astro:content")) return;
22861
22963
  const exportedStem = kebabCase(only.name);
22862
22964
  if (exportedStem === "") return;
22863
22965
  const expected = `${fileStem.startsWith("_") ? "_" : ""}${exportedStem}`;
22864
- if (expected === fileStem.toLowerCase() || reflectsExportName(fileStem, exportedStem)) return;
22966
+ if (expected === fileStem.toLowerCase()) return;
22865
22967
  context.report({ node: only.node, messageId: "matchSoleExport", data: { exported: only.name, expected } });
22866
22968
  }
22867
22969
  };
@@ -23079,7 +23181,7 @@ var chainMemberNames2 = (node) => {
23079
23181
  names.reverse();
23080
23182
  return names;
23081
23183
  };
23082
- var unwrapExpression7 = (node) => {
23184
+ var unwrapExpression8 = (node) => {
23083
23185
  let current = node;
23084
23186
  while (current.type === AST_NODE_TYPES103.TSAsExpression || current.type === AST_NODE_TYPES103.TSSatisfiesExpression || current.type === AST_NODE_TYPES103.TSNonNullExpression || current.type === AST_NODE_TYPES103.TSTypeAssertion) {
23085
23187
  current = current.expression;
@@ -23119,18 +23221,8 @@ var require_pascal_case_zod_schema_name_default = createRule({
23119
23221
  const binding = resolvedBinding(identifier);
23120
23222
  if (binding !== null) zodBindings.add(binding);
23121
23223
  }
23122
- function isZodChain(node) {
23123
- const root = calleeChainRoot2(node);
23124
- if (root === null) return false;
23125
- const binding = resolvedBinding(root);
23126
- return binding !== null && zodBindings.has(binding);
23127
- }
23128
- function isSchemaBinding(identifier) {
23129
- const binding = resolvedBinding(identifier);
23130
- return binding !== null && schemaBindings.has(binding);
23131
- }
23132
23224
  function isConfirmedSchema(expression) {
23133
- const init = unwrapExpression7(expression);
23225
+ const init = unwrapExpression8(expression);
23134
23226
  if (init.type === AST_NODE_TYPES103.Identifier) return isSchemaBinding(init);
23135
23227
  if (init.type !== AST_NODE_TYPES103.CallExpression || init.callee.type !== AST_NODE_TYPES103.MemberExpression) {
23136
23228
  return false;
@@ -23145,6 +23237,16 @@ var require_pascal_case_zod_schema_name_default = createRule({
23145
23237
  const root = calleeChainRoot2(init.callee);
23146
23238
  return root !== null && isSchemaBinding(root) && SCHEMA_RETURNING_METHODS.has(terminal);
23147
23239
  }
23240
+ function isSchemaBinding(identifier) {
23241
+ const binding = resolvedBinding(identifier);
23242
+ return binding !== null && schemaBindings.has(binding);
23243
+ }
23244
+ function isZodChain(node) {
23245
+ const root = calleeChainRoot2(node);
23246
+ if (root === null) return false;
23247
+ const binding = resolvedBinding(root);
23248
+ return binding !== null && zodBindings.has(binding);
23249
+ }
23148
23250
  if (isTestFile(context.filename) || BENCHMARK_PATH_RE2.test(context.filename.replaceAll("\\", "/")) || isGeneratedFile(context.filename, context.sourceCode.text)) {
23149
23251
  return {};
23150
23252
  }
@@ -23175,7 +23277,7 @@ var require_pascal_case_zod_schema_name_default = createRule({
23175
23277
  }
23176
23278
  });
23177
23279
 
23178
- // src/rules/_renames.ts
23280
+ // src/rules/_renamed-rules.ts
23179
23281
  var RENAMED_RULES = {
23180
23282
  "jsdoc-restates-signature": "no-restated-jsdoc",
23181
23283
  "zod-naming-convention": "require-pascal-case-zod-schema-name",
@@ -23184,7 +23286,7 @@ var RENAMED_RULES = {
23184
23286
  "trailing-value-narration": "no-trailing-value-narration"
23185
23287
  };
23186
23288
 
23187
- // src/rules/_retired.ts
23289
+ // src/rules/_retired-rules.ts
23188
23290
  var RETIRED_RULES = {
23189
23291
  "ban-loose-type-guards-in-tests": {
23190
23292
  removedIn: "5.0.0",
@@ -23376,7 +23478,7 @@ var RULES = {
23376
23478
  };
23377
23479
  var meta = {
23378
23480
  name: "@sarj/eslint-plugin",
23379
- version: "15.28.1"
23481
+ version: "16.1.0"
23380
23482
  };
23381
23483
  var APPLICATION_ONLY_RULES = [];
23382
23484
  var LIBRARY_IMPORT_POLICY = ["error", {
@@ -23401,8 +23503,7 @@ var ADVISORY_RULES = [
23401
23503
  "@sarj/prefer-whole-object-assertion",
23402
23504
  "@sarj/require-camelcase-properties",
23403
23505
  "@sarj/require-interface-for-exported-class",
23404
- "@sarj/require-sql-access-class",
23405
- "@sarj/sole-export-matches-filename"
23506
+ "@sarj/require-sql-access-class"
23406
23507
  ];
23407
23508
  var RECOMMENDED_RULES = {
23408
23509
  "@sarj/no-conditional-empty-object-spread": "error",
@@ -23514,7 +23615,7 @@ var RECOMMENDED_RULES = {
23514
23615
  "@sarj/store-insert-requires-on-conflict": "error",
23515
23616
  "@sarj/stepdown": "error",
23516
23617
  "@sarj/source-coupled-test": "error",
23517
- "@sarj/sole-export-matches-filename": "warn",
23618
+ "@sarj/sole-export-matches-filename": "error",
23518
23619
  "@sarj/test-phase-label-comment": "error",
23519
23620
  "@sarj/require-pascal-case-zod-schema-name": "error"
23520
23621
  };
@@ -23632,7 +23733,7 @@ var STRICT_RULES = {
23632
23733
  "@sarj/store-insert-requires-on-conflict": "error",
23633
23734
  "@sarj/stepdown": "error",
23634
23735
  "@sarj/source-coupled-test": "error",
23635
- "@sarj/sole-export-matches-filename": "warn",
23736
+ "@sarj/sole-export-matches-filename": "error",
23636
23737
  "@sarj/test-phase-label-comment": "error",
23637
23738
  "@sarj/require-pascal-case-zod-schema-name": "error"
23638
23739
  };
@@ -23655,7 +23756,7 @@ var PLUGIN = {
23655
23756
  };
23656
23757
  }
23657
23758
  };
23658
- var index_default = PLUGIN;
23759
+ var src_default = PLUGIN;
23659
23760
  export {
23660
23761
  ADVISORY_RULES,
23661
23762
  APPLICATION_ONLY_RULES,
@@ -23666,7 +23767,7 @@ export {
23666
23767
  STRICT_RULES,
23667
23768
  ADVISORY_RULES as advisoryRules,
23668
23769
  APPLICATION_ONLY_RULES as applicationOnlyRules,
23669
- index_default as default,
23770
+ src_default as default,
23670
23771
  publicDocumentation,
23671
23772
  RECOMMENDED_RULES as recommendedRules,
23672
23773
  RENAMED_RULES as renamedRules,