@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.cjs CHANGED
@@ -28,8 +28,8 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
28
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
29
 
30
30
  // src/index.ts
31
- var index_exports = {};
32
- __export(index_exports, {
31
+ var src_exports = {};
32
+ __export(src_exports, {
33
33
  ADVISORY_RULES: () => ADVISORY_RULES,
34
34
  APPLICATION_ONLY_RULES: () => APPLICATION_ONLY_RULES,
35
35
  RECOMMENDED_RULES: () => RECOMMENDED_RULES,
@@ -39,7 +39,7 @@ __export(index_exports, {
39
39
  STRICT_RULES: () => STRICT_RULES,
40
40
  advisoryRules: () => ADVISORY_RULES,
41
41
  applicationOnlyRules: () => APPLICATION_ONLY_RULES,
42
- default: () => index_default,
42
+ default: () => src_default,
43
43
  publicDocumentation: () => publicDocumentation,
44
44
  recommendedRules: () => RECOMMENDED_RULES,
45
45
  renamedRules: () => RENAMED_RULES,
@@ -47,7 +47,7 @@ __export(index_exports, {
47
47
  rules: () => RULES,
48
48
  strictRules: () => STRICT_RULES
49
49
  });
50
- module.exports = __toCommonJS(index_exports);
50
+ module.exports = __toCommonJS(src_exports);
51
51
 
52
52
  // src/rules/no-conditional-empty-object-spread.ts
53
53
  var import_utils2 = require("@typescript-eslint/utils");
@@ -489,8 +489,8 @@ var prefer_typed_reflection_default = createRule({
489
489
  const services = import_utils3.ESLintUtils.getParserServices(context);
490
490
  if (!services.program) return {};
491
491
  const checker = services.program.getTypeChecker();
492
- const globalName = (node, name) => node.type === import_utils3.AST_NODE_TYPES.Identifier && node.name === name && !import_utils3.ASTUtils.findVariable(context.sourceCode.getScope(node), name)?.defs.length;
493
492
  const isReflect = (node) => globalName(node, "Reflect") || node.type === import_utils3.AST_NODE_TYPES.MemberExpression && propertyName(node) === "Reflect" && globalName(node.object, "globalThis");
493
+ const globalName = (node, name) => node.type === import_utils3.AST_NODE_TYPES.Identifier && node.name === name && !import_utils3.ASTUtils.findVariable(context.sourceCode.getScope(node), name)?.defs.length;
494
494
  const closedObject = (type) => {
495
495
  if (type.isUnion()) return type.types.every(closedObject);
496
496
  return knownType(type) && type.getProperties().length > 0 && checker.getIndexInfosOfType(type).length === 0;
@@ -727,6 +727,14 @@ var no_reduce_accumulator_copy_default = createRule({
727
727
  const accumulator = context.sourceCode.getDeclaredVariables(callback).find((variable) => variable.identifiers.includes(parameter));
728
728
  if (!accumulator || accumulator.references.some((reference) => reference.isWrite())) return;
729
729
  const referencesAccumulator = (value) => value.type === import_utils5.AST_NODE_TYPES.Identifier && import_utils5.ASTUtils.findVariable(context.sourceCode.getScope(value), value.name) === accumulator;
730
+ const inspect = (current) => {
731
+ if (current !== callback.body && [import_utils5.AST_NODE_TYPES.ArrowFunctionExpression, import_utils5.AST_NODE_TYPES.FunctionExpression, import_utils5.AST_NODE_TYPES.FunctionDeclaration].some((kind) => kind === current.type)) return;
732
+ if (current.type === import_utils5.AST_NODE_TYPES.SpreadElement && (arraySeed && current.parent.type === import_utils5.AST_NODE_TYPES.ArrayExpression || objectSeed && current.parent.type === import_utils5.AST_NODE_TYPES.ObjectExpression) && referencesAccumulator(current.argument)) {
733
+ context.report({ node: current, messageId: "copy" });
734
+ }
735
+ if (current.type === import_utils5.AST_NODE_TYPES.CallExpression) inspectCall(current);
736
+ forEachAstChild(current, context.sourceCode.visitorKeys, inspect);
737
+ };
730
738
  const inspectCall = (current) => {
731
739
  if (current.callee.type !== import_utils5.AST_NODE_TYPES.MemberExpression) return;
732
740
  const member = current.callee;
@@ -739,14 +747,6 @@ var no_reduce_accumulator_copy_default = createRule({
739
747
  const assignCopy = objectSeed && name === "assign" && globalObject && target?.type === import_utils5.AST_NODE_TYPES.ObjectExpression && current.arguments.slice(1).some(referencesAccumulator);
740
748
  if (directCopy || fromCopy || assignCopy) context.report({ node: current, messageId: "copy" });
741
749
  };
742
- const inspect = (current) => {
743
- if (current !== callback.body && [import_utils5.AST_NODE_TYPES.ArrowFunctionExpression, import_utils5.AST_NODE_TYPES.FunctionExpression, import_utils5.AST_NODE_TYPES.FunctionDeclaration].some((kind) => kind === current.type)) return;
744
- if (current.type === import_utils5.AST_NODE_TYPES.SpreadElement && (arraySeed && current.parent.type === import_utils5.AST_NODE_TYPES.ArrayExpression || objectSeed && current.parent.type === import_utils5.AST_NODE_TYPES.ObjectExpression) && referencesAccumulator(current.argument)) {
745
- context.report({ node: current, messageId: "copy" });
746
- }
747
- if (current.type === import_utils5.AST_NODE_TYPES.CallExpression) inspectCall(current);
748
- forEachAstChild(current, context.sourceCode.visitorKeys, inspect);
749
- };
750
750
  inspect(callback.body);
751
751
  }
752
752
  };
@@ -3650,28 +3650,6 @@ var no_cors_wildcard_with_credentials_default = createRule({
3650
3650
  const scopeHeaderSets = /* @__PURE__ */ new Map();
3651
3651
  const variableIds = /* @__PURE__ */ new WeakMap();
3652
3652
  let nextVariableId = 0;
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
- function receiverIdentity(node) {
3661
- if (node.type === import_utils23.AST_NODE_TYPES.Identifier) {
3662
- const variable = import_utils23.ASTUtils.findVariable(
3663
- context.sourceCode.getScope(node),
3664
- node.name
3665
- );
3666
- return variable === null ? `global:${node.name}` : `variable:${variableId(variable)}`;
3667
- }
3668
- if (node.type === import_utils23.AST_NODE_TYPES.ThisExpression) return "this";
3669
- if (node.type === import_utils23.AST_NODE_TYPES.MemberExpression && !node.computed && node.property.type === import_utils23.AST_NODE_TYPES.Identifier) {
3670
- const owner = receiverIdentity(node.object);
3671
- return owner === null ? null : `${owner}.${node.property.name}`;
3672
- }
3673
- return null;
3674
- }
3675
3653
  function recordHeaderSet(node, kind) {
3676
3654
  if (node.callee.type !== import_utils23.AST_NODE_TYPES.MemberExpression) return;
3677
3655
  const receiver = receiverIdentity(node.callee.object);
@@ -3693,6 +3671,28 @@ var no_cors_wildcard_with_credentials_default = createRule({
3693
3671
  entry.credentialsNodes.push(node);
3694
3672
  }
3695
3673
  }
3674
+ function receiverIdentity(node) {
3675
+ if (node.type === import_utils23.AST_NODE_TYPES.Identifier) {
3676
+ const variable = import_utils23.ASTUtils.findVariable(
3677
+ context.sourceCode.getScope(node),
3678
+ node.name
3679
+ );
3680
+ return variable === null ? `global:${node.name}` : `variable:${variableId(variable)}`;
3681
+ }
3682
+ if (node.type === import_utils23.AST_NODE_TYPES.ThisExpression) return "this";
3683
+ if (node.type === import_utils23.AST_NODE_TYPES.MemberExpression && !node.computed && node.property.type === import_utils23.AST_NODE_TYPES.Identifier) {
3684
+ const owner = receiverIdentity(node.object);
3685
+ return owner === null ? null : `${owner}.${node.property.name}`;
3686
+ }
3687
+ return null;
3688
+ }
3689
+ function variableId(variable) {
3690
+ const existing = variableIds.get(variable);
3691
+ if (existing !== void 0) return existing;
3692
+ const value = nextVariableId++;
3693
+ variableIds.set(variable, value);
3694
+ return value;
3695
+ }
3696
3696
  return {
3697
3697
  NewExpression(node) {
3698
3698
  if (isCorsWildcardCredentialsCall(node)) {
@@ -4482,20 +4482,6 @@ function functionComplexity(fn, visitorKeys) {
4482
4482
  function add(node, nesting, construct) {
4483
4483
  points.push({ line: node.loc.start.line, amount: nesting + 1, construct });
4484
4484
  }
4485
- function logical(node, nesting) {
4486
- let previous;
4487
- function flatten(expression) {
4488
- if (expression.type !== import_utils29.AST_NODE_TYPES.LogicalExpression || expression.operator === "??") {
4489
- visit(expression, nesting);
4490
- return;
4491
- }
4492
- flatten(expression.left);
4493
- if (previous !== expression.operator) add(expression, 0, expression.operator);
4494
- previous = expression.operator;
4495
- flatten(expression.right);
4496
- }
4497
- flatten(node);
4498
- }
4499
4485
  function conditional(node, nesting) {
4500
4486
  add(node, nesting, "if");
4501
4487
  let branch = node;
@@ -4574,6 +4560,20 @@ function functionComplexity(fn, visitorKeys) {
4574
4560
  }
4575
4561
  visitChildren(node, nesting);
4576
4562
  }
4563
+ function logical(node, nesting) {
4564
+ let previous;
4565
+ function flatten(expression) {
4566
+ if (expression.type !== import_utils29.AST_NODE_TYPES.LogicalExpression || expression.operator === "??") {
4567
+ visit(expression, nesting);
4568
+ return;
4569
+ }
4570
+ flatten(expression.left);
4571
+ if (previous !== expression.operator) add(expression, 0, expression.operator);
4572
+ previous = expression.operator;
4573
+ flatten(expression.right);
4574
+ }
4575
+ flatten(node);
4576
+ }
4577
4577
  function visitChildren(node, nesting) {
4578
4578
  forEachAstChild(node, visitorKeys, (child) => visit(child, nesting));
4579
4579
  }
@@ -5196,6 +5196,14 @@ var no_hand_rolled_sleep_default = createRule({
5196
5196
  const callee = callback.type === import_utils31.AST_NODE_TYPES.Identifier ? callback : callback.type === import_utils31.AST_NODE_TYPES.ArrowFunctionExpression || callback.type === import_utils31.AST_NODE_TYPES.FunctionExpression ? soleCall(callback)?.callee : null;
5197
5197
  return callee?.type === import_utils31.AST_NODE_TYPES.Identifier && bindingOf(callee) === bindingOf(parameter);
5198
5198
  };
5199
+ let clientModule = null;
5200
+ const reportsSleepHere = () => {
5201
+ if (checkClientModules) {
5202
+ return true;
5203
+ }
5204
+ clientModule ??= isClientModule2();
5205
+ return !clientModule;
5206
+ };
5199
5207
  function isClientModule2() {
5200
5208
  if (/\.[cm]?[jt]sx$/.test(filename)) {
5201
5209
  return true;
@@ -5211,14 +5219,6 @@ var no_hand_rolled_sleep_default = createRule({
5211
5219
  }
5212
5220
  return false;
5213
5221
  }
5214
- let clientModule = null;
5215
- const reportsSleepHere = () => {
5216
- if (checkClientModules) {
5217
- return true;
5218
- }
5219
- clientModule ??= isClientModule2();
5220
- return !clientModule;
5221
- };
5222
5222
  return {
5223
5223
  NewExpression(node) {
5224
5224
  if (node.callee.type !== import_utils31.AST_NODE_TYPES.Identifier || node.callee.name !== "Promise" || !isGlobal(node.callee)) {
@@ -5648,13 +5648,6 @@ var no_detached_global_fetch_default = createRule({
5648
5648
  const variable = bindingOf(identifier);
5649
5649
  if (variable !== null && isStableAlias(variable)) aliases.add(variable);
5650
5650
  }
5651
- function isGlobalFetchMember(node) {
5652
- if (!isGlobalReceiver(node.object)) return false;
5653
- if (!node.computed) {
5654
- return node.property.type === import_utils34.AST_NODE_TYPES.Identifier && node.property.name === "fetch";
5655
- }
5656
- return node.property.type === import_utils34.AST_NODE_TYPES.Literal && node.property.value === "fetch";
5657
- }
5658
5651
  function staticMemberName9(node) {
5659
5652
  if (!node.computed) {
5660
5653
  return node.property.type === import_utils34.AST_NODE_TYPES.Identifier ? node.property.name : null;
@@ -5683,6 +5676,13 @@ var no_detached_global_fetch_default = createRule({
5683
5676
  }
5684
5677
  return false;
5685
5678
  }
5679
+ function isGlobalFetchMember(node) {
5680
+ if (!isGlobalReceiver(node.object)) return false;
5681
+ if (!node.computed) {
5682
+ return node.property.type === import_utils34.AST_NODE_TYPES.Identifier && node.property.name === "fetch";
5683
+ }
5684
+ return node.property.type === import_utils34.AST_NODE_TYPES.Literal && node.property.value === "fetch";
5685
+ }
5686
5686
  function recordAliasFromValue(identifier, value) {
5687
5687
  if (mayBeRawFetch(value)) recordAlias(identifier);
5688
5688
  }
@@ -6241,17 +6241,6 @@ var no_impossible_zod_literal_bounds_default = createRule({
6241
6241
  }
6242
6242
  return false;
6243
6243
  }
6244
- function baseKind(node) {
6245
- const callee = node.callee;
6246
- if (callee.type === import_utils37.AST_NODE_TYPES.Identifier) {
6247
- return resolvesToTrackedImport(callee) ? constructors.get(callee.name) ?? null : null;
6248
- }
6249
- if (callee.type !== import_utils37.AST_NODE_TYPES.MemberExpression || callee.object.type !== import_utils37.AST_NODE_TYPES.Identifier || !namespaces.has(callee.object.name) || !resolvesToTrackedImport(callee.object)) {
6250
- return null;
6251
- }
6252
- const name = memberName(callee);
6253
- return name !== null && KINDS.has(name) ? name : null;
6254
- }
6255
6244
  function readChain(node) {
6256
6245
  const calls = [];
6257
6246
  let current = node;
@@ -6268,6 +6257,17 @@ var no_impossible_zod_literal_bounds_default = createRule({
6268
6257
  current = callee.object;
6269
6258
  }
6270
6259
  }
6260
+ function baseKind(node) {
6261
+ const callee = node.callee;
6262
+ if (callee.type === import_utils37.AST_NODE_TYPES.Identifier) {
6263
+ return resolvesToTrackedImport(callee) ? constructors.get(callee.name) ?? null : null;
6264
+ }
6265
+ if (callee.type !== import_utils37.AST_NODE_TYPES.MemberExpression || callee.object.type !== import_utils37.AST_NODE_TYPES.Identifier || !namespaces.has(callee.object.name) || !resolvesToTrackedImport(callee.object)) {
6266
+ return null;
6267
+ }
6268
+ const name = memberName(callee);
6269
+ return name !== null && KINDS.has(name) ? name : null;
6270
+ }
6271
6271
  function isInsideReshapingCall(node) {
6272
6272
  let child = node;
6273
6273
  let parent = child.parent;
@@ -6581,30 +6581,30 @@ var no_redundant_optional_array_default_default = createRule({
6581
6581
  }
6582
6582
  return false;
6583
6583
  }
6584
- function isZodSchemaExpression(node) {
6584
+ function isArraySchemaExpression(node) {
6585
6585
  if (node.type !== import_utils39.AST_NODE_TYPES.CallExpression) return false;
6586
6586
  const { callee } = node;
6587
6587
  if (callee.type === import_utils39.AST_NODE_TYPES.Identifier) {
6588
- return resolvesToTrackedImport(callee);
6588
+ return arrayConstructors.has(callee.name) && resolvesToTrackedImport(callee);
6589
6589
  }
6590
6590
  if (callee.type !== import_utils39.AST_NODE_TYPES.MemberExpression) return false;
6591
- if (callee.object.type === import_utils39.AST_NODE_TYPES.Identifier && namespaces.has(callee.object.name) && resolvesToTrackedImport(callee.object)) {
6591
+ const method = memberName2(callee);
6592
+ if (method === "array" && (callee.object.type === import_utils39.AST_NODE_TYPES.Identifier ? namespaces.has(callee.object.name) && resolvesToTrackedImport(callee.object) : isZodSchemaExpression(callee.object))) {
6592
6593
  return true;
6593
6594
  }
6594
- return isZodSchemaExpression(callee.object);
6595
+ return isArraySchemaExpression(callee.object);
6595
6596
  }
6596
- function isArraySchemaExpression(node) {
6597
+ function isZodSchemaExpression(node) {
6597
6598
  if (node.type !== import_utils39.AST_NODE_TYPES.CallExpression) return false;
6598
6599
  const { callee } = node;
6599
6600
  if (callee.type === import_utils39.AST_NODE_TYPES.Identifier) {
6600
- return arrayConstructors.has(callee.name) && resolvesToTrackedImport(callee);
6601
+ return resolvesToTrackedImport(callee);
6601
6602
  }
6602
6603
  if (callee.type !== import_utils39.AST_NODE_TYPES.MemberExpression) return false;
6603
- const method = memberName2(callee);
6604
- if (method === "array" && (callee.object.type === import_utils39.AST_NODE_TYPES.Identifier ? namespaces.has(callee.object.name) && resolvesToTrackedImport(callee.object) : isZodSchemaExpression(callee.object))) {
6604
+ if (callee.object.type === import_utils39.AST_NODE_TYPES.Identifier && namespaces.has(callee.object.name) && resolvesToTrackedImport(callee.object)) {
6605
6605
  return true;
6606
6606
  }
6607
- return isArraySchemaExpression(callee.object);
6607
+ return isZodSchemaExpression(callee.object);
6608
6608
  }
6609
6609
  return {
6610
6610
  ImportDeclaration(node) {
@@ -7036,10 +7036,6 @@ var no_log_only_catch_default = createRule({
7036
7036
  }
7037
7037
  return matcher.isLoggingCall(statement.expression);
7038
7038
  }
7039
- function hasCommentDirectlyAbove(node) {
7040
- const above = sourceCode.getCommentsBefore(node).at(-1);
7041
- return above !== void 0 && above.loc.end.line === node.loc.start.line - 1;
7042
- }
7043
7039
  function hasAdjacentRationale(node) {
7044
7040
  const tryStatement = node.parent;
7045
7041
  if (hasCommentDirectlyAbove(tryStatement) || hasCommentDirectlyAbove(node)) return true;
@@ -7049,6 +7045,10 @@ var no_log_only_catch_default = createRule({
7049
7045
  }
7050
7046
  return hasCommentDirectlyAbove(block.parent);
7051
7047
  }
7048
+ function hasCommentDirectlyAbove(node) {
7049
+ const above = sourceCode.getCommentsBefore(node).at(-1);
7050
+ return above !== void 0 && above.loc.end.line === node.loc.start.line - 1;
7051
+ }
7052
7052
  if (isTestFile(filename) || BENCHMARK_DIR_RE.test(filename.replaceAll("\\", "/"))) {
7053
7053
  return {};
7054
7054
  }
@@ -7521,20 +7521,9 @@ var no_vague_suppression_description_default = createRule({
7521
7521
  }
7522
7522
  });
7523
7523
 
7524
- // src/rules/no-generic-single-export-module.ts
7524
+ // src/rules/_runtime-exports.ts
7525
7525
  var import_utils47 = require("@typescript-eslint/utils");
7526
- var NO_GENERIC_SINGLE_EXPORT_MODULE_DOCUMENTATION = {
7527
- summary: "Disallow generic module stems when one runtime export already names the responsibility.",
7528
- rationale: "A generic filename hides the sole exported responsibility and makes navigation less descriptive.",
7529
- remediation: "Choose a responsibility-bearing module name or colocate the export with its domain.",
7530
- category: "maintainability",
7531
- limitations: ["Only the fixed generic-stem vocabulary with exactly one public runtime export is checked; exported destructuring patterns are excluded rather than undercounted."],
7532
- examples: [
7533
- { 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 },
7534
- { 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 }
7535
- ]
7536
- };
7537
- var GENERIC_STEMS = /* @__PURE__ */ new Set([
7526
+ var GENERIC_MODULE_STEMS = /* @__PURE__ */ new Set([
7538
7527
  "common",
7539
7528
  "helper",
7540
7529
  "helpers",
@@ -7545,164 +7534,172 @@ var GENERIC_STEMS = /* @__PURE__ */ new Set([
7545
7534
  "utils"
7546
7535
  ]);
7547
7536
  var CJS_OBJECT_EXPORT_METHODS = /* @__PURE__ */ new Set(["assign", "defineProperties", "defineProperty"]);
7548
- function fileParts(filename) {
7549
- const base = filename.replaceAll("\\", "/").split("/").at(-1) ?? "";
7550
- const extension = base.match(/(\.[cm]?[jt]sx?)$/u)?.[1] ?? ".ts";
7551
- const [stem4 = "", ...suffixes] = base.slice(0, -extension.length).split(".");
7552
- return { stem: stem4, suffixes: suffixes.map((suffix) => suffix.toLowerCase()) };
7553
- }
7554
- function declaredNames(declaration) {
7555
- if (declaration.declare === true) return [];
7556
- if (declaration.type === import_utils47.AST_NODE_TYPES.FunctionDeclaration || declaration.type === import_utils47.AST_NODE_TYPES.ClassDeclaration || declaration.type === import_utils47.AST_NODE_TYPES.TSEnumDeclaration) {
7557
- if (declaration.type === import_utils47.AST_NODE_TYPES.TSEnumDeclaration && declaration.const) return [];
7558
- return declaration.id === null ? [] : [declaration.id.name];
7559
- }
7560
- if (declaration.type === import_utils47.AST_NODE_TYPES.TSModuleDeclaration && declaration.id.type === import_utils47.AST_NODE_TYPES.Identifier) {
7561
- return [declaration.id.name];
7562
- }
7563
- if (declaration.type !== import_utils47.AST_NODE_TYPES.VariableDeclaration) return [];
7564
- return declaration.declarations.flatMap(
7565
- (item) => item.id.type === import_utils47.AST_NODE_TYPES.Identifier ? [item.id.name] : []
7566
- );
7567
- }
7568
7537
  function runtimeExports(program) {
7569
- const exports2 = [];
7570
- const typeBindings = typeOnlyBindings(program);
7538
+ const bindings = localBindings(program);
7539
+ const exports2 = /* @__PURE__ */ new Map();
7571
7540
  let ambiguous = false;
7572
- function collectRuntimeExport(statement) {
7573
- if (statement.type === import_utils47.AST_NODE_TYPES.ExportAllDeclaration) {
7574
- if (statement.exportKind !== "type") ambiguous = true;
7575
- return;
7576
- }
7577
- if (statement.type === import_utils47.AST_NODE_TYPES.ExportDefaultDeclaration) {
7578
- collectDefaultExport(statement);
7579
- return;
7580
- }
7581
- if (statement.type !== import_utils47.AST_NODE_TYPES.ExportNamedDeclaration || statement.exportKind === "type") return;
7541
+ function add(key, name, node, emission) {
7542
+ if (emission === "unknown") ambiguous = true;
7543
+ if (emission === "runtime") exports2.set(key, { key, name, node });
7544
+ }
7545
+ function collectDefault(statement) {
7546
+ const declaration = statement.declaration;
7547
+ if (declaration.type === import_utils47.AST_NODE_TYPES.Identifier) {
7548
+ add("default", declaration.name, statement, bindings.get(declaration.name) ?? "unknown");
7549
+ } else if ("id" in declaration && declaration.id?.type === import_utils47.AST_NODE_TYPES.Identifier) {
7550
+ add("default", declaration.id.name, declaration, declarationEmission(declaration));
7551
+ } else ambiguous = true;
7552
+ }
7553
+ function collectNamed(statement) {
7554
+ if (statement.exportKind === "type") return;
7582
7555
  if (statement.source !== null) {
7583
7556
  if (statement.specifiers.some((specifier) => specifier.exportKind !== "type")) ambiguous = true;
7584
7557
  return;
7585
7558
  }
7586
- if (statement.declaration !== null) {
7587
- const declaration = statement.declaration;
7559
+ const declaration = statement.declaration;
7560
+ if (declaration !== null) {
7588
7561
  if (declaration.type === import_utils47.AST_NODE_TYPES.VariableDeclaration && declaration.declarations.some((item) => item.id.type !== import_utils47.AST_NODE_TYPES.Identifier)) ambiguous = true;
7589
- exports2.push(...declaredNames(declaration).map((name) => ({ key: name, name, node: declaration })));
7562
+ const names = declarationNames(declaration);
7563
+ if (names.length === 0 && declarationEmission(declaration) !== "erased") ambiguous = true;
7564
+ for (const name of names) add(name, name, declaration, bindings.get(name) ?? "unknown");
7590
7565
  }
7591
- collectExportSpecifiers(statement);
7592
- }
7593
- function collectExportSpecifiers(statement) {
7594
7566
  for (const specifier of statement.specifiers) {
7595
- if (specifier.exportKind === "type" || typeBindings.has(specifier.local.name)) continue;
7596
- const exported = specifier.exported.type === import_utils47.AST_NODE_TYPES.Identifier ? specifier.exported.name : specifier.exported.value;
7567
+ if (specifier.exportKind === "type") continue;
7568
+ const key = specifier.exported.type === import_utils47.AST_NODE_TYPES.Identifier ? specifier.exported.name : specifier.exported.value;
7597
7569
  const local = specifier.local.name;
7598
- exports2.push({ key: exported, name: exported === "default" ? local : exported, node: specifier });
7570
+ add(key, key === "default" ? local : key, specifier, bindings.get(local) ?? "unknown");
7599
7571
  }
7600
7572
  }
7601
- function collectDefaultExport(statement) {
7602
- const declaration = statement.declaration;
7603
- if (declaration.type === import_utils47.AST_NODE_TYPES.Identifier) {
7604
- if (!typeBindings.has(declaration.name)) {
7605
- exports2.push({ key: "default", name: declaration.name, node: statement });
7606
- }
7607
- } else if ((declaration.type === import_utils47.AST_NODE_TYPES.FunctionDeclaration || declaration.type === import_utils47.AST_NODE_TYPES.ClassDeclaration) && declaration.id !== null && declaration.declare !== true) exports2.push({ key: "default", name: declaration.id.name, node: declaration });
7608
- else if (declaration.type !== import_utils47.AST_NODE_TYPES.TSInterfaceDeclaration && declaration.type !== import_utils47.AST_NODE_TYPES.TSTypeAliasDeclaration) ambiguous = true;
7609
- }
7610
7573
  for (const statement of program.body) {
7611
- collectRuntimeExport(statement);
7574
+ if (statement.type === import_utils47.AST_NODE_TYPES.ExportAllDeclaration && statement.exportKind !== "type") ambiguous = true;
7575
+ if (statement.type === import_utils47.AST_NODE_TYPES.TSExportAssignment) ambiguous = true;
7576
+ if (statement.type === import_utils47.AST_NODE_TYPES.ExportDefaultDeclaration) collectDefault(statement);
7577
+ if (statement.type === import_utils47.AST_NODE_TYPES.ExportNamedDeclaration) collectNamed(statement);
7612
7578
  }
7613
- const unique = new Map(exports2.map((entry) => [entry.key, entry]));
7614
- return { exports: [...unique.values()], ambiguous };
7579
+ return { exports: [...exports2.values()], ambiguous };
7615
7580
  }
7616
- function typeOnlyBindings(program) {
7617
- const names = /* @__PURE__ */ new Set();
7618
- const runtimeNames = /* @__PURE__ */ new Set();
7619
- function collectTypeBinding(statement) {
7620
- const declaration = statement.type === import_utils47.AST_NODE_TYPES.ExportNamedDeclaration ? statement.declaration : statement;
7621
- if (declaration?.type === import_utils47.AST_NODE_TYPES.TSInterfaceDeclaration || declaration?.type === import_utils47.AST_NODE_TYPES.TSTypeAliasDeclaration) {
7622
- names.add(declaration.id.name);
7623
- return;
7624
- }
7625
- if (declaration?.type === import_utils47.AST_NODE_TYPES.TSEnumDeclaration && declaration.const) {
7626
- names.add(declaration.id.name);
7627
- return;
7628
- }
7629
- if (statement.type === import_utils47.AST_NODE_TYPES.ImportDeclaration) {
7630
- collectImportBindings(statement);
7631
- return;
7632
- }
7633
- if (declaration?.type === import_utils47.AST_NODE_TYPES.TSDeclareFunction && declaration.id !== null) {
7634
- names.add(declaration.id.name);
7635
- return;
7636
- }
7637
- if (declaration !== null && declaration.declare === true) {
7638
- collectDeclaredNames(declaration);
7639
- return;
7640
- }
7641
- if (declaration !== null && "type" in declaration) {
7642
- for (const name of declaredNames(declaration)) {
7643
- runtimeNames.add(name);
7644
- }
7645
- }
7581
+ function localBindings(program) {
7582
+ const bindings = /* @__PURE__ */ new Map();
7583
+ function register(name, emission) {
7584
+ const previous = bindings.get(name);
7585
+ if (previous === "runtime" || emission === "runtime") bindings.set(name, "runtime");
7586
+ else if (previous === "unknown" || emission === "unknown") bindings.set(name, "unknown");
7587
+ else bindings.set(name, "erased");
7646
7588
  }
7647
- function collectImportBindings(statement) {
7648
- for (const specifier of statement.specifiers) {
7649
- if (statement.importKind === "type" || specifier.type === import_utils47.AST_NODE_TYPES.ImportSpecifier && specifier.importKind === "type") {
7650
- names.add(specifier.local.name);
7651
- } else {
7652
- runtimeNames.add(specifier.local.name);
7589
+ for (const statement of program.body) {
7590
+ if (statement.type === import_utils47.AST_NODE_TYPES.ImportDeclaration) {
7591
+ for (const specifier of statement.specifiers) {
7592
+ const typeOnly = statement.importKind === "type" || specifier.type === import_utils47.AST_NODE_TYPES.ImportSpecifier && specifier.importKind === "type";
7593
+ register(specifier.local.name, typeOnly ? "erased" : "unknown");
7653
7594
  }
7595
+ continue;
7654
7596
  }
7597
+ const declaration = statement.type === import_utils47.AST_NODE_TYPES.ExportNamedDeclaration || statement.type === import_utils47.AST_NODE_TYPES.ExportDefaultDeclaration ? statement.declaration : statement;
7598
+ if (declaration === null) continue;
7599
+ for (const name of declarationNames(declaration)) register(name, declarationEmission(declaration));
7655
7600
  }
7656
- function collectDeclaredNames(declaration) {
7657
- if ((declaration.type === import_utils47.AST_NODE_TYPES.ClassDeclaration || declaration.type === import_utils47.AST_NODE_TYPES.FunctionDeclaration || declaration.type === import_utils47.AST_NODE_TYPES.TSEnumDeclaration || declaration.type === import_utils47.AST_NODE_TYPES.TSModuleDeclaration) && declaration.id !== null && declaration.id.type === import_utils47.AST_NODE_TYPES.Identifier) names.add(declaration.id.name);
7658
- if (declaration.type === import_utils47.AST_NODE_TYPES.VariableDeclaration) {
7659
- for (const item of declaration.declarations) {
7660
- if (item.id.type === import_utils47.AST_NODE_TYPES.Identifier) names.add(item.id.name);
7661
- }
7662
- }
7601
+ return bindings;
7602
+ }
7603
+ function declarationNames(declaration) {
7604
+ if ("id" in declaration && declaration.id !== null) {
7605
+ let id = declaration.id;
7606
+ while (id.type === import_utils47.AST_NODE_TYPES.TSQualifiedName) id = id.left;
7607
+ if (id.type === import_utils47.AST_NODE_TYPES.Identifier) return [id.name];
7663
7608
  }
7664
- for (const statement of program.body) {
7665
- collectTypeBinding(statement);
7609
+ if (declaration.type !== import_utils47.AST_NODE_TYPES.VariableDeclaration) return [];
7610
+ return declaration.declarations.flatMap((item) => item.id.type === import_utils47.AST_NODE_TYPES.Identifier ? [item.id.name] : []);
7611
+ }
7612
+ function declarationEmission(declaration) {
7613
+ if ("declare" in declaration && declaration.declare === true) return "erased";
7614
+ switch (declaration.type) {
7615
+ case import_utils47.AST_NODE_TYPES.TSInterfaceDeclaration:
7616
+ case import_utils47.AST_NODE_TYPES.TSTypeAliasDeclaration:
7617
+ case import_utils47.AST_NODE_TYPES.TSDeclareFunction:
7618
+ return "erased";
7619
+ case import_utils47.AST_NODE_TYPES.ClassDeclaration:
7620
+ case import_utils47.AST_NODE_TYPES.FunctionDeclaration:
7621
+ case import_utils47.AST_NODE_TYPES.VariableDeclaration:
7622
+ return "runtime";
7623
+ case import_utils47.AST_NODE_TYPES.TSEnumDeclaration:
7624
+ return declaration.const ? "unknown" : "runtime";
7625
+ case import_utils47.AST_NODE_TYPES.TSModuleDeclaration:
7626
+ return namespaceEmission(declaration);
7627
+ default:
7628
+ return "unknown";
7666
7629
  }
7667
- return new Set([...names].filter((name) => !runtimeNames.has(name)));
7668
7630
  }
7669
- function isGlobalIdentifier2(context, node) {
7670
- const variable = import_utils47.ASTUtils.findVariable(context.sourceCode.getScope(node), node.name);
7671
- return variable === null || variable.defs.length === 0;
7631
+ function namespaceEmission(declaration) {
7632
+ const { body: body2 } = declaration;
7633
+ if (body2 === void 0) return "unknown";
7634
+ if (body2.body.length === 0) return "unknown";
7635
+ let ambiguous = false;
7636
+ for (const statement of body2.body) {
7637
+ if (statement.type === import_utils47.AST_NODE_TYPES.ExportNamedDeclaration && statement.exportKind === "type") continue;
7638
+ const inner = statement.type === import_utils47.AST_NODE_TYPES.ExportNamedDeclaration ? statement.declaration : statement;
7639
+ const emission = inner === null ? "unknown" : declarationEmission(inner);
7640
+ if (emission === "runtime") return "runtime";
7641
+ if (emission === "unknown") ambiguous = true;
7642
+ }
7643
+ return ambiguous ? "unknown" : "erased";
7672
7644
  }
7673
- function isConventionalFrameworkUtility(filename, exported) {
7674
- const normalized = filename.replaceAll("\\", "/");
7675
- return exported === "cn" && /(?:^|\/)lib\/utils\.[cm]?[jt]sx?$/u.test(normalized);
7645
+ function isCommonJsExportReference(node, sourceCode) {
7646
+ function isGlobal(node2) {
7647
+ const variable = import_utils47.ASTUtils.findVariable(sourceCode.getScope(node2), node2.name);
7648
+ return variable === null || variable.defs.length === 0;
7649
+ }
7650
+ if (node.type === import_utils47.AST_NODE_TYPES.MemberExpression) {
7651
+ return node.object.type === import_utils47.AST_NODE_TYPES.Identifier && isGlobal(node.object) && (node.object.name === "exports" || node.object.name === "module" && memberPropertyName(node) === "exports");
7652
+ }
7653
+ const first = node.arguments[0];
7654
+ return first?.type === import_utils47.AST_NODE_TYPES.Identifier && first.name === "exports" && isGlobal(first) && node.callee.type === import_utils47.AST_NODE_TYPES.MemberExpression && node.callee.object.type === import_utils47.AST_NODE_TYPES.Identifier && node.callee.object.name === "Object" && isGlobal(node.callee.object) && CJS_OBJECT_EXPORT_METHODS.has(memberPropertyName(node.callee) ?? "");
7676
7655
  }
7677
7656
  function memberPropertyName(node) {
7678
7657
  if (!node.computed && node.property.type === import_utils47.AST_NODE_TYPES.Identifier) return node.property.name;
7679
7658
  return node.computed && node.property.type === import_utils47.AST_NODE_TYPES.Literal && typeof node.property.value === "string" ? node.property.value : null;
7680
7659
  }
7681
- var no_generic_single_export_module_default = createRule({
7682
- name: "no-generic-single-export-module",
7683
- documentation: NO_GENERIC_SINGLE_EXPORT_MODULE_DOCUMENTATION,
7684
- meta: {
7685
- type: "suggestion",
7686
- docs: { description: "Disallow generic module stems when one runtime export already names the responsibility." },
7687
- schema: [],
7688
- messages: {
7689
- 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."
7690
- }
7660
+
7661
+ // src/rules/no-generic-single-export-module.ts
7662
+ var NO_GENERIC_SINGLE_EXPORT_MODULE_DOCUMENTATION = {
7663
+ summary: "Disallow generic module stems when one runtime export already names the responsibility.",
7664
+ rationale: "A generic filename hides the sole exported responsibility and makes navigation less descriptive.",
7665
+ remediation: "Choose a responsibility-bearing module name or colocate the export with its domain.",
7666
+ category: "maintainability",
7667
+ limitations: ["Only the fixed generic-stem vocabulary with exactly one public runtime export is checked; exported destructuring patterns are excluded rather than undercounted."],
7668
+ examples: [
7669
+ { 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 },
7670
+ { 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 }
7671
+ ]
7672
+ };
7673
+ function fileParts(filename) {
7674
+ const base = filename.replaceAll("\\", "/").split("/").at(-1) ?? "";
7675
+ const extension = base.match(/(\.[cm]?[jt]sx?)$/u)?.[1] ?? ".ts";
7676
+ const [stem4 = "", ...suffixes] = base.slice(0, -extension.length).split(".");
7677
+ return { stem: stem4, suffixes: suffixes.map((suffix) => suffix.toLowerCase()) };
7678
+ }
7679
+ function isConventionalFrameworkUtility(filename, exported) {
7680
+ const normalized = filename.replaceAll("\\", "/");
7681
+ return exported === "cn" && /(?:^|\/)lib\/utils\.[cm]?[jt]sx?$/u.test(normalized);
7682
+ }
7683
+ var no_generic_single_export_module_default = createRule({
7684
+ name: "no-generic-single-export-module",
7685
+ documentation: NO_GENERIC_SINGLE_EXPORT_MODULE_DOCUMENTATION,
7686
+ meta: {
7687
+ type: "suggestion",
7688
+ docs: { description: "Disallow generic module stems when one runtime export already names the responsibility." },
7689
+ schema: [],
7690
+ messages: {
7691
+ 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."
7692
+ }
7691
7693
  },
7692
7694
  defaultOptions: [],
7693
7695
  create(context) {
7694
7696
  const file = fileParts(context.filename);
7695
7697
  const { stem: stem4 } = file;
7696
- if (!GENERIC_STEMS.has(stem4) || isTestFile(context.filename) || isGeneratedFile(context.filename, context.sourceCode.text)) return {};
7698
+ if (!GENERIC_MODULE_STEMS.has(stem4) || isTestFile(context.filename) || isGeneratedFile(context.filename, context.sourceCode.text)) return {};
7697
7699
  let hasCommonJsExport = false;
7698
7700
  return {
7699
- CallExpression(node) {
7700
- const first = node.arguments[0];
7701
- if (first?.type === import_utils47.AST_NODE_TYPES.Identifier && first.name === "exports" && isGlobalIdentifier2(context, first) && node.callee.type === import_utils47.AST_NODE_TYPES.MemberExpression && node.callee.object.type === import_utils47.AST_NODE_TYPES.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;
7702
- },
7703
- MemberExpression(node) {
7704
- if (node.object.type === import_utils47.AST_NODE_TYPES.Identifier && node.object.name === "exports" && isGlobalIdentifier2(context, node.object)) hasCommonJsExport = true;
7705
- if (node.object.type === import_utils47.AST_NODE_TYPES.Identifier && node.object.name === "module" && isGlobalIdentifier2(context, node.object) && memberPropertyName(node) === "exports") hasCommonJsExport = true;
7701
+ "CallExpression, MemberExpression"(node) {
7702
+ if (isCommonJsExportReference(node, context.sourceCode)) hasCommonJsExport = true;
7706
7703
  },
7707
7704
  "Program:exit"(program) {
7708
7705
  if (hasCommonJsExport) return;
@@ -8052,6 +8049,10 @@ var no_positional_tuple_return_default = createRule({
8052
8049
  data: { name, count: String(tuple.elements.length) }
8053
8050
  });
8054
8051
  };
8052
+ const enterFunction = (node) => {
8053
+ functionStack.push(node);
8054
+ check(node);
8055
+ };
8055
8056
  const check = (node) => {
8056
8057
  if (isQueryKeyFactory(node)) return;
8057
8058
  const annotation = node.returnType?.typeAnnotation;
@@ -8067,10 +8068,6 @@ var no_positional_tuple_return_default = createRule({
8067
8068
  }
8068
8069
  report2(annotation, name);
8069
8070
  };
8070
- const enterFunction = (node) => {
8071
- functionStack.push(node);
8072
- check(node);
8073
- };
8074
8071
  const exitFunction = () => {
8075
8072
  functionStack.pop();
8076
8073
  };
@@ -8517,32 +8514,16 @@ var no_raw_fetch_outside_clients_default = createRule({
8517
8514
  const definition = variable.defs[0];
8518
8515
  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 === import_utils51.AST_NODE_TYPES.ObjectExpression && variable.references.some((reference) => reference.identifier !== node && reference.init !== true)) ? definition.node.init : node;
8519
8516
  }
8520
- function propertyValue(node, name) {
8521
- if (node?.type !== import_utils51.AST_NODE_TYPES.ObjectExpression) return null;
8522
- if (node.properties.some((property) => property.type !== import_utils51.AST_NODE_TYPES.Property || property.computed)) return null;
8523
- for (const property of [...node.properties].reverse()) {
8524
- if (property.type !== import_utils51.AST_NODE_TYPES.Property || property.computed) continue;
8525
- const key = property.key;
8526
- const keyName = key.type === import_utils51.AST_NODE_TYPES.Identifier ? key.name : key.type === import_utils51.AST_NODE_TYPES.Literal && typeof key.value === "string" ? key.value : null;
8527
- if (keyName !== name) continue;
8528
- return property.value.type === import_utils51.AST_NODE_TYPES.AssignmentPattern || property.value.type === import_utils51.AST_NODE_TYPES.ArrayPattern || property.value.type === import_utils51.AST_NODE_TYPES.ObjectPattern ? null : property.value;
8529
- }
8530
- return null;
8531
- }
8532
- function isInternalApiUrl(node) {
8533
- const resolved = resolveNode2(node ?? void 0);
8534
- if (resolved?.type === import_utils51.AST_NODE_TYPES.Literal) {
8535
- return typeof resolved.value === "string" && internalApiPrefixes.some(
8536
- (prefix) => resolved.value === prefix || resolved.value.startsWith(`${prefix}/`)
8537
- );
8517
+ function serverActionOwns(node) {
8518
+ if (node.callee.type !== import_utils51.AST_NODE_TYPES.Identifier || !hasUseClientDirective || hasUseServerDirective || importsServerOnly || SERVER_ACTION_SKIP_FILE_RE.test(filename) || nonReactFramework) {
8519
+ return false;
8538
8520
  }
8539
- if (resolved?.type === import_utils51.AST_NODE_TYPES.TemplateLiteral) {
8540
- const prefix = resolved.quasis[0]?.value.cooked;
8541
- return typeof prefix === "string" && internalApiPrefixes.some(
8542
- (apiPrefix) => prefix === apiPrefix || prefix.startsWith(`${apiPrefix}/`)
8543
- );
8521
+ const url = node.arguments[0];
8522
+ const init = node.arguments[1];
8523
+ if (url === void 0 || url.type === import_utils51.AST_NODE_TYPES.SpreadElement || init === void 0 || init.type === import_utils51.AST_NODE_TYPES.SpreadElement || !isInternalApiUrl(url)) {
8524
+ return false;
8544
8525
  }
8545
- return resolved?.type === import_utils51.AST_NODE_TYPES.BinaryExpression && resolved.operator === "+" && isInternalApiUrl(resolved.left);
8526
+ return isMutationMethod2(propertyValue(resolveNode2(init), "method"));
8546
8527
  }
8547
8528
  function isMutationMethod2(node) {
8548
8529
  const resolved = resolveNode2(node ?? void 0);
@@ -8559,16 +8540,32 @@ var no_raw_fetch_outside_clients_default = createRule({
8559
8540
  }
8560
8541
  return resolved?.type === import_utils51.AST_NODE_TYPES.LogicalExpression && resolved.operator === "||" && (isMutationMethod2(resolved.left) || isMutationMethod2(resolved.right));
8561
8542
  }
8562
- function serverActionOwns(node) {
8563
- if (node.callee.type !== import_utils51.AST_NODE_TYPES.Identifier || !hasUseClientDirective || hasUseServerDirective || importsServerOnly || SERVER_ACTION_SKIP_FILE_RE.test(filename) || nonReactFramework) {
8564
- return false;
8543
+ function isInternalApiUrl(node) {
8544
+ const resolved = resolveNode2(node ?? void 0);
8545
+ if (resolved?.type === import_utils51.AST_NODE_TYPES.Literal) {
8546
+ return typeof resolved.value === "string" && internalApiPrefixes.some(
8547
+ (prefix) => resolved.value === prefix || resolved.value.startsWith(`${prefix}/`)
8548
+ );
8565
8549
  }
8566
- const url = node.arguments[0];
8567
- const init = node.arguments[1];
8568
- if (url === void 0 || url.type === import_utils51.AST_NODE_TYPES.SpreadElement || init === void 0 || init.type === import_utils51.AST_NODE_TYPES.SpreadElement || !isInternalApiUrl(url)) {
8569
- return false;
8550
+ if (resolved?.type === import_utils51.AST_NODE_TYPES.TemplateLiteral) {
8551
+ const prefix = resolved.quasis[0]?.value.cooked;
8552
+ return typeof prefix === "string" && internalApiPrefixes.some(
8553
+ (apiPrefix) => prefix === apiPrefix || prefix.startsWith(`${apiPrefix}/`)
8554
+ );
8570
8555
  }
8571
- return isMutationMethod2(propertyValue(resolveNode2(init), "method"));
8556
+ return resolved?.type === import_utils51.AST_NODE_TYPES.BinaryExpression && resolved.operator === "+" && isInternalApiUrl(resolved.left);
8557
+ }
8558
+ function propertyValue(node, name) {
8559
+ if (node?.type !== import_utils51.AST_NODE_TYPES.ObjectExpression) return null;
8560
+ if (node.properties.some((property) => property.type !== import_utils51.AST_NODE_TYPES.Property || property.computed)) return null;
8561
+ for (const property of [...node.properties].reverse()) {
8562
+ if (property.type !== import_utils51.AST_NODE_TYPES.Property || property.computed) continue;
8563
+ const key = property.key;
8564
+ const keyName = key.type === import_utils51.AST_NODE_TYPES.Identifier ? key.name : key.type === import_utils51.AST_NODE_TYPES.Literal && typeof key.value === "string" ? key.value : null;
8565
+ if (keyName !== name) continue;
8566
+ return property.value.type === import_utils51.AST_NODE_TYPES.AssignmentPattern || property.value.type === import_utils51.AST_NODE_TYPES.ArrayPattern || property.value.type === import_utils51.AST_NODE_TYPES.ObjectPattern ? null : property.value;
8567
+ }
8568
+ return null;
8572
8569
  }
8573
8570
  if (allowed.some((re) => re.test(filename))) {
8574
8571
  return {};
@@ -9243,19 +9240,19 @@ var no_restated_jsdoc_default = createRule({
9243
9240
  function enclosingDeclarationNames(node) {
9244
9241
  let declaration = null;
9245
9242
  while (node != null && node.type !== import_utils57.AST_NODE_TYPES.Program) {
9246
- declaration = declarationNames(node);
9243
+ declaration = declarationNames2(node);
9247
9244
  if (declaration !== null) break;
9248
9245
  node = node.parent ?? null;
9249
9246
  }
9250
9247
  return declaration;
9251
9248
  }
9252
- function declarationNames(node) {
9249
+ function declarationNames2(node) {
9253
9250
  switch (node.type) {
9254
9251
  // `export function f()` — the JSDoc sits above the `export`, so the token
9255
9252
  // after it resolves to the wrapper, not to the thing being documented.
9256
9253
  case import_utils57.AST_NODE_TYPES.ExportNamedDeclaration:
9257
9254
  case import_utils57.AST_NODE_TYPES.ExportDefaultDeclaration:
9258
- return node.declaration == null ? null : declarationNames(node.declaration);
9255
+ return node.declaration == null ? null : declarationNames2(node.declaration);
9259
9256
  case import_utils57.AST_NODE_TYPES.FunctionDeclaration:
9260
9257
  case import_utils57.AST_NODE_TYPES.TSDeclareFunction:
9261
9258
  return node.id === null ? null : { name: node.id.name, params: paramNames(node.params) };
@@ -9667,35 +9664,30 @@ var no_secret_in_log_default = createRule({
9667
9664
  create(context, [loggingOptions]) {
9668
9665
  const matcher = createLogMatcher(loggingOptions);
9669
9666
  const blobArmApplies = !isTestFile(context.filename);
9670
- function reportSecretArgument(arg) {
9671
- const name = valueName(arg);
9672
- if (name === null || !isSecretKeyword(name)) {
9673
- return false;
9667
+ function inspectLoggedValue(value) {
9668
+ if (value.type === "ObjectExpression") {
9669
+ for (const property of literalProperties(value)) {
9670
+ if (reportSecretProperty(property) || reportRawBlob(property, property.value)) continue;
9671
+ inspectLoggedValue(property.value);
9672
+ }
9673
+ return;
9674
9674
  }
9675
- context.report({ node: arg, messageId: "noSecretInLog", data: { name } });
9676
- return true;
9677
- }
9678
- function reportSecretProperty(prop) {
9679
- const keyName = propertyKeyName2(prop);
9680
- const value = valueName(prop.value);
9681
- if (value !== null && hasRedactionMarker(value)) return false;
9682
- const name = value !== null && isSecretKeyword(value) ? value : keyName;
9683
- if (name === null || !isSecretKeyword(name) || !isRawSecretValue(prop)) {
9684
- return false;
9675
+ if (value.type === "ArrayExpression") {
9676
+ for (const element of value.elements) {
9677
+ if (element !== null && element.type !== "SpreadElement") inspectLoggedValue(element);
9678
+ }
9679
+ return;
9685
9680
  }
9686
- context.report({ node: prop, messageId: "noSecretInLog", data: { name } });
9687
- return true;
9688
- }
9689
- function reportRawBlob(node, value) {
9690
- if (!blobArmApplies) {
9691
- return false;
9681
+ if (value.type === "TemplateLiteral") {
9682
+ for (const expression of value.expressions) inspectLoggedValue(expression);
9683
+ return;
9692
9684
  }
9693
- const name = rawBlobValueName(value);
9694
- if (name !== null) {
9695
- context.report({ node, messageId: "noRawBodyInLog", data: { name } });
9696
- return true;
9685
+ if (value.type === "BinaryExpression" && value.operator === "+") {
9686
+ inspectLoggedValue(value.left);
9687
+ inspectLoggedValue(value.right);
9688
+ return;
9697
9689
  }
9698
- return false;
9690
+ if (!reportSecretArgument(value)) reportRawBlob(value, value);
9699
9691
  }
9700
9692
  function literalProperties(value) {
9701
9693
  const effective = /* @__PURE__ */ new Map();
@@ -9720,30 +9712,35 @@ var no_secret_in_log_default = createRule({
9720
9712
  }
9721
9713
  return [...effective.values()];
9722
9714
  }
9723
- function inspectLoggedValue(value) {
9724
- if (value.type === "ObjectExpression") {
9725
- for (const property of literalProperties(value)) {
9726
- if (reportSecretProperty(property) || reportRawBlob(property, property.value)) continue;
9727
- inspectLoggedValue(property.value);
9728
- }
9729
- return;
9715
+ function reportRawBlob(node, value) {
9716
+ if (!blobArmApplies) {
9717
+ return false;
9730
9718
  }
9731
- if (value.type === "ArrayExpression") {
9732
- for (const element of value.elements) {
9733
- if (element !== null && element.type !== "SpreadElement") inspectLoggedValue(element);
9734
- }
9735
- return;
9719
+ const name = rawBlobValueName(value);
9720
+ if (name !== null) {
9721
+ context.report({ node, messageId: "noRawBodyInLog", data: { name } });
9722
+ return true;
9736
9723
  }
9737
- if (value.type === "TemplateLiteral") {
9738
- for (const expression of value.expressions) inspectLoggedValue(expression);
9739
- return;
9724
+ return false;
9725
+ }
9726
+ function reportSecretProperty(prop) {
9727
+ const keyName = propertyKeyName2(prop);
9728
+ const value = valueName(prop.value);
9729
+ if (value !== null && hasRedactionMarker(value)) return false;
9730
+ const name = value !== null && isSecretKeyword(value) ? value : keyName;
9731
+ if (name === null || !isSecretKeyword(name) || !isRawSecretValue(prop)) {
9732
+ return false;
9740
9733
  }
9741
- if (value.type === "BinaryExpression" && value.operator === "+") {
9742
- inspectLoggedValue(value.left);
9743
- inspectLoggedValue(value.right);
9744
- return;
9734
+ context.report({ node: prop, messageId: "noSecretInLog", data: { name } });
9735
+ return true;
9736
+ }
9737
+ function reportSecretArgument(arg) {
9738
+ const name = valueName(arg);
9739
+ if (name === null || !isSecretKeyword(name)) {
9740
+ return false;
9745
9741
  }
9746
- if (!reportSecretArgument(value)) reportRawBlob(value, value);
9742
+ context.report({ node: arg, messageId: "noSecretInLog", data: { name } });
9743
+ return true;
9747
9744
  }
9748
9745
  return {
9749
9746
  CallExpression(node) {
@@ -10041,9 +10038,6 @@ function bindsName(param, name) {
10041
10038
  }
10042
10039
  function subtreeReadsName(node, name) {
10043
10040
  let found = false;
10044
- const shadowsName = (fn) => isFunctionNode(fn) && fn.params.some(
10045
- (param) => bindsName(param, name)
10046
- );
10047
10041
  const recurse = (current) => {
10048
10042
  if (found) {
10049
10043
  return;
@@ -10060,6 +10054,9 @@ function subtreeReadsName(node, name) {
10060
10054
  return found;
10061
10055
  }, (key) => !isNonReadingProperty(current, key));
10062
10056
  };
10057
+ const shadowsName = (fn) => isFunctionNode(fn) && fn.params.some(
10058
+ (param) => bindsName(param, name)
10059
+ );
10063
10060
  recurse(node);
10064
10061
  return found;
10065
10062
  }
@@ -11921,14 +11918,6 @@ var no_declaration_comment_wall_default = createRule({
11921
11918
  const trail = startingOn.get(member.loc.end.line);
11922
11919
  return trail !== void 0 && trail.range[0] > member.range[0] ? trail : void 0;
11923
11920
  }
11924
- function isGroupLabel(comment, member, headsRun) {
11925
- if (comment.loc.end.line >= member.node.loc.start.line) return false;
11926
- const body2 = commentBody(comment);
11927
- if (!BARE_LABEL_RE.test(body2)) return false;
11928
- if (labelStems(body2) === labelStems(sourceCode.getText(member.key))) return false;
11929
- const lineAbove = sourceCode.lines[comment.loc.start.line - 2];
11930
- return headsRun || lineAbove !== void 0 && lineAbove.trim().length === 0;
11931
- }
11932
11921
  function check(node, members) {
11933
11922
  const judged = members.map(named).filter((member) => member !== void 0);
11934
11923
  if (judged.length === 0) return;
@@ -11967,6 +11956,14 @@ var no_declaration_comment_wall_default = createRule({
11967
11956
  data: { restated: String(restated), commented: String(commented) }
11968
11957
  });
11969
11958
  }
11959
+ function isGroupLabel(comment, member, headsRun) {
11960
+ if (comment.loc.end.line >= member.node.loc.start.line) return false;
11961
+ const body2 = commentBody(comment);
11962
+ if (!BARE_LABEL_RE.test(body2)) return false;
11963
+ if (labelStems(body2) === labelStems(sourceCode.getText(member.key))) return false;
11964
+ const lineAbove = sourceCode.lines[comment.loc.start.line - 2];
11965
+ return headsRun || lineAbove !== void 0 && lineAbove.trim().length === 0;
11966
+ }
11970
11967
  return {
11971
11968
  ClassBody: (node) => {
11972
11969
  check(node, node.body);
@@ -12202,14 +12199,6 @@ var no_type_member_comment_wall_default = createRule({
12202
12199
  const trail = startingOn.get(member.loc.end.line);
12203
12200
  return trail !== void 0 && trail.range[0] > member.range[0] ? trail : void 0;
12204
12201
  }
12205
- function isGroupLabel(comment, member, headsRun) {
12206
- if (comment.loc.end.line >= member.loc.start.line) return false;
12207
- const body2 = commentBody(comment);
12208
- if (!BARE_LABEL_RE.test(body2)) return false;
12209
- if (labelStems(body2) === labelStems(sourceCode.getText(member.key))) return false;
12210
- const lineAbove = sourceCode.lines[comment.loc.start.line - 2];
12211
- return headsRun || lineAbove !== void 0 && lineAbove.trim().length === 0;
12212
- }
12213
12202
  function check(node) {
12214
12203
  const members = node.type === import_utils71.AST_NODE_TYPES.TSInterfaceBody ? node.body : node.members;
12215
12204
  const named2 = members.filter(isNamedMember);
@@ -12245,6 +12234,14 @@ var no_type_member_comment_wall_default = createRule({
12245
12234
  data: { restated: String(restated), commented: String(commented) }
12246
12235
  });
12247
12236
  }
12237
+ function isGroupLabel(comment, member, headsRun) {
12238
+ if (comment.loc.end.line >= member.loc.start.line) return false;
12239
+ const body2 = commentBody(comment);
12240
+ if (!BARE_LABEL_RE.test(body2)) return false;
12241
+ if (labelStems(body2) === labelStems(sourceCode.getText(member.key))) return false;
12242
+ const lineAbove = sourceCode.lines[comment.loc.start.line - 2];
12243
+ return headsRun || lineAbove !== void 0 && lineAbove.trim().length === 0;
12244
+ }
12248
12245
  return {
12249
12246
  TSInterfaceBody: check,
12250
12247
  TSTypeLiteral: check
@@ -12560,6 +12557,11 @@ var no_unsafe_mock_casting_default = createRule({
12560
12557
  const binding = resolve2(identifier);
12561
12558
  if (binding !== null) destination.add(binding);
12562
12559
  }
12560
+ function checkAssertion(node) {
12561
+ if (isMockTypeReference(node.typeAnnotation)) {
12562
+ context.report({ node, messageId: "unsafeMockCast" });
12563
+ }
12564
+ }
12563
12565
  function isMockTypeReference(node) {
12564
12566
  if (node.type !== import_utils73.AST_NODE_TYPES.TSTypeReference) return false;
12565
12567
  const typeName = node.typeName;
@@ -12573,11 +12575,6 @@ var no_unsafe_mock_casting_default = createRule({
12573
12575
  }
12574
12576
  return false;
12575
12577
  }
12576
- function checkAssertion(node) {
12577
- if (isMockTypeReference(node.typeAnnotation)) {
12578
- context.report({ node, messageId: "unsafeMockCast" });
12579
- }
12580
- }
12581
12578
  return {
12582
12579
  ImportDeclaration(node) {
12583
12580
  if (!MOCK_MODULES.has(node.source.value)) return;
@@ -17888,7 +17885,7 @@ var staticallyImportsExternalRenderer = (program) => program.body.some((statemen
17888
17885
  var semanticForegroundRoles = (filename) => {
17889
17886
  const packageRoot = nearestPackageRoot((0, import_path.dirname)(filename));
17890
17887
  if (packageRoot === null) return /* @__PURE__ */ new Set();
17891
- const candidates = CSS_DETECTION_FILES.map((relative2) => (0, import_path.join)(packageRoot, relative2));
17888
+ const candidates = CSS_DETECTION_FILES.map((relative3) => (0, import_path.join)(packageRoot, relative3));
17892
17889
  const fingerprint = candidates.map(fileFingerprint2).join("|");
17893
17890
  const cached = SEMANTIC_DECLARATIONS_CACHE.get(packageRoot);
17894
17891
  if (cached?.fingerprint === fingerprint) return cached.value;
@@ -17971,37 +17968,6 @@ var prefer_semantic_colors_default = createRule({
17971
17968
  const key = `${node.range[0]}:${node.range[1]}:${messageId}:${JSON.stringify(data)}`;
17972
17969
  pendingReports.set(key, { node, messageId, data });
17973
17970
  };
17974
- const reportClasses = (value, node) => {
17975
- const tokens = classTokens(value);
17976
- for (const token of tokens) {
17977
- const base = tailwindBase(token);
17978
- if (RAW_PALETTE_RE.test(base)) {
17979
- report2(node, "rawPalette", { class: token });
17980
- } else if (ARBITRARY_COLOR_RE.test(base) && !CSS_VAR_REFERENCE_RE.test(base)) {
17981
- report2(node, "arbitraryColor", { class: token });
17982
- }
17983
- }
17984
- if (!checkOpaqueForegroundPairs || isInsideSvg(node)) return;
17985
- for (const token of tokens) {
17986
- const prefix = tailwindVariantPrefix(token);
17987
- if (prefix.split(":").includes("print")) continue;
17988
- const base = tailwindBase(token);
17989
- if (!OPAQUE_FOREGROUND_RE.test(base)) continue;
17990
- const semanticBackground = tokens.find((candidate2) => {
17991
- if (tailwindVariantPrefix(candidate2) !== prefix) return false;
17992
- const match = SEMANTIC_BACKGROUND_RE.exec(tailwindBase(candidate2));
17993
- return match?.[1] !== void 0 && foregroundRoles.has(match[1]);
17994
- });
17995
- if (semanticBackground === void 0) continue;
17996
- const role = SEMANTIC_BACKGROUND_RE.exec(tailwindBase(semanticBackground))?.[1];
17997
- if (role === void 0) continue;
17998
- report2(node, "opaqueForegroundPair", {
17999
- background: semanticBackground,
18000
- class: token,
18001
- replacement: `${prefix}text-${role}-foreground`
18002
- });
18003
- }
18004
- };
18005
17971
  const checkClassNode = (node, objectKeys = false) => {
18006
17972
  if (node === null) return;
18007
17973
  switch (node.type) {
@@ -18030,6 +17996,37 @@ var prefer_semantic_colors_default = createRule({
18030
17996
  break;
18031
17997
  }
18032
17998
  };
17999
+ const reportClasses = (value, node) => {
18000
+ const tokens = classTokens(value);
18001
+ for (const token of tokens) {
18002
+ const base = tailwindBase(token);
18003
+ if (RAW_PALETTE_RE.test(base)) {
18004
+ report2(node, "rawPalette", { class: token });
18005
+ } else if (ARBITRARY_COLOR_RE.test(base) && !CSS_VAR_REFERENCE_RE.test(base)) {
18006
+ report2(node, "arbitraryColor", { class: token });
18007
+ }
18008
+ }
18009
+ if (!checkOpaqueForegroundPairs || isInsideSvg(node)) return;
18010
+ for (const token of tokens) {
18011
+ const prefix = tailwindVariantPrefix(token);
18012
+ if (prefix.split(":").includes("print")) continue;
18013
+ const base = tailwindBase(token);
18014
+ if (!OPAQUE_FOREGROUND_RE.test(base)) continue;
18015
+ const semanticBackground = tokens.find((candidate2) => {
18016
+ if (tailwindVariantPrefix(candidate2) !== prefix) return false;
18017
+ const match = SEMANTIC_BACKGROUND_RE.exec(tailwindBase(candidate2));
18018
+ return match?.[1] !== void 0 && foregroundRoles.has(match[1]);
18019
+ });
18020
+ if (semanticBackground === void 0) continue;
18021
+ const role = SEMANTIC_BACKGROUND_RE.exec(tailwindBase(semanticBackground))?.[1];
18022
+ if (role === void 0) continue;
18023
+ report2(node, "opaqueForegroundPair", {
18024
+ background: semanticBackground,
18025
+ class: token,
18026
+ replacement: `${prefix}text-${role}-foreground`
18027
+ });
18028
+ }
18029
+ };
18033
18030
  function checkClassProperties(node, objectKeys) {
18034
18031
  for (const property of node.properties) {
18035
18032
  if (property.type !== import_utils103.AST_NODE_TYPES.Property) continue;
@@ -18463,80 +18460,6 @@ var prefer_whole_object_assertion_default = createRule({
18463
18460
  return {};
18464
18461
  }
18465
18462
  const { sourceCode } = context;
18466
- function parseAssertion(statement) {
18467
- if (statement.type !== import_utils105.AST_NODE_TYPES.ExpressionStatement) {
18468
- return null;
18469
- }
18470
- const call = statement.expression;
18471
- if (call.type !== import_utils105.AST_NODE_TYPES.CallExpression) {
18472
- return null;
18473
- }
18474
- const callee = call.callee;
18475
- if (callee.type !== import_utils105.AST_NODE_TYPES.MemberExpression || callee.computed || callee.property.type !== import_utils105.AST_NODE_TYPES.Identifier) {
18476
- return null;
18477
- }
18478
- const matcher = callee.property.name;
18479
- const expectCall = callee.object;
18480
- if (expectCall.type !== import_utils105.AST_NODE_TYPES.CallExpression || expectCall.callee.type !== import_utils105.AST_NODE_TYPES.Identifier || expectCall.callee.name !== "expect" || expectCall.arguments.length !== 1) {
18481
- return null;
18482
- }
18483
- const actual = expectCall.arguments[0];
18484
- if (!isTestExpect(expectCall.callee)) return null;
18485
- if (actual === void 0 || actual.type !== import_utils105.AST_NODE_TYPES.MemberExpression || actual.optional) {
18486
- return null;
18487
- }
18488
- if (!isPureReceiver(actual.object)) {
18489
- return null;
18490
- }
18491
- let key;
18492
- let receiver;
18493
- if (actual.computed) {
18494
- const index = literalIndex(actual.property);
18495
- if (index === null) {
18496
- return null;
18497
- }
18498
- key = { kind: "index", index };
18499
- receiver = actual.object;
18500
- } else {
18501
- const access = propertyAccess(actual);
18502
- if (access === null) return null;
18503
- key = { kind: "property", path: access.path };
18504
- receiver = access.receiver;
18505
- }
18506
- return assertionExpectation(statement, call, receiver, key, matcher);
18507
- }
18508
- function assertionExpectation(statement, call, receiver, key, matcher) {
18509
- const synthetic = SYNTHETIC_LITERAL_MATCHERS.get(matcher);
18510
- if (synthetic !== void 0 && call.arguments.length === 0) {
18511
- return { statement, receiver, key, matcher, expectedText: synthetic, expectedIsLiteral: true };
18512
- }
18513
- if (!MERGEABLE_MATCHERS.has(matcher)) {
18514
- return null;
18515
- }
18516
- const expected = call.arguments[0];
18517
- if (call.arguments.length !== 1 || expected === void 0 || expected.type === import_utils105.AST_NODE_TYPES.SpreadElement) {
18518
- return null;
18519
- }
18520
- const literal = literalText(expected, (node) => sourceCode.getText(node));
18521
- return {
18522
- statement,
18523
- receiver,
18524
- key,
18525
- matcher,
18526
- expectedText: literal ?? sourceCode.getText(expected),
18527
- expectedIsLiteral: literal !== null
18528
- };
18529
- }
18530
- function isTestExpect(callee) {
18531
- const variable = import_utils105.ASTUtils.findVariable(sourceCode.getScope(callee), callee.name);
18532
- if (variable !== null && variable.defs.some((definition) => {
18533
- if (definition.node.type !== import_utils105.AST_NODE_TYPES.ImportSpecifier) return true;
18534
- const declaration = definition.node.parent;
18535
- const imported = definition.node.imported;
18536
- return declaration.type !== import_utils105.AST_NODE_TYPES.ImportDeclaration || !["vitest", "@jest/globals", "@playwright/test", "bun:test"].includes(String(declaration.source.value)) || (imported.type === import_utils105.AST_NODE_TYPES.Identifier ? imported.name : imported.value) !== "expect";
18537
- })) return false;
18538
- return true;
18539
- }
18540
18463
  function reportPropertyRun(run) {
18541
18464
  const tree = /* @__PURE__ */ new Map();
18542
18465
  const paths = [];
@@ -18646,6 +18569,80 @@ var prefer_whole_object_assertion_default = createRule({
18646
18569
  }
18647
18570
  flush();
18648
18571
  }
18572
+ function parseAssertion(statement) {
18573
+ if (statement.type !== import_utils105.AST_NODE_TYPES.ExpressionStatement) {
18574
+ return null;
18575
+ }
18576
+ const call = statement.expression;
18577
+ if (call.type !== import_utils105.AST_NODE_TYPES.CallExpression) {
18578
+ return null;
18579
+ }
18580
+ const callee = call.callee;
18581
+ if (callee.type !== import_utils105.AST_NODE_TYPES.MemberExpression || callee.computed || callee.property.type !== import_utils105.AST_NODE_TYPES.Identifier) {
18582
+ return null;
18583
+ }
18584
+ const matcher = callee.property.name;
18585
+ const expectCall = callee.object;
18586
+ if (expectCall.type !== import_utils105.AST_NODE_TYPES.CallExpression || expectCall.callee.type !== import_utils105.AST_NODE_TYPES.Identifier || expectCall.callee.name !== "expect" || expectCall.arguments.length !== 1) {
18587
+ return null;
18588
+ }
18589
+ const actual = expectCall.arguments[0];
18590
+ if (!isTestExpect(expectCall.callee)) return null;
18591
+ if (actual === void 0 || actual.type !== import_utils105.AST_NODE_TYPES.MemberExpression || actual.optional) {
18592
+ return null;
18593
+ }
18594
+ if (!isPureReceiver(actual.object)) {
18595
+ return null;
18596
+ }
18597
+ let key;
18598
+ let receiver;
18599
+ if (actual.computed) {
18600
+ const index = literalIndex(actual.property);
18601
+ if (index === null) {
18602
+ return null;
18603
+ }
18604
+ key = { kind: "index", index };
18605
+ receiver = actual.object;
18606
+ } else {
18607
+ const access = propertyAccess(actual);
18608
+ if (access === null) return null;
18609
+ key = { kind: "property", path: access.path };
18610
+ receiver = access.receiver;
18611
+ }
18612
+ return assertionExpectation(statement, call, receiver, key, matcher);
18613
+ }
18614
+ function isTestExpect(callee) {
18615
+ const variable = import_utils105.ASTUtils.findVariable(sourceCode.getScope(callee), callee.name);
18616
+ if (variable !== null && variable.defs.some((definition) => {
18617
+ if (definition.node.type !== import_utils105.AST_NODE_TYPES.ImportSpecifier) return true;
18618
+ const declaration = definition.node.parent;
18619
+ const imported = definition.node.imported;
18620
+ return declaration.type !== import_utils105.AST_NODE_TYPES.ImportDeclaration || !["vitest", "@jest/globals", "@playwright/test", "bun:test"].includes(String(declaration.source.value)) || (imported.type === import_utils105.AST_NODE_TYPES.Identifier ? imported.name : imported.value) !== "expect";
18621
+ })) return false;
18622
+ return true;
18623
+ }
18624
+ function assertionExpectation(statement, call, receiver, key, matcher) {
18625
+ const synthetic = SYNTHETIC_LITERAL_MATCHERS.get(matcher);
18626
+ if (synthetic !== void 0 && call.arguments.length === 0) {
18627
+ return { statement, receiver, key, matcher, expectedText: synthetic, expectedIsLiteral: true };
18628
+ }
18629
+ if (!MERGEABLE_MATCHERS.has(matcher)) {
18630
+ return null;
18631
+ }
18632
+ const expected = call.arguments[0];
18633
+ if (call.arguments.length !== 1 || expected === void 0 || expected.type === import_utils105.AST_NODE_TYPES.SpreadElement) {
18634
+ return null;
18635
+ }
18636
+ const literal = literalText(expected, (node) => sourceCode.getText(node));
18637
+ return {
18638
+ statement,
18639
+ receiver,
18640
+ key,
18641
+ matcher,
18642
+ expectedText: literal ?? sourceCode.getText(expected),
18643
+ expectedIsLiteral: literal !== null
18644
+ };
18645
+ }
18649
18646
  return {
18650
18647
  BlockStatement: (node) => {
18651
18648
  checkBody(node.body);
@@ -21385,6 +21382,11 @@ var require_use_form_default_values_default = createRule({
21385
21382
  const value = unwrapExpression6(node);
21386
21383
  return value.type === import_utils115.AST_NODE_TYPES.UnaryExpression && value.operator === "void" || value.type === import_utils115.AST_NODE_TYPES.Identifier && value.name === "undefined" && (bindingOf(value)?.defs.length ?? 0) === 0;
21387
21384
  };
21385
+ const uninitializedUseFormCall = (node) => {
21386
+ if (node.type !== import_utils115.AST_NODE_TYPES.CallExpression || node.callee.type !== import_utils115.AST_NODE_TYPES.Identifier || importedKind(node.callee) !== "useForm") return false;
21387
+ const options = node.arguments[0];
21388
+ return options?.type !== import_utils115.AST_NODE_TYPES.SpreadElement && initializationState(options) === "uninitialized";
21389
+ };
21388
21390
  const initializationState = (node) => {
21389
21391
  if (node === void 0) return "uninitialized";
21390
21392
  if (node.type !== import_utils115.AST_NODE_TYPES.ObjectExpression) return "unknown";
@@ -21397,11 +21399,6 @@ var require_use_form_default_values_default = createRule({
21397
21399
  }
21398
21400
  return [...initialization.values()].some(Boolean) ? "initialized" : "uninitialized";
21399
21401
  };
21400
- const uninitializedUseFormCall = (node) => {
21401
- if (node.type !== import_utils115.AST_NODE_TYPES.CallExpression || node.callee.type !== import_utils115.AST_NODE_TYPES.Identifier || importedKind(node.callee) !== "useForm") return false;
21402
- const options = node.arguments[0];
21403
- return options?.type !== import_utils115.AST_NODE_TYPES.SpreadElement && initializationState(options) === "uninitialized";
21404
- };
21405
21402
  const isUninitializedForm = (node) => {
21406
21403
  if (node.type !== import_utils115.AST_NODE_TYPES.Identifier) return false;
21407
21404
  const variable = bindingOf(node);
@@ -21630,28 +21627,13 @@ var require_zod_form_validation_default = createRule({
21630
21627
  context.sourceCode.getScope(identifier),
21631
21628
  identifier.name
21632
21629
  );
21633
- const isProvablyNonZodLocal = (identifier) => {
21634
- const binding = resolvedBinding(identifier);
21635
- if (binding === null || zodBindings.has(binding) || binding.defs.length !== 1) {
21636
- return false;
21637
- }
21638
- const definition = binding.defs[0];
21639
- if (definition?.type !== "Variable" || definition.node.type !== import_utils117.AST_NODE_TYPES.VariableDeclarator) {
21640
- return false;
21641
- }
21642
- const init = definition.node.init;
21643
- return init?.type === import_utils117.AST_NODE_TYPES.ObjectExpression || init?.type === import_utils117.AST_NODE_TYPES.ArrayExpression || init?.type === import_utils117.AST_NODE_TYPES.Literal || init?.type === import_utils117.AST_NODE_TYPES.ArrowFunctionExpression || init?.type === import_utils117.AST_NODE_TYPES.FunctionExpression;
21644
- };
21645
- const isZodParseCall = (node) => {
21646
- if (node.type !== import_utils117.AST_NODE_TYPES.CallExpression) return false;
21630
+ const isFormDataGetCall = (node) => {
21647
21631
  const callee = node.callee;
21648
- if (callee.type !== import_utils117.AST_NODE_TYPES.MemberExpression || callee.computed || callee.property.type !== import_utils117.AST_NODE_TYPES.Identifier || !ZOD_PARSE_METHODS.has(callee.property.name)) {
21632
+ if (callee.type !== import_utils117.AST_NODE_TYPES.MemberExpression) return false;
21633
+ if (callee.property.type !== import_utils117.AST_NODE_TYPES.Identifier || !FORM_VALUE_METHODS.has(callee.property.name)) {
21649
21634
  return false;
21650
21635
  }
21651
- const root = zodReceiverRoot(callee.object);
21652
- if (root === null) return false;
21653
- const binding = resolvedBinding(root);
21654
- return binding !== null && zodBindings.has(binding) || (root.name === "z" || ZOD_SCHEMA_NAME_RE.test(root.name)) && !isProvablyNonZodLocal(root);
21636
+ return isFormSourceIdentifier(callee.object);
21655
21637
  };
21656
21638
  const isFormSourceIdentifier = (node) => {
21657
21639
  if (node.type !== import_utils117.AST_NODE_TYPES.Identifier) return false;
@@ -21670,14 +21652,6 @@ var require_zod_form_validation_default = createRule({
21670
21652
  }
21671
21653
  return conventionalName;
21672
21654
  };
21673
- const isFormDataGetCall = (node) => {
21674
- const callee = node.callee;
21675
- if (callee.type !== import_utils117.AST_NODE_TYPES.MemberExpression) return false;
21676
- if (callee.property.type !== import_utils117.AST_NODE_TYPES.Identifier || !FORM_VALUE_METHODS.has(callee.property.name)) {
21677
- return false;
21678
- }
21679
- return isFormSourceIdentifier(callee.object);
21680
- };
21681
21655
  const zodParseAncestor = (node) => {
21682
21656
  let parent = node.parent;
21683
21657
  while (parent !== null && parent !== void 0) {
@@ -21695,6 +21669,29 @@ var require_zod_form_validation_default = createRule({
21695
21669
  }
21696
21670
  return null;
21697
21671
  };
21672
+ const isZodParseCall = (node) => {
21673
+ if (node.type !== import_utils117.AST_NODE_TYPES.CallExpression) return false;
21674
+ const callee = node.callee;
21675
+ if (callee.type !== import_utils117.AST_NODE_TYPES.MemberExpression || callee.computed || callee.property.type !== import_utils117.AST_NODE_TYPES.Identifier || !ZOD_PARSE_METHODS.has(callee.property.name)) {
21676
+ return false;
21677
+ }
21678
+ const root = zodReceiverRoot(callee.object);
21679
+ if (root === null) return false;
21680
+ const binding = resolvedBinding(root);
21681
+ return binding !== null && zodBindings.has(binding) || (root.name === "z" || ZOD_SCHEMA_NAME_RE.test(root.name)) && !isProvablyNonZodLocal(root);
21682
+ };
21683
+ const isProvablyNonZodLocal = (identifier) => {
21684
+ const binding = resolvedBinding(identifier);
21685
+ if (binding === null || zodBindings.has(binding) || binding.defs.length !== 1) {
21686
+ return false;
21687
+ }
21688
+ const definition = binding.defs[0];
21689
+ if (definition?.type !== "Variable" || definition.node.type !== import_utils117.AST_NODE_TYPES.VariableDeclarator) {
21690
+ return false;
21691
+ }
21692
+ const init = definition.node.init;
21693
+ return init?.type === import_utils117.AST_NODE_TYPES.ObjectExpression || init?.type === import_utils117.AST_NODE_TYPES.ArrayExpression || init?.type === import_utils117.AST_NODE_TYPES.Literal || init?.type === import_utils117.AST_NODE_TYPES.ArrowFunctionExpression || init?.type === import_utils117.AST_NODE_TYPES.FunctionExpression;
21694
+ };
21698
21695
  const hasZodParseAncestor = (node) => zodParseAncestor(node) !== null;
21699
21696
  const isInstanceofNarrowing = (node) => {
21700
21697
  const parent = node.parent;
@@ -21723,28 +21720,6 @@ var require_zod_form_validation_default = createRule({
21723
21720
  }
21724
21721
  return null;
21725
21722
  };
21726
- const zodParseMethod = (call) => {
21727
- const callee = call.callee;
21728
- return callee.type === import_utils117.AST_NODE_TYPES.MemberExpression && !callee.computed && callee.property.type === import_utils117.AST_NODE_TYPES.Identifier ? callee.property.name : null;
21729
- };
21730
- const hasConditionalAncestorBeforeStatement = (node, statement) => {
21731
- let current = node.parent;
21732
- while (current !== void 0 && current !== statement) {
21733
- if (current.type === import_utils117.AST_NODE_TYPES.LogicalExpression || current.type === import_utils117.AST_NODE_TYPES.ConditionalExpression) {
21734
- return true;
21735
- }
21736
- current = current.parent;
21737
- }
21738
- return false;
21739
- };
21740
- const isAwaitedBeforeStatement = (node, statement) => {
21741
- let current = node.parent;
21742
- while (current !== void 0 && current !== statement) {
21743
- if (current.type === import_utils117.AST_NODE_TYPES.AwaitExpression) return true;
21744
- current = current.parent;
21745
- }
21746
- return false;
21747
- };
21748
21723
  const guaranteedValidationStatement = (declarator, reference) => {
21749
21724
  const parse2 = zodParseAncestor(reference);
21750
21725
  if (parse2 === null) return null;
@@ -21763,6 +21738,28 @@ var require_zod_form_validation_default = createRule({
21763
21738
  }
21764
21739
  return null;
21765
21740
  };
21741
+ const isAwaitedBeforeStatement = (node, statement) => {
21742
+ let current = node.parent;
21743
+ while (current !== void 0 && current !== statement) {
21744
+ if (current.type === import_utils117.AST_NODE_TYPES.AwaitExpression) return true;
21745
+ current = current.parent;
21746
+ }
21747
+ return false;
21748
+ };
21749
+ const hasConditionalAncestorBeforeStatement = (node, statement) => {
21750
+ let current = node.parent;
21751
+ while (current !== void 0 && current !== statement) {
21752
+ if (current.type === import_utils117.AST_NODE_TYPES.LogicalExpression || current.type === import_utils117.AST_NODE_TYPES.ConditionalExpression) {
21753
+ return true;
21754
+ }
21755
+ current = current.parent;
21756
+ }
21757
+ return false;
21758
+ };
21759
+ const zodParseMethod = (call) => {
21760
+ const callee = call.callee;
21761
+ return callee.type === import_utils117.AST_NODE_TYPES.MemberExpression && !callee.computed && callee.property.type === import_utils117.AST_NODE_TYPES.Identifier ? callee.property.name : null;
21762
+ };
21766
21763
  const isSafePrevalidationInspection = (identifier) => {
21767
21764
  const parent = identifier.parent;
21768
21765
  if (parent.type === import_utils117.AST_NODE_TYPES.UnaryExpression && parent.operator === "typeof") {
@@ -21943,9 +21940,9 @@ var STEPDOWN_DOCUMENTATION = {
21943
21940
  remediation: "Consider moving the private helper below its sole caller after reviewing initialization and reflection dependencies.",
21944
21941
  category: "maintainability",
21945
21942
  limitations: [
21946
- "Generated and test files, cycles, dynamic references, overload targets, and helpers with multiple callers are excluded.",
21943
+ "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.",
21947
21944
  "Class helpers must be private; their sole caller may be public, protected, or private.",
21948
- "Runtime class-field, static-block, computed-member, and decorator barriers are never crossed.",
21945
+ "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.",
21949
21946
  "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."
21950
21947
  ],
21951
21948
  examples: [
@@ -21957,7 +21954,7 @@ function isFunction(node) {
21957
21954
  return node.type === import_utils119.AST_NODE_TYPES.ArrowFunctionExpression || node.type === import_utils119.AST_NODE_TYPES.FunctionDeclaration || node.type === import_utils119.AST_NODE_TYPES.FunctionExpression;
21958
21955
  }
21959
21956
  function reportMisordered(context, candidates, scopeDefinitions, calls, pinned, canMove = () => true) {
21960
- const byName = new Map(scopeDefinitions.map((definition) => [definition.name, definition]));
21957
+ const byName = new Map(scopeDefinitions.map((definition) => [definition.key, definition]));
21961
21958
  const cycles = cycleComponents(calls);
21962
21959
  const callers = /* @__PURE__ */ new Map();
21963
21960
  for (const [caller, callees] of calls) {
@@ -21969,16 +21966,16 @@ function reportMisordered(context, candidates, scopeDefinitions, calls, pinned,
21969
21966
  }
21970
21967
  }
21971
21968
  for (const helper of candidates) {
21972
- const helperCallers = [...callers.get(helper.name) ?? []];
21973
- if (pinned.has(helper.name) || helperCallers.length !== 1) continue;
21969
+ const helperCallers = [...callers.get(helper.key) ?? []];
21970
+ if (pinned.has(helper.key) || helperCallers.length !== 1) continue;
21974
21971
  const callerName2 = helperCallers[0];
21975
- if (callerName2 === void 0 || cycles.has(helper.name) && cycles.get(helper.name) === cycles.get(callerName2)) continue;
21972
+ if (callerName2 === void 0 || cycles.has(helper.key) && cycles.get(helper.key) === cycles.get(callerName2)) continue;
21976
21973
  const caller = byName.get(callerName2);
21977
21974
  if (caller === void 0 || helper.node.range[0] >= caller.node.range[0] || !canMove(helper, caller)) continue;
21978
21975
  context.report({
21979
21976
  node: helper.node,
21980
21977
  messageId: "helperAboveOnlyCaller",
21981
- data: { helper: helper.name, caller: callerName2 }
21978
+ data: { helper: helper.name, caller: caller.name }
21982
21979
  });
21983
21980
  }
21984
21981
  }
@@ -22049,8 +22046,46 @@ function cycleComponents(graph) {
22049
22046
  }
22050
22047
  return components;
22051
22048
  }
22052
- function moduleScope(context, program) {
22049
+ function isErasedExpression(node) {
22050
+ return node.type === import_utils119.AST_NODE_TYPES.TSAsExpression || node.type === import_utils119.AST_NODE_TYPES.TSTypeAssertion || node.type === import_utils119.AST_NODE_TYPES.TSSatisfiesExpression || node.type === import_utils119.AST_NODE_TYPES.TSNonNullExpression || node.type === import_utils119.AST_NODE_TYPES.TSInstantiationExpression;
22051
+ }
22052
+ function unwrapExpression7(node) {
22053
+ let current = node;
22054
+ while (isErasedExpression(current)) current = current.expression;
22055
+ return current;
22056
+ }
22057
+ function wrappedExpression(node) {
22058
+ let current = node;
22059
+ while (current.parent !== void 0 && isErasedExpression(current.parent) && current.parent.expression === current) current = current.parent;
22060
+ return current;
22061
+ }
22062
+ function enclosingFunction5(context, node) {
22063
+ return [...context.sourceCode.getAncestors(node)].reverse().find(isFunction);
22064
+ }
22065
+ function localCallCount(context, node, owner) {
22066
+ const seen = /* @__PURE__ */ new Set();
22067
+ const pending = [node];
22068
+ let count = 0;
22069
+ while (pending.length > 0) {
22070
+ const current = pending.pop();
22071
+ if (current === void 0 || enclosingFunction5(context, current) !== owner) return null;
22072
+ const expression = wrappedExpression(current);
22073
+ const parent = expression.parent;
22074
+ if (parent?.type === import_utils119.AST_NODE_TYPES.CallExpression && parent.callee === expression) {
22075
+ count += 1;
22076
+ continue;
22077
+ }
22078
+ if (parent?.type !== import_utils119.AST_NODE_TYPES.VariableDeclarator || parent.init !== expression || parent.id.type !== import_utils119.AST_NODE_TYPES.Identifier || parent.parent.type !== import_utils119.AST_NODE_TYPES.VariableDeclaration || parent.parent.kind !== "const") return null;
22079
+ const variable = context.sourceCode.getDeclaredVariables(parent)[0];
22080
+ if (variable === void 0 || seen.has(variable) || !stableVariable(variable)) return null;
22081
+ seen.add(variable);
22082
+ pending.push(...variable.references.filter((reference) => reference.isRead()).map((reference) => reference.identifier));
22083
+ }
22084
+ return count;
22085
+ }
22086
+ function declarationScope(context, program) {
22053
22087
  const declarations = moduleDefinitions(program);
22088
+ if (declarations.length < 2) return;
22054
22089
  const counts = /* @__PURE__ */ new Map();
22055
22090
  for (const node of declarations) counts.set(node.name, (counts.get(node.name) ?? 0) + 1);
22056
22091
  const overloadNames = new Set(
@@ -22059,11 +22094,31 @@ function moduleScope(context, program) {
22059
22094
  return node?.type === import_utils119.AST_NODE_TYPES.TSDeclareFunction && node.id !== null ? [node.id.name] : [];
22060
22095
  })
22061
22096
  );
22062
- const exported = exportedNames(program);
22097
+ const exported = program.type === import_utils119.AST_NODE_TYPES.Program ? exportedNames(program) : /* @__PURE__ */ new Set();
22063
22098
  const scopeDefinitions = declarations.filter((node) => counts.get(node.name) === 1);
22064
22099
  const definitions = scopeDefinitions.filter(
22065
22100
  (definition) => !exported.has(definition.name) && !overloadNames.has(definition.name)
22066
22101
  );
22102
+ const { calls, pinned } = moduleCallGraph(context, scopeDefinitions);
22103
+ const statementIndexes = new Map(program.body.map((statement, index) => [statement, index]));
22104
+ const runtimeBarrierPrefix = [0];
22105
+ for (const statement of program.body) {
22106
+ runtimeBarrierPrefix.push((runtimeBarrierPrefix.at(-1) ?? 0) + (isDeferredModuleStatement(statement) ? 0 : 1));
22107
+ }
22108
+ const canMove = (helper, caller) => {
22109
+ if (helper.node.type === import_utils119.AST_NODE_TYPES.FunctionDeclaration) return true;
22110
+ const helperIndex = statementIndex(helper);
22111
+ const callerIndex = statementIndex(caller);
22112
+ return helperIndex !== void 0 && callerIndex !== void 0 && runtimeBarrierPrefix[callerIndex + 1] === runtimeBarrierPrefix[helperIndex + 1];
22113
+ };
22114
+ const statementIndex = (definition) => {
22115
+ let current = definition.node;
22116
+ while (current.parent !== void 0 && current.parent !== program) current = current.parent;
22117
+ return statementIndexes.get(current);
22118
+ };
22119
+ reportMisordered(context, definitions, scopeDefinitions, calls, pinned, canMove);
22120
+ }
22121
+ function moduleCallGraph(context, scopeDefinitions) {
22067
22122
  const byFunction = new Map(scopeDefinitions.map((definition) => [definition.functionNode, definition]));
22068
22123
  const calls = /* @__PURE__ */ new Map();
22069
22124
  const pinned = /* @__PURE__ */ new Set();
@@ -22071,26 +22126,33 @@ function moduleScope(context, program) {
22071
22126
  const variable = context.sourceCode.getDeclaredVariables(definition.bindingNode)[0];
22072
22127
  for (const reference of variable?.references ?? []) {
22073
22128
  if (reference.isWrite() && reference.init !== true) {
22074
- pinned.add(definition.name);
22129
+ pinned.add(definition.key);
22075
22130
  continue;
22076
22131
  }
22077
22132
  if (!reference.isRead()) continue;
22078
- const identifier = reference.identifier;
22079
- const ancestors = context.sourceCode.getAncestors(identifier);
22080
- const nearestFunction2 = [...ancestors].reverse().find(isFunction);
22081
- const parent = identifier.parent;
22082
- const callerDefinition = nearestFunction2 === void 0 ? void 0 : byFunction.get(nearestFunction2);
22083
- if (callerDefinition === void 0 || parent.type !== import_utils119.AST_NODE_TYPES.CallExpression || parent.callee !== identifier) {
22084
- pinned.add(definition.name);
22133
+ const callerDefinition = byFunction.get(enclosingFunction5(context, reference.identifier));
22134
+ if (callerDefinition?.functionNode === void 0) {
22135
+ pinned.add(definition.key);
22085
22136
  continue;
22086
22137
  }
22087
- const caller = callerDefinition.name;
22088
- const callees = calls.get(caller) ?? /* @__PURE__ */ new Set();
22089
- callees.add(definition.name);
22090
- calls.set(caller, callees);
22138
+ const count = localCallCount(context, reference.identifier, callerDefinition.functionNode);
22139
+ if (count === null) {
22140
+ pinned.add(definition.key);
22141
+ } else if (count > 0) {
22142
+ const callees = calls.get(callerDefinition.key) ?? /* @__PURE__ */ new Set();
22143
+ callees.add(definition.key);
22144
+ calls.set(callerDefinition.key, callees);
22145
+ }
22091
22146
  }
22092
22147
  }
22093
- reportMisordered(context, definitions, scopeDefinitions, calls, pinned);
22148
+ return { calls, pinned };
22149
+ }
22150
+ function isDeferredModuleStatement(statement) {
22151
+ const node = statement.type === import_utils119.AST_NODE_TYPES.ExportNamedDeclaration || statement.type === import_utils119.AST_NODE_TYPES.ExportDefaultDeclaration ? statement.declaration : statement;
22152
+ if (node === null || node.type === import_utils119.AST_NODE_TYPES.FunctionDeclaration || node.type === import_utils119.AST_NODE_TYPES.TSDeclareFunction || node.type === import_utils119.AST_NODE_TYPES.TSInterfaceDeclaration || node.type === import_utils119.AST_NODE_TYPES.TSTypeAliasDeclaration || node.type === import_utils119.AST_NODE_TYPES.ImportDeclaration || node.type === import_utils119.AST_NODE_TYPES.ExportAllDeclaration || node.type === import_utils119.AST_NODE_TYPES.EmptyStatement) return true;
22153
+ return node.type === import_utils119.AST_NODE_TYPES.VariableDeclaration && node.declarations.every(
22154
+ (declaration) => declaration.id.type === import_utils119.AST_NODE_TYPES.Identifier && declaration.init !== null && isFunction(unwrapExpression7(declaration.init))
22155
+ );
22094
22156
  }
22095
22157
  function exportedNames(program) {
22096
22158
  const names = /* @__PURE__ */ new Set();
@@ -22124,16 +22186,18 @@ function moduleDefinitions(program) {
22124
22186
  for (const statement of program.body) {
22125
22187
  const node = statement.type === import_utils119.AST_NODE_TYPES.ExportNamedDeclaration || statement.type === import_utils119.AST_NODE_TYPES.ExportDefaultDeclaration ? statement.declaration : statement;
22126
22188
  if (node?.type === import_utils119.AST_NODE_TYPES.FunctionDeclaration && node.id !== null && node.body !== null) {
22127
- definitions.push({ name: node.id.name, node, functionNode: node, bindingNode: node });
22189
+ definitions.push({ key: node.id.name, name: node.id.name, node, functionNode: node, bindingNode: node });
22128
22190
  continue;
22129
22191
  }
22130
- if (node?.type !== import_utils119.AST_NODE_TYPES.VariableDeclaration || node.kind !== "const") continue;
22192
+ if (node?.type !== import_utils119.AST_NODE_TYPES.VariableDeclaration || node.kind !== "const" || node.declarations.length !== 1) continue;
22131
22193
  for (const declarator of node.declarations) {
22132
- if (declarator.id.type === import_utils119.AST_NODE_TYPES.Identifier && declarator.init !== null && isFunction(declarator.init)) {
22194
+ const initializer = declarator.init === null ? null : unwrapExpression7(declarator.init);
22195
+ if (declarator.id.type === import_utils119.AST_NODE_TYPES.Identifier && initializer !== null && isFunction(initializer)) {
22133
22196
  definitions.push({
22197
+ key: declarator.id.name,
22134
22198
  name: declarator.id.name,
22135
22199
  node: declarator,
22136
- functionNode: declarator.init,
22200
+ functionNode: initializer,
22137
22201
  bindingNode: declarator
22138
22202
  });
22139
22203
  }
@@ -22143,15 +22207,50 @@ function moduleDefinitions(program) {
22143
22207
  }
22144
22208
  function methodName2(node) {
22145
22209
  if (node.key.type === import_utils119.AST_NODE_TYPES.PrivateIdentifier) return `#${node.key.name}`;
22146
- return !node.computed && node.key.type === import_utils119.AST_NODE_TYPES.Identifier ? node.key.name : null;
22210
+ if (!node.computed && node.key.type === import_utils119.AST_NODE_TYPES.Identifier) return node.key.name;
22211
+ return node.key.type === import_utils119.AST_NODE_TYPES.Literal && typeof node.key.value === "string" ? node.key.value : null;
22147
22212
  }
22148
- function referencedMethod(context, node, classVariables) {
22149
- const objectVariable = node.object.type === import_utils119.AST_NODE_TYPES.Identifier ? import_utils119.ASTUtils.findVariable(context.sourceCode.getScope(node.object), node.object.name) : null;
22150
- const isClassReference = objectVariable !== null && classVariables.has(objectVariable);
22151
- if (node.object.type !== import_utils119.AST_NODE_TYPES.ThisExpression && !isClassReference) return null;
22152
- if (node.property.type === import_utils119.AST_NODE_TYPES.PrivateIdentifier) return `#${node.property.name}`;
22153
- if (!node.computed && node.property.type === import_utils119.AST_NODE_TYPES.Identifier) return node.property.name;
22154
- return node.computed && node.property.type === import_utils119.AST_NODE_TYPES.Literal && typeof node.property.value === "string" ? node.property.value : null;
22213
+ function methodKey(name, isStatic2) {
22214
+ return `${isStatic2 ? "static" : "instance"}:${name}`;
22215
+ }
22216
+ function receiverDomain(context, object, receivers, thisIsStatic) {
22217
+ const unwrapped = unwrapExpression7(object);
22218
+ if (unwrapped.type === import_utils119.AST_NODE_TYPES.ThisExpression) return thisIsStatic;
22219
+ return externalReceiverDomain(context, unwrapped, receivers);
22220
+ }
22221
+ function externalReceiverDomain(context, object, receivers) {
22222
+ const origin = receiverOrigin(context, object, receivers);
22223
+ if (origin === null || typeof origin === "boolean") return origin;
22224
+ if (origin.type === import_utils119.AST_NODE_TYPES.NewExpression) {
22225
+ return receiverOrigin(context, origin.callee, receivers) === true ? false : null;
22226
+ }
22227
+ if (origin.type === import_utils119.AST_NODE_TYPES.ObjectExpression || origin.type === import_utils119.AST_NODE_TYPES.ArrayExpression || origin.type === import_utils119.AST_NODE_TYPES.Literal || origin.type === import_utils119.AST_NODE_TYPES.ArrowFunctionExpression || origin.type === import_utils119.AST_NODE_TYPES.FunctionExpression) return "unrelated";
22228
+ return null;
22229
+ }
22230
+ function receiverOrigin(context, object, receivers) {
22231
+ let current = object;
22232
+ const seen = /* @__PURE__ */ new Set();
22233
+ while (true) {
22234
+ const unwrapped = unwrapExpression7(current);
22235
+ if (unwrapped.type !== import_utils119.AST_NODE_TYPES.Identifier) return unwrapped;
22236
+ const variable = import_utils119.ASTUtils.findVariable(context.sourceCode.getScope(unwrapped), unwrapped.name);
22237
+ if (variable === null) return null;
22238
+ const known = receivers.get(variable);
22239
+ if (known !== void 0) return known;
22240
+ const initializer = immutableInitializer(variable, seen);
22241
+ if (initializer === null) return null;
22242
+ current = initializer;
22243
+ }
22244
+ }
22245
+ function immutableInitializer(variable, seen) {
22246
+ if (seen.has(variable) || !stableVariable(variable) || variable.defs.length !== 1) return null;
22247
+ seen.add(variable);
22248
+ const definition = variable.defs[0];
22249
+ if (definition?.node.type !== import_utils119.AST_NODE_TYPES.VariableDeclarator || definition.node.parent.type !== import_utils119.AST_NODE_TYPES.VariableDeclaration || definition.node.parent.kind !== "const") return null;
22250
+ return definition.node.init;
22251
+ }
22252
+ function stableVariable(variable) {
22253
+ return !variable.references.some((reference) => reference.isWrite() && reference.init !== true);
22155
22254
  }
22156
22255
  function referencedPropertyName(node) {
22157
22256
  if (node.property.type === import_utils119.AST_NODE_TYPES.PrivateIdentifier) return `#${node.property.name}`;
@@ -22160,131 +22259,145 @@ function referencedPropertyName(node) {
22160
22259
  }
22161
22260
  function walk(node, visitorKeys, visit, nestedFunction = false) {
22162
22261
  visit(node, nestedFunction);
22163
- const nested = nestedFunction || isFunction(node);
22262
+ const nested = nestedFunction || isFunction(node) || node.type === import_utils119.AST_NODE_TYPES.ClassDeclaration || node.type === import_utils119.AST_NODE_TYPES.ClassExpression;
22164
22263
  forEachAstChild(node, visitorKeys, (child) => walk(child, visitorKeys, visit, nested));
22165
22264
  }
22166
- function classScope(context, node, computedReferenceNames) {
22265
+ function classScope(context, node, computedReferences) {
22167
22266
  const methods = node.body.body.filter(
22168
22267
  (member) => member.type === import_utils119.AST_NODE_TYPES.MethodDefinition
22169
22268
  );
22170
22269
  const counts = classMethodCounts(node.body, methods);
22171
- const scopeDefinitions = methods.flatMap((method) => {
22172
- const name = methodName2(method);
22173
- return name !== null && counts.get(name) === 1 ? [{ name, node: method }] : [];
22174
- });
22175
- const definitions = methods.flatMap((method) => {
22270
+ const implementations = methods.filter((method) => isFunction(method.value));
22271
+ const implementationCounts = classMethodCounts(node.body, implementations);
22272
+ const scopeDefinitions = implementations.flatMap((method) => {
22176
22273
  const name = methodName2(method);
22177
- const isPrivate = method.accessibility === "private" || method.key.type === import_utils119.AST_NODE_TYPES.PrivateIdentifier;
22178
- return name !== null && isPrivate && counts.get(name) === 1 && method.decorators.length === 0 ? [{ name, node: method }] : [];
22274
+ const key = name === null ? null : methodKey(name, method.static);
22275
+ return name !== null && key !== null && implementationCounts.get(key) === 1 ? [{ key, name, node: method }] : [];
22179
22276
  });
22277
+ const definitions = scopeDefinitions.filter(
22278
+ ({ key, node: method }) => (method.accessibility === "private" || method.key.type === import_utils119.AST_NODE_TYPES.PrivateIdentifier) && counts.get(key) === 1 && method.decorators.length === 0 && !method.computed && method.kind === "method"
22279
+ );
22180
22280
  if (definitions.length === 0) return;
22181
- const privateNames = new Set(definitions.map((definition) => definition.name));
22281
+ const methodKeys = new Set(scopeDefinitions.map((definition) => definition.key));
22182
22282
  const calls = /* @__PURE__ */ new Map();
22183
22283
  const pinned = /* @__PURE__ */ new Set();
22184
- const classVariables = /* @__PURE__ */ new Set();
22185
- if (node.id !== null) {
22186
- const internal = import_utils119.ASTUtils.findVariable(context.sourceCode.getScope(node), node.id.name);
22187
- if (internal !== null) classVariables.add(internal);
22188
- }
22189
- if (node.type === import_utils119.AST_NODE_TYPES.ClassExpression && node.parent.type === import_utils119.AST_NODE_TYPES.VariableDeclarator && node.parent.id.type === import_utils119.AST_NODE_TYPES.Identifier) {
22190
- const outer = import_utils119.ASTUtils.findVariable(context.sourceCode.getScope(node.parent), node.parent.id.name);
22191
- if (outer !== null) classVariables.add(outer);
22284
+ const classReceivers = classReceiverBindings(context, node);
22285
+ const pinNames = (name, domain = null) => {
22286
+ for (const definition of definitions) {
22287
+ if ((name === null || definition.name === name) && (domain === null || definition.node.static === domain)) {
22288
+ pinned.add(definition.key);
22289
+ }
22290
+ }
22291
+ };
22292
+ function pinDestructuredMembers(binding, domain) {
22293
+ for (const property of binding.properties) {
22294
+ if (property.type === import_utils119.AST_NODE_TYPES.RestElement || property.computed) {
22295
+ pinNames(null, domain);
22296
+ } else if (property.key.type === import_utils119.AST_NODE_TYPES.Identifier) {
22297
+ pinNames(property.key.name, domain);
22298
+ } else if (property.key.type === import_utils119.AST_NODE_TYPES.Literal && typeof property.key.value === "string") {
22299
+ pinNames(property.key.value, domain);
22300
+ }
22301
+ }
22192
22302
  }
22193
22303
  function collectMethodCalls(method) {
22194
- const caller = methodName2(method);
22195
- if (caller === null || method.value.body === null) return;
22196
- const methodClassVariables = new Set(classVariables);
22197
- const methodAliases = /* @__PURE__ */ new Set();
22304
+ const name = methodName2(method);
22305
+ if (name === null) {
22306
+ pinNames(null);
22307
+ return;
22308
+ }
22309
+ if (!isFunction(method.value)) return;
22310
+ const methodFunction = method.value;
22311
+ const caller = methodKey(name, method.static);
22312
+ const receivers = new Map(classReceivers);
22198
22313
  const parameterDecoratorNodes = /* @__PURE__ */ new Set();
22199
22314
  for (const parameter of method.value.params) {
22200
22315
  for (const decorator of parameter.decorators) {
22201
22316
  walk(decorator, context.sourceCode.visitorKeys, (current) => parameterDecoratorNodes.add(current));
22202
22317
  }
22203
22318
  }
22204
- const thisValue = (value) => {
22205
- let current = value;
22206
- while (current?.type === import_utils119.AST_NODE_TYPES.TSAsExpression || current?.type === import_utils119.AST_NODE_TYPES.TSSatisfiesExpression || current?.type === import_utils119.AST_NODE_TYPES.TSNonNullExpression) current = current.expression;
22207
- return current?.type === import_utils119.AST_NODE_TYPES.ThisExpression;
22208
- };
22209
22319
  const collectAlias = (current, nestedFunction) => {
22210
- if (nestedFunction || current.type !== import_utils119.AST_NODE_TYPES.VariableDeclarator && current.type !== import_utils119.AST_NODE_TYPES.AssignmentPattern) return;
22211
- if (current.type === import_utils119.AST_NODE_TYPES.VariableDeclarator && (current.parent.type !== import_utils119.AST_NODE_TYPES.VariableDeclaration || current.parent.kind !== "const")) return;
22212
- const binding = current.type === import_utils119.AST_NODE_TYPES.VariableDeclarator ? current.id : current.left;
22213
- const value = current.type === import_utils119.AST_NODE_TYPES.VariableDeclarator ? current.init : current.right;
22214
- if (!thisValue(value)) return;
22215
- if (binding.type === import_utils119.AST_NODE_TYPES.ObjectPattern) {
22216
- pinDestructuredMembers(binding);
22320
+ if (nestedFunction || current.type !== import_utils119.AST_NODE_TYPES.VariableDeclarator || current.init === null) return;
22321
+ const domain = receiverDomain(context, current.init, receivers, method.static);
22322
+ if (domain === null || domain === "unrelated") return;
22323
+ if (current.id.type === import_utils119.AST_NODE_TYPES.ObjectPattern) {
22324
+ pinDestructuredMembers(current.id, domain);
22217
22325
  return;
22218
22326
  }
22219
- if (binding.type !== import_utils119.AST_NODE_TYPES.Identifier) return;
22220
- const variable = import_utils119.ASTUtils.findVariable(context.sourceCode.getScope(binding), binding.name);
22221
- if (variable !== null) {
22222
- methodClassVariables.add(variable);
22223
- methodAliases.add(variable);
22327
+ if (current.id.type !== import_utils119.AST_NODE_TYPES.Identifier) return;
22328
+ if (current.parent.type !== import_utils119.AST_NODE_TYPES.VariableDeclaration || current.parent.kind !== "const") {
22329
+ pinNames(null, domain);
22330
+ return;
22224
22331
  }
22332
+ const variable = context.sourceCode.getDeclaredVariables(current)[0];
22333
+ if (variable === void 0 || !stableVariable(variable)) return;
22334
+ const local = variable.references.every((reference) => {
22335
+ if (!reference.isRead()) return true;
22336
+ const expression = wrappedExpression(reference.identifier);
22337
+ return enclosingFunction5(context, reference.identifier) === methodFunction && expression.parent?.type === import_utils119.AST_NODE_TYPES.MemberExpression && expression.parent.object === expression;
22338
+ });
22339
+ if (local) receivers.set(variable, domain);
22340
+ else pinNames(null, domain);
22225
22341
  };
22226
- for (const parameter of method.value.params) {
22227
- walk(parameter, context.sourceCode.visitorKeys, collectAlias);
22228
- }
22229
- for (const statement of method.value.body.body) {
22230
- walk(statement, context.sourceCode.visitorKeys, collectAlias);
22231
- }
22232
- function pinDestructuredMembers(binding) {
22233
- for (const property of binding.properties) {
22234
- if (property.type === import_utils119.AST_NODE_TYPES.RestElement) {
22235
- for (const name of privateNames) pinned.add(name);
22236
- } else if (property.key.type === import_utils119.AST_NODE_TYPES.Identifier && privateNames.has(property.key.name)) {
22237
- pinned.add(property.key.name);
22238
- }
22239
- }
22240
- }
22342
+ for (const statement of method.value.body.body) walk(statement, context.sourceCode.visitorKeys, collectAlias);
22241
22343
  const visitCall = (current, nestedFunction) => {
22242
- if (current.type === import_utils119.AST_NODE_TYPES.VariableDeclarator && current.id.type === import_utils119.AST_NODE_TYPES.ObjectPattern && thisValue(current.init)) {
22243
- pinDestructuredMembers(current.id);
22344
+ const destructuring = receiverDestructuring(current);
22345
+ if (destructuring !== null) {
22346
+ const domain2 = receiverDomain(context, destructuring.value, receivers, method.static);
22347
+ if (domain2 !== "unrelated") pinDestructuredMembers(destructuring.binding, domain2);
22244
22348
  }
22245
22349
  if (current.type !== import_utils119.AST_NODE_TYPES.MemberExpression) return;
22246
- const target = referencedMethod(context, current, methodClassVariables);
22247
- if (target === null) {
22248
- const possibleTarget = referencedPropertyName(current);
22249
- if (possibleTarget !== null && privateNames.has(possibleTarget)) pinned.add(possibleTarget);
22350
+ const domain = receiverDomain(context, current.object, receivers, method.static);
22351
+ const targetName = referencedPropertyName(current);
22352
+ if (domain === "unrelated") return;
22353
+ if (domain === null) {
22354
+ pinNames(targetName);
22250
22355
  return;
22251
22356
  }
22252
- if (!privateNames.has(target)) return;
22253
- const objectVariable = current.object.type === import_utils119.AST_NODE_TYPES.Identifier ? import_utils119.ASTUtils.findVariable(context.sourceCode.getScope(current.object), current.object.name) : null;
22254
- if (objectVariable !== null && methodAliases.has(objectVariable)) {
22255
- pinned.add(target);
22357
+ if (targetName === null) {
22358
+ if (current.computed) pinNames(null, domain);
22256
22359
  return;
22257
22360
  }
22258
- if (current.computed || nestedFunction || parameterDecoratorNodes.has(current) || current.parent.type !== import_utils119.AST_NODE_TYPES.CallExpression || current.parent.callee !== current) {
22361
+ const target = methodKey(targetName, domain);
22362
+ if (!methodKeys.has(target)) return;
22363
+ if (current.computed || nestedFunction || parameterDecoratorNodes.has(current)) {
22259
22364
  pinned.add(target);
22260
22365
  return;
22261
22366
  }
22262
- const callees = calls.get(caller) ?? /* @__PURE__ */ new Set();
22263
- callees.add(target);
22264
- calls.set(caller, callees);
22367
+ const count = localCallCount(context, current, methodFunction);
22368
+ if (count === null) {
22369
+ pinned.add(target);
22370
+ } else if (count > 0) {
22371
+ const callees = calls.get(caller) ?? /* @__PURE__ */ new Set();
22372
+ callees.add(target);
22373
+ calls.set(caller, callees);
22374
+ }
22265
22375
  };
22266
- for (const decorator of method.decorators) {
22267
- walk(decorator, context.sourceCode.visitorKeys, visitCall, true);
22268
- }
22376
+ for (const decorator of method.decorators) walk(decorator, context.sourceCode.visitorKeys, visitCall, true);
22269
22377
  if (method.computed) walk(method.key, context.sourceCode.visitorKeys, visitCall, true);
22270
- for (const parameter of method.value.params) {
22271
- walk(parameter, context.sourceCode.visitorKeys, visitCall);
22272
- }
22273
- for (const statement of method.value.body.body) {
22274
- walk(statement, context.sourceCode.visitorKeys, visitCall);
22275
- }
22378
+ for (const parameter of method.value.params) walk(parameter, context.sourceCode.visitorKeys, visitCall);
22379
+ for (const statement of method.value.body.body) walk(statement, context.sourceCode.visitorKeys, visitCall);
22276
22380
  }
22277
22381
  for (const method of methods) collectMethodCalls(method);
22278
22382
  for (const member of node.body.body) {
22279
22383
  if (member.type === import_utils119.AST_NODE_TYPES.MethodDefinition || member.type === import_utils119.AST_NODE_TYPES.TSAbstractMethodDefinition) continue;
22280
22384
  walk(member, context.sourceCode.visitorKeys, (current) => {
22281
22385
  if (current.type !== import_utils119.AST_NODE_TYPES.MemberExpression) return;
22282
- const target = referencedMethod(context, current, classVariables);
22283
- const possibleTarget = target ?? referencedPropertyName(current);
22284
- if (possibleTarget !== null && privateNames.has(possibleTarget)) pinned.add(possibleTarget);
22386
+ if (externalReceiverDomain(context, current.object, classReceivers) === "unrelated") return;
22387
+ pinNames(referencedPropertyName(current));
22285
22388
  });
22286
22389
  }
22287
- for (const name of privateNames) if (computedReferenceNames.has(name)) pinned.add(name);
22390
+ const externalReceivers = new Map(classReceivers);
22391
+ for (const variable of context.sourceCode.getDeclaredVariables(node)) {
22392
+ if (stableVariable(variable)) externalReceivers.set(variable, true);
22393
+ }
22394
+ for (const reference of computedReferences) {
22395
+ if (context.sourceCode.getAncestors(reference).includes(node)) continue;
22396
+ const domain = externalReceiverDomain(context, reference.object, externalReceivers);
22397
+ if (domain === "unrelated") continue;
22398
+ const name = referencedPropertyName(reference);
22399
+ if (name !== null || domain !== null) pinNames(name, domain);
22400
+ }
22288
22401
  const memberIndexes = new Map(node.body.body.map((member, index) => [member, index]));
22289
22402
  const runtimeBarrierPrefix = [0];
22290
22403
  for (const member of node.body.body) {
@@ -22298,6 +22411,27 @@ function classScope(context, node, computedReferenceNames) {
22298
22411
  };
22299
22412
  reportMisordered(context, definitions, scopeDefinitions, calls, pinned, canMove);
22300
22413
  }
22414
+ function classReceiverBindings(context, node) {
22415
+ const classReceivers = /* @__PURE__ */ new Map();
22416
+ if (node.id !== null) {
22417
+ const internal = import_utils119.ASTUtils.findVariable(context.sourceCode.getScope(node), node.id.name);
22418
+ if (internal !== null && stableVariable(internal)) classReceivers.set(internal, true);
22419
+ }
22420
+ if (node.type === import_utils119.AST_NODE_TYPES.ClassExpression && node.parent.type === import_utils119.AST_NODE_TYPES.VariableDeclarator && node.parent.id.type === import_utils119.AST_NODE_TYPES.Identifier && node.parent.parent.type === import_utils119.AST_NODE_TYPES.VariableDeclaration && node.parent.parent.kind === "const") {
22421
+ const outer = import_utils119.ASTUtils.findVariable(context.sourceCode.getScope(node.parent), node.parent.id.name);
22422
+ if (outer !== null && stableVariable(outer)) classReceivers.set(outer, true);
22423
+ }
22424
+ return classReceivers;
22425
+ }
22426
+ function receiverDestructuring(node) {
22427
+ if (node.type === import_utils119.AST_NODE_TYPES.VariableDeclarator && node.id.type === import_utils119.AST_NODE_TYPES.ObjectPattern && node.init !== null) {
22428
+ return { binding: node.id, value: node.init };
22429
+ }
22430
+ if ((node.type === import_utils119.AST_NODE_TYPES.AssignmentPattern || node.type === import_utils119.AST_NODE_TYPES.AssignmentExpression) && node.left.type === import_utils119.AST_NODE_TYPES.ObjectPattern) {
22431
+ return { binding: node.left, value: node.right };
22432
+ }
22433
+ return null;
22434
+ }
22301
22435
  function isClassRuntimeBarrier(member) {
22302
22436
  switch (member.type) {
22303
22437
  case import_utils119.AST_NODE_TYPES.StaticBlock:
@@ -22326,6 +22460,7 @@ var stepdown_default = createRule({
22326
22460
  create(context) {
22327
22461
  if (isTestFile(context.filename) || isGeneratedFile(context.filename, context.sourceCode.text)) return {};
22328
22462
  const classes = [];
22463
+ const functionBodies = [];
22329
22464
  return {
22330
22465
  ClassDeclaration: (node) => {
22331
22466
  classes.push(node);
@@ -22333,13 +22468,17 @@ var stepdown_default = createRule({
22333
22468
  ClassExpression: (node) => {
22334
22469
  classes.push(node);
22335
22470
  },
22471
+ "FunctionDeclaration, FunctionExpression, ArrowFunctionExpression": (node) => {
22472
+ if (isFunction(node) && node.body?.type === import_utils119.AST_NODE_TYPES.BlockStatement) functionBodies.push(node.body);
22473
+ },
22336
22474
  "Program:exit": (program) => {
22337
- moduleScope(context, program);
22338
- const computedReferenceNames = /* @__PURE__ */ new Set();
22475
+ declarationScope(context, program);
22476
+ for (const body2 of functionBodies) declarationScope(context, body2);
22477
+ const computedReferences = [];
22339
22478
  walk(program, context.sourceCode.visitorKeys, (node) => {
22340
- if (node.type === import_utils119.AST_NODE_TYPES.MemberExpression && node.computed && node.property.type === import_utils119.AST_NODE_TYPES.Literal && typeof node.property.value === "string") computedReferenceNames.add(node.property.value);
22479
+ if (node.type === import_utils119.AST_NODE_TYPES.MemberExpression && node.computed) computedReferences.push(node);
22341
22480
  });
22342
- for (const node of classes) classScope(context, node, computedReferenceNames);
22481
+ for (const node of classes) classScope(context, node, computedReferences);
22343
22482
  }
22344
22483
  };
22345
22484
  }
@@ -22348,12 +22487,18 @@ function classMethodCounts(body2, methods) {
22348
22487
  const counts = /* @__PURE__ */ new Map();
22349
22488
  for (const method of methods) {
22350
22489
  const name = methodName2(method);
22351
- if (name !== null) counts.set(name, (counts.get(name) ?? 0) + 1);
22490
+ if (name !== null) {
22491
+ const key = methodKey(name, method.static);
22492
+ counts.set(key, (counts.get(key) ?? 0) + 1);
22493
+ }
22352
22494
  }
22353
22495
  for (const member of body2.body) {
22354
22496
  if (member.type !== import_utils119.AST_NODE_TYPES.TSAbstractMethodDefinition) continue;
22355
22497
  const name = !member.computed && member.key.type === import_utils119.AST_NODE_TYPES.Identifier ? member.key.name : null;
22356
- if (name !== null) counts.set(name, (counts.get(name) ?? 0) + 1);
22498
+ if (name !== null) {
22499
+ const key = methodKey(name, member.static);
22500
+ counts.set(key, (counts.get(key) ?? 0) + 1);
22501
+ }
22357
22502
  }
22358
22503
  return counts;
22359
22504
  }
@@ -22685,16 +22830,70 @@ function importedAssertionKind(specifier) {
22685
22830
 
22686
22831
  // src/rules/sole-export-matches-filename.ts
22687
22832
  var import_utils121 = require("@typescript-eslint/utils");
22833
+
22834
+ // src/rules/_is-framework-entrypoint.ts
22835
+ var import_node_fs2 = require("fs");
22836
+ var import_node_path2 = require("path");
22837
+ var HTTP_METHODS = /* @__PURE__ */ new Set(["GET", "HEAD", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"]);
22838
+ var NEXT_COMPONENT = /^(?:src\/)?app\/(?:.*\/)?(?:page|layout|loading|not-found|template|error|global-error|default|forbidden|unauthorized)\.[jt]sx?$/u;
22839
+ var NEXT_ROUTE = /^(?:src\/)?app\/(?:.*\/)?route\.[jt]s$/u;
22840
+ function isFrameworkEntrypoint(filename, exportKey) {
22841
+ const normalized = filename.replaceAll("\\", "/");
22842
+ if (!/(?:^|\/)(?:app|pages)\/|(?:^|\/)(?:middleware|proxy)\.[jt]s$/u.test(normalized)) return false;
22843
+ const owner = packageOwner(normalized);
22844
+ if (owner === null) return false;
22845
+ const path = (0, import_node_path2.relative)(owner.root, normalized).replaceAll("\\", "/");
22846
+ if (declaresFramework(owner.metadata, "next") && isNextEntrypoint(path, exportKey)) return true;
22847
+ return declaresFramework(owner.metadata, "astro") && isAstroEntrypoint(path, exportKey);
22848
+ }
22849
+ function isNextEntrypoint(path, exportKey) {
22850
+ const privateAppFolder = /^(?:src\/)?app\/(?:.*\/)?_[^/]+\//u.test(path);
22851
+ if (!privateAppFolder && NEXT_COMPONENT.test(path) && exportKey === "default") return true;
22852
+ if (!privateAppFolder && NEXT_ROUTE.test(path) && HTTP_METHODS.has(exportKey)) return true;
22853
+ if (/^(?:src\/)?pages\/.*\.[jt]sx?$/u.test(path) && exportKey === "default") return true;
22854
+ const middleware = /^(?:src\/)?(middleware|proxy)\.[jt]s$/u.exec(path);
22855
+ return middleware !== null && (exportKey === "default" || exportKey === middleware[1]);
22856
+ }
22857
+ function isAstroEntrypoint(path, exportKey) {
22858
+ return (
22859
+ // Astro pages implicitly export their rendered component, including when only a routing hook is explicit.
22860
+ /^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"
22861
+ );
22862
+ }
22863
+ function packageOwner(filename) {
22864
+ let root = (0, import_node_path2.dirname)(filename);
22865
+ while (true) {
22866
+ try {
22867
+ return { root, metadata: JSON.parse((0, import_node_fs2.readFileSync)((0, import_node_path2.join)(root, "package.json"), "utf8")) };
22868
+ } catch (error) {
22869
+ if (typeof error !== "object" || error === null || !("code" in error) || error.code !== "ENOENT") return null;
22870
+ }
22871
+ const parent = (0, import_node_path2.dirname)(root);
22872
+ if (parent === root) return null;
22873
+ root = parent;
22874
+ }
22875
+ }
22876
+ function declaresFramework(metadata, name) {
22877
+ if (typeof metadata !== "object" || metadata === null) return false;
22878
+ for (const section of ["dependencies", "devDependencies", "peerDependencies", "optionalDependencies"]) {
22879
+ const dependencies = Reflect.get(metadata, section);
22880
+ if (typeof dependencies === "object" && dependencies !== null && typeof Reflect.get(dependencies, name) === "string") return true;
22881
+ }
22882
+ return false;
22883
+ }
22884
+
22885
+ // src/rules/sole-export-matches-filename.ts
22688
22886
  var SOLE_EXPORT_MATCHES_FILENAME_DOCUMENTATION = {
22689
- defaultLevel: "warning",
22887
+ defaultLevel: "error",
22690
22888
  summary: "Make a module filename reflect its sole named public runtime export.",
22691
22889
  rationale: "When a module owns one runtime responsibility, matching names make that responsibility directly discoverable.",
22692
- 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.",
22890
+ remediation: "Name the module for the exported responsibility, using the full kebab-case export name; otherwise colocate genuinely related exports.",
22693
22891
  category: "maintainability",
22694
22892
  limitations: [
22695
- "Framework entrypoints, generic stems covered by no-generic-single-export-module, tests, generated files, anonymous defaults, CommonJS, and re-exports are excluded.",
22696
- "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.",
22697
- "Exported destructuring patterns are excluded rather than undercounted as public exports."
22893
+ "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.",
22894
+ "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.",
22895
+ "Exported destructuring patterns are excluded rather than undercounted as public exports.",
22896
+ "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."
22698
22897
  ],
22699
22898
  examples: [
22700
22899
  { 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 },
@@ -22702,39 +22901,9 @@ var SOLE_EXPORT_MATCHES_FILENAME_DOCUMENTATION = {
22702
22901
  ]
22703
22902
  };
22704
22903
  var EXCLUDED_STEMS = /* @__PURE__ */ new Set([
22705
- "common",
22706
22904
  "global",
22707
- "helpers",
22708
22905
  "index",
22709
- "layout",
22710
- "loading",
22711
- "middleware",
22712
- "misc",
22713
- "not-found",
22714
- "page",
22715
- "route",
22716
- "shared",
22717
- "template",
22718
- "types",
22719
- "util",
22720
- "utils"
22721
- ]);
22722
- var WEAK_DOMAIN_TOKENS = /* @__PURE__ */ new Set([
22723
- "adapter",
22724
- "client",
22725
- "config",
22726
- "controller",
22727
- "factory",
22728
- "handler",
22729
- "manager",
22730
- "provider",
22731
- "record",
22732
- "repository",
22733
- "router",
22734
- "schema",
22735
- "service",
22736
- "store",
22737
- "worker"
22906
+ "types"
22738
22907
  ]);
22739
22908
  function stem3(filename) {
22740
22909
  const base = filename.replaceAll("\\", "/").split("/").at(-1) ?? "";
@@ -22743,34 +22912,6 @@ function stem3(filename) {
22743
22912
  function kebabCase(name) {
22744
22913
  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();
22745
22914
  }
22746
- function reflectsExportName(fileStem, exportedStem) {
22747
- if (fileStem.startsWith("_")) return false;
22748
- const visibleFileStem = fileStem.toLowerCase();
22749
- const fileTokens = visibleFileStem.split("-").filter(Boolean);
22750
- const exportTokens = exportedStem.split("-").filter(Boolean);
22751
- if (fileTokens.length === 0 || exportTokens.length === 0) return false;
22752
- if (fileTokens.length === 1) {
22753
- const [token] = fileTokens;
22754
- return token !== void 0 && token.length >= 4 && !WEAK_DOMAIN_TOKENS.has(token) && (exportTokens[0] === token || exportTokens.at(-1) === token);
22755
- }
22756
- const compactFile = fileTokens.join("");
22757
- if (compactFile.length < 6) return false;
22758
- const boundaryPhrases = /* @__PURE__ */ new Set();
22759
- for (let index = 1; index <= exportTokens.length; index += 1) {
22760
- boundaryPhrases.add(exportTokens.slice(0, index).join(""));
22761
- boundaryPhrases.add(exportTokens.slice(-index).join(""));
22762
- }
22763
- return boundaryPhrases.has(compactFile);
22764
- }
22765
- function declarationExport(statement) {
22766
- const declaration = statement.declaration;
22767
- if (declaration === null || declaration.declare === true) return [];
22768
- if (declaration.type === import_utils121.AST_NODE_TYPES.ClassDeclaration || declaration.type === import_utils121.AST_NODE_TYPES.FunctionDeclaration || declaration.type === import_utils121.AST_NODE_TYPES.TSEnumDeclaration) return declaration.id === null ? [] : [{ name: declaration.id.name, node: declaration }];
22769
- if (declaration.type !== import_utils121.AST_NODE_TYPES.VariableDeclaration) return [];
22770
- return declaration.declarations.flatMap(
22771
- (item) => item.id.type === import_utils121.AST_NODE_TYPES.Identifier ? [{ name: item.id.name, node: item }] : []
22772
- );
22773
- }
22774
22915
  var sole_export_matches_filename_default = createRule({
22775
22916
  name: "sole-export-matches-filename",
22776
22917
  documentation: SOLE_EXPORT_MATCHES_FILENAME_DOCUMENTATION,
@@ -22786,64 +22927,25 @@ var sole_export_matches_filename_default = createRule({
22786
22927
  create(context) {
22787
22928
  const fileStem = stem3(context.filename);
22788
22929
  const normalizedFilename = context.filename.replaceAll("\\", "/");
22789
- 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 {};
22930
+ 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 {};
22931
+ let hasCommonJsExport = false;
22790
22932
  return {
22933
+ "CallExpression, MemberExpression"(node) {
22934
+ if (isCommonJsExportReference(node, context.sourceCode)) hasCommonJsExport = true;
22935
+ },
22791
22936
  "Program:exit"(program) {
22792
- const exports2 = [];
22793
- const publicExports = /* @__PURE__ */ new Set();
22794
- function collectPublicExport(statement) {
22795
- if (statement.type === import_utils121.AST_NODE_TYPES.ExportAllDeclaration || statement.type === import_utils121.AST_NODE_TYPES.ExportNamedDeclaration && statement.source !== null) return false;
22796
- if (statement.type === import_utils121.AST_NODE_TYPES.ExportDefaultDeclaration) {
22797
- publicExports.add("default");
22798
- const declaration = statement.declaration;
22799
- if ((declaration.type === import_utils121.AST_NODE_TYPES.ClassDeclaration || declaration.type === import_utils121.AST_NODE_TYPES.FunctionDeclaration) && declaration.id !== null) exports2.push({ name: declaration.id.name, node: declaration });
22800
- else return false;
22801
- }
22802
- if (statement.type !== import_utils121.AST_NODE_TYPES.ExportNamedDeclaration) return true;
22803
- return collectNamedExport(statement);
22804
- }
22805
- function collectNamedExport(statement) {
22806
- const declaration = statement.declaration;
22807
- if (declaration !== null && "id" in declaration && declaration.id?.type === import_utils121.AST_NODE_TYPES.Identifier) {
22808
- publicExports.add(declaration.id.name);
22809
- }
22810
- if (declaration?.type === import_utils121.AST_NODE_TYPES.VariableDeclaration) {
22811
- if (declaration.declarations.some((item) => item.id.type !== import_utils121.AST_NODE_TYPES.Identifier)) return false;
22812
- for (const item of declaration.declarations) {
22813
- if (item.id.type === import_utils121.AST_NODE_TYPES.Identifier) publicExports.add(item.id.name);
22814
- }
22815
- }
22816
- for (const specifier of statement.specifiers) {
22817
- const exported = specifier.exported.type === import_utils121.AST_NODE_TYPES.Identifier ? specifier.exported.name : specifier.exported.value;
22818
- publicExports.add(String(exported));
22819
- }
22820
- if (statement.exportKind === "type") return true;
22821
- exports2.push(...declarationExport(statement));
22822
- collectRuntimeSpecifiers(statement);
22823
- return true;
22824
- }
22825
- function collectRuntimeSpecifiers(statement) {
22826
- for (const specifier of statement.specifiers) {
22827
- const exported = specifier.exported.type === import_utils121.AST_NODE_TYPES.Identifier ? specifier.exported.name : specifier.exported.value;
22828
- publicExports.add(String(exported));
22829
- if (specifier.exportKind === "type") continue;
22830
- if (exported === "default") exports2.push({ name: specifier.local.name, node: specifier });
22831
- else exports2.push({ name: String(exported), node: specifier });
22832
- }
22833
- }
22834
- for (const statement of program.body) {
22835
- if (!collectPublicExport(statement)) return;
22836
- }
22837
- const unique = new Map(exports2.map((item) => [item.name, item]));
22838
- if (unique.size !== 1 || publicExports.size !== 1) return;
22839
- const only = [...unique.values()][0];
22937
+ if (hasCommonJsExport) return;
22938
+ const exports2 = runtimeExports(program);
22939
+ if (exports2.ambiguous || exports2.exports.length !== 1) return;
22940
+ const only = exports2.exports[0];
22840
22941
  if (only === void 0) return;
22942
+ if (isFrameworkEntrypoint(normalizedFilename, only.key)) return;
22841
22943
  if (only.name === "onRouterTransitionStart" && /(?:^|\/)instrumentation-client\.[jt]s$/u.test(normalizedFilename)) return;
22842
22944
  if (only.name === "collections" && /(?:^|\/)src\/content\.config\.(?:ts|js|mjs)$/u.test(normalizedFilename) && program.body.some((statement) => statement.type === import_utils121.AST_NODE_TYPES.ImportDeclaration && statement.source.value === "astro:content")) return;
22843
22945
  const exportedStem = kebabCase(only.name);
22844
22946
  if (exportedStem === "") return;
22845
22947
  const expected = `${fileStem.startsWith("_") ? "_" : ""}${exportedStem}`;
22846
- if (expected === fileStem.toLowerCase() || reflectsExportName(fileStem, exportedStem)) return;
22948
+ if (expected === fileStem.toLowerCase()) return;
22847
22949
  context.report({ node: only.node, messageId: "matchSoleExport", data: { exported: only.name, expected } });
22848
22950
  }
22849
22951
  };
@@ -23058,7 +23160,7 @@ var chainMemberNames2 = (node) => {
23058
23160
  names.reverse();
23059
23161
  return names;
23060
23162
  };
23061
- var unwrapExpression7 = (node) => {
23163
+ var unwrapExpression8 = (node) => {
23062
23164
  let current = node;
23063
23165
  while (current.type === import_utils122.AST_NODE_TYPES.TSAsExpression || current.type === import_utils122.AST_NODE_TYPES.TSSatisfiesExpression || current.type === import_utils122.AST_NODE_TYPES.TSNonNullExpression || current.type === import_utils122.AST_NODE_TYPES.TSTypeAssertion) {
23064
23166
  current = current.expression;
@@ -23098,18 +23200,8 @@ var require_pascal_case_zod_schema_name_default = createRule({
23098
23200
  const binding = resolvedBinding(identifier);
23099
23201
  if (binding !== null) zodBindings.add(binding);
23100
23202
  }
23101
- function isZodChain(node) {
23102
- const root = calleeChainRoot2(node);
23103
- if (root === null) return false;
23104
- const binding = resolvedBinding(root);
23105
- return binding !== null && zodBindings.has(binding);
23106
- }
23107
- function isSchemaBinding(identifier) {
23108
- const binding = resolvedBinding(identifier);
23109
- return binding !== null && schemaBindings.has(binding);
23110
- }
23111
23203
  function isConfirmedSchema(expression) {
23112
- const init = unwrapExpression7(expression);
23204
+ const init = unwrapExpression8(expression);
23113
23205
  if (init.type === import_utils122.AST_NODE_TYPES.Identifier) return isSchemaBinding(init);
23114
23206
  if (init.type !== import_utils122.AST_NODE_TYPES.CallExpression || init.callee.type !== import_utils122.AST_NODE_TYPES.MemberExpression) {
23115
23207
  return false;
@@ -23124,6 +23216,16 @@ var require_pascal_case_zod_schema_name_default = createRule({
23124
23216
  const root = calleeChainRoot2(init.callee);
23125
23217
  return root !== null && isSchemaBinding(root) && SCHEMA_RETURNING_METHODS.has(terminal);
23126
23218
  }
23219
+ function isSchemaBinding(identifier) {
23220
+ const binding = resolvedBinding(identifier);
23221
+ return binding !== null && schemaBindings.has(binding);
23222
+ }
23223
+ function isZodChain(node) {
23224
+ const root = calleeChainRoot2(node);
23225
+ if (root === null) return false;
23226
+ const binding = resolvedBinding(root);
23227
+ return binding !== null && zodBindings.has(binding);
23228
+ }
23127
23229
  if (isTestFile(context.filename) || BENCHMARK_PATH_RE2.test(context.filename.replaceAll("\\", "/")) || isGeneratedFile(context.filename, context.sourceCode.text)) {
23128
23230
  return {};
23129
23231
  }
@@ -23154,7 +23256,7 @@ var require_pascal_case_zod_schema_name_default = createRule({
23154
23256
  }
23155
23257
  });
23156
23258
 
23157
- // src/rules/_renames.ts
23259
+ // src/rules/_renamed-rules.ts
23158
23260
  var RENAMED_RULES = {
23159
23261
  "jsdoc-restates-signature": "no-restated-jsdoc",
23160
23262
  "zod-naming-convention": "require-pascal-case-zod-schema-name",
@@ -23163,7 +23265,7 @@ var RENAMED_RULES = {
23163
23265
  "trailing-value-narration": "no-trailing-value-narration"
23164
23266
  };
23165
23267
 
23166
- // src/rules/_retired.ts
23268
+ // src/rules/_retired-rules.ts
23167
23269
  var RETIRED_RULES = {
23168
23270
  "ban-loose-type-guards-in-tests": {
23169
23271
  removedIn: "5.0.0",
@@ -23355,7 +23457,7 @@ var RULES = {
23355
23457
  };
23356
23458
  var meta = {
23357
23459
  name: "@sarj/eslint-plugin",
23358
- version: "15.28.1"
23460
+ version: "16.1.0"
23359
23461
  };
23360
23462
  var APPLICATION_ONLY_RULES = [];
23361
23463
  var LIBRARY_IMPORT_POLICY = ["error", {
@@ -23380,8 +23482,7 @@ var ADVISORY_RULES = [
23380
23482
  "@sarj/prefer-whole-object-assertion",
23381
23483
  "@sarj/require-camelcase-properties",
23382
23484
  "@sarj/require-interface-for-exported-class",
23383
- "@sarj/require-sql-access-class",
23384
- "@sarj/sole-export-matches-filename"
23485
+ "@sarj/require-sql-access-class"
23385
23486
  ];
23386
23487
  var RECOMMENDED_RULES = {
23387
23488
  "@sarj/no-conditional-empty-object-spread": "error",
@@ -23493,7 +23594,7 @@ var RECOMMENDED_RULES = {
23493
23594
  "@sarj/store-insert-requires-on-conflict": "error",
23494
23595
  "@sarj/stepdown": "error",
23495
23596
  "@sarj/source-coupled-test": "error",
23496
- "@sarj/sole-export-matches-filename": "warn",
23597
+ "@sarj/sole-export-matches-filename": "error",
23497
23598
  "@sarj/test-phase-label-comment": "error",
23498
23599
  "@sarj/require-pascal-case-zod-schema-name": "error"
23499
23600
  };
@@ -23611,7 +23712,7 @@ var STRICT_RULES = {
23611
23712
  "@sarj/store-insert-requires-on-conflict": "error",
23612
23713
  "@sarj/stepdown": "error",
23613
23714
  "@sarj/source-coupled-test": "error",
23614
- "@sarj/sole-export-matches-filename": "warn",
23715
+ "@sarj/sole-export-matches-filename": "error",
23615
23716
  "@sarj/test-phase-label-comment": "error",
23616
23717
  "@sarj/require-pascal-case-zod-schema-name": "error"
23617
23718
  };
@@ -23634,7 +23735,7 @@ var PLUGIN = {
23634
23735
  };
23635
23736
  }
23636
23737
  };
23637
- var index_default = PLUGIN;
23738
+ var src_default = PLUGIN;
23638
23739
  // Annotate the CommonJS export names for ESM import in node:
23639
23740
  0 && (module.exports = {
23640
23741
  ADVISORY_RULES,